Skip to content

Commit 5506b6e

Browse files
authored
Merge pull request #136 from Code-Hex/fix/PR-132
fixed some code for #132 (withObjectType)
2 parents 726a19a + 3085340 commit 5506b6e

File tree

10 files changed

+375
-124
lines changed

10 files changed

+375
-124
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,12 @@ type: `ScalarSchemas`
152152

153153
Extends or overrides validation schema for the built-in scalars and custom GraphQL scalars.
154154

155+
### `withObjectType`
156+
157+
type: `boolean` default: `false`
158+
159+
Generates validation schema with GraphQL type objects. But excludes `Query`, `Mutation`, `Subscription` objects.
160+
155161
#### yup schema
156162

157163
```yml

codegen.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ generates:
99
- ./dist/main/index.js:
1010
schema: yup
1111
importFrom: ../types
12-
useObjectTypes: true
12+
withObjectType: true
1313
directives:
1414
required:
1515
msg: required
@@ -43,7 +43,7 @@ generates:
4343
- ./dist/main/index.js:
4444
schema: zod
4545
importFrom: ../types
46-
useObjectTypes: true
46+
withObjectType: true
4747
directives:
4848
# Write directives like
4949
#
@@ -64,7 +64,7 @@ generates:
6464
- ./dist/main/index.js:
6565
schema: myzod
6666
importFrom: ../types
67-
useObjectTypes: true
67+
withObjectType: true
6868
directives:
6969
constraint:
7070
minLength: min

src/config.ts

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,25 @@ export interface ValidationSchemaPluginConfig extends TypeScriptPluginConfig {
152152
* ```
153153
*/
154154
scalarSchemas?: ScalarSchemas;
155+
/**
156+
* @description Generates validation schema with GraphQL type objects.
157+
* but excludes "Query", "Mutation", "Subscription" objects.
158+
*
159+
* @exampleMarkdown
160+
* ```yml
161+
* generates:
162+
* path/to/types.ts:
163+
* plugins:
164+
* - typescript
165+
* path/to/schemas.ts:
166+
* plugins:
167+
* - graphql-codegen-validation-schema
168+
* config:
169+
* schema: yup
170+
* withObjectType: true
171+
* ```
172+
*/
173+
withObjectType?: boolean;
155174
/**
156175
* @description Generates validation schema with more API based on directive schema.
157176
* @exampleMarkdown
@@ -193,22 +212,4 @@ export interface ValidationSchemaPluginConfig extends TypeScriptPluginConfig {
193212
* ```
194213
*/
195214
directives?: DirectiveConfig;
196-
/**
197-
* @description Converts the regular graphql type into a zod validation function.
198-
*
199-
* @exampleMarkdown
200-
* ```yml
201-
* generates:
202-
* path/to/types.ts:
203-
* plugins:
204-
* - typescript
205-
* path/to/schemas.ts:
206-
* plugins:
207-
* - graphql-codegen-validation-schema
208-
* config:
209-
* schema: yup
210-
* useObjectTypes: true
211-
* ```
212-
*/
213-
useObjectTypes?: boolean;
214215
}

src/graphql.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,22 @@
1-
import { ListTypeNode, NonNullTypeNode, NamedTypeNode, TypeNode } from 'graphql';
1+
import { ListTypeNode, NonNullTypeNode, NamedTypeNode, TypeNode, ObjectTypeDefinitionNode } from 'graphql';
22

33
export const isListType = (typ?: TypeNode): typ is ListTypeNode => typ?.kind === 'ListType';
44
export const isNonNullType = (typ?: TypeNode): typ is NonNullTypeNode => typ?.kind === 'NonNullType';
55
export const isNamedType = (typ?: TypeNode): typ is NamedTypeNode => typ?.kind === 'NamedType';
66

77
export const isInput = (kind: string) => kind.includes('Input');
8+
9+
type ObjectTypeDefinitionFn = (node: ObjectTypeDefinitionNode) => any;
10+
11+
export const ObjectTypeDefinitionBuilder = (
12+
useObjectTypes: boolean | undefined,
13+
callback: ObjectTypeDefinitionFn
14+
): ObjectTypeDefinitionFn | undefined => {
15+
if (!useObjectTypes) return undefined;
16+
return node => {
17+
if (/^Query|Mutation|Subscription$/.test(node.name.value)) {
18+
return;
19+
}
20+
return callback(node);
21+
};
22+
};

