File tree 7 files changed +121
-12
lines changed
7 files changed +121
-12
lines changed Original file line number Diff line number Diff line change @@ -212,9 +212,8 @@ const generateFieldTypeMyZodSchema = (
212
212
}
213
213
const appliedDirectivesGen = applyDirectives ( config , field , gen ) ;
214
214
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)` ;
218
217
}
219
218
return appliedDirectivesGen ;
220
219
}
Original file line number Diff line number Diff line change 1
1
import { TsVisitor } from '@graphql-codegen/typescript' ;
2
- import { GraphQLSchema , NameNode } from 'graphql' ;
2
+ import { GraphQLSchema , NameNode , specifiedScalarTypes } from 'graphql' ;
3
3
4
4
import { ValidationSchemaPluginConfig } from './config' ;
5
5
6
6
export class Visitor extends TsVisitor {
7
7
constructor (
8
8
private scalarDirection : 'input' | 'output' | 'both' ,
9
9
private schema : GraphQLSchema ,
10
- config : ValidationSchemaPluginConfig
10
+ private pluginConfig : ValidationSchemaPluginConfig
11
11
) {
12
- super ( schema , config ) ;
12
+ super ( schema , pluginConfig ) ;
13
+ }
14
+
15
+ private isSpecifiedScalarName ( scalarName : string ) {
16
+ return specifiedScalarTypes . some ( ( { name } ) => name === scalarName ) ;
13
17
}
14
18
15
19
public getType ( name : string ) {
@@ -34,4 +38,16 @@ export class Visitor extends TsVisitor {
34
38
}
35
39
return this . scalars [ scalarName ] [ this . scalarDirection ] ;
36
40
}
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
+ }
37
53
}
Original file line number Diff line number Diff line change @@ -262,9 +262,8 @@ const generateFieldTypeYupSchema = (
262
262
if ( isNamedType ( type ) ) {
263
263
const gen = generateNameNodeYupSchema ( config , visitor , type . name ) ;
264
264
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()` ;
268
267
}
269
268
return `${ gen } .nonNullable()` ;
270
269
}
Original file line number Diff line number Diff line change @@ -222,9 +222,8 @@ const generateFieldTypeZodSchema = (
222
222
}
223
223
const appliedDirectivesGen = applyDirectives ( config , field , gen ) ;
224
224
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)` ;
228
227
}
229
228
return appliedDirectivesGen ;
230
229
}
Original file line number Diff line number Diff line change 1
1
import { buildSchema } from 'graphql' ;
2
+ import dedent from 'ts-dedent' ;
2
3
3
4
import { plugin } from '../src/index' ;
4
5
@@ -297,6 +298,37 @@ describe('myzod', () => {
297
298
}
298
299
} ) ;
299
300
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
+
300
332
it ( 'with scalarSchemas' , async ( ) => {
301
333
const schema = buildSchema ( /* GraphQL */ `
302
334
input ScalarsInput {
Original file line number Diff line number Diff line change 1
1
import { buildSchema } from 'graphql' ;
2
+ import dedent from 'ts-dedent' ;
2
3
3
4
import { plugin } from '../src/index' ;
4
5
@@ -294,6 +295,37 @@ describe('yup', () => {
294
295
}
295
296
} ) ;
296
297
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
+
297
329
it ( 'with scalarSchemas' , async ( ) => {
298
330
const schema = buildSchema ( /* GraphQL */ `
299
331
input ScalarsInput {
Original file line number Diff line number Diff line change 1
1
import { buildSchema } from 'graphql' ;
2
+ import { dedent } from 'ts-dedent' ;
2
3
3
4
import { plugin } from '../src/index' ;
4
5
@@ -297,6 +298,37 @@ describe('zod', () => {
297
298
}
298
299
} ) ;
299
300
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
+
300
332
it ( 'with scalarSchemas' , async ( ) => {
301
333
const schema = buildSchema ( /* GraphQL */ `
302
334
input ScalarsInput {
You can’t perform that action at this time.
0 commit comments