Skip to content

Commit 3fd4ed6

Browse files
authored
Merge pull request #391 from Code-Hex/fix/386
fix #386
2 parents 6940b13 + dcb20dc commit 3fd4ed6

File tree

7 files changed

+121
-12
lines changed

7 files changed

+121
-12
lines changed

src/myzod/index.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -212,9 +212,8 @@ const generateFieldTypeMyZodSchema = (
212212
}
213213
const appliedDirectivesGen = applyDirectives(config, field, gen);
214214
if (isNonNullType(parentType)) {
215-
if (config.notAllowEmptyString === true) {
216-
const tsType = visitor.getScalarType(type.name.value);
217-
if (tsType === 'string') return `${gen}.min(1)`;
215+
if (visitor.shouldEmitAsNotAllowEmptyString(type.name.value)) {
216+
return `${gen}.min(1)`;
218217
}
219218
return appliedDirectivesGen;
220219
}

src/visitor.ts

+19-3
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
import { TsVisitor } from '@graphql-codegen/typescript';
2-
import { GraphQLSchema, NameNode } from 'graphql';
2+
import { GraphQLSchema, NameNode, specifiedScalarTypes } from 'graphql';
33

44
import { ValidationSchemaPluginConfig } from './config';
55

66
export class Visitor extends TsVisitor {
77
constructor(
88
private scalarDirection: 'input' | 'output' | 'both',
99
private schema: GraphQLSchema,
10-
config: ValidationSchemaPluginConfig
10+
private pluginConfig: ValidationSchemaPluginConfig
1111
) {
12-
super(schema, config);
12+
super(schema, pluginConfig);
13+
}
14+
15+
private isSpecifiedScalarName(scalarName: string) {
16+
return specifiedScalarTypes.some(({ name }) => name === scalarName);
1317
}
1418

1519
public getType(name: string) {
@@ -34,4 +38,16 @@ export class Visitor extends TsVisitor {
3438
}
3539
return this.scalars[scalarName][this.scalarDirection];
3640
}
41+
42+
public shouldEmitAsNotAllowEmptyString(name: string): boolean {
43+
if (this.pluginConfig.notAllowEmptyString !== true) {
44+
return false;
45+
}
46+
const typ = this.getType(name);
47+
if (typ?.astNode?.kind !== 'ScalarTypeDefinition' && !this.isSpecifiedScalarName(name)) {
48+
return false;
49+
}
50+
const tsType = this.getScalarType(name);
51+
return tsType === 'string';
52+
}
3753
}

src/yup/index.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -262,9 +262,8 @@ const generateFieldTypeYupSchema = (
262262
if (isNamedType(type)) {
263263
const gen = generateNameNodeYupSchema(config, visitor, type.name);
264264
if (isNonNullType(parentType)) {
265-
if (config.notAllowEmptyString === true) {
266-
const tsType = visitor.getScalarType(type.name.value);
267-
if (tsType === 'string') return `${gen}.required()`;
265+
if (visitor.shouldEmitAsNotAllowEmptyString(type.name.value)) {
266+
return `${gen}.required()`;
268267
}
269268
return `${gen}.nonNullable()`;
270269
}

src/zod/index.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -222,9 +222,8 @@ const generateFieldTypeZodSchema = (
222222
}
223223
const appliedDirectivesGen = applyDirectives(config, field, gen);
224224
if (isNonNullType(parentType)) {
225-
if (config.notAllowEmptyString === true) {
226-
const tsType = visitor.getScalarType(type.name.value);
227-
if (tsType === 'string') return `${appliedDirectivesGen}.min(1)`;
225+
if (visitor.shouldEmitAsNotAllowEmptyString(type.name.value)) {
226+
return `${appliedDirectivesGen}.min(1)`;
228227
}
229228
return appliedDirectivesGen;
230229
}

tests/myzod.spec.ts

+32
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { buildSchema } from 'graphql';
2+
import dedent from 'ts-dedent';
23

34
import { plugin } from '../src/index';
45

@@ -297,6 +298,37 @@ describe('myzod', () => {
297298
}
298299
});
299300

301+
it('with notAllowEmptyString issue #386', async () => {
302+
const schema = buildSchema(/* GraphQL */ `
303+
input InputOne {
304+
field: InputNested!
305+
}
306+
307+
input InputNested {
308+
field: String!
309+
}
310+
`);
311+
const result = await plugin(
312+
schema,
313+
[],
314+
{
315+
schema: 'myzod',
316+
notAllowEmptyString: true,
317+
scalars: {
318+
ID: 'string',
319+
},
320+
},
321+
{}
322+
);
323+
const wantContain = dedent`
324+
export function InputNestedSchema(): myzod.Type<InputNested> {
325+
return myzod.object({
326+
field: myzod.string().min(1)
327+
})
328+
}`;
329+
expect(result.content).toContain(wantContain);
330+
});
331+
300332
it('with scalarSchemas', async () => {
301333
const schema = buildSchema(/* GraphQL */ `
302334
input ScalarsInput {

tests/yup.spec.ts

+32
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { buildSchema } from 'graphql';
2+
import dedent from 'ts-dedent';
23

34
import { plugin } from '../src/index';
45

@@ -294,6 +295,37 @@ describe('yup', () => {
294295
}
295296
});
296297

298+
it('with notAllowEmptyString issue #386', async () => {
299+
const schema = buildSchema(/* GraphQL */ `
300+
input InputOne {
301+
field: InputNested!
302+
}
303+
304+
input InputNested {
305+
field: String!
306+
}
307+
`);
308+
const result = await plugin(
309+
schema,
310+
[],
311+
{
312+
schema: 'yup',
313+
notAllowEmptyString: true,
314+
scalars: {
315+
ID: 'string',
316+
},
317+
},
318+
{}
319+
);
320+
const wantContain = dedent`
321+
export function InputNestedSchema(): yup.ObjectSchema<InputNested> {
322+
return yup.object({
323+
field: yup.string().defined().required()
324+
})
325+
}`;
326+
expect(result.content).toContain(wantContain);
327+
});
328+
297329
it('with scalarSchemas', async () => {
298330
const schema = buildSchema(/* GraphQL */ `
299331
input ScalarsInput {

tests/zod.spec.ts

+32
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { buildSchema } from 'graphql';
2+
import { dedent } from 'ts-dedent';
23

34
import { plugin } from '../src/index';
45

@@ -297,6 +298,37 @@ describe('zod', () => {
297298
}
298299
});
299300

301+
it('with notAllowEmptyString issue #386', async () => {
302+
const schema = buildSchema(/* GraphQL */ `
303+
input InputOne {
304+
field: InputNested!
305+
}
306+
307+
input InputNested {
308+
field: String!
309+
}
310+
`);
311+
const result = await plugin(
312+
schema,
313+
[],
314+
{
315+
schema: 'zod',
316+
notAllowEmptyString: true,
317+
scalars: {
318+
ID: 'string',
319+
},
320+
},
321+
{}
322+
);
323+
const wantContain = dedent`
324+
export function InputNestedSchema(): z.ZodObject<Properties<InputNested>> {
325+
return z.object({
326+
field: z.string().min(1)
327+
})
328+
}`;
329+
expect(result.content).toContain(wantContain);
330+
});
331+
300332
it('with scalarSchemas', async () => {
301333
const schema = buildSchema(/* GraphQL */ `
302334
input ScalarsInput {

0 commit comments

Comments
 (0)