@newmo/graphql-fake-core 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,306 @@
1
+ import { convertFactory, transformComment } from "@graphql-codegen/visitor-plugin-common";
2
+ import { Kind, } from "graphql";
3
+ import { generateCreateReferenceCode } from "./code-generator.js";
4
+ function convertName(node, config) {
5
+ const convert = config.namingConvention
6
+ ? convertFactory({ namingConvention: config.namingConvention })
7
+ : convertFactory({});
8
+ let convertedName = "";
9
+ convertedName += config.typesPrefix;
10
+ convertedName += convert(node);
11
+ convertedName += config.typesSuffix;
12
+ return convertedName;
13
+ }
14
+ const createIDFactory = () => {
15
+ return (name, key) => {
16
+ return `__id({ name: "${name}", key:"${key}", depth })`;
17
+ };
18
+ };
19
+ const parseTypeNodeStructure = (node) => {
20
+ if (node.kind === Kind.NON_NULL_TYPE) {
21
+ return parseTypeNodeStructure(node.type);
22
+ }
23
+ if (node.kind === Kind.LIST_TYPE) {
24
+ return "array";
25
+ }
26
+ // string, number, boolean, null
27
+ if (node.name.value === "String") {
28
+ return "string";
29
+ }
30
+ if (node.name.value === "Int") {
31
+ return "number";
32
+ }
33
+ if (node.name.value === "Float") {
34
+ return "number";
35
+ }
36
+ if (node.name.value === "Boolean") {
37
+ return "boolean";
38
+ }
39
+ if (node.name.value === "ID") {
40
+ return "string";
41
+ }
42
+ return "object";
43
+ };
44
+ function valueOfNode(value) {
45
+ // object
46
+ if (value.kind === Kind.OBJECT) {
47
+ return value.fields.reduce((acc, field) => {
48
+ // @ts-expect-error TODO: nesting type
49
+ acc[field.name.value] = valueOfNode(field.value);
50
+ return acc;
51
+ }, {});
52
+ }
53
+ // list
54
+ if (value.kind === Kind.LIST) {
55
+ return value.values.map((v) => {
56
+ return valueOfNode(v);
57
+ });
58
+ }
59
+ // null
60
+ if (value.kind === Kind.NULL) {
61
+ return null;
62
+ }
63
+ // string
64
+ if (value.kind === Kind.STRING) {
65
+ return value.value;
66
+ }
67
+ // enum
68
+ if (value.kind === Kind.ENUM) {
69
+ return value.value;
70
+ }
71
+ // int
72
+ if (value.kind === Kind.INT) {
73
+ return Number.parseInt(value.value, 10);
74
+ }
75
+ // float
76
+ if (value.kind === Kind.FLOAT) {
77
+ return Number.parseFloat(value.value);
78
+ }
79
+ // boolean
80
+ if (value.kind === Kind.BOOLEAN) {
81
+ return value.value;
82
+ }
83
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
84
+ throw new Error(`Unknown kind of value ${value}`);
85
+ }
86
+ const typeToFunction = ({ convertedTypeName, fieldName, type, config, idFactory, }) => {
87
+ switch (type) {
88
+ case "String":
89
+ return `"${config.defaultValues.String}"`;
90
+ case "Int":
91
+ return `${config.defaultValues.Int}`;
92
+ case "Float":
93
+ return `${config.defaultValues.Float}`;
94
+ case "Boolean":
95
+ return `${config.defaultValues.Boolean ? "true" : "false"}`;
96
+ case "ID": {
97
+ const pathOfField = `${convertedTypeName}.${fieldName}`;
98
+ return `${idFactory(config.defaultValues.ID, pathOfField)}`;
99
+ }
100
+ default:
101
+ // reference to the object
102
+ return `${generateCreateReferenceCode({ fieldName, typeName: type, config: config })}`;
103
+ }
104
+ };
105
+ const typeToFunctionWithArray = ({ convertedTypeName, fieldName, type, config, idFactory, }) => {
106
+ // Avoid [null, null, null]
107
+ // Mock server can't handle null values in the array
108
+ return `(depth < ${config.maxFieldRecursionDepth}) ? Array.from({ length: ${config.defaultValues.listLength} }).map(() => ${typeToFunction({
109
+ convertedTypeName,
110
+ fieldName: fieldName,
111
+ type: type,
112
+ config: config,
113
+ idFactory: idFactory,
114
+ })}) : []`;
115
+ };
116
+ // NamedType/ListType handling
117
+ const nodeToExpression = ({ convertedTypeName, fieldName, currentNode, isArray = false, config, idFactory, }) => {
118
+ if (currentNode.kind === "NonNullType") {
119
+ return nodeToExpression({
120
+ convertedTypeName,
121
+ fieldName,
122
+ currentNode: currentNode.type,
123
+ isArray,
124
+ config,
125
+ idFactory,
126
+ });
127
+ }
128
+ if (currentNode.kind === "NamedType") {
129
+ if (isArray) {
130
+ return {
131
+ expression: typeToFunctionWithArray({
132
+ convertedTypeName,
133
+ fieldName: fieldName,
134
+ type: currentNode.name.value,
135
+ config: config,
136
+ idFactory: idFactory,
137
+ }),
138
+ };
139
+ }
140
+ return {
141
+ expression: typeToFunction({
142
+ convertedTypeName,
143
+ fieldName,
144
+ type: currentNode.name.value,
145
+ config: config,
146
+ idFactory: idFactory,
147
+ }),
148
+ };
149
+ }
150
+ if (currentNode.kind === "ListType") {
151
+ return nodeToExpression({
152
+ convertedTypeName,
153
+ fieldName,
154
+ currentNode: currentNode.type,
155
+ isArray: true,
156
+ config,
157
+ idFactory,
158
+ });
159
+ }
160
+ throw new Error("Unknown node kind");
161
+ };
162
+ const SUPPORTED_EXAMPLE_DIRECTIVES = [
163
+ "exampleID",
164
+ "exampleString",
165
+ "exampleInt",
166
+ "exampleFloat",
167
+ "exampleBoolean",
168
+ ];
169
+ const isIdType = (node) => {
170
+ if (node.kind === "NonNullType") {
171
+ return isIdType(node.type);
172
+ }
173
+ if (node.kind === "NamedType") {
174
+ return node.name.value === "ID";
175
+ }
176
+ if (node.kind === "ListType") {
177
+ return false;
178
+ }
179
+ return false;
180
+ };
181
+ function parseFieldOrInputValueDefinition({ node, convertedTypeName, config, idFactory, }) {
182
+ const fieldName = node.name.value;
183
+ const comment = node.description ? transformComment(node.description) : undefined;
184
+ const exampleDirective = node.directives?.find((d) => {
185
+ return SUPPORTED_EXAMPLE_DIRECTIVES.includes(d.name.value);
186
+ });
187
+ // @example* directive is not found, return random value for the scalar type
188
+ if (!exampleDirective) {
189
+ return {
190
+ comment,
191
+ example: nodeToExpression({
192
+ convertedTypeName,
193
+ fieldName,
194
+ currentNode: node.type,
195
+ config,
196
+ idFactory,
197
+ }),
198
+ };
199
+ }
200
+ if (!exampleDirective.arguments) {
201
+ throw new Error(`@${exampleDirective.name.value} directive must have arguments. @${exampleDirective.name.value}(value: ...)`);
202
+ }
203
+ /**
204
+ * @exampleID(value: "id")
205
+ * -> { value: "id1" }
206
+ * @exampleString(value: "value")
207
+ * -> { value: "value" }
208
+ * @exampleInt(value: 1)
209
+ * -> { value: 1 }
210
+ * @exampleFloat(value: 1.1)
211
+ * -> { value: 1.1 }
212
+ * @exampleBoolean(value: true)
213
+ * -> { value: true }
214
+ */
215
+ const value = exampleDirective.arguments.find((a) => a.name.value === "value");
216
+ if (!value) {
217
+ throw new Error(`@${exampleDirective.name.value} directive must have value argument. @${exampleDirective.name.value}(value: ...)`);
218
+ }
219
+ const rawValue = valueOfNode(value.value);
220
+ // if node type is not equal to the value type, throw an error
221
+ const nodeType = parseTypeNodeStructure(node.type);
222
+ // array, object, string, number, boolean, null
223
+ const rawValueType = Object.prototype.toString.call(rawValue).slice(8, -1).toLowerCase();
224
+ if (nodeType !== rawValueType) {
225
+ throw new Error(`${convertedTypeName}.${fieldName}: @${exampleDirective.name.value} directive value type must be ${nodeType}. Got ${rawValueType}`);
226
+ }
227
+ // if ID type, add idFactory() to the value
228
+ // e.g. @exampleID(value: "id") -> { expression: __id("id") }
229
+ const isExampleIdDirective = exampleDirective.name.value === "exampleID";
230
+ if (isExampleIdDirective && typeof rawValue === "string") {
231
+ const pathOfField = `${convertedTypeName}.${fieldName}.${rawValue}`;
232
+ return { comment, example: { expression: idFactory(rawValue, pathOfField) } };
233
+ }
234
+ return { comment, example: { value: rawValue } };
235
+ }
236
+ function parseObjectTypeOrInputObjectTypeDefinition({ node, config, idFactory, }) {
237
+ const originalTypeName = node.name.value;
238
+ const convertedTypeName = convertName(originalTypeName, config);
239
+ return {
240
+ type: "object",
241
+ name: originalTypeName,
242
+ fields: [
243
+ ...(node.fields ?? []).map((field) => ({
244
+ name: field.name.value,
245
+ ...parseFieldOrInputValueDefinition({
246
+ node: field,
247
+ convertedTypeName,
248
+ config,
249
+ idFactory,
250
+ }),
251
+ })),
252
+ ],
253
+ };
254
+ }
255
+ export function getTypeInfos(config, schema) {
256
+ const types = Object.values(schema.getTypeMap());
257
+ const idFactory = createIDFactory();
258
+ const userDefinedTypeDefinitions = types
259
+ .map((type) => type.astNode)
260
+ .filter((node) => {
261
+ if (!node)
262
+ return false;
263
+ return (node.kind === Kind.OBJECT_TYPE_DEFINITION ||
264
+ node.kind === Kind.INPUT_OBJECT_TYPE_DEFINITION ||
265
+ node.kind === Kind.INTERFACE_TYPE_DEFINITION ||
266
+ node.kind === Kind.UNION_TYPE_DEFINITION);
267
+ });
268
+ const objectTypeDefinitions = userDefinedTypeDefinitions.filter((node) => {
269
+ if (!node)
270
+ return false;
271
+ return node.kind === Kind.OBJECT_TYPE_DEFINITION;
272
+ });
273
+ return types
274
+ .map((type) => type.astNode)
275
+ .filter((node) => {
276
+ if (!node)
277
+ return false;
278
+ return (node.kind === Kind.OBJECT_TYPE_DEFINITION ||
279
+ node.kind === Kind.INPUT_OBJECT_TYPE_DEFINITION ||
280
+ node.kind === Kind.INTERFACE_TYPE_DEFINITION ||
281
+ node.kind === Kind.UNION_TYPE_DEFINITION);
282
+ })
283
+ .map((node) => {
284
+ if (node?.kind === Kind.OBJECT_TYPE_DEFINITION ||
285
+ node?.kind === Kind.INPUT_OBJECT_TYPE_DEFINITION) {
286
+ return parseObjectTypeOrInputObjectTypeDefinition({ node, config, idFactory });
287
+ }
288
+ if (node?.kind === Kind.INTERFACE_TYPE_DEFINITION) {
289
+ return {
290
+ type: "abstract",
291
+ name: convertName(node.name.value, config),
292
+ possibleTypes: objectTypeDefinitions
293
+ .filter((objectTypeDefinitionNode) => (objectTypeDefinitionNode.interfaces ?? []).some((i) => i.name.value === node.name.value))
294
+ .map((objectTypeDefinitionNode) => convertName(objectTypeDefinitionNode.name.value, config)),
295
+ comment: node.description ? transformComment(node.description) : undefined,
296
+ };
297
+ }
298
+ return {
299
+ type: "abstract",
300
+ name: convertName(node.name.value, config),
301
+ possibleTypes: (node.types ?? []).map((type) => convertName(type.name.value, config)),
302
+ comment: node.description ? transformComment(node.description) : undefined,
303
+ };
304
+ });
305
+ }
306
+ //# sourceMappingURL=schema-scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-scanner.js","sourceRoot":"","sources":["../../src/schema-scanner.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "@newmo/graphql-fake-core",
3
+ "version": "0.3.0",
4
+ "private": false,
5
+ "description": "GraphQL fake core library",
6
+ "keywords": [
7
+ "testing",
8
+ "mock",
9
+ "graphql"
10
+ ],
11
+ "repository": "https://github.com/newmo-oss/graphql-fake-server.git",
12
+ "license": "MIT",
13
+ "author": "newmo, Inc.",
14
+ "sideEffects": false,
15
+ "type": "module",
16
+ "exports": {
17
+ ".": {
18
+ "import": {
19
+ "types": "./dist/esm/index.d.ts",
20
+ "default": "./dist/esm/index.js"
21
+ }
22
+ }
23
+ },
24
+ "files": [
25
+ "src/",
26
+ "!src/test",
27
+ "!src/**/*.test.ts",
28
+ "!src/**/__snapshots__",
29
+ "dist/"
30
+ ],
31
+ "scripts": {
32
+ "prepare": "npm run build",
33
+ "build": "run-s -c build:*",
34
+ "build:esm": "tsc -p tsconfig.build.json",
35
+ "lint": "run-s -c lint:*",
36
+ "lint:tsc": "tsc",
37
+ "test": "vitest run",
38
+ "updateSnapshot": "vitest run -u"
39
+ },
40
+ "dependencies": {
41
+ "@graphql-codegen/visitor-plugin-common": "^4.0.1"
42
+ },
43
+ "devDependencies": {
44
+ "@graphql-codegen/cli": "^5.0.0",
45
+ "@graphql-codegen/typescript": "^4.0.1",
46
+ "@tsconfig/node18": "^18.2.0",
47
+ "@tsconfig/strictest": "^2.0.1",
48
+ "@types/eslint": "^8.44.2",
49
+ "@types/node": "^20.5.1",
50
+ "eslint": "^8.47.0",
51
+ "graphql": "^16.8.1",
52
+ "npm-run-all": "^4.1.5",
53
+ "tsx": "^4.7.1",
54
+ "typescript": "^5.4.2",
55
+ "vitest": "^1.3.1",
56
+ "vitest-github-actions-reporter": "^0.11.1"
57
+ },
58
+ "peerDependencies": {
59
+ "graphql": "^16.8.1"
60
+ },
61
+ "engines": {
62
+ "node": ">=18.0.0"
63
+ },
64
+ "publishConfig": {
65
+ "access": "public",
66
+ "registry": "https://registry.npmjs.org/"
67
+ },
68
+ "gitHead": "6a7c37aca13e97d9ad47bc78ee6a84ba0dfa0dbc"
69
+ }
@@ -0,0 +1,119 @@
1
+ import type { Config } from "./config.js";
2
+ import type { ExampleDirective, ObjectTypeInfo, TypeInfo } from "./schema-scanner.js";
3
+
4
+ export type ConfigWithOutput = {
5
+ outputType: "typescript" | "javascript" | "commonjs";
6
+ } & Config;
7
+ const handleExample = (exampleDirective: ExampleDirective): string => {
8
+ if ("value" in exampleDirective) {
9
+ return JSON.stringify(exampleDirective.value);
10
+ }
11
+ if ("expression" in exampleDirective) {
12
+ return exampleDirective.expression;
13
+ }
14
+ throw new Error(`Invalid example directive${JSON.stringify(exampleDirective)}`);
15
+ };
16
+ export const generateCreateReferenceCode = ({
17
+ fieldName,
18
+ typeName,
19
+ config,
20
+ }: {
21
+ fieldName: string;
22
+ typeName: string;
23
+ config: Config;
24
+ }): string => {
25
+ /**
26
+ * function createAuthor({ defaultFields, depth = 0 }: { defaultFields?: Partial<Author>, depth?: number } = {}): Author {
27
+ * return {
28
+ * foo: depth < 1 ? createAuthor({ defaultFields: defaultFields?.foo, depth: depth + 1 }) : undefined,
29
+ * }
30
+ *}
31
+ */
32
+ return `(depth < ${config.maxFieldRecursionDepth} ? create${typeName}({ defaultFields: defaultFields?.${fieldName} ?? {}, depth: depth + 1 }) : undefined)`;
33
+ };
34
+
35
+ function generateExampleCode(config: ConfigWithOutput, typeInfo: ObjectTypeInfo): string {
36
+ const { name } = typeInfo;
37
+ const indent = " ";
38
+ const isTypescript = config.outputType === "typescript";
39
+ const functionBodyCode = `
40
+ ${indent}return {
41
+ ${typeInfo.fields
42
+ .map((field) => {
43
+ const example = field.example ? handleExample(field.example) : "undefined";
44
+ return `${indent}${indent}${field.name}: ${example},`;
45
+ })
46
+ .join("\n")}
47
+ ${indent}};
48
+ `.trim();
49
+ if (config.outputType === "commonjs") {
50
+ return `
51
+ function create${name}({ defaultFields, depth = 0 } = {}) {
52
+ ${functionBodyCode}
53
+ }
54
+ exports.create${name} = create${name};
55
+ `.trim();
56
+ }
57
+ return `
58
+ export function create${name}({ defaultFields, depth = 0 }${
59
+ isTypescript ? `: { defaultFields?: Partial<${name}>, depth?: number }` : ""
60
+ } = {})${isTypescript ? `: ${name}Type` : ""} {
61
+ ${functionBodyCode}
62
+ }
63
+ `.trimStart();
64
+ }
65
+
66
+ function generateDefaultCode(config: ConfigWithOutput, typeInfo: ObjectTypeInfo): string {
67
+ const { name } = typeInfo;
68
+ if (config.outputType === "commonjs") {
69
+ return `const ${name} = create${name}();
70
+ exports.${name} = ${name};`;
71
+ }
72
+ return `export const ${name} = create${name}();`;
73
+ }
74
+
75
+ function generateImportTypeCode(config: ConfigWithOutput, typeInfos: TypeInfo[]): string {
76
+ const isTypescript = config.outputType === "typescript";
77
+ if (!isTypescript) return "";
78
+ const indent = " ";
79
+ const joinedTypeNames = typeInfos
80
+ .filter(({ type }) => type === "object")
81
+ .map(({ name }) => `${indent}${name}`)
82
+ .join(",\n");
83
+ return `import type {
84
+ ${joinedTypeNames}
85
+ } from '${config.typesFile}';`;
86
+ }
87
+
88
+ function idGeneratorCode(config: ConfigWithOutput): string {
89
+ // __id("name);
90
+ const isTypescript = config.outputType === "typescript";
91
+ return `
92
+ const __idCountMap = new Map${isTypescript ? "<string, number>" : ""}()
93
+ function __id({ name, key, depth }${
94
+ isTypescript ? "{ name: string; key: string; depth: number; }" : ""
95
+ })${isTypescript ? ": string" : ""} {
96
+ const count = __idCountMap.get(key) ?? 0;
97
+ __idCountMap.set(key, count + 1);
98
+ return name + String(depth) + String(count);
99
+ }`;
100
+ }
101
+
102
+ export function generateCode(config: ConfigWithOutput, typeInfos: TypeInfo[]): string {
103
+ let code = "";
104
+ if (config.outputType === "typescript") {
105
+ code += generateImportTypeCode(config, typeInfos);
106
+ code += "\n";
107
+ }
108
+ code += idGeneratorCode(config);
109
+ code += "\n";
110
+ for (const typeInfo of typeInfos) {
111
+ if (typeInfo.type === "object") {
112
+ code += generateExampleCode(config, typeInfo);
113
+ code += "\n";
114
+ code += generateDefaultCode(config, typeInfo);
115
+ code += "\n";
116
+ }
117
+ }
118
+ return code;
119
+ }
package/src/config.ts ADDED
@@ -0,0 +1,117 @@
1
+ import type { RawTypesConfig } from "@graphql-codegen/visitor-plugin-common";
2
+
3
+ export type RawConfig = {
4
+ /**
5
+ * path to type definitions file
6
+ * this is generated by client preset
7
+ * e.g. ) "typeFile: "./graphql"
8
+ */
9
+ typesFile?: string;
10
+ skipTypename?: RawTypesConfig["skipTypename"];
11
+ namingConvention?: RawTypesConfig["namingConvention"];
12
+ typesPrefix?: RawTypesConfig["typesPrefix"];
13
+ typesSuffix?: RawTypesConfig["typesSuffix"];
14
+ maxFieldRecursionDepth?: number;
15
+ defaultValues?: {
16
+ String?: string;
17
+ Int?: number;
18
+ Float?: number;
19
+ Boolean?: boolean;
20
+ ID?: string;
21
+ listLength?: number;
22
+ };
23
+ };
24
+
25
+ export const DefaultValues = {
26
+ String: "string",
27
+ Int: 12,
28
+ Float: 12.3,
29
+ Boolean: true,
30
+ ID: "xxxx-xxxx-xxxx-xxxx",
31
+ listLength: 3,
32
+ };
33
+ export type Config = {
34
+ typesFile: string;
35
+ skipTypename: Exclude<RawTypesConfig["skipTypename"], undefined>;
36
+ typesPrefix: Exclude<RawTypesConfig["typesPrefix"], undefined>;
37
+ typesSuffix: Exclude<RawTypesConfig["typesSuffix"], undefined>;
38
+ namingConvention: Exclude<RawTypesConfig["namingConvention"], undefined>;
39
+ maxFieldRecursionDepth: number;
40
+ defaultValues: {
41
+ String: string;
42
+ Int: number;
43
+ Float: number;
44
+ Boolean: boolean;
45
+ ID: string;
46
+ listLength: number;
47
+ };
48
+ };
49
+
50
+ export function validateConfig(
51
+ rawConfig: unknown,
52
+ outputType: "typescript" | "javascript" = "javascript",
53
+ ): asserts rawConfig is RawConfig {
54
+ // defaultValues type validations
55
+ if (rawConfig === null || rawConfig === undefined) {
56
+ throw new Error("config.defaultValues must be an object");
57
+ }
58
+ if (typeof rawConfig !== "object") {
59
+ throw new Error("config.defaultValues must be an object");
60
+ }
61
+ if ("maxFieldRecursionDepth" in rawConfig) {
62
+ if (typeof rawConfig.maxFieldRecursionDepth !== "number") {
63
+ throw new Error("config.maxFieldRecursionDepth must be a number");
64
+ }
65
+ }
66
+ if (outputType === "typescript") {
67
+ if (!("typesFile" in rawConfig)) {
68
+ throw new Error("config.typesFile is required");
69
+ }
70
+ }
71
+ if ("defaultValues" in rawConfig) {
72
+ if (typeof rawConfig.defaultValues !== "object") {
73
+ throw new Error("config.defaultValues must be an object");
74
+ }
75
+ const defaultValues = rawConfig.defaultValues as Config["defaultValues"];
76
+ if (defaultValues.String !== undefined && typeof defaultValues.String !== "string") {
77
+ throw new Error("config.defaultValues.String must be a string");
78
+ }
79
+ if (defaultValues.Int !== undefined && typeof defaultValues.Int !== "number") {
80
+ throw new Error("config.defaultValues.Int must be a number");
81
+ }
82
+ if (defaultValues.Float !== undefined && typeof defaultValues.Float !== "number") {
83
+ throw new Error("config.defaultValues.Float must be a number");
84
+ }
85
+ if (defaultValues.Boolean !== undefined && typeof defaultValues.Boolean !== "boolean") {
86
+ throw new Error("config.defaultValues.Boolean must be a boolean");
87
+ }
88
+ if (defaultValues.ID !== undefined && typeof defaultValues.ID !== "string") {
89
+ throw new Error("config.defaultValues.ID must be a string");
90
+ }
91
+ if (
92
+ defaultValues.listLength !== undefined &&
93
+ typeof defaultValues.listLength !== "number"
94
+ ) {
95
+ throw new Error("config.defaultValues.listLength must be a number");
96
+ }
97
+ }
98
+ }
99
+
100
+ export function normalizeConfig(rawConfig: RawConfig): Config {
101
+ return {
102
+ typesFile: rawConfig.typesFile ?? "",
103
+ skipTypename: rawConfig.skipTypename ?? false,
104
+ typesPrefix: rawConfig.typesPrefix ?? "",
105
+ typesSuffix: rawConfig.typesSuffix ?? "",
106
+ namingConvention: rawConfig.namingConvention ?? "",
107
+ maxFieldRecursionDepth: rawConfig.maxFieldRecursionDepth ?? 3,
108
+ defaultValues: {
109
+ String: rawConfig.defaultValues?.String ?? DefaultValues.String,
110
+ Int: rawConfig.defaultValues?.Int ?? DefaultValues.Int,
111
+ Float: rawConfig.defaultValues?.Float ?? DefaultValues.Float,
112
+ Boolean: rawConfig.defaultValues?.Boolean ?? DefaultValues.Boolean,
113
+ ID: rawConfig.defaultValues?.ID ?? DefaultValues.ID,
114
+ listLength: rawConfig.defaultValues?.listLength ?? DefaultValues.listLength,
115
+ },
116
+ };
117
+ }