Skip to content

Commit b5ab94d

Browse files
authored
Merge pull request #28 from Code-Hex/fix/myzod
fixed non-compilation example code for myzod
2 parents 163658b + 5ecd96c commit b5ab94d

File tree

6 files changed

+129
-50
lines changed

6 files changed

+129
-50
lines changed

README.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
- [x] support [yup](https://github.com/jquense/yup)
88
- [x] support [zod](https://github.com/colinhacks/zod)
9+
- [x] support [myzod](https://github.com/davidmdm/myzod)
910

1011
## Quick Start
1112

@@ -29,9 +30,9 @@ generates:
2930
schema: yup # or zod
3031
```
3132
32-
You can check [example directory](https://github.com/Code-Hex/graphql-codegen-typescript-validation-schema/tree/main/example) if you want to see more complex config example or how is generated some files.
33+
You can check [example](https://github.com/Code-Hex/graphql-codegen-typescript-validation-schema/tree/main/example) directory if you want to see more complex config example or how is generated some files.
3334
34-
...And I wrote some tips in there.
35+
The Q&A for each schema is written in the README in the respective example directory.
3536
3637
## Config API Reference
3738
@@ -41,7 +42,7 @@ type: `ValidationSchema` default: `'yup'`
4142

4243
Specify generete validation schema you want.
4344

44-
You can specify `yup` or `zod`.
45+
You can specify `yup` or `zod` or `myzod`.
4546

4647
```yml
4748
generates:
@@ -207,3 +208,7 @@ export function ExampleInputSchema(): z.ZodSchema<ExampleInput> {
207208
})
208209
}
209210
```
211+
212+
#### other schema
213+
214+
Please see [example](https://github.com/Code-Hex/graphql-codegen-typescript-validation-schema/tree/main/example) directory.

codegen.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,15 @@ generates:
5757
startsWith: ['regex', '/^$1/', 'message']
5858
format:
5959
email: email
60+
example/myzod/schemas.ts:
61+
plugins:
62+
- ./dist/main/index.js:
63+
schema: myzod
64+
importFrom: ../types
65+
directives:
66+
constraint:
67+
minLength: min
68+
# Replace $1 with specified `startsWith` argument value of the constraint directive
69+
startsWith: ['pattern', '/^$1/']
70+
format:
71+
email: email

example/myzod/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Tips for myzod schema
2+
3+
## How to overwrite generated schema?
4+
5+
Basically, I think [it does not support overwrite schema](https://github.com/davidmdm/myzod/issues/51) in myzod. However, [`and`](https://github.com/davidmdm/myzod#typeand) and [`or`](https://github.com/davidmdm/myzod#typeor) may helps you.
6+
7+
See also: https://github.com/Code-Hex/graphql-codegen-typescript-validation-schema/issues/25#issuecomment-1086532098

example/myzod/schemas.ts

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import * as myzod from 'myzod'
2+
import { AttributeInput, ButtonComponentType, ComponentInput, DropDownComponentInput, EventArgumentInput, EventInput, EventOptionType, HttpInput, HttpMethod, LayoutInput, PageInput, PageType } from '../types'
3+
4+
export const definedNonNullAnySchema = myzod.object({});
5+
6+
export function AttributeInputSchema(): myzod.Type<AttributeInput> {
7+
return myzod.object({
8+
key: myzod.string().optional().nullable(),
9+
val: myzod.string().optional().nullable()
10+
})
11+
}
12+
13+
export const ButtonComponentTypeSchema = myzod.enum(ButtonComponentType);
14+
15+
export function ComponentInputSchema(): myzod.Type<ComponentInput> {
16+
return myzod.object({
17+
child: myzod.lazy(() => ComponentInputSchema().optional().nullable()),
18+
childrens: myzod.array(myzod.lazy(() => ComponentInputSchema().nullable())).optional().nullable(),
19+
event: myzod.lazy(() => EventInputSchema().optional().nullable()),
20+
name: myzod.string(),
21+
type: ButtonComponentTypeSchema
22+
})
23+
}
24+
25+
export function DropDownComponentInputSchema(): myzod.Type<DropDownComponentInput> {
26+
return myzod.object({
27+
dropdownComponent: myzod.lazy(() => ComponentInputSchema().optional().nullable()),
28+
getEvent: myzod.lazy(() => EventInputSchema())
29+
})
30+
}
31+
32+
export function EventArgumentInputSchema(): myzod.Type<EventArgumentInput> {
33+
return myzod.object({
34+
name: myzod.string().min(5),
35+
value: myzod.string().pattern(/^foo/)
36+
})
37+
}
38+
39+
export function EventInputSchema(): myzod.Type<EventInput> {
40+
return myzod.object({
41+
arguments: myzod.array(myzod.lazy(() => EventArgumentInputSchema())),
42+
options: myzod.array(EventOptionTypeSchema).optional().nullable()
43+
})
44+
}
45+
46+
export const EventOptionTypeSchema = myzod.enum(EventOptionType);
47+
48+
export function HttpInputSchema(): myzod.Type<HttpInput> {
49+
return myzod.object({
50+
method: HttpMethodSchema.optional().nullable(),
51+
url: definedNonNullAnySchema
52+
})
53+
}
54+
55+
export const HttpMethodSchema = myzod.enum(HttpMethod);
56+
57+
export function LayoutInputSchema(): myzod.Type<LayoutInput> {
58+
return myzod.object({
59+
dropdown: myzod.lazy(() => DropDownComponentInputSchema().optional().nullable())
60+
})
61+
}
62+
63+
export function PageInputSchema(): myzod.Type<PageInput> {
64+
return myzod.object({
65+
attributes: myzod.array(myzod.lazy(() => AttributeInputSchema())).optional().nullable(),
66+
date: definedNonNullAnySchema.optional().nullable(),
67+
height: myzod.number(),
68+
id: myzod.string(),
69+
layout: myzod.lazy(() => LayoutInputSchema()),
70+
pageType: PageTypeSchema,
71+
postIDs: myzod.array(myzod.string()).optional().nullable(),
72+
show: myzod.boolean(),
73+
tags: myzod.array(myzod.string().nullable()).optional().nullable(),
74+
title: myzod.string(),
75+
width: myzod.number()
76+
})
77+
}
78+
79+
export const PageTypeSchema = myzod.enum(PageType);

src/myzod/index.ts

Lines changed: 8 additions & 32 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 myzod from 'myzod'`;
15+
const importZod = `import * as myzod from 'myzod'`;
1616
const anySchema = `definedNonNullAnySchema`;
1717

1818
export const MyZodSchemaVisitor = (schema: GraphQLSchema, config: ValidationSchemaPluginConfig) => {
@@ -30,32 +30,8 @@ export const MyZodSchemaVisitor = (schema: GraphQLSchema, config: ValidationSche
3030
initialEmit: (): string =>
3131
'\n' +
3232
[
33-
/*
34-
* MyZod allows you to create typed objects with `myzod.Type<YourCustomType>`
35-
* See https://www.npmjs.com/package/myzod#lazy
36-
new DeclarationBlock({})
37-
.asKind('type')
38-
.withName('Properties<T>')
39-
.withContent(['Required<{', ' [K in keyof T]: z.ZodType<T[K], any, T[K]>;', '}>'].join('\n')).string,
40-
*/
41-
/*
42-
* MyZod allows empty object hence no need for these hacks
43-
* See https://www.npmjs.com/package/myzod#object
44-
// Unfortunately, zod doesn’t provide non-null defined any schema.
45-
// This is a temporary hack until it is fixed.
46-
// see: https://github.com/colinhacks/zod/issues/884
47-
new DeclarationBlock({}).asKind('type').withName('definedNonNullAny').withContent('{}').string,
48-
new DeclarationBlock({})
49-
.export()
50-
.asKind('const')
51-
.withName(`isDefinedNonNullAny`)
52-
.withContent(`(v: any): v is definedNonNullAny => v !== undefined && v !== null`).string,
53-
new DeclarationBlock({})
54-
.export()
55-
.asKind('const')
56-
.withName(`${anySchema}`)
57-
.withContent(`z.any().refine((v) => isDefinedNonNullAny(v))`).string,
58-
*/
33+
new DeclarationBlock({}).export().asKind('const').withName(`${anySchema}`).withContent(`myzod.object({})`)
34+
.string,
5935
].join('\n'),
6036
InputObjectTypeDefinition: (node: InputObjectTypeDefinitionNode) => {
6137
const name = tsVisitor.convertName(node.name.value);
@@ -67,9 +43,9 @@ export const MyZodSchemaVisitor = (schema: GraphQLSchema, config: ValidationSche
6743

6844
return new DeclarationBlock({})
6945
.export()
70-
.asKind('const')
71-
.withName(`${name}Schema: myzod.Type<${name}>`) //TODO: Test this
72-
.withBlock([indent(`myzod.object({`), shape, indent('})')].join('\n')).string;
46+
.asKind('function')
47+
.withName(`${name}Schema(): myzod.Type<${name}>`)
48+
.withBlock([indent(`return myzod.object({`), shape, indent('})')].join('\n')).string;
7349
},
7450
EnumTypeDefinition: (node: EnumTypeDefinitionNode) => {
7551
const enumname = tsVisitor.convertName(node.name.value);
@@ -177,7 +153,7 @@ const generateNameNodeMyZodSchema = (
177153
return `${enumName}Schema`;
178154
}
179155

180-
return zod4Scalar(config, tsVisitor, node.value);
156+
return myzod4Scalar(config, tsVisitor, node.value);
181157
};
182158

183159
const maybeLazy = (type: TypeNode, schema: string): string => {
@@ -187,7 +163,7 @@ const maybeLazy = (type: TypeNode, schema: string): string => {
187163
return schema;
188164
};
189165

190-
const zod4Scalar = (config: ValidationSchemaPluginConfig, tsVisitor: TsVisitor, scalarName: string): string => {
166+
const myzod4Scalar = (config: ValidationSchemaPluginConfig, tsVisitor: TsVisitor, scalarName: string): string => {
191167
if (config.scalarSchemas?.[scalarName]) {
192168
return config.scalarSchemas[scalarName];
193169
}

tests/myzod.spec.ts

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ describe('myzod', () => {
1515
}
1616
`,
1717
[
18-
'export const PrimitiveInputSchema: myzod.Type<PrimitiveInput>',
18+
'export function PrimitiveInputSchema(): myzod.Type<PrimitiveInput> {',
1919
'a: myzod.string()',
2020
'b: myzod.string()',
2121
'c: myzod.boolean()',
@@ -36,7 +36,7 @@ describe('myzod', () => {
3636
}
3737
`,
3838
[
39-
'export const PrimitiveInputSchema: myzod.Type<PrimitiveInput>',
39+
'export function PrimitiveInputSchema(): myzod.Type<PrimitiveInput> {',
4040
// alphabet order
4141
'a: myzod.string().optional().nullable(),',
4242
'b: myzod.string().optional().nullable(),',
@@ -58,7 +58,7 @@ describe('myzod', () => {
5858
}
5959
`,
6060
[
61-
'export const ArrayInputSchema: myzod.Type<ArrayInput>',
61+
'export function ArrayInputSchema(): myzod.Type<ArrayInput> {',
6262
'a: myzod.array(myzod.string().nullable()).optional().nullable(),',
6363
'b: myzod.array(myzod.string()).optional().nullable(),',
6464
'c: myzod.array(myzod.string()),',
@@ -81,11 +81,11 @@ describe('myzod', () => {
8181
}
8282
`,
8383
[
84-
'export const AInputSchema: myzod.Type<AInput>',
84+
'export function AInputSchema(): myzod.Type<AInput> {',
8585
'b: myzod.lazy(() => BInputSchema())',
86-
'export const BInputSchema: myzod.Type<BInput>',
86+
'export function BInputSchema(): myzod.Type<BInput> {',
8787
'c: myzod.lazy(() => CInputSchema())',
88-
'export const CInputSchema: myzod.Type<CInput>',
88+
'export function CInputSchema(): myzod.Type<CInput> {',
8989
'a: myzod.lazy(() => AInputSchema())',
9090
],
9191
],
@@ -98,7 +98,7 @@ describe('myzod', () => {
9898
}
9999
`,
100100
[
101-
'export const NestedInputSchema: myzod.Type<NestedInput>',
101+
'export function NestedInputSchema(): myzod.Type<NestedInput> {',
102102
'child: myzod.lazy(() => NestedInputSchema().optional().nullable()),',
103103
'childrens: myzod.array(myzod.lazy(() => NestedInputSchema().nullable())).optional().nullable()',
104104
],
@@ -116,7 +116,7 @@ describe('myzod', () => {
116116
`,
117117
[
118118
'export const PageTypeSchema = myzod.enum(PageType)',
119-
'export const PageInputSchema: myzod.Type<PageInput>',
119+
'export function PageInputSchema(): myzod.Type<PageInput> {',
120120
'pageType: PageTypeSchema',
121121
],
122122
],
@@ -136,7 +136,7 @@ describe('myzod', () => {
136136
scalar URL # unknown scalar, should be any (definedNonNullAnySchema)
137137
`,
138138
[
139-
'export const HttpInputSchema: myzod.Type<HttpInput>',
139+
'export function HttpInputSchema(): myzod.Type<HttpInput> {',
140140
'export const HttpMethodSchema = myzod.enum(HttpMethod)',
141141
'method: HttpMethodSchema',
142142
'url: definedNonNullAnySchema',
@@ -145,7 +145,7 @@ describe('myzod', () => {
145145
])('%s', async (_, textSchema, wantContains) => {
146146
const schema = buildSchema(textSchema);
147147
const result = await plugin(schema, [], { schema: 'myzod' }, {});
148-
expect(result.prepend).toContain("import myzod from 'myzod'");
148+
expect(result.prepend).toContain("import * as myzod from 'myzod'");
149149

150150
for (const wantContain of wantContains) {
151151
expect(result.content).toContain(wantContain);
@@ -236,7 +236,7 @@ describe('myzod', () => {
236236
{}
237237
);
238238
const wantContains = [
239-
'export const PrimitiveInputSchema: myzod.Type<PrimitiveInput>',
239+
'export function PrimitiveInputSchema(): myzod.Type<PrimitiveInput> {',
240240
'a: myzod.string().min(1),',
241241
'b: myzod.string().min(1),',
242242
'c: myzod.boolean(),',
@@ -271,7 +271,7 @@ describe('myzod', () => {
271271
{}
272272
);
273273
const wantContains = [
274-
'export const ScalarsInputSchema: myzod.Type<ScalarsInput>',
274+
'export function ScalarsInputSchema(): myzod.Type<ScalarsInput> {',
275275
'date: myzod.date(),',
276276
'email: myzod.string()', // TODO: Test implementation
277277
'str: myzod.string()',
@@ -304,7 +304,7 @@ describe('myzod', () => {
304304
{}
305305
);
306306
const wantContains = [
307-
'export const UserCreateInputSchema: myzod.Type<UserCreateInput>',
307+
'export function UserCreateInputSchema(): myzod.Type<UserCreateInput> {',
308308
'profile: myzod.string().min(1, "Please input more than 1").max(5000, "Please input less than 5000").optional().nullable()',
309309
];
310310
for (const wantContain of wantContains) {
@@ -334,7 +334,7 @@ describe('myzod', () => {
334334
{}
335335
);
336336
const wantContains = [
337-
'export const UserCreateInputSchema: myzod.Type<UserCreateInput>',
337+
'export function UserCreateInputSchema(): myzod.Type<UserCreateInput> {',
338338
'profile: myzod.string().min(1, "Please input more than 1").max(5000, "Please input less than 5000")',
339339
];
340340
for (const wantContain of wantContains) {
@@ -364,7 +364,7 @@ describe('myzod', () => {
364364
{}
365365
);
366366
const wantContains = [
367-
'export const UserCreateInputSchema: myzod.Type<UserCreateInput>',
367+
'export function UserCreateInputSchema(): myzod.Type<UserCreateInput> {',
368368
'profile: myzod.array(myzod.string().nullable()).min(1, "Please input more than 1").max(5000, "Please input less than 5000").optional().nullable()',
369369
];
370370
for (const wantContain of wantContains) {

0 commit comments

Comments
 (0)