Skip to content

Commit 9379dc6

Browse files
authored
Merge branch 'main' into main
2 parents 44aeb89 + 9585ea8 commit 9379dc6

File tree

8 files changed

+526
-97
lines changed

8 files changed

+526
-97
lines changed

CHANGELOG.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,28 @@
1+
# v4.3.0 (Wed Feb 26 2025)
2+
3+
#### 🚀 Enhancement
4+
5+
- feat: add includedTypes and excludedTypes options for selective mock generation [#179](https://github.com/ardeois/graphql-codegen-typescript-mock-data/pull/179) ([@huseyinbuyukdere](https://github.com/huseyinbuyukdere) [email protected])
6+
7+
#### Authors: 2
8+
9+
- Hüseyin Büyükdere ([@huseyinbuyukdere](https://github.com/huseyinbuyukdere))
10+
- huseyinbuyukdere ([email protected])
11+
12+
---
13+
14+
# v4.2.0 (Thu Feb 06 2025)
15+
16+
#### 🚀 Enhancement
17+
18+
- Add support for oneOf directive [#180](https://github.com/ardeois/graphql-codegen-typescript-mock-data/pull/180) ([@thomasobrien99](https://github.com/thomasobrien99))
19+
20+
#### Authors: 1
21+
22+
- [@thomasobrien99](https://github.com/thomasobrien99)
23+
24+
---
25+
126
# v4.1.0 (Fri Sep 20 2024)
227

328
#### 🚀 Enhancement

README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,34 @@ Adds `__typename` property to mock data
2626

2727
Changes enums to TypeScript string union types
2828

29+
### includedTypes (`string[]`, defaultValue: `undefined`)
30+
31+
Specifies an array of types to **include** in the mock generation. When provided, only the types listed in this array will have mock data generated.
32+
33+
Example:
34+
35+
```yaml
36+
plugins:
37+
- typescript-mock-data:
38+
includedTypes:
39+
- User
40+
- Avatar
41+
```
42+
43+
### excludedTypes (`string[]`, defaultValue: `undefined`)
44+
45+
Specifies an array of types to **exclude** in the mock generation. When provided, the types listed in this array will not have mock data generated.
46+
47+
Example:
48+
49+
```yaml
50+
plugins:
51+
- typescript-mock-data:
52+
excludedTypes:
53+
- User
54+
- Avatar
55+
```
56+
2957
### terminateCircularRelationships (`boolean | 'immediate'`, defaultValue: `false`)
3058

3159
When enabled, prevents circular relationships from triggering infinite recursion. After the first resolution of a

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "graphql-codegen-typescript-mock-data",
3-
"version": "4.1.0",
3+
"version": "4.3.0",
44
"description": "GraphQL Codegen plugin for building mock data",
55
"main": "dist/commonjs/index.js",
66
"module": "dist/esnext/index.js",
@@ -24,6 +24,7 @@
2424
"dependencies": {
2525
"@faker-js/faker": "^8.4.1",
2626
"@graphql-codegen/plugin-helpers": "^5.0.4",
27+
"@graphql-tools/utils": "^10.7.2",
2728
"casual": "^1.6.2",
2829
"change-case-all": "^1.0.15",
2930
"indefinite": "^2.4.1",
@@ -39,6 +40,7 @@
3940
"@auto-it/conventional-commits": "^11.1.6",
4041
"@graphql-codegen/testing": "^3.0.3",
4142
"@graphql-codegen/typescript": "^4.0.7",
43+
"@types/indefinite": "^2.3.4",
4244
"@types/jest": "^27.0.2",
4345
"@typescript-eslint/eslint-plugin": "^5.1.0",
4446
"@typescript-eslint/parser": "^5.1.0",
@@ -57,7 +59,7 @@
5759
"prettier": "^2.4.1",
5860
"prettier-config-landr": "^0.2.0",
5961
"ts-jest": "^27.0.7",
60-
"typescript": "^4.4.4"
62+
"typescript": "^5.7.3"
6163
},
6264
"sideEffects": false,
6365
"scripts": {

src/index.ts

Lines changed: 89 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,10 @@
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';
102
import * as allFakerLocales from '@faker-js/faker';
113
import casual from 'casual';
124
import { oldVisit, PluginFunction, resolveExternalModuleAndFn } from '@graphql-codegen/plugin-helpers';
135
import { sentenceCase } from 'sentence-case';
146
import a from 'indefinite';
7+
import { printSchemaWithDirectives } from '@graphql-tools/utils';
158
import { setupFunctionTokens, setupMockValueGenerator } from './mockValueGenerator';
169

1710
type NamingConvention = 'change-case-all#pascalCase' | 'keep' | string;
@@ -463,6 +456,7 @@ const getMockString = (
463456
typesPrefix = '',
464457
transformUnderscore: boolean,
465458
typeNamesMapping?: Record<string, string>,
459+
hasOneOfDirective = false,
466460
) => {
467461
const typeNameConverter = createNameConverter(typeNamesConvention, transformUnderscore);
468462
const NewTypeName = typeNamesMapping[typeName] || typeName;
@@ -471,6 +465,10 @@ const getMockString = (
471465
const typename = addTypename ? `\n __typename: '${typeName}',` : '';
472466
const typenameReturnType = addTypename ? `{ __typename: '${typeName}' } & ` : '';
473467

468+
const overridesArgumentString = !hasOneOfDirective
469+
? `overrides?: Partial<${casedNameWithPrefix}>`
470+
: `override?: ${casedNameWithPrefix}`;
471+
474472
if (terminateCircularRelationships) {
475473
const relationshipsToOmitInit =
476474
terminateCircularRelationships === 'immediate' ? '_relationshipsToOmit' : 'new Set(_relationshipsToOmit)';
@@ -479,7 +477,7 @@ export const ${toMockName(
479477
typeName,
480478
casedName,
481479
prefix,
482-
)} = (overrides?: Partial<${casedNameWithPrefix}>, _relationshipsToOmit: Set<string> = new Set()): ${typenameReturnType}${casedNameWithPrefix} => {
480+
)} = (${overridesArgumentString}, _relationshipsToOmit: Set<string> = new Set()): ${typenameReturnType}${casedNameWithPrefix} => {
483481
const relationshipsToOmit: Set<string> = ${relationshipsToOmitInit};
484482
relationshipsToOmit.add('${casedName}');
485483
return {${typename}
@@ -492,7 +490,7 @@ export const ${toMockName(
492490
typeName,
493491
casedName,
494492
prefix,
495-
)} = (overrides?: Partial<${casedNameWithPrefix}>): ${typenameReturnType}${casedNameWithPrefix} => {
493+
)} = (${overridesArgumentString}): ${typenameReturnType}${casedNameWithPrefix} => {
496494
return {${typename}
497495
${fields}
498496
};
@@ -593,6 +591,8 @@ export interface TypescriptMocksPluginConfig {
593591
defaultNullableToNull?: boolean;
594592
useTypeImports?: boolean;
595593
typeNamesMapping?: Record<string, string>;
594+
includedTypes?: string[];
595+
excludedTypes?: string[];
596596
}
597597

598598
interface TypeItem {
@@ -625,7 +625,8 @@ type VisitorType = { [K in keyof ASTKindToNode]?: VisitFn<ASTKindToNode[keyof AS
625625
// https://astexplorer.net
626626
// Paste your graphql schema in it, and you'll be able to see what the `astNode` will look like
627627
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+
629630
const astNode = parse(printedSchema); // Transforms the string into ASTNode
630631

631632
if ('typenames' in config) {
@@ -693,6 +694,30 @@ export const plugin: PluginFunction<TypescriptMocksPluginConfig> = (schema, docu
693694
}
694695
},
695696
};
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+
696721
const visitor: VisitorType = {
697722
FieldDefinition: (node) => {
698723
const fieldName = node.name.value;
@@ -703,27 +728,8 @@ export const plugin: PluginFunction<TypescriptMocksPluginConfig> = (schema, docu
703728
const value = generateMockValue({
704729
typeName,
705730
fieldName,
706-
types,
707-
typeNamesConvention,
708-
enumValuesConvention,
709-
terminateCircularRelationships: getTerminateCircularRelationshipsConfig(config),
710-
prefix: config.prefix,
711-
typesPrefix: config.typesPrefix,
712-
enumsPrefix: config.enumsPrefix,
713731
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,
727733
});
728734

729735
return ` ${fieldName}: overrides && overrides.hasOwnProperty('${fieldName}') ? overrides.${fieldName}! : ${value},`;
@@ -736,50 +742,49 @@ export const plugin: PluginFunction<TypescriptMocksPluginConfig> = (schema, docu
736742
return {
737743
typeName: fieldName,
738744
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+
}
772776

773777
return getMockString(
774778
fieldName,
775-
mockFields,
779+
mockFieldsString,
776780
typeNamesConvention,
777781
getTerminateCircularRelationshipsConfig(config),
778782
false,
779783
config.prefix,
780784
config.typesPrefix,
781785
transformUnderscore,
782786
typeNamesMapping,
787+
hasOneOfDirective,
783788
);
784789
},
785790
};
@@ -835,7 +840,24 @@ export const plugin: PluginFunction<TypescriptMocksPluginConfig> = (schema, docu
835840
// run on the types first
836841
oldVisit(astNode, { leave: typeVisitor });
837842
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+
);
839861
const typesFile = config.typesFile ? config.typesFile.replace(/\.[\w]+$/, '') : null;
840862

841863
const typesFileImport = getImportTypes({

0 commit comments

Comments
 (0)