src/myzod/index.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { isInput, isNonNullType, isListType, isNamedType } from './../graphql';
1+
import { isInput, isNonNullType, isListType, isNamedType, ObjectTypeDefinitionBuilder } from './../graphql';
22
import { ValidationSchemaPluginConfig } from '../config';
33
import {
44
InputValueDefinitionNode,
@@ -49,8 +49,7 @@ export const MyZodSchemaVisitor = (schema: GraphQLSchema, config: ValidationSche
4949
.withName(`${name}Schema(): myzod.Type<${name}>`)
5050
.withBlock([indent(`return myzod.object({`), shape, indent('})')].join('\n')).string;
5151
},
52-
ObjectTypeDefinition: (node: ObjectTypeDefinitionNode) => {
53-
if (!config.useObjectTypes) return;
52+
ObjectTypeDefinition: ObjectTypeDefinitionBuilder(config.withObjectType, (node: ObjectTypeDefinitionNode) => {
5453
const name = tsVisitor.convertName(node.name.value);
5554
importTypes.push(name);
5655

@@ -65,11 +64,12 @@ export const MyZodSchemaVisitor = (schema: GraphQLSchema, config: ValidationSche
6564
.withBlock(
6665
[
6766
indent(`return myzod.object({`),
68-
` __typename: myzod.literal('${node.name.value}').optional(),\n${shape}`,
67+
indent(`__typename: myzod.literal('${node.name.value}').optional(),`, 2),
68+
shape,
6969
indent('})'),
7070
].join('\n')
7171
).string;
72-
},
72+
}),
7373
EnumTypeDefinition: (node: EnumTypeDefinitionNode) => {
7474
const enumname = tsVisitor.convertName(node.name.value);
7575
importTypes.push(enumname);
@@ -166,12 +166,17 @@ const generateNameNodeMyZodSchema = (
166166
): string => {
167167
const typ = schema.getType(node.value);
168168

169-
if (typ && typ.astNode?.kind === 'InputObjectTypeDefinition') {
169+
if (typ?.astNode?.kind === 'InputObjectTypeDefinition') {
170+
const enumName = tsVisitor.convertName(typ.astNode.name.value);
171+
return `${enumName}Schema()`;
172+
}
173+
174+
if (typ?.astNode?.kind === 'ObjectTypeDefinition') {
170175
const enumName = tsVisitor.convertName(typ.astNode.name.value);
171176
return `${enumName}Schema()`;
172177
}
173178

174-
if (typ && typ.astNode?.kind === 'EnumTypeDefinition') {
179+
if (typ?.astNode?.kind === 'EnumTypeDefinition') {
175180
const enumName = tsVisitor.convertName(typ.astNode.name.value);
176181
return `${enumName}Schema`;
177182
}

src/yup/index.ts

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { isInput, isNonNullType, isListType, isNamedType } from './../graphql';
1+
import { isInput, isNonNullType, isListType, isNamedType, ObjectTypeDefinitionBuilder } from './../graphql';
22
import { ValidationSchemaPluginConfig } from '../config';
33
import {
44
InputValueDefinitionNode,
@@ -41,8 +41,7 @@ export const YupSchemaVisitor = (schema: GraphQLSchema, config: ValidationSchema
4141
.withName(`${name}Schema(): yup.SchemaOf<${name}>`)
4242
.withBlock([indent(`return yup.object({`), shape, indent('})')].join('\n')).string;
4343
},
44-
ObjectTypeDefinition: (node: ObjectTypeDefinitionNode) => {
45-
if (!config.useObjectTypes) return;
44+
ObjectTypeDefinition: ObjectTypeDefinitionBuilder(config.withObjectType, (node: ObjectTypeDefinitionNode) => {
4645
const name = tsVisitor.convertName(node.name.value);
4746
importTypes.push(name);
4847

@@ -55,11 +54,12 @@ export const YupSchemaVisitor = (schema: GraphQLSchema, config: ValidationSchema
5554
.withBlock(
5655
[
5756
indent(`return yup.object({`),
58-
` __typename: yup.mixed().oneOf(['${node.name.value}', undefined]),\n${shape}`,
57+
indent(`__typename: yup.mixed().oneOf(['${node.name.value}', undefined]),`, 2),
58+
shape,
5959
indent('})'),
6060
].join('\n')
6161
).string;
62-
},
62+
}),
6363
EnumTypeDefinition: (node: EnumTypeDefinitionNode) => {
6464
const enumname = tsVisitor.convertName(node.name.value);
6565
importTypes.push(enumname);
@@ -146,7 +146,12 @@ const generateFieldTypeYupSchema = (
146146
return maybeLazy(type.type, nonNullGen);
147147
}
148148
if (isNamedType(type)) {
149-
return generateNameNodeYupSchema(config, tsVisitor, schema, type.name);
149+
const gen = generateNameNodeYupSchema(config, tsVisitor, schema, type.name);
150+
const typ = schema.getType(type.name.value);
151+
if (typ?.astNode?.kind === 'ObjectTypeDefinition') {
152+
return `${gen}.optional()`;
153+
}
154+
return gen;
150155
}
151156
console.warn('unhandled type:', type);
152157
return '';
@@ -160,12 +165,17 @@ const generateNameNodeYupSchema = (
160165
): string => {
161166
const typ = schema.getType(node.value);
162167

163-
if (typ && typ.astNode?.kind === 'InputObjectTypeDefinition') {
168+
if (typ?.astNode?.kind === 'InputObjectTypeDefinition') {
169+
const enumName = tsVisitor.convertName(typ.astNode.name.value);
170+
return `${enumName}Schema()`;
171+
}
172+
173+
if (typ?.astNode?.kind === 'ObjectTypeDefinition') {
164174
const enumName = tsVisitor.convertName(typ.astNode.name.value);
165175
return `${enumName}Schema()`;
166176
}
167177

168-
if (typ && typ.astNode?.kind === 'EnumTypeDefinition') {
178+
if (typ?.astNode?.kind === 'EnumTypeDefinition') {
169179
const enumName = tsVisitor.convertName(typ.astNode.name.value);
170180
return `${enumName}Schema`;
171181
}

src/zod/index.ts

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { isInput, isNonNullType, isListType, isNamedType } from './../graphql';
1+
import { isInput, isNonNullType, isListType, isNamedType, ObjectTypeDefinitionBuilder } from './../graphql';
22
import { ValidationSchemaPluginConfig } from '../config';
33
import {
44
InputValueDefinitionNode,
@@ -63,8 +63,7 @@ export const ZodSchemaVisitor = (schema: GraphQLSchema, config: ValidationSchema
6363
.withName(`${name}Schema(): z.ZodObject<Properties<${name}>>`)
6464
.withBlock([indent(`return z.object({`), shape, indent('})')].join('\n')).string;
6565
},
66-
ObjectTypeDefinition: (node: ObjectTypeDefinitionNode) => {
67-
if (!config.useObjectTypes) return;
66+
ObjectTypeDefinition: ObjectTypeDefinitionBuilder(config.withObjectType, (node: ObjectTypeDefinitionNode) => {
6867
const name = tsVisitor.convertName(node.name.value);
6968
importTypes.push(name);
7069

@@ -77,11 +76,12 @@ export const ZodSchemaVisitor = (schema: GraphQLSchema, config: ValidationSchema
7776
.withBlock(
7877
[
7978
indent(`return z.object({`),
80-
` __typename: z.literal('${node.name.value}').optional(),\n${shape}`,
79+
indent(`__typename: z.literal('${node.name.value}').optional(),`, 2),
80+
shape,
8181
indent('})'),
8282
].join('\n')
8383
).string;
84-
},
84+
}),
8585
EnumTypeDefinition: (node: EnumTypeDefinitionNode) => {
8686
const enumname = tsVisitor.convertName(node.name.value);
8787
importTypes.push(enumname);
@@ -177,12 +177,17 @@ const generateNameNodeZodSchema = (
177177
): string => {
178178
const typ = schema.getType(node.value);
179179

180-
if (typ && typ.astNode?.kind === 'InputObjectTypeDefinition') {
180+
if (typ?.astNode?.kind === 'InputObjectTypeDefinition') {
181+
const enumName = tsVisitor.convertName(typ.astNode.name.value);
182+
return `${enumName}Schema()`;
183+
}
184+
185+
if (typ?.astNode?.kind === 'ObjectTypeDefinition') {
181186
const enumName = tsVisitor.convertName(typ.astNode.name.value);
182187
return `${enumName}Schema()`;
183188
}
184189

185-
if (typ && typ.astNode?.kind === 'EnumTypeDefinition') {
190+
if (typ?.astNode?.kind === 'EnumTypeDefinition') {
186191
const enumName = tsVisitor.convertName(typ.astNode.name.value);
187192
return `${enumName}Schema`;
188193
}
@@ -210,6 +215,6 @@ const zod4Scalar = (config: ValidationSchemaPluginConfig, tsVisitor: TsVisitor,
210215
case 'boolean':
211216
return `z.boolean()`;
212217
}
213-
console.warn('unhandled name:', scalarName);
218+
console.warn('unhandled scalar name:', scalarName);
214219
return anySchema;
215220
};

0 commit comments

Comments
 (0)