@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.
- package/LICENSE +23 -0
- package/README.md +97 -0
- package/dist/esm/code-generator.d.ts +12 -0
- package/dist/esm/code-generator.d.ts.map +1 -0
- package/dist/esm/code-generator.js +98 -0
- package/dist/esm/code-generator.js.map +1 -0
- package/dist/esm/config.d.ts +49 -0
- package/dist/esm/config.d.ts.map +1 -0
- package/dist/esm/config.js +71 -0
- package/dist/esm/config.js.map +1 -0
- package/dist/esm/extend-schema.d.ts +3 -0
- package/dist/esm/extend-schema.d.ts.map +1 -0
- package/dist/esm/extend-schema.js +62 -0
- package/dist/esm/extend-schema.js.map +1 -0
- package/dist/esm/index.d.ts +8 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +5 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/schema-scanner.d.ts +32 -0
- package/dist/esm/schema-scanner.d.ts.map +1 -0
- package/dist/esm/schema-scanner.js +306 -0
- package/dist/esm/schema-scanner.js.map +1 -0
- package/package.json +69 -0
- package/src/code-generator.ts +119 -0
- package/src/config.ts +117 -0
- package/src/extend-schema.ts +61 -0
- package/src/index.ts +14 -0
- package/src/schema-scanner.ts +454 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export const EXAMPLE_DIRECTIVE = `
|
|
2
|
+
"""
|
|
3
|
+
@exampleID directive specifies an example value for a ID field.
|
|
4
|
+
This example value is used in the fake data.
|
|
5
|
+
ID value will be unique between all ID fake data.
|
|
6
|
+
"""
|
|
7
|
+
directive @exampleID(
|
|
8
|
+
"""
|
|
9
|
+
The value of the ID field.
|
|
10
|
+
@exampleID(value: "id")
|
|
11
|
+
"""
|
|
12
|
+
value: ID!
|
|
13
|
+
) on FIELD_DEFINITION
|
|
14
|
+
"""
|
|
15
|
+
@exampleString directive specifies an example value for a String field.
|
|
16
|
+
This example value is used in the fake data.
|
|
17
|
+
"""
|
|
18
|
+
directive @exampleString(
|
|
19
|
+
"""
|
|
20
|
+
The value of the String field.
|
|
21
|
+
@exampleString(value: "example")
|
|
22
|
+
"""
|
|
23
|
+
value: String!
|
|
24
|
+
) on FIELD_DEFINITION
|
|
25
|
+
"""
|
|
26
|
+
@exampleInt directive specifies an example value for a Inf field.
|
|
27
|
+
This example value is used in the fake data.
|
|
28
|
+
"""
|
|
29
|
+
directive @exampleInt(
|
|
30
|
+
"""
|
|
31
|
+
The value of the Int field.
|
|
32
|
+
@exampleInt(value: 1)
|
|
33
|
+
"""
|
|
34
|
+
value: Int!
|
|
35
|
+
) on FIELD_DEFINITION
|
|
36
|
+
"""
|
|
37
|
+
@exampleFloat directive specifies an example value for a Float field.
|
|
38
|
+
This example value is used in the fake data.
|
|
39
|
+
"""
|
|
40
|
+
directive @exampleFloat(
|
|
41
|
+
"""
|
|
42
|
+
The value of the Float field.
|
|
43
|
+
@exampleFloat(value: 1.0)
|
|
44
|
+
"""
|
|
45
|
+
value: Float!
|
|
46
|
+
) on FIELD_DEFINITION
|
|
47
|
+
"""
|
|
48
|
+
@exampleBoolean directive specifies an example value for a Boolean field.
|
|
49
|
+
This example value is used in the fake data.
|
|
50
|
+
"""
|
|
51
|
+
directive @exampleBoolean(
|
|
52
|
+
"""
|
|
53
|
+
The value of the Boolean field.
|
|
54
|
+
@exampleBoolean(value: true)
|
|
55
|
+
"""
|
|
56
|
+
value: Boolean!
|
|
57
|
+
) on FIELD_DEFINITION
|
|
58
|
+
`;
|
|
59
|
+
export const extendSchema = (schema: string) => {
|
|
60
|
+
return EXAMPLE_DIRECTIVE + schema;
|
|
61
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { generateCode } from "./code-generator.js";
|
|
2
|
+
export type { ConfigWithOutput } from "./code-generator.js";
|
|
3
|
+
export { normalizeConfig, validateConfig } from "./config.js";
|
|
4
|
+
export type { Config, RawConfig } from "./config.js";
|
|
5
|
+
export { extendSchema, EXAMPLE_DIRECTIVE } from "./extend-schema.js";
|
|
6
|
+
export { getTypeInfos } from "./schema-scanner.js";
|
|
7
|
+
export type {
|
|
8
|
+
TypeInfo,
|
|
9
|
+
AbstractTypeInfo,
|
|
10
|
+
ObjectTypeInfo,
|
|
11
|
+
ExampleDirective,
|
|
12
|
+
ExampleDirectiveValue,
|
|
13
|
+
ExampleDirectionExpression,
|
|
14
|
+
} from "./schema-scanner.js";
|
|
@@ -0,0 +1,454 @@
|
|
|
1
|
+
import { convertFactory, transformComment } from "@graphql-codegen/visitor-plugin-common";
|
|
2
|
+
import {
|
|
3
|
+
type ASTNode,
|
|
4
|
+
type ConstValueNode,
|
|
5
|
+
type FieldDefinitionNode,
|
|
6
|
+
type GraphQLSchema,
|
|
7
|
+
type InputObjectTypeDefinitionNode,
|
|
8
|
+
type InputValueDefinitionNode,
|
|
9
|
+
type InterfaceTypeDefinitionNode,
|
|
10
|
+
Kind,
|
|
11
|
+
type ListTypeNode,
|
|
12
|
+
type NamedTypeNode,
|
|
13
|
+
type NonNullTypeNode,
|
|
14
|
+
type ObjectTypeDefinitionNode,
|
|
15
|
+
type TypeNode,
|
|
16
|
+
type UnionTypeDefinitionNode,
|
|
17
|
+
} from "graphql";
|
|
18
|
+
import { generateCreateReferenceCode } from "./code-generator.js";
|
|
19
|
+
import type { Config } from "./config.js";
|
|
20
|
+
|
|
21
|
+
function convertName(node: ASTNode | string, config: Config): string {
|
|
22
|
+
const convert = config.namingConvention
|
|
23
|
+
? convertFactory({ namingConvention: config.namingConvention })
|
|
24
|
+
: convertFactory({});
|
|
25
|
+
let convertedName = "";
|
|
26
|
+
convertedName += config.typesPrefix;
|
|
27
|
+
convertedName += convert(node);
|
|
28
|
+
convertedName += config.typesSuffix;
|
|
29
|
+
return convertedName;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const createIDFactory = () => {
|
|
33
|
+
return (name: string, key: string) => {
|
|
34
|
+
return `__id({ name: "${name}", key:"${key}", depth })`;
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const parseTypeNodeStructure = (node: TypeNode): string => {
|
|
39
|
+
if (node.kind === Kind.NON_NULL_TYPE) {
|
|
40
|
+
return parseTypeNodeStructure(node.type);
|
|
41
|
+
}
|
|
42
|
+
if (node.kind === Kind.LIST_TYPE) {
|
|
43
|
+
return "array";
|
|
44
|
+
}
|
|
45
|
+
// string, number, boolean, null
|
|
46
|
+
if (node.name.value === "String") {
|
|
47
|
+
return "string";
|
|
48
|
+
}
|
|
49
|
+
if (node.name.value === "Int") {
|
|
50
|
+
return "number";
|
|
51
|
+
}
|
|
52
|
+
if (node.name.value === "Float") {
|
|
53
|
+
return "number";
|
|
54
|
+
}
|
|
55
|
+
if (node.name.value === "Boolean") {
|
|
56
|
+
return "boolean";
|
|
57
|
+
}
|
|
58
|
+
if (node.name.value === "ID") {
|
|
59
|
+
return "string";
|
|
60
|
+
}
|
|
61
|
+
return "object";
|
|
62
|
+
};
|
|
63
|
+
type ValuePrimitive = string | number | boolean | null;
|
|
64
|
+
type ValueArray = ValuePrimitive[];
|
|
65
|
+
type ValueObject = Record<string, ValuePrimitive | ValueArray>;
|
|
66
|
+
export type ExampleDirectiveValue = {
|
|
67
|
+
// value is serialized value
|
|
68
|
+
value: ValuePrimitive | ValueArray | ValueObject;
|
|
69
|
+
};
|
|
70
|
+
export type ExampleDirectionExpression = {
|
|
71
|
+
expression: string;
|
|
72
|
+
};
|
|
73
|
+
export type ExampleDirective = ExampleDirectiveValue | ExampleDirectionExpression;
|
|
74
|
+
|
|
75
|
+
function valueOfNode(value: ConstValueNode): ValuePrimitive | ValueArray | ValueObject {
|
|
76
|
+
// object
|
|
77
|
+
if (value.kind === Kind.OBJECT) {
|
|
78
|
+
return value.fields.reduce((acc, field) => {
|
|
79
|
+
// @ts-expect-error TODO: nesting type
|
|
80
|
+
acc[field.name.value] = valueOfNode(field.value);
|
|
81
|
+
return acc;
|
|
82
|
+
}, {} as ValueObject);
|
|
83
|
+
}
|
|
84
|
+
// list
|
|
85
|
+
if (value.kind === Kind.LIST) {
|
|
86
|
+
return value.values.map((v) => {
|
|
87
|
+
return valueOfNode(v);
|
|
88
|
+
}) as ValueArray;
|
|
89
|
+
}
|
|
90
|
+
// null
|
|
91
|
+
if (value.kind === Kind.NULL) {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
// string
|
|
95
|
+
if (value.kind === Kind.STRING) {
|
|
96
|
+
return value.value;
|
|
97
|
+
}
|
|
98
|
+
// enum
|
|
99
|
+
if (value.kind === Kind.ENUM) {
|
|
100
|
+
return value.value;
|
|
101
|
+
}
|
|
102
|
+
// int
|
|
103
|
+
if (value.kind === Kind.INT) {
|
|
104
|
+
return Number.parseInt(value.value, 10);
|
|
105
|
+
}
|
|
106
|
+
// float
|
|
107
|
+
if (value.kind === Kind.FLOAT) {
|
|
108
|
+
return Number.parseFloat(value.value);
|
|
109
|
+
}
|
|
110
|
+
// boolean
|
|
111
|
+
if (value.kind === Kind.BOOLEAN) {
|
|
112
|
+
return value.value;
|
|
113
|
+
}
|
|
114
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
115
|
+
throw new Error(`Unknown kind of value ${value satisfies never}`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const typeToFunction = ({
|
|
119
|
+
convertedTypeName,
|
|
120
|
+
fieldName,
|
|
121
|
+
type,
|
|
122
|
+
config,
|
|
123
|
+
idFactory,
|
|
124
|
+
}: {
|
|
125
|
+
convertedTypeName: string;
|
|
126
|
+
fieldName: string;
|
|
127
|
+
type: string;
|
|
128
|
+
config: Config;
|
|
129
|
+
idFactory: ReturnType<typeof createIDFactory>;
|
|
130
|
+
}): string => {
|
|
131
|
+
switch (type) {
|
|
132
|
+
case "String":
|
|
133
|
+
return `"${config.defaultValues.String}"`;
|
|
134
|
+
case "Int":
|
|
135
|
+
return `${config.defaultValues.Int}`;
|
|
136
|
+
case "Float":
|
|
137
|
+
return `${config.defaultValues.Float}`;
|
|
138
|
+
case "Boolean":
|
|
139
|
+
return `${config.defaultValues.Boolean ? "true" : "false"}`;
|
|
140
|
+
case "ID": {
|
|
141
|
+
const pathOfField = `${convertedTypeName}.${fieldName}`;
|
|
142
|
+
return `${idFactory(config.defaultValues.ID, pathOfField)}`;
|
|
143
|
+
}
|
|
144
|
+
default:
|
|
145
|
+
// reference to the object
|
|
146
|
+
return `${generateCreateReferenceCode({ fieldName, typeName: type, config: config })}`;
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
const typeToFunctionWithArray = ({
|
|
150
|
+
convertedTypeName,
|
|
151
|
+
fieldName,
|
|
152
|
+
type,
|
|
153
|
+
config,
|
|
154
|
+
idFactory,
|
|
155
|
+
}: {
|
|
156
|
+
convertedTypeName: string;
|
|
157
|
+
fieldName: string;
|
|
158
|
+
type: string;
|
|
159
|
+
config: Config;
|
|
160
|
+
idFactory: ReturnType<typeof createIDFactory>;
|
|
161
|
+
}): string => {
|
|
162
|
+
// Avoid [null, null, null]
|
|
163
|
+
// Mock server can't handle null values in the array
|
|
164
|
+
return `(depth < ${config.maxFieldRecursionDepth}) ? Array.from({ length: ${
|
|
165
|
+
config.defaultValues.listLength
|
|
166
|
+
} }).map(() => ${typeToFunction({
|
|
167
|
+
convertedTypeName,
|
|
168
|
+
fieldName: fieldName,
|
|
169
|
+
type: type,
|
|
170
|
+
config: config,
|
|
171
|
+
idFactory: idFactory,
|
|
172
|
+
})}) : []`;
|
|
173
|
+
};
|
|
174
|
+
// NamedType/ListType handling
|
|
175
|
+
const nodeToExpression = ({
|
|
176
|
+
convertedTypeName,
|
|
177
|
+
fieldName,
|
|
178
|
+
currentNode,
|
|
179
|
+
isArray = false,
|
|
180
|
+
config,
|
|
181
|
+
idFactory,
|
|
182
|
+
}: {
|
|
183
|
+
convertedTypeName: string;
|
|
184
|
+
fieldName: string;
|
|
185
|
+
currentNode: NonNullTypeNode | NamedTypeNode | ListTypeNode;
|
|
186
|
+
config: Config;
|
|
187
|
+
isArray?: boolean;
|
|
188
|
+
idFactory: ReturnType<typeof createIDFactory>;
|
|
189
|
+
}): ExampleDirectionExpression => {
|
|
190
|
+
if (currentNode.kind === "NonNullType") {
|
|
191
|
+
return nodeToExpression({
|
|
192
|
+
convertedTypeName,
|
|
193
|
+
fieldName,
|
|
194
|
+
currentNode: currentNode.type,
|
|
195
|
+
isArray,
|
|
196
|
+
config,
|
|
197
|
+
idFactory,
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
if (currentNode.kind === "NamedType") {
|
|
201
|
+
if (isArray) {
|
|
202
|
+
return {
|
|
203
|
+
expression: typeToFunctionWithArray({
|
|
204
|
+
convertedTypeName,
|
|
205
|
+
fieldName: fieldName,
|
|
206
|
+
type: currentNode.name.value,
|
|
207
|
+
config: config,
|
|
208
|
+
idFactory: idFactory,
|
|
209
|
+
}),
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
return {
|
|
213
|
+
expression: typeToFunction({
|
|
214
|
+
convertedTypeName,
|
|
215
|
+
fieldName,
|
|
216
|
+
type: currentNode.name.value,
|
|
217
|
+
config: config,
|
|
218
|
+
idFactory: idFactory,
|
|
219
|
+
}),
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
if (currentNode.kind === "ListType") {
|
|
223
|
+
return nodeToExpression({
|
|
224
|
+
convertedTypeName,
|
|
225
|
+
fieldName,
|
|
226
|
+
currentNode: currentNode.type,
|
|
227
|
+
isArray: true,
|
|
228
|
+
config,
|
|
229
|
+
idFactory,
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
throw new Error("Unknown node kind");
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
const SUPPORTED_EXAMPLE_DIRECTIVES = [
|
|
236
|
+
"exampleID",
|
|
237
|
+
"exampleString",
|
|
238
|
+
"exampleInt",
|
|
239
|
+
"exampleFloat",
|
|
240
|
+
"exampleBoolean",
|
|
241
|
+
];
|
|
242
|
+
const isIdType = (node: NonNullTypeNode | NamedTypeNode | ListTypeNode): boolean => {
|
|
243
|
+
if (node.kind === "NonNullType") {
|
|
244
|
+
return isIdType(node.type);
|
|
245
|
+
}
|
|
246
|
+
if (node.kind === "NamedType") {
|
|
247
|
+
return node.name.value === "ID";
|
|
248
|
+
}
|
|
249
|
+
if (node.kind === "ListType") {
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
return false;
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
function parseFieldOrInputValueDefinition({
|
|
256
|
+
node,
|
|
257
|
+
convertedTypeName,
|
|
258
|
+
config,
|
|
259
|
+
idFactory,
|
|
260
|
+
}: {
|
|
261
|
+
node: FieldDefinitionNode | InputValueDefinitionNode;
|
|
262
|
+
convertedTypeName: string;
|
|
263
|
+
config: Config;
|
|
264
|
+
idFactory: ReturnType<typeof createIDFactory>;
|
|
265
|
+
}): { comment?: string | undefined; example?: ExampleDirective | undefined } {
|
|
266
|
+
const fieldName = node.name.value;
|
|
267
|
+
const comment = node.description ? transformComment(node.description) : undefined;
|
|
268
|
+
const exampleDirective = node.directives?.find((d) => {
|
|
269
|
+
return SUPPORTED_EXAMPLE_DIRECTIVES.includes(d.name.value);
|
|
270
|
+
});
|
|
271
|
+
// @example* directive is not found, return random value for the scalar type
|
|
272
|
+
if (!exampleDirective) {
|
|
273
|
+
return {
|
|
274
|
+
comment,
|
|
275
|
+
example: nodeToExpression({
|
|
276
|
+
convertedTypeName,
|
|
277
|
+
fieldName,
|
|
278
|
+
currentNode: node.type,
|
|
279
|
+
config,
|
|
280
|
+
idFactory,
|
|
281
|
+
}),
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
if (!exampleDirective.arguments) {
|
|
285
|
+
throw new Error(
|
|
286
|
+
`@${exampleDirective.name.value} directive must have arguments. @${exampleDirective.name.value}(value: ...)`,
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* @exampleID(value: "id")
|
|
291
|
+
* -> { value: "id1" }
|
|
292
|
+
* @exampleString(value: "value")
|
|
293
|
+
* -> { value: "value" }
|
|
294
|
+
* @exampleInt(value: 1)
|
|
295
|
+
* -> { value: 1 }
|
|
296
|
+
* @exampleFloat(value: 1.1)
|
|
297
|
+
* -> { value: 1.1 }
|
|
298
|
+
* @exampleBoolean(value: true)
|
|
299
|
+
* -> { value: true }
|
|
300
|
+
*/
|
|
301
|
+
const value = exampleDirective.arguments.find((a) => a.name.value === "value");
|
|
302
|
+
if (!value) {
|
|
303
|
+
throw new Error(
|
|
304
|
+
`@${exampleDirective.name.value} directive must have value argument. @${exampleDirective.name.value}(value: ...)`,
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
const rawValue = valueOfNode(value.value);
|
|
308
|
+
// if node type is not equal to the value type, throw an error
|
|
309
|
+
const nodeType = parseTypeNodeStructure(node.type);
|
|
310
|
+
// array, object, string, number, boolean, null
|
|
311
|
+
const rawValueType = Object.prototype.toString.call(rawValue).slice(8, -1).toLowerCase();
|
|
312
|
+
if (nodeType !== rawValueType) {
|
|
313
|
+
throw new Error(
|
|
314
|
+
`${convertedTypeName}.${fieldName}: @${exampleDirective.name.value} directive value type must be ${nodeType}. Got ${rawValueType}`,
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
// if ID type, add idFactory() to the value
|
|
318
|
+
// e.g. @exampleID(value: "id") -> { expression: __id("id") }
|
|
319
|
+
const isExampleIdDirective = exampleDirective.name.value === "exampleID";
|
|
320
|
+
if (isExampleIdDirective && typeof rawValue === "string") {
|
|
321
|
+
const pathOfField = `${convertedTypeName}.${fieldName}.${rawValue}`;
|
|
322
|
+
return { comment, example: { expression: idFactory(rawValue, pathOfField) } };
|
|
323
|
+
}
|
|
324
|
+
return { comment, example: { value: rawValue } };
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
function parseObjectTypeOrInputObjectTypeDefinition({
|
|
328
|
+
node,
|
|
329
|
+
config,
|
|
330
|
+
idFactory,
|
|
331
|
+
}: {
|
|
332
|
+
node: ObjectTypeDefinitionNode | InputObjectTypeDefinitionNode;
|
|
333
|
+
config: Config;
|
|
334
|
+
idFactory: ReturnType<typeof createIDFactory>;
|
|
335
|
+
}): ObjectTypeInfo {
|
|
336
|
+
const originalTypeName = node.name.value;
|
|
337
|
+
const convertedTypeName = convertName(originalTypeName, config);
|
|
338
|
+
return {
|
|
339
|
+
type: "object",
|
|
340
|
+
name: originalTypeName,
|
|
341
|
+
fields: [
|
|
342
|
+
...(node.fields ?? []).map((field) => ({
|
|
343
|
+
name: field.name.value,
|
|
344
|
+
...parseFieldOrInputValueDefinition({
|
|
345
|
+
node: field,
|
|
346
|
+
convertedTypeName,
|
|
347
|
+
config,
|
|
348
|
+
idFactory,
|
|
349
|
+
}),
|
|
350
|
+
})),
|
|
351
|
+
],
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
type FieldInfo = {
|
|
356
|
+
name: string;
|
|
357
|
+
example?: ExampleDirective | undefined;
|
|
358
|
+
};
|
|
359
|
+
export type ObjectTypeInfo = {
|
|
360
|
+
type: "object";
|
|
361
|
+
name: string;
|
|
362
|
+
fields: FieldInfo[];
|
|
363
|
+
};
|
|
364
|
+
export type AbstractTypeInfo = {
|
|
365
|
+
type: "abstract";
|
|
366
|
+
name: string;
|
|
367
|
+
possibleTypes: string[];
|
|
368
|
+
comment?: string | undefined;
|
|
369
|
+
example?: ExampleDirective | undefined;
|
|
370
|
+
};
|
|
371
|
+
export type TypeInfo = ObjectTypeInfo | AbstractTypeInfo;
|
|
372
|
+
|
|
373
|
+
export function getTypeInfos(config: Config, schema: GraphQLSchema): TypeInfo[] {
|
|
374
|
+
const types = Object.values(schema.getTypeMap());
|
|
375
|
+
|
|
376
|
+
const idFactory = createIDFactory();
|
|
377
|
+
const userDefinedTypeDefinitions = types
|
|
378
|
+
.map((type) => type.astNode)
|
|
379
|
+
.filter(
|
|
380
|
+
(
|
|
381
|
+
node,
|
|
382
|
+
): node is
|
|
383
|
+
| ObjectTypeDefinitionNode
|
|
384
|
+
| InputObjectTypeDefinitionNode
|
|
385
|
+
| InterfaceTypeDefinitionNode
|
|
386
|
+
| UnionTypeDefinitionNode => {
|
|
387
|
+
if (!node) return false;
|
|
388
|
+
return (
|
|
389
|
+
node.kind === Kind.OBJECT_TYPE_DEFINITION ||
|
|
390
|
+
node.kind === Kind.INPUT_OBJECT_TYPE_DEFINITION ||
|
|
391
|
+
node.kind === Kind.INTERFACE_TYPE_DEFINITION ||
|
|
392
|
+
node.kind === Kind.UNION_TYPE_DEFINITION
|
|
393
|
+
);
|
|
394
|
+
},
|
|
395
|
+
);
|
|
396
|
+
const objectTypeDefinitions = userDefinedTypeDefinitions.filter(
|
|
397
|
+
(node): node is ObjectTypeDefinitionNode => {
|
|
398
|
+
if (!node) return false;
|
|
399
|
+
return node.kind === Kind.OBJECT_TYPE_DEFINITION;
|
|
400
|
+
},
|
|
401
|
+
);
|
|
402
|
+
|
|
403
|
+
return types
|
|
404
|
+
.map((type) => type.astNode)
|
|
405
|
+
.filter(
|
|
406
|
+
(
|
|
407
|
+
node,
|
|
408
|
+
): node is
|
|
409
|
+
| ObjectTypeDefinitionNode
|
|
410
|
+
| InputObjectTypeDefinitionNode
|
|
411
|
+
| InterfaceTypeDefinitionNode
|
|
412
|
+
| UnionTypeDefinitionNode => {
|
|
413
|
+
if (!node) return false;
|
|
414
|
+
return (
|
|
415
|
+
node.kind === Kind.OBJECT_TYPE_DEFINITION ||
|
|
416
|
+
node.kind === Kind.INPUT_OBJECT_TYPE_DEFINITION ||
|
|
417
|
+
node.kind === Kind.INTERFACE_TYPE_DEFINITION ||
|
|
418
|
+
node.kind === Kind.UNION_TYPE_DEFINITION
|
|
419
|
+
);
|
|
420
|
+
},
|
|
421
|
+
)
|
|
422
|
+
.map((node) => {
|
|
423
|
+
if (
|
|
424
|
+
node?.kind === Kind.OBJECT_TYPE_DEFINITION ||
|
|
425
|
+
node?.kind === Kind.INPUT_OBJECT_TYPE_DEFINITION
|
|
426
|
+
) {
|
|
427
|
+
return parseObjectTypeOrInputObjectTypeDefinition({ node, config, idFactory });
|
|
428
|
+
}
|
|
429
|
+
if (node?.kind === Kind.INTERFACE_TYPE_DEFINITION) {
|
|
430
|
+
return {
|
|
431
|
+
type: "abstract",
|
|
432
|
+
name: convertName(node.name.value, config),
|
|
433
|
+
possibleTypes: objectTypeDefinitions
|
|
434
|
+
.filter((objectTypeDefinitionNode) =>
|
|
435
|
+
(objectTypeDefinitionNode.interfaces ?? []).some(
|
|
436
|
+
(i) => i.name.value === node.name.value,
|
|
437
|
+
),
|
|
438
|
+
)
|
|
439
|
+
.map((objectTypeDefinitionNode) =>
|
|
440
|
+
convertName(objectTypeDefinitionNode.name.value, config),
|
|
441
|
+
),
|
|
442
|
+
comment: node.description ? transformComment(node.description) : undefined,
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
return {
|
|
446
|
+
type: "abstract",
|
|
447
|
+
name: convertName(node.name.value, config),
|
|
448
|
+
possibleTypes: (node.types ?? []).map((type) =>
|
|
449
|
+
convertName(type.name.value, config),
|
|
450
|
+
),
|
|
451
|
+
comment: node.description ? transformComment(node.description) : undefined,
|
|
452
|
+
};
|
|
453
|
+
});
|
|
454
|
+
}
|