Skip to content

Commit 97da322

Browse files
committed
Implemented support for myzod
1 parent 6ab7a59 commit 97da322

File tree

1 file changed

+35
-25
lines changed

1 file changed

+35
-25
lines changed

src/myzod/index.ts

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { DeclarationBlock, indent } from '@graphql-codegen/visitor-plugin-common
1212
import { TsVisitor } from '@graphql-codegen/typescript';
1313
import { buildApi, formatDirectiveConfig } from '../directive';
1414

15-
const importZod = `import { z } from 'zod'`;
15+
const importZod = `import myzod from 'myzod'`;
1616
const anySchema = `definedNonNullAnySchema`;
1717

1818
export const ZodSchemaVisitor = (schema: GraphQLSchema, config: ValidationSchemaPluginConfig) => {
@@ -27,13 +27,21 @@ export const ZodSchemaVisitor = (schema: GraphQLSchema, config: ValidationSchema
2727
}
2828
return [importZod];
2929
},
30+
3031
initialEmit: (): string =>
3132
'\n' +
3233
[
34+
/*
35+
* MyZod allows you to create typed objects with `myzod.Type<YourCustomType>`
36+
* See https://www.npmjs.com/package/myzod#lazy
3337
new DeclarationBlock({})
3438
.asKind('type')
3539
.withName('Properties<T>')
3640
.withContent(['Required<{', ' [K in keyof T]: z.ZodType<T[K], any, T[K]>;', '}>'].join('\n')).string,
41+
*/
42+
/*
43+
* MyZod allows empty object hence no need for these hacks
44+
* See https://www.npmjs.com/package/myzod#object
3745
// Unfortunately, zod doesn’t provide non-null defined any schema.
3846
// This is a temporary hack until it is fixed.
3947
// see: https://github.com/colinhacks/zod/issues/884
@@ -48,54 +56,55 @@ export const ZodSchemaVisitor = (schema: GraphQLSchema, config: ValidationSchema
4856
.asKind('const')
4957
.withName(`${anySchema}`)
5058
.withContent(`z.any().refine((v) => isDefinedNonNullAny(v))`).string,
59+
*/
5160
].join('\n'),
5261
InputObjectTypeDefinition: (node: InputObjectTypeDefinitionNode) => {
5362
const name = tsVisitor.convertName(node.name.value);
5463
importTypes.push(name);
5564

5665
const shape = node.fields
57-
?.map(field => generateInputObjectFieldZodSchema(config, tsVisitor, schema, field, 2))
66+
?.map(field => generateInputObjectFieldMyZodSchema(config, tsVisitor, schema, field, 2))
5867
.join(',\n');
5968

6069
return new DeclarationBlock({})
6170
.export()
62-
.asKind('function')
63-
.withName(`${name}Schema(): z.ZodObject<Properties<${name}>>`)
64-
.withBlock([indent(`return z.object({`), shape, indent('})')].join('\n')).string;
71+
.asKind('const')
72+
.withName(`${name}Schema: myzod.Type<${name}>`) //TODO: Test this
73+
.withBlock([indent(`myzod.object({`), shape, indent('})')].join('\n')).string;
6574
},
6675
EnumTypeDefinition: (node: EnumTypeDefinitionNode) => {
6776
const enumname = tsVisitor.convertName(node.name.value);
6877
importTypes.push(enumname);
69-
78+
/*
7079
if (config.enumsAsTypes) {
7180
return new DeclarationBlock({})
7281
.export()
7382
.asKind('const')
7483
.withName(`${enumname}Schema`)
7584
.withContent(`z.enum([${node.values?.map(enumOption => `'${enumOption.name.value}'`).join(', ')}])`).string;
7685
}
77-
86+
*/
7887
return new DeclarationBlock({})
7988
.export()
8089
.asKind('const')
8190
.withName(`${enumname}Schema`)
82-
.withContent(`z.nativeEnum(${enumname})`).string;
91+
.withContent(`myzod.enum(${enumname})`).string;
8392
},
8493
};
8594
};
8695

