1
- import {
2
- parse ,
3
- printSchema ,
4
- TypeNode ,
5
- ASTKindToNode ,
6
- ListTypeNode ,
7
- NamedTypeNode ,
8
- ObjectTypeDefinitionNode ,
9
- } from 'graphql' ;
1
+ import { parse , TypeNode , ASTKindToNode , ListTypeNode , NamedTypeNode , ObjectTypeDefinitionNode } from 'graphql' ;
10
2
import * as allFakerLocales from '@faker-js/faker' ;
11
3
import casual from 'casual' ;
12
4
import { oldVisit , PluginFunction , resolveExternalModuleAndFn } from '@graphql-codegen/plugin-helpers' ;
13
5
import { sentenceCase } from 'sentence-case' ;
14
6
import a from 'indefinite' ;
7
+ import { printSchemaWithDirectives } from '@graphql-tools/utils' ;
15
8
import { setupFunctionTokens , setupMockValueGenerator } from './mockValueGenerator' ;
16
9
17
10
type NamingConvention = 'change-case-all#pascalCase' | 'keep' | string ;
@@ -463,6 +456,7 @@ const getMockString = (
463
456
typesPrefix = '' ,
464
457
transformUnderscore : boolean ,
465
458
typeNamesMapping ?: Record < string , string > ,
459
+ hasOneOfDirective = false ,
466
460
) => {
467
461
const typeNameConverter = createNameConverter ( typeNamesConvention , transformUnderscore ) ;
468
462
const NewTypeName = typeNamesMapping [ typeName ] || typeName ;
@@ -471,6 +465,10 @@ const getMockString = (
471
465
const typename = addTypename ? `\n __typename: '${ typeName } ',` : '' ;
472
466
const typenameReturnType = addTypename ? `{ __typename: '${ typeName } ' } & ` : '' ;
473
467
468
+ const overridesArgumentString = ! hasOneOfDirective
469
+ ? `overrides?: Partial<${ casedNameWithPrefix } >`
470
+ : `override?: ${ casedNameWithPrefix } ` ;
471
+
474
472
if ( terminateCircularRelationships ) {
475
473
const relationshipsToOmitInit =
476
474
terminateCircularRelationships === 'immediate' ? '_relationshipsToOmit' : 'new Set(_relationshipsToOmit)' ;
@@ -479,7 +477,7 @@ export const ${toMockName(
479
477
typeName ,
480
478
casedName ,
481
479
prefix ,
482
- ) } = (overrides?: Partial< ${ casedNameWithPrefix } > , _relationshipsToOmit: Set<string> = new Set()): ${ typenameReturnType } ${ casedNameWithPrefix } => {
480
+ ) } = (${ overridesArgumentString } , _relationshipsToOmit: Set<string> = new Set()): ${ typenameReturnType } ${ casedNameWithPrefix } => {
483
481
const relationshipsToOmit: Set<string> = ${ relationshipsToOmitInit } ;
484
482
relationshipsToOmit.add('${ casedName } ');
485
483
return {${ typename }
@@ -492,7 +490,7 @@ export const ${toMockName(
492
490
typeName ,
493
491
casedName ,
494
492
prefix ,
495
- ) } = (overrides?: Partial< ${ casedNameWithPrefix } > ): ${ typenameReturnType } ${ casedNameWithPrefix } => {
493
+ ) } = (${ overridesArgumentString } ): ${ typenameReturnType } ${ casedNameWithPrefix } => {
496
494
return {${ typename }
497
495
${ fields }
498
496
};
@@ -593,6 +591,8 @@ export interface TypescriptMocksPluginConfig {
593
591
defaultNullableToNull ?: boolean ;
594
592
useTypeImports ?: boolean ;
595
593
typeNamesMapping ?: Record < string , string > ;
594
+ includedTypes ?: string [ ] ;
595
+ excludedTypes ?: string [ ] ;
596
596
}
597
597
598
598
interface TypeItem {
@@ -625,7 +625,8 @@ type VisitorType = { [K in keyof ASTKindToNode]?: VisitFn<ASTKindToNode[keyof AS
625
625
// https://astexplorer.net
626
626
// Paste your graphql schema in it, and you'll be able to see what the `astNode` will look like
627
627
export const plugin : PluginFunction < TypescriptMocksPluginConfig > = ( schema , documents , config ) => {
628
- const printedSchema = printSchema ( schema ) ; // Returns a string representation of the schema
628
+ const printedSchema = printSchemaWithDirectives ( schema ) ; // Returns a string representation of the schema
629
+
629
630
const astNode = parse ( printedSchema ) ; // Transforms the string into ASTNode
630
631
631
632
if ( 'typenames' in config ) {
@@ -693,6 +694,30 @@ export const plugin: PluginFunction<TypescriptMocksPluginConfig> = (schema, docu
693
694
}
694
695
} ,
695
696
} ;
697
+
698
+ const sharedGenerateMockOpts = {
699
+ customScalars : config . scalars ,
700
+ defaultNullableToNull,
701
+ dynamicValues,
702
+ enumsAsTypes,
703
+ enumsPrefix : config . enumsPrefix ,
704
+ enumValuesConvention,
705
+ fieldGeneration : config . fieldGeneration ,
706
+ generateLibrary,
707
+ generatorLocale,
708
+ listElementCount,
709
+ nonNull : false ,
710
+ prefix : config . prefix ,
711
+ terminateCircularRelationships : getTerminateCircularRelationshipsConfig ( config ) ,
712
+ transformUnderscore,
713
+ typeNamesConvention,
714
+ typeNamesMapping,
715
+ types,
716
+ typesPrefix : config . typesPrefix ,
717
+ useImplementingTypes,
718
+ useTypeImports,
719
+ } ;
720
+
696
721
const visitor : VisitorType = {
697
722
FieldDefinition : ( node ) => {
698
723
const fieldName = node . name . value ;
@@ -703,27 +728,8 @@ export const plugin: PluginFunction<TypescriptMocksPluginConfig> = (schema, docu
703
728
const value = generateMockValue ( {
704
729
typeName,
705
730
fieldName,
706
- types,
707
- typeNamesConvention,
708
- enumValuesConvention,
709
- terminateCircularRelationships : getTerminateCircularRelationshipsConfig ( config ) ,
710
- prefix : config . prefix ,
711
- typesPrefix : config . typesPrefix ,
712
- enumsPrefix : config . enumsPrefix ,
713
731
currentType : node . type ,
714
- customScalars : config . scalars ,
715
- transformUnderscore,
716
- listElementCount,
717
- dynamicValues,
718
- generateLibrary,
719
- generatorLocale,
720
- fieldGeneration : config . fieldGeneration ,
721
- enumsAsTypes,
722
- useTypeImports,
723
- useImplementingTypes,
724
- defaultNullableToNull,
725
- nonNull : false ,
726
- typeNamesMapping : config . typeNamesMapping ,
732
+ ...sharedGenerateMockOpts ,
727
733
} ) ;
728
734
729
735
return ` ${ fieldName } : overrides && overrides.hasOwnProperty('${ fieldName } ') ? overrides.${ fieldName } ! : ${ value } ,` ;
@@ -736,50 +742,49 @@ export const plugin: PluginFunction<TypescriptMocksPluginConfig> = (schema, docu
736
742
return {
737
743
typeName : fieldName ,
738
744
mockFn : ( ) => {
739
- const mockFields = node . fields
740
- ? node . fields
741
- . map ( ( field ) => {
742
- const value = generateMockValue ( {
743
- typeName : fieldName ,
744
- fieldName : field . name . value ,
745
- types,
746
- typeNamesConvention,
747
- enumValuesConvention,
748
- terminateCircularRelationships : getTerminateCircularRelationshipsConfig ( config ) ,
749
- prefix : config . prefix ,
750
- typesPrefix : config . typesPrefix ,
751
- enumsPrefix : config . enumsPrefix ,
752
- currentType : field . type ,
753
- customScalars : config . scalars ,
754
- transformUnderscore,
755
- listElementCount,
756
- dynamicValues,
757
- generateLibrary,
758
- generatorLocale,
759
- fieldGeneration : config . fieldGeneration ,
760
- enumsAsTypes,
761
- useTypeImports,
762
- useImplementingTypes,
763
- defaultNullableToNull,
764
- nonNull : false ,
765
- typeNamesMapping : config . typeNamesMapping ,
766
- } ) ;
767
-
768
- return ` ${ field . name . value } : overrides && overrides.hasOwnProperty('${ field . name . value } ') ? overrides.${ field . name . value } ! : ${ value } ,` ;
769
- } )
770
- . join ( '\n' )
771
- : '' ;
745
+ let mockFieldsString = '' ;
746
+
747
+ const { directives } = node ;
748
+ const hasOneOfDirective = directives . some ( ( directive ) => directive . name . value === 'oneOf' ) ;
749
+
750
+ if ( node . fields && node . fields . length > 0 && hasOneOfDirective ) {
751
+ const field = node . fields [ 0 ] ;
752
+ const value = generateMockValue ( {
753
+ typeName : fieldName ,
754
+ fieldName : field . name . value ,
755
+ currentType : field . type ,
756
+ ...sharedGenerateMockOpts ,
757
+ } ) ;
758
+
759
+ mockFieldsString = ` ...(override ? override : {${ field . name . value } : ${ value } }),` ;
760
+ } else if ( node . fields ) {
761
+ mockFieldsString = node . fields
762
+ . map ( ( field ) => {
763
+ const value = generateMockValue ( {
764
+ typeName : fieldName ,
765
+ fieldName : field . name . value ,
766
+ currentType : field . type ,
767
+ ...sharedGenerateMockOpts ,
768
+ } ) ;
769
+
770
+ const valueWithOverride = `overrides && overrides.hasOwnProperty('${ field . name . value } ') ? overrides.${ field . name . value } ! : ${ value } ` ;
771
+
772
+ return ` ${ field . name . value } : ${ valueWithOverride } ,` ;
773
+ } )
774
+ . join ( '\n' ) ;
775
+ }
772
776
773
777
return getMockString (
774
778
fieldName ,
775
- mockFields ,
779
+ mockFieldsString ,
776
780
typeNamesConvention ,
777
781
getTerminateCircularRelationshipsConfig ( config ) ,
778
782
false ,
779
783
config . prefix ,
780
784
config . typesPrefix ,
781
785
transformUnderscore ,
782
786
typeNamesMapping ,
787
+ hasOneOfDirective ,
783
788
) ;
784
789
} ,
785
790
} ;
@@ -835,7 +840,24 @@ export const plugin: PluginFunction<TypescriptMocksPluginConfig> = (schema, docu
835
840
// run on the types first
836
841
oldVisit ( astNode , { leave : typeVisitor } ) ;
837
842
const result = oldVisit ( astNode , { leave : visitor } ) ;
838
- const definitions = result . definitions . filter ( ( definition : any ) => ! ! definition ) ;
843
+
844
+ const { includedTypes, excludedTypes } = config ;
845
+ const shouldGenerateMockForType = ( typeName ?: string ) => {
846
+ if ( ! typeName ) {
847
+ return true ;
848
+ }
849
+ if ( includedTypes && includedTypes . length > 0 ) {
850
+ return includedTypes . includes ( typeName ) ;
851
+ }
852
+ if ( excludedTypes && excludedTypes . length > 0 ) {
853
+ return ! excludedTypes . includes ( typeName ) ;
854
+ }
855
+ return true ;
856
+ } ;
857
+
858
+ const definitions = result . definitions . filter (
859
+ ( definition : any ) => ! ! definition && shouldGenerateMockForType ( definition . typeName ) ,
860
+ ) ;
839
861
const typesFile = config . typesFile ? config . typesFile . replace ( / \. [ \w ] + $ / , '' ) : null ;
840
862
841
863
const typesFileImport = getImportTypes ( {
0 commit comments