Skip to content

Commit 0eeb1f1

Browse files
committed
directives
1 parent 380b3a8 commit 0eeb1f1

File tree

2 files changed

+65
-20
lines changed

2 files changed

+65
-20
lines changed

workspaces/leetcode-api/src/api/question-list/fetchGraphQL.generated.ts

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

workspaces/leetcode-api/src/scripts/codegen/graphqlToZod.ts

Lines changed: 64 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,36 @@ import {
77
GraphQLObjectType,
88
GraphQLScalarType,
99
Kind,
10+
type ConstDirectiveNode,
1011
type GraphQLNamedType,
1112
type SelectionSetNode,
1213
} from "graphql";
1314

15+
// TODO: get some of these directives added to the schema
16+
type DirectivesConfig = {
17+
nonnegative: boolean;
18+
};
19+
20+
function parseDirectives(
21+
directives: readonly ConstDirectiveNode[],
22+
): DirectivesConfig {
23+
const res = { nonnegative: false };
24+
for (const directive of directives) {
25+
switch (directive.name.value) {
26+
case "nonnegative": {
27+
invariant(!directive.arguments?.length, "No arguments allowed!");
28+
res.nonnegative = true;
29+
break;
30+
}
31+
default: {
32+
throw new Error("Unsupported directive " + directive.name.value);
33+
}
34+
}
35+
}
36+
37+
return res;
38+
}
39+
1440
class ZodOutput {
1541
constructor(
1642
public text: string,
@@ -34,19 +60,29 @@ class ZodOutput {
3460
function generateZod(
3561
currentType: GraphQLNamedType,
3662
selectionSet: SelectionSetNode | undefined,
63+
directives: readonly ConstDirectiveNode[] = [],
3764
): ZodOutput {
3865
if (currentType instanceof GraphQLScalarType) {
3966
switch (currentType.name) {
4067
case "Boolean": {
68+
invariant(directives.length === 0, "Directives not supported here.");
4169
return new ZodOutput("z.boolean()", true);
4270
}
4371
case "Int": {
44-
return new ZodOutput("z.number().int()", true);
72+
const directiveConfig = parseDirectives(directives);
73+
return new ZodOutput(
74+
[
75+
"z.number().int()",
76+
directiveConfig.nonnegative ? ".nonnegative()" : "",
77+
].join(""),
78+
true,
79+
);
4580
}
4681
case "Date":
4782
case "DateTime":
4883
case "ID":
4984
case "String": {
85+
invariant(directives.length === 0, "Directives not supported here.");
5086
return new ZodOutput("z.string()", true);
5187
}
5288
default: {
@@ -56,37 +92,46 @@ function generateZod(
5692
}
5793

5894
if (currentType instanceof GraphQLObjectType) {
95+
invariant(directives.length === 0, "Directives not supported here.");
96+
5997
const selections = nullthrows(selectionSet).selections.map((s) => {
6098
invariant(s.kind === Kind.FIELD, "Expected direct fields!");
6199

62100
const processStack: ((prev: ZodOutput) => ZodOutput)[] = [];
63101

64-
let fieldType = currentType.getFields()[s.name.value].type;
65-
while (
66-
fieldType instanceof GraphQLList ||
67-
fieldType instanceof GraphQLNonNull
68-
) {
102+
const field = currentType.getFields()[s.name.value];
103+
let fieldType = field.type;
104+
105+
while (true) {
69106
if (fieldType instanceof GraphQLList) {
70107
processStack.push(
71108
(prev) => new ZodOutput(`z.array(${prev.stringify(false)})`, true),
72109
);
73-
} else {
110+
fieldType = fieldType.ofType;
111+
continue;
112+
}
113+
114+
if (fieldType instanceof GraphQLNonNull) {
74115
processStack.push((prev) => prev.setIsNullable(false));
116+
fieldType = fieldType.ofType;
117+
continue;
75118
}
76119

77-
fieldType = fieldType.ofType;
120+
return (
121+
JSON.stringify(s.name.value) +
122+
": " +
123+
processStack
124+
.reduceRight(
125+
(acc, fn) => fn(acc),
126+
generateZod(
127+
fieldType,
128+
s.selectionSet,
129+
field.astNode?.directives ?? [],
130+
),
131+
)
132+
.stringify()
133+
);
78134
}
79-
80-
return (
81-
JSON.stringify(s.name.value) +
82-
": " +
83-
processStack
84-
.reduceRight(
85-
(acc, fn) => fn(acc),
86-
generateZod(fieldType, s.selectionSet),
87-
)
88-
.stringify()
89-
);
90135
});
91136

92137
return new ZodOutput(`z.object({${selections.join(",")}})`, true);

0 commit comments

Comments
 (0)