87-
const generateInputObjectFieldZodSchema = (
96+
const generateInputObjectFieldMyZodSchema = (
8897
config: ValidationSchemaPluginConfig,
8998
tsVisitor: TsVisitor,
9099
schema: GraphQLSchema,
91100
field: InputValueDefinitionNode,
92101
indentCount: number
93102
): string => {
94-
const gen = generateInputObjectFieldTypeZodSchema(config, tsVisitor, schema, field, field.type);
103+
const gen = generateInputObjectFieldTypeMyZodSchema(config, tsVisitor, schema, field, field.type);
95104
return indent(`${field.name.value}: ${maybeLazy(field.type, gen)}`, indentCount);
96105
};
97106

98-
const generateInputObjectFieldTypeZodSchema = (
107+
const generateInputObjectFieldTypeMyZodSchema = (
99108
config: ValidationSchemaPluginConfig,
100109
tsVisitor: TsVisitor,
101110
schema: GraphQLSchema,
@@ -104,22 +113,22 @@ const generateInputObjectFieldTypeZodSchema = (
104113
parentType?: TypeNode
105114
): string => {
106115
if (isListType(type)) {
107-
const gen = generateInputObjectFieldTypeZodSchema(config, tsVisitor, schema, field, type.type, type);
116+
const gen = generateInputObjectFieldTypeMyZodSchema(config, tsVisitor, schema, field, type.type, type);
108117
if (!isNonNullType(parentType)) {
109-
const arrayGen = `z.array(${maybeLazy(type.type, gen)})`;
118+
const arrayGen = `myzod.array(${maybeLazy(type.type, gen)})`;
110119
const maybeLazyGen = applyDirectives(config, field, arrayGen);
111-
return `${maybeLazyGen}.nullish()`;
120+
return `${maybeLazyGen}.optional()`; // to make it equivalent to nullish: `${maybeLazyGen}.optional().optional().or(nullable())`;
112121
}
113-
return `z.array(${maybeLazy(type.type, gen)})`;
122+
return `myzod.array(${maybeLazy(type.type, gen)})`;
114123
}
115124
if (isNonNullType(type)) {
116-
const gen = generateInputObjectFieldTypeZodSchema(config, tsVisitor, schema, field, type.type, type);
125+
const gen = generateInputObjectFieldTypeMyZodSchema(config, tsVisitor, schema, field, type.type, type);
117126
return maybeLazy(type.type, gen);
118127
}
119128
if (isNamedType(type)) {
120-
const gen = generateNameNodeZodSchema(config, tsVisitor, schema, type.name);
129+
const gen = generateNameNodeMyZodSchema(config, tsVisitor, schema, type.name);
121130
if (isListType(parentType)) {
122-
return `${gen}.nullable()`;
131+
return `${gen}.nullable()`; //TODO: Test this later
123132
}
124133
const appliedDirectivesGen = applyDirectives(config, field, gen);
125134
if (isNonNullType(parentType)) {
@@ -130,14 +139,15 @@ const generateInputObjectFieldTypeZodSchema = (
130139
return appliedDirectivesGen;
131140
}
132141
if (isListType(parentType)) {
133-
return `${appliedDirectivesGen}.nullable()`;
142+
return `${appliedDirectivesGen}.nullable()`; //TODO: Test this later
134143
}
135-
return `${appliedDirectivesGen}.nullish()`;
144+
return `${appliedDirectivesGen}.optional()`; // to make it equivalent to nullish: `${appliedDirectivesGen}.optional().or(nullable())`;
136145
}
137146
console.warn('unhandled type:', type);
138147
return '';
139148
};
140149

150+
// TODO: Find out how it works and implement it
141151
const applyDirectives = (
142152
config: ValidationSchemaPluginConfig,
143153
field: InputValueDefinitionNode,
@@ -150,7 +160,7 @@ const applyDirectives = (
150160
return gen;
151161
};
152162

153-
const generateNameNodeZodSchema = (
163+
const generateNameNodeMyZodSchema = (
154164
config: ValidationSchemaPluginConfig,
155165
tsVisitor: TsVisitor,
156166
schema: GraphQLSchema,
@@ -173,7 +183,7 @@ const generateNameNodeZodSchema = (
173183

174184
const maybeLazy = (type: TypeNode, schema: string): string => {
175185
if (isNamedType(type) && isInput(type.name.value)) {
176-
return `z.lazy(() => ${schema})`;
186+
return `myzod.lazy(() => ${schema})`;
177187
}
178188
return schema;
179189
};
@@ -185,11 +195,11 @@ const zod4Scalar = (config: ValidationSchemaPluginConfig, tsVisitor: TsVisitor,
185195
const tsType = tsVisitor.scalars[scalarName];
186196
switch (tsType) {
187197
case 'string':
188-
return `z.string()`;
198+
return `myzod.string()`;
189199
case 'number':
190-
return `z.number()`;
200+
return `myzod.number()`;
191201
case 'boolean':
192-
return `z.boolean()`;
202+
return `myzod.boolean()`;
193203
}
194204
console.warn('unhandled name:', scalarName);
195205
return anySchema;

0 commit comments

Comments
 (0)