@gqlkit-ts/cli 0.2.0 → 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/dist/auto-type-generator/auto-type-generator.d.ts +10 -4
- package/dist/auto-type-generator/auto-type-generator.d.ts.map +1 -1
- package/dist/auto-type-generator/auto-type-generator.js +640 -133
- package/dist/auto-type-generator/auto-type-generator.js.map +1 -1
- package/dist/auto-type-generator/index.d.ts +8 -1
- package/dist/auto-type-generator/index.d.ts.map +1 -1
- package/dist/auto-type-generator/index.js +3 -0
- package/dist/auto-type-generator/index.js.map +1 -1
- package/dist/auto-type-generator/inline-enum-collector.d.ts +13 -5
- package/dist/auto-type-generator/inline-enum-collector.d.ts.map +1 -1
- package/dist/auto-type-generator/inline-enum-collector.js +107 -71
- package/dist/auto-type-generator/inline-enum-collector.js.map +1 -1
- package/dist/auto-type-generator/inline-object-traverser.d.ts +20 -0
- package/dist/auto-type-generator/inline-object-traverser.d.ts.map +1 -0
- package/dist/auto-type-generator/inline-object-traverser.js +22 -0
- package/dist/auto-type-generator/inline-object-traverser.js.map +1 -0
- package/dist/auto-type-generator/inline-union-collector.d.ts +29 -0
- package/dist/auto-type-generator/inline-union-collector.d.ts.map +1 -0
- package/dist/auto-type-generator/inline-union-collector.js +216 -0
- package/dist/auto-type-generator/inline-union-collector.js.map +1 -0
- package/dist/auto-type-generator/inline-union-types.d.ts +29 -0
- package/dist/auto-type-generator/inline-union-types.d.ts.map +1 -0
- package/dist/auto-type-generator/inline-union-types.js +2 -0
- package/dist/auto-type-generator/inline-union-types.js.map +1 -0
- package/dist/auto-type-generator/inline-union-validator.d.ts +76 -0
- package/dist/auto-type-generator/inline-union-validator.d.ts.map +1 -0
- package/dist/auto-type-generator/inline-union-validator.js +329 -0
- package/dist/auto-type-generator/inline-union-validator.js.map +1 -0
- package/dist/auto-type-generator/naming-convention.d.ts +18 -1
- package/dist/auto-type-generator/naming-convention.d.ts.map +1 -1
- package/dist/auto-type-generator/naming-convention.js +16 -0
- package/dist/auto-type-generator/naming-convention.js.map +1 -1
- package/dist/auto-type-generator/resolve-type-generator.d.ts +20 -0
- package/dist/auto-type-generator/resolve-type-generator.d.ts.map +1 -0
- package/dist/auto-type-generator/resolve-type-generator.js +2 -0
- package/dist/auto-type-generator/resolve-type-generator.js.map +1 -0
- package/dist/auto-type-generator/resolver-field-iterator.d.ts +13 -0
- package/dist/auto-type-generator/resolver-field-iterator.d.ts.map +1 -0
- package/dist/auto-type-generator/resolver-field-iterator.js +22 -0
- package/dist/auto-type-generator/resolver-field-iterator.js.map +1 -0
- package/dist/auto-type-generator/typename-extractor.d.ts +26 -0
- package/dist/auto-type-generator/typename-extractor.d.ts.map +1 -0
- package/dist/auto-type-generator/typename-extractor.js +142 -0
- package/dist/auto-type-generator/typename-extractor.js.map +1 -0
- package/dist/auto-type-generator/typename-resolve-type-generator.d.ts +35 -0
- package/dist/auto-type-generator/typename-resolve-type-generator.d.ts.map +1 -0
- package/dist/auto-type-generator/typename-resolve-type-generator.js +177 -0
- package/dist/auto-type-generator/typename-resolve-type-generator.js.map +1 -0
- package/dist/auto-type-generator/typename-types.d.ts +43 -0
- package/dist/auto-type-generator/typename-types.d.ts.map +1 -0
- package/dist/auto-type-generator/typename-types.js +37 -0
- package/dist/auto-type-generator/typename-types.js.map +1 -0
- package/dist/auto-type-generator/typename-validator.d.ts +37 -0
- package/dist/auto-type-generator/typename-validator.d.ts.map +1 -0
- package/dist/auto-type-generator/typename-validator.js +206 -0
- package/dist/auto-type-generator/typename-validator.js.map +1 -0
- package/dist/cli.js +2 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/docs.d.ts +51 -0
- package/dist/commands/docs.d.ts.map +1 -0
- package/dist/commands/docs.js +154 -0
- package/dist/commands/docs.js.map +1 -0
- package/dist/gen-orchestrator/orchestrator.d.ts.map +1 -1
- package/dist/gen-orchestrator/orchestrator.js +13 -6
- package/dist/gen-orchestrator/orchestrator.js.map +1 -1
- package/dist/resolver-extractor/extract-resolvers.d.ts +19 -1
- package/dist/resolver-extractor/extract-resolvers.d.ts.map +1 -1
- package/dist/resolver-extractor/extractor/define-api-extractor.d.ts +5 -0
- package/dist/resolver-extractor/extractor/define-api-extractor.d.ts.map +1 -1
- package/dist/resolver-extractor/extractor/define-api-extractor.js +14 -61
- package/dist/resolver-extractor/extractor/define-api-extractor.js.map +1 -1
- package/dist/resolver-extractor/index.d.ts +0 -1
- package/dist/resolver-extractor/index.d.ts.map +1 -1
- package/dist/resolver-extractor/validator/abstract-resolver-validator.d.ts +1 -0
- package/dist/resolver-extractor/validator/abstract-resolver-validator.d.ts.map +1 -1
- package/dist/resolver-extractor/validator/abstract-resolver-validator.js +9 -5
- package/dist/resolver-extractor/validator/abstract-resolver-validator.js.map +1 -1
- package/dist/schema-generator/emitter/code-emitter.d.ts.map +1 -1
- package/dist/schema-generator/emitter/code-emitter.js +20 -0
- package/dist/schema-generator/emitter/code-emitter.js.map +1 -1
- package/dist/schema-generator/generate-schema.d.ts +1 -0
- package/dist/schema-generator/generate-schema.d.ts.map +1 -1
- package/dist/schema-generator/generate-schema.js +72 -3
- package/dist/schema-generator/generate-schema.js.map +1 -1
- package/dist/schema-generator/integrator/result-integrator.d.ts +14 -2
- package/dist/schema-generator/integrator/result-integrator.d.ts.map +1 -1
- package/dist/schema-generator/integrator/result-integrator.js +54 -1
- package/dist/schema-generator/integrator/result-integrator.js.map +1 -1
- package/dist/schema-generator/resolver-collector/resolver-collector.d.ts +2 -0
- package/dist/schema-generator/resolver-collector/resolver-collector.d.ts.map +1 -1
- package/dist/schema-generator/resolver-collector/resolver-collector.js +22 -0
- package/dist/schema-generator/resolver-collector/resolver-collector.js.map +1 -1
- package/dist/shared/enum-prefix-detector.d.ts +63 -0
- package/dist/shared/enum-prefix-detector.d.ts.map +1 -0
- package/dist/shared/enum-prefix-detector.js +80 -0
- package/dist/shared/enum-prefix-detector.js.map +1 -0
- package/dist/shared/ignore-fields-detector.d.ts +26 -0
- package/dist/shared/ignore-fields-detector.d.ts.map +1 -0
- package/dist/shared/ignore-fields-detector.js +83 -0
- package/dist/shared/ignore-fields-detector.js.map +1 -0
- package/dist/shared/ignore-fields-validator.d.ts +29 -0
- package/dist/shared/ignore-fields-validator.d.ts.map +1 -0
- package/dist/shared/ignore-fields-validator.js +43 -0
- package/dist/shared/ignore-fields-validator.js.map +1 -0
- package/dist/shared/index.d.ts +2 -0
- package/dist/shared/index.d.ts.map +1 -1
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/source-location.d.ts +5 -0
- package/dist/shared/source-location.d.ts.map +1 -1
- package/dist/shared/source-location.js +7 -0
- package/dist/shared/source-location.js.map +1 -1
- package/dist/type-extractor/converter/graphql-converter.d.ts.map +1 -1
- package/dist/type-extractor/converter/graphql-converter.js +21 -7
- package/dist/type-extractor/converter/graphql-converter.js.map +1 -1
- package/dist/type-extractor/extractor/field-type-resolver.js +42 -3
- package/dist/type-extractor/extractor/field-type-resolver.js.map +1 -1
- package/dist/type-extractor/extractor/type-extractor.d.ts.map +1 -1
- package/dist/type-extractor/extractor/type-extractor.js +88 -23
- package/dist/type-extractor/extractor/type-extractor.js.map +1 -1
- package/dist/type-extractor/types/diagnostics.d.ts +1 -1
- package/dist/type-extractor/types/diagnostics.d.ts.map +1 -1
- package/dist/type-extractor/types/ts-type-reference-factory.d.ts +10 -2
- package/dist/type-extractor/types/ts-type-reference-factory.d.ts.map +1 -1
- package/dist/type-extractor/types/ts-type-reference-factory.js +8 -2
- package/dist/type-extractor/types/ts-type-reference-factory.js.map +1 -1
- package/dist/type-extractor/types/typescript.d.ts +4 -0
- package/dist/type-extractor/types/typescript.d.ts.map +1 -1
- package/docs/coding-agents.md +64 -0
- package/docs/configuration.md +6 -20
- package/docs/getting-started.md +15 -12
- package/docs/index.md +36 -22
- package/docs/integration/apollo.md +8 -40
- package/docs/integration/drizzle.md +6 -10
- package/docs/integration/prisma.md +196 -0
- package/docs/integration/yoga.md +8 -40
- package/docs/schema/abstract-resolvers.md +117 -0
- package/docs/schema/directives.md +5 -0
- package/docs/schema/documentation.md +5 -0
- package/docs/schema/enums.md +99 -0
- package/docs/schema/fields.md +64 -0
- package/docs/schema/index.md +21 -0
- package/docs/schema/inputs.md +115 -15
- package/docs/schema/interfaces.md +31 -1
- package/docs/schema/objects.md +40 -0
- package/docs/schema/queries-mutations.md +136 -22
- package/docs/schema/scalars.md +5 -0
- package/docs/schema/unions.md +208 -1
- package/docs/what-is-gqlkit.md +13 -8
- package/package.json +6 -4
- package/src/auto-type-generator/auto-type-generator.ts +946 -201
- package/src/auto-type-generator/index.ts +42 -0
- package/src/auto-type-generator/inline-enum-collector.ts +187 -139
- package/src/auto-type-generator/inline-object-traverser.ts +49 -0
- package/src/auto-type-generator/inline-union-collector.ts +402 -0
- package/src/auto-type-generator/inline-union-types.ts +33 -0
- package/src/auto-type-generator/inline-union-validator.ts +482 -0
- package/src/auto-type-generator/naming-convention.ts +38 -1
- package/src/auto-type-generator/resolve-type-generator.ts +21 -0
- package/src/auto-type-generator/resolver-field-iterator.ts +39 -0
- package/src/auto-type-generator/typename-extractor.ts +230 -0
- package/src/auto-type-generator/typename-resolve-type-generator.ts +281 -0
- package/src/auto-type-generator/typename-types.ts +66 -0
- package/src/auto-type-generator/typename-validator.ts +326 -0
- package/src/cli.ts +2 -0
- package/src/commands/docs.ts +211 -0
- package/src/gen-orchestrator/orchestrator.ts +20 -6
- package/src/resolver-extractor/extract-resolvers.ts +19 -0
- package/src/resolver-extractor/extractor/define-api-extractor.ts +23 -89
- package/src/resolver-extractor/index.ts +0 -6
- package/src/resolver-extractor/validator/abstract-resolver-validator.ts +16 -8
- package/src/schema-generator/emitter/code-emitter.ts +34 -0
- package/src/schema-generator/generate-schema.ts +99 -2
- package/src/schema-generator/integrator/result-integrator.ts +70 -1
- package/src/schema-generator/resolver-collector/resolver-collector.ts +34 -0
- package/src/shared/enum-prefix-detector.ts +99 -0
- package/src/shared/ignore-fields-detector.ts +109 -0
- package/src/shared/ignore-fields-validator.ts +66 -0
- package/src/shared/index.ts +2 -0
- package/src/shared/source-location.ts +11 -0
- package/src/type-extractor/converter/graphql-converter.ts +31 -7
- package/src/type-extractor/extractor/field-type-resolver.ts +48 -3
- package/src/type-extractor/extractor/type-extractor.ts +103 -26
- package/src/type-extractor/types/diagnostics.ts +12 -2
- package/src/type-extractor/types/ts-type-reference-factory.ts +18 -5
- package/src/type-extractor/types/typescript.ts +4 -0
- package/dist/resolver-extractor/validator/only-validator.d.ts +0 -61
- package/dist/resolver-extractor/validator/only-validator.d.ts.map +0 -1
- package/dist/resolver-extractor/validator/only-validator.js +0 -76
- package/dist/resolver-extractor/validator/only-validator.js.map +0 -1
- package/src/resolver-extractor/validator/only-validator.ts +0 -158
|
@@ -1,10 +1,45 @@
|
|
|
1
|
+
import { detectEnumPrefix, stripEnumPrefix, } from "../shared/enum-prefix-detector.js";
|
|
2
|
+
import { getSourceLocationOrDefault } from "../shared/source-location.js";
|
|
1
3
|
import { convertTsTypeToGraphQLType } from "../shared/type-converter.js";
|
|
2
4
|
import { isEligibleAsInputObjectField, isEligibleAsObjectField, } from "../type-extractor/converter/field-eligibility.js";
|
|
3
5
|
import { createReferenceType, } from "../type-extractor/types/index.js";
|
|
4
|
-
import { collectInlineEnumsFromResolvers, collectInlineEnumsFromTypes, } from "./inline-enum-collector.js";
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
import { collectInlineEnumsFromPayloads, collectInlineEnumsFromResolvers, collectInlineEnumsFromTypes, } from "./inline-enum-collector.js";
|
|
7
|
+
import { collectInlineUnionsFromPayloads, collectInlineUnionsFromResolvers, collectInlineUnionsFromTypes, } from "./inline-union-collector.js";
|
|
8
|
+
import { validateOneOfMembers, validateUnionMembers, validateUnionMemberTypenames, } from "./inline-union-validator.js";
|
|
9
|
+
import { buildFieldContext, generateAutoTypeName, isInputTypeName, } from "./naming-convention.js";
|
|
10
|
+
import { forEachResolverField } from "./resolver-field-iterator.js";
|
|
11
|
+
import { createFieldNameSet, findTypenameProperty, } from "./typename-types.js";
|
|
12
|
+
function extractNestedInlineObjectsRecursively(params) {
|
|
13
|
+
const { properties, currentPath, sourceLocation, buildContext, preserveDocumentation, results, } = params;
|
|
14
|
+
for (const prop of properties) {
|
|
15
|
+
if (prop.tsType.kind === "inlineObject" &&
|
|
16
|
+
prop.tsType.inlineObjectProperties) {
|
|
17
|
+
const nestedPath = [...currentPath, prop.name];
|
|
18
|
+
const nestedContext = buildContext(nestedPath);
|
|
19
|
+
// Use property's source location if available for more accurate diagnostics
|
|
20
|
+
const nestedSourceLocation = prop.sourceLocation ?? sourceLocation;
|
|
21
|
+
results.push({
|
|
22
|
+
properties: prop.tsType.inlineObjectProperties,
|
|
23
|
+
context: nestedContext,
|
|
24
|
+
sourceLocation: nestedSourceLocation,
|
|
25
|
+
nullable: prop.tsType.nullable,
|
|
26
|
+
description: preserveDocumentation
|
|
27
|
+
? prop.tsType.inlineObjectDescription
|
|
28
|
+
: null,
|
|
29
|
+
deprecated: preserveDocumentation
|
|
30
|
+
? prop.tsType.inlineObjectDeprecated
|
|
31
|
+
: null,
|
|
32
|
+
});
|
|
33
|
+
extractNestedInlineObjectsRecursively({
|
|
34
|
+
properties: prop.tsType.inlineObjectProperties,
|
|
35
|
+
currentPath: nestedPath,
|
|
36
|
+
sourceLocation: nestedSourceLocation,
|
|
37
|
+
buildContext,
|
|
38
|
+
preserveDocumentation,
|
|
39
|
+
results,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
8
43
|
}
|
|
9
44
|
function getContextKey(context) {
|
|
10
45
|
switch (context.kind) {
|
|
@@ -14,6 +49,8 @@ function getContextKey(context) {
|
|
|
14
49
|
return `inputField:${context.parentTypeName}:${context.fieldPath.join(".")}`;
|
|
15
50
|
case "resolverArg":
|
|
16
51
|
return `resolverArg:${context.resolverType}:${context.parentTypeName ?? ""}:${context.fieldName}:${context.argName}:${context.fieldPath.join(".")}`;
|
|
52
|
+
case "resolverPayload":
|
|
53
|
+
return `resolverPayload:${context.resolverType}:${context.parentTypeName ?? ""}:${context.fieldName}:${context.fieldPath.join(".")}`;
|
|
17
54
|
}
|
|
18
55
|
}
|
|
19
56
|
function mapContextKindToGeneratedFromContext(kind) {
|
|
@@ -24,6 +61,8 @@ function mapContextKindToGeneratedFromContext(kind) {
|
|
|
24
61
|
return "inputField";
|
|
25
62
|
case "resolverArg":
|
|
26
63
|
return "resolverArg";
|
|
64
|
+
case "resolverPayload":
|
|
65
|
+
return "resolverPayload";
|
|
27
66
|
}
|
|
28
67
|
}
|
|
29
68
|
function buildGeneratedFromInfo(context) {
|
|
@@ -61,78 +100,31 @@ function collectInlineObjectsFromField(field, parentTypeName, parentPath, isInpu
|
|
|
61
100
|
parentTypeName,
|
|
62
101
|
fieldPath,
|
|
63
102
|
};
|
|
103
|
+
const sourceLocation = getSourceLocationOrDefault(field.sourceLocation, sourceFile);
|
|
64
104
|
results.push({
|
|
65
105
|
properties: tsType.inlineObjectProperties,
|
|
66
106
|
context,
|
|
67
|
-
sourceLocation
|
|
68
|
-
file: sourceFile,
|
|
69
|
-
line: 1,
|
|
70
|
-
column: 1,
|
|
71
|
-
},
|
|
107
|
+
sourceLocation,
|
|
72
108
|
nullable: tsType.nullable,
|
|
109
|
+
description: tsType.inlineObjectDescription,
|
|
110
|
+
deprecated: tsType.inlineObjectDeprecated,
|
|
73
111
|
});
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
: {
|
|
85
|
-
kind: "objectField",
|
|
86
|
-
parentTypeName,
|
|
87
|
-
fieldPath: nestedPath,
|
|
88
|
-
};
|
|
89
|
-
extractNestedInlineObjects(prop.tsType.inlineObjectProperties, nestedContext, nestedPath, parentTypeName, isInput, sourceFile, prop.sourceLocation, results);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
function extractNestedInlineObjects(properties, context, currentPath, parentTypeName, isInput, sourceFile, parentSourceLocation, results) {
|
|
94
|
-
results.push({
|
|
95
|
-
properties,
|
|
96
|
-
context,
|
|
97
|
-
sourceLocation: parentSourceLocation ?? {
|
|
98
|
-
file: sourceFile,
|
|
99
|
-
line: 1,
|
|
100
|
-
column: 1,
|
|
101
|
-
},
|
|
102
|
-
nullable: false,
|
|
112
|
+
extractNestedInlineObjectsRecursively({
|
|
113
|
+
properties: tsType.inlineObjectProperties,
|
|
114
|
+
currentPath: fieldPath,
|
|
115
|
+
sourceLocation,
|
|
116
|
+
buildContext: (nestedPath) => isInput
|
|
117
|
+
? { kind: "inputField", parentTypeName, fieldPath: nestedPath }
|
|
118
|
+
: { kind: "objectField", parentTypeName, fieldPath: nestedPath },
|
|
119
|
+
preserveDocumentation: true,
|
|
120
|
+
results,
|
|
103
121
|
});
|
|
104
|
-
for (const prop of properties) {
|
|
105
|
-
if (prop.tsType.kind === "inlineObject" &&
|
|
106
|
-
prop.tsType.inlineObjectProperties) {
|
|
107
|
-
const nestedPath = [...currentPath, prop.name];
|
|
108
|
-
const nestedContext = isInput
|
|
109
|
-
? {
|
|
110
|
-
kind: "inputField",
|
|
111
|
-
parentTypeName,
|
|
112
|
-
fieldPath: nestedPath,
|
|
113
|
-
}
|
|
114
|
-
: {
|
|
115
|
-
kind: "objectField",
|
|
116
|
-
parentTypeName,
|
|
117
|
-
fieldPath: nestedPath,
|
|
118
|
-
};
|
|
119
|
-
extractNestedInlineObjects(prop.tsType.inlineObjectProperties, nestedContext, nestedPath, parentTypeName, isInput, sourceFile, prop.sourceLocation, results);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
122
|
}
|
|
123
123
|
function collectInlineObjectsFromResolvers(resolversResult) {
|
|
124
124
|
const results = [];
|
|
125
|
-
|
|
126
|
-
collectInlineObjectsFromResolverArgs(field,
|
|
127
|
-
}
|
|
128
|
-
for (const field of resolversResult.mutationFields.fields) {
|
|
129
|
-
collectInlineObjectsFromResolverArgs(field, "mutation", null, results);
|
|
130
|
-
}
|
|
131
|
-
for (const ext of resolversResult.typeExtensions) {
|
|
132
|
-
for (const field of ext.fields) {
|
|
133
|
-
collectInlineObjectsFromResolverArgs(field, "field", ext.targetTypeName, results);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
125
|
+
forEachResolverField(resolversResult, ({ field, resolverType, parentTypeName }) => {
|
|
126
|
+
collectInlineObjectsFromResolverArgs(field, resolverType, parentTypeName, results);
|
|
127
|
+
});
|
|
136
128
|
return results;
|
|
137
129
|
}
|
|
138
130
|
function collectInlineObjectsFromResolverArgs(field, resolverType, parentTypeName, results) {
|
|
@@ -154,35 +146,68 @@ function collectInlineObjectsFromResolverArgs(field, resolverType, parentTypeNam
|
|
|
154
146
|
context,
|
|
155
147
|
sourceLocation: field.sourceLocation,
|
|
156
148
|
nullable: arg.type.nullable,
|
|
149
|
+
description: null,
|
|
150
|
+
deprecated: null,
|
|
157
151
|
});
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
if (prop.tsType.kind === "inlineObject" &&
|
|
164
|
-
prop.tsType.inlineObjectProperties) {
|
|
165
|
-
const nestedPath = [...currentPath, prop.name];
|
|
166
|
-
const nestedContext = {
|
|
152
|
+
extractNestedInlineObjectsRecursively({
|
|
153
|
+
properties: arg.inlineObjectProperties,
|
|
154
|
+
currentPath: [],
|
|
155
|
+
sourceLocation: field.sourceLocation,
|
|
156
|
+
buildContext: (nestedPath) => ({
|
|
167
157
|
kind: "resolverArg",
|
|
168
158
|
resolverType,
|
|
169
|
-
fieldName,
|
|
170
|
-
argName,
|
|
159
|
+
fieldName: field.name,
|
|
160
|
+
argName: arg.name,
|
|
171
161
|
parentTypeName,
|
|
172
162
|
fieldPath: nestedPath,
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
sourceLocation,
|
|
178
|
-
nullable: prop.tsType.nullable,
|
|
179
|
-
});
|
|
180
|
-
extractNestedInlineObjectsFromArg(prop.tsType.inlineObjectProperties, resolverType, fieldName, argName, parentTypeName, nestedPath, sourceLocation, results);
|
|
181
|
-
}
|
|
163
|
+
}),
|
|
164
|
+
preserveDocumentation: false,
|
|
165
|
+
results,
|
|
166
|
+
});
|
|
182
167
|
}
|
|
183
168
|
}
|
|
169
|
+
function collectInlinePayloadsFromResolvers(resolversResult) {
|
|
170
|
+
const results = [];
|
|
171
|
+
forEachResolverField(resolversResult, ({ field, resolverType, parentTypeName }) => {
|
|
172
|
+
collectInlinePayloadFromReturnType(field, resolverType, parentTypeName, results);
|
|
173
|
+
});
|
|
174
|
+
return results;
|
|
175
|
+
}
|
|
176
|
+
function collectInlinePayloadFromReturnType(field, resolverType, parentTypeName, results) {
|
|
177
|
+
if (!field.returnTypeInlineObjectProperties)
|
|
178
|
+
return;
|
|
179
|
+
const context = {
|
|
180
|
+
kind: "resolverPayload",
|
|
181
|
+
resolverType,
|
|
182
|
+
fieldName: field.name,
|
|
183
|
+
parentTypeName,
|
|
184
|
+
fieldPath: [],
|
|
185
|
+
};
|
|
186
|
+
results.push({
|
|
187
|
+
properties: field.returnTypeInlineObjectProperties,
|
|
188
|
+
context,
|
|
189
|
+
sourceLocation: field.sourceLocation,
|
|
190
|
+
nullable: field.type.nullable,
|
|
191
|
+
description: field.returnTypeInlineObjectDescription,
|
|
192
|
+
deprecated: field.returnTypeInlineObjectDeprecated,
|
|
193
|
+
});
|
|
194
|
+
extractNestedInlineObjectsRecursively({
|
|
195
|
+
properties: field.returnTypeInlineObjectProperties,
|
|
196
|
+
currentPath: [],
|
|
197
|
+
sourceLocation: field.sourceLocation,
|
|
198
|
+
buildContext: (nestedPath) => ({
|
|
199
|
+
kind: "resolverPayload",
|
|
200
|
+
resolverType,
|
|
201
|
+
fieldName: field.name,
|
|
202
|
+
parentTypeName,
|
|
203
|
+
fieldPath: nestedPath,
|
|
204
|
+
}),
|
|
205
|
+
preserveDocumentation: true,
|
|
206
|
+
results,
|
|
207
|
+
});
|
|
208
|
+
}
|
|
184
209
|
function generateAutoType(params) {
|
|
185
|
-
const { inlineObj, generatedTypeNames, enumTypeNames } = params;
|
|
210
|
+
const { inlineObj, generatedTypeNames, enumTypeNames, unionTypeNames } = params;
|
|
186
211
|
const name = generateAutoTypeName(inlineObj.context);
|
|
187
212
|
const isInput = inlineObj.context.kind === "inputField" ||
|
|
188
213
|
inlineObj.context.kind === "resolverArg";
|
|
@@ -205,6 +230,7 @@ function generateAutoType(params) {
|
|
|
205
230
|
prop,
|
|
206
231
|
generatedTypeNames,
|
|
207
232
|
enumTypeNames,
|
|
233
|
+
unionTypeNames,
|
|
208
234
|
parentContext: inlineObj.context,
|
|
209
235
|
});
|
|
210
236
|
fields.push({
|
|
@@ -222,50 +248,51 @@ function generateAutoType(params) {
|
|
|
222
248
|
kind: isInput ? "InputObject" : "Object",
|
|
223
249
|
fields,
|
|
224
250
|
enumValues: null,
|
|
251
|
+
unionMembers: null,
|
|
225
252
|
needsStringEnumMapping: false,
|
|
226
253
|
sourceLocation: inlineObj.sourceLocation,
|
|
227
254
|
generatedFrom: buildGeneratedFromInfo(inlineObj.context),
|
|
228
|
-
description:
|
|
255
|
+
description: inlineObj.description,
|
|
256
|
+
resolveTypeFieldPattern: null,
|
|
229
257
|
},
|
|
230
258
|
diagnostics,
|
|
231
259
|
};
|
|
232
260
|
}
|
|
261
|
+
function tryResolveNestedType(prop, parentContext, typeNamesMap) {
|
|
262
|
+
const nestedPath = [...parentContext.fieldPath, prop.name];
|
|
263
|
+
const nestedContext = {
|
|
264
|
+
...parentContext,
|
|
265
|
+
fieldPath: nestedPath,
|
|
266
|
+
};
|
|
267
|
+
const contextKey = getContextKey(nestedContext);
|
|
268
|
+
const resolvedTypeName = typeNamesMap.get(contextKey);
|
|
269
|
+
if (resolvedTypeName) {
|
|
270
|
+
return {
|
|
271
|
+
typeName: resolvedTypeName,
|
|
272
|
+
nullable: prop.tsType.nullable || prop.optional,
|
|
273
|
+
list: false,
|
|
274
|
+
listItemNullable: null,
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
233
279
|
function resolveFieldType(params) {
|
|
234
|
-
const { prop, generatedTypeNames, enumTypeNames, parentContext } = params;
|
|
280
|
+
const { prop, generatedTypeNames, enumTypeNames, unionTypeNames, parentContext, } = params;
|
|
235
281
|
if (prop.tsType.kind === "inlineObject" &&
|
|
236
282
|
prop.tsType.inlineObjectProperties) {
|
|
237
|
-
const
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
fieldPath: nestedPath,
|
|
241
|
-
};
|
|
242
|
-
const contextKey = getContextKey(nestedContext);
|
|
243
|
-
const resolvedTypeName = generatedTypeNames.get(contextKey);
|
|
244
|
-
if (resolvedTypeName) {
|
|
245
|
-
return {
|
|
246
|
-
typeName: resolvedTypeName,
|
|
247
|
-
nullable: prop.tsType.nullable || prop.optional,
|
|
248
|
-
list: false,
|
|
249
|
-
listItemNullable: null,
|
|
250
|
-
};
|
|
251
|
-
}
|
|
283
|
+
const result = tryResolveNestedType(prop, parentContext, generatedTypeNames);
|
|
284
|
+
if (result)
|
|
285
|
+
return result;
|
|
252
286
|
}
|
|
253
287
|
if (prop.tsType.kind === "inlineEnum" && prop.tsType.inlineEnumMembers) {
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
const
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
return {
|
|
263
|
-
typeName: resolvedTypeName,
|
|
264
|
-
nullable: prop.tsType.nullable || prop.optional,
|
|
265
|
-
list: false,
|
|
266
|
-
listItemNullable: null,
|
|
267
|
-
};
|
|
268
|
-
}
|
|
288
|
+
const result = tryResolveNestedType(prop, parentContext, enumTypeNames);
|
|
289
|
+
if (result)
|
|
290
|
+
return result;
|
|
291
|
+
}
|
|
292
|
+
if (prop.tsType.kind === "union" && prop.tsType.members) {
|
|
293
|
+
const result = tryResolveNestedType(prop, parentContext, unionTypeNames);
|
|
294
|
+
if (result)
|
|
295
|
+
return result;
|
|
269
296
|
}
|
|
270
297
|
return convertTsTypeToGraphQLType(prop.tsType, prop.optional);
|
|
271
298
|
}
|
|
@@ -279,7 +306,7 @@ function updateExtractedTypes(extractedTypes, params) {
|
|
|
279
306
|
});
|
|
280
307
|
}
|
|
281
308
|
function updateField(field, params, parentTypeName, isInput) {
|
|
282
|
-
const { generatedTypeNames, enumTypeNames } = params;
|
|
309
|
+
const { generatedTypeNames, enumTypeNames, unionTypeNames } = params;
|
|
283
310
|
const context = buildFieldContext(parentTypeName, [field.name], isInput);
|
|
284
311
|
const contextKey = getContextKey(context);
|
|
285
312
|
// Handle inline objects
|
|
@@ -327,6 +354,19 @@ function updateField(field, params, parentTypeName, isInput) {
|
|
|
327
354
|
};
|
|
328
355
|
}
|
|
329
356
|
}
|
|
357
|
+
// Handle inline union types
|
|
358
|
+
if (field.tsType.kind === "union" && field.tsType.members) {
|
|
359
|
+
const resolvedTypeName = unionTypeNames.get(contextKey);
|
|
360
|
+
if (resolvedTypeName) {
|
|
361
|
+
return {
|
|
362
|
+
...field,
|
|
363
|
+
tsType: createReferenceType({
|
|
364
|
+
name: resolvedTypeName,
|
|
365
|
+
nullable: field.tsType.nullable,
|
|
366
|
+
}),
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
}
|
|
330
370
|
return field;
|
|
331
371
|
}
|
|
332
372
|
function updateResolversResult(resolversResult, params) {
|
|
@@ -345,9 +385,51 @@ function updateResolversResult(resolversResult, params) {
|
|
|
345
385
|
};
|
|
346
386
|
}
|
|
347
387
|
function updateResolverField(field, params, resolverType, parentTypeName) {
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
388
|
+
const { generatedTypeNames, enumTypeNames, unionTypeNames } = params;
|
|
389
|
+
let updatedType = field.type;
|
|
390
|
+
// Create payload context once for all inline return type checks
|
|
391
|
+
const hasInlinePayload = field.returnTypeInlineObjectProperties ||
|
|
392
|
+
field.returnTypeInlineEnumMembers ||
|
|
393
|
+
field.returnTypeInlineUnionMembers;
|
|
394
|
+
if (hasInlinePayload) {
|
|
395
|
+
const payloadContext = {
|
|
396
|
+
kind: "resolverPayload",
|
|
397
|
+
resolverType,
|
|
398
|
+
fieldName: field.name,
|
|
399
|
+
parentTypeName,
|
|
400
|
+
fieldPath: [],
|
|
401
|
+
};
|
|
402
|
+
const payloadContextKey = getContextKey(payloadContext);
|
|
403
|
+
// These are mutually exclusive - a return type can only be one of:
|
|
404
|
+
// inline object, inline enum, or inline union
|
|
405
|
+
if (field.returnTypeInlineObjectProperties) {
|
|
406
|
+
// Handle inline payload objects in return type
|
|
407
|
+
const resolvedTypeName = generatedTypeNames.get(payloadContextKey);
|
|
408
|
+
if (resolvedTypeName) {
|
|
409
|
+
updatedType = { ...field.type, typeName: resolvedTypeName };
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
else if (field.returnTypeInlineEnumMembers) {
|
|
413
|
+
// Handle inline enum in return type
|
|
414
|
+
const resolvedTypeName = enumTypeNames.get(payloadContextKey);
|
|
415
|
+
if (resolvedTypeName) {
|
|
416
|
+
updatedType = { ...field.type, typeName: resolvedTypeName };
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
else if (field.returnTypeInlineUnionMembers) {
|
|
420
|
+
// Handle inline union in return type
|
|
421
|
+
const resolvedTypeName = unionTypeNames.get(payloadContextKey);
|
|
422
|
+
if (resolvedTypeName) {
|
|
423
|
+
updatedType = { ...field.type, typeName: resolvedTypeName };
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
if (!field.args) {
|
|
428
|
+
return {
|
|
429
|
+
...field,
|
|
430
|
+
type: updatedType,
|
|
431
|
+
};
|
|
432
|
+
}
|
|
351
433
|
const updatedArgs = field.args.map((arg) => {
|
|
352
434
|
const context = {
|
|
353
435
|
kind: "resolverArg",
|
|
@@ -384,10 +466,24 @@ function updateResolverField(field, params, resolverType, parentTypeName) {
|
|
|
384
466
|
};
|
|
385
467
|
}
|
|
386
468
|
}
|
|
469
|
+
// Handle inline unions (OneOf input objects)
|
|
470
|
+
if (arg.inlineUnionMembers) {
|
|
471
|
+
const resolvedTypeName = unionTypeNames.get(contextKey);
|
|
472
|
+
if (resolvedTypeName) {
|
|
473
|
+
return {
|
|
474
|
+
...arg,
|
|
475
|
+
type: {
|
|
476
|
+
...arg.type,
|
|
477
|
+
typeName: resolvedTypeName,
|
|
478
|
+
},
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
}
|
|
387
482
|
return arg;
|
|
388
483
|
});
|
|
389
484
|
return {
|
|
390
485
|
...field,
|
|
486
|
+
type: updatedType,
|
|
391
487
|
args: updatedArgs,
|
|
392
488
|
};
|
|
393
489
|
}
|
|
@@ -412,27 +508,40 @@ function convertInlineEnumMembers(params) {
|
|
|
412
508
|
let needsStringEnumMapping = false;
|
|
413
509
|
const enumValues = [];
|
|
414
510
|
const diagnostics = [];
|
|
415
|
-
const
|
|
511
|
+
const convertedMembers = [];
|
|
416
512
|
for (const member of members) {
|
|
417
513
|
const convertedName = toScreamingSnakeCase(member.value);
|
|
418
|
-
|
|
514
|
+
convertedMembers.push({ convertedName, member });
|
|
515
|
+
}
|
|
516
|
+
const prefixDetectionResult = detectEnumPrefix({
|
|
517
|
+
enumName,
|
|
518
|
+
memberValues: convertedMembers.map((m) => m.convertedName),
|
|
519
|
+
});
|
|
520
|
+
const finalNameToOriginals = new Map();
|
|
521
|
+
for (const { convertedName, member } of convertedMembers) {
|
|
522
|
+
let finalName = convertedName;
|
|
523
|
+
if (prefixDetectionResult.shouldStrip && prefixDetectionResult.prefix) {
|
|
524
|
+
finalName = stripEnumPrefix(convertedName, prefixDetectionResult.prefix);
|
|
525
|
+
needsStringEnumMapping = true;
|
|
526
|
+
}
|
|
527
|
+
else if (convertedName !== member.value) {
|
|
419
528
|
needsStringEnumMapping = true;
|
|
420
529
|
}
|
|
421
|
-
const originals =
|
|
530
|
+
const originals = finalNameToOriginals.get(finalName) ?? [];
|
|
422
531
|
originals.push(member.value);
|
|
423
|
-
|
|
532
|
+
finalNameToOriginals.set(finalName, originals);
|
|
424
533
|
enumValues.push({
|
|
425
|
-
name:
|
|
534
|
+
name: finalName,
|
|
426
535
|
originalValue: member.value,
|
|
427
536
|
description: member.description,
|
|
428
537
|
deprecated: member.deprecated,
|
|
429
538
|
});
|
|
430
539
|
}
|
|
431
|
-
for (const [
|
|
540
|
+
for (const [finalName, originals] of finalNameToOriginals) {
|
|
432
541
|
if (originals.length > 1) {
|
|
433
542
|
diagnostics.push({
|
|
434
543
|
code: "DUPLICATE_ENUM_VALUE_AFTER_CONVERSION",
|
|
435
|
-
message: `Enum '${enumName}' has duplicate value '${
|
|
544
|
+
message: `Enum '${enumName}' has duplicate value '${finalName}' after conversion (from '${originals.join("' and '")}')`,
|
|
436
545
|
severity: "error",
|
|
437
546
|
location: sourceLocation,
|
|
438
547
|
});
|
|
@@ -452,10 +561,12 @@ function generateAutoEnumType(inlineEnum, typeName) {
|
|
|
452
561
|
kind: "Enum",
|
|
453
562
|
fields: null,
|
|
454
563
|
enumValues,
|
|
564
|
+
unionMembers: null,
|
|
455
565
|
needsStringEnumMapping,
|
|
456
566
|
sourceLocation: inlineEnum.sourceLocation,
|
|
457
567
|
generatedFrom: buildGeneratedFromInfo(inlineEnum.context),
|
|
458
568
|
description: inlineEnum.externalEnumDescription,
|
|
569
|
+
resolveTypeFieldPattern: null,
|
|
459
570
|
},
|
|
460
571
|
diagnostics,
|
|
461
572
|
};
|
|
@@ -491,21 +602,404 @@ function buildEnumTypeNamesMap(inlineEnums) {
|
|
|
491
602
|
uniqueInlineEnums,
|
|
492
603
|
};
|
|
493
604
|
}
|
|
605
|
+
function buildUnionTypeNamesMap(inlineUnions) {
|
|
606
|
+
const unionTypeNames = new Map();
|
|
607
|
+
for (const inlineUnion of inlineUnions) {
|
|
608
|
+
const contextKey = getContextKey(inlineUnion.context);
|
|
609
|
+
const typeName = generateAutoTypeName(inlineUnion.context);
|
|
610
|
+
unionTypeNames.set(contextKey, typeName);
|
|
611
|
+
}
|
|
612
|
+
return unionTypeNames;
|
|
613
|
+
}
|
|
614
|
+
function processOneOfInputObjects(params) {
|
|
615
|
+
const { inlineUnions, knownTypeNames, typeMap, unionTypeNames } = params;
|
|
616
|
+
const types = [];
|
|
617
|
+
const diagnostics = [];
|
|
618
|
+
for (const inlineUnion of inlineUnions) {
|
|
619
|
+
const contextKey = getContextKey(inlineUnion.context);
|
|
620
|
+
const typeName = generateAutoTypeName(inlineUnion.context);
|
|
621
|
+
const validationResult = validateOneOfMembers({
|
|
622
|
+
members: inlineUnion.members,
|
|
623
|
+
typeName,
|
|
624
|
+
sourceLocation: inlineUnion.sourceLocation,
|
|
625
|
+
typeMap,
|
|
626
|
+
});
|
|
627
|
+
diagnostics.push(...validationResult.diagnostics);
|
|
628
|
+
if (!validationResult.valid) {
|
|
629
|
+
continue;
|
|
630
|
+
}
|
|
631
|
+
const fields = generateOneOfFields({
|
|
632
|
+
members: inlineUnion.members,
|
|
633
|
+
knownTypeNames,
|
|
634
|
+
});
|
|
635
|
+
types.push({
|
|
636
|
+
name: typeName,
|
|
637
|
+
kind: "OneOfInputObject",
|
|
638
|
+
fields,
|
|
639
|
+
enumValues: null,
|
|
640
|
+
unionMembers: null,
|
|
641
|
+
needsStringEnumMapping: false,
|
|
642
|
+
sourceLocation: inlineUnion.sourceLocation,
|
|
643
|
+
generatedFrom: buildGeneratedFromInfo(inlineUnion.context),
|
|
644
|
+
description: null,
|
|
645
|
+
resolveTypeFieldPattern: null,
|
|
646
|
+
});
|
|
647
|
+
unionTypeNames.set(contextKey, typeName);
|
|
648
|
+
}
|
|
649
|
+
return { types, diagnostics };
|
|
650
|
+
}
|
|
651
|
+
function processUnionTypes(params) {
|
|
652
|
+
const { inlineUnions, knownTypeNames, generatedTypeNames, enumTypeNames, unionTypeNames, typeMap, } = params;
|
|
653
|
+
const types = [];
|
|
654
|
+
const diagnostics = [];
|
|
655
|
+
const generatedTypenameTypes = new Map();
|
|
656
|
+
for (const inlineUnion of inlineUnions) {
|
|
657
|
+
const contextKey = getContextKey(inlineUnion.context);
|
|
658
|
+
const typeName = generateAutoTypeName(inlineUnion.context);
|
|
659
|
+
const validationResult = validateUnionMembers({
|
|
660
|
+
members: inlineUnion.members,
|
|
661
|
+
typeName,
|
|
662
|
+
sourceLocation: inlineUnion.sourceLocation,
|
|
663
|
+
typeMap,
|
|
664
|
+
});
|
|
665
|
+
diagnostics.push(...validationResult.diagnostics);
|
|
666
|
+
if (!validationResult.valid) {
|
|
667
|
+
continue;
|
|
668
|
+
}
|
|
669
|
+
let resolveTypeFieldPattern = null;
|
|
670
|
+
if (inlineUnion.context.kind === "resolverPayload") {
|
|
671
|
+
const typenameValidationResult = validateUnionMemberTypenames({
|
|
672
|
+
members: inlineUnion.members,
|
|
673
|
+
unionTypeName: typeName,
|
|
674
|
+
sourceLocation: inlineUnion.sourceLocation,
|
|
675
|
+
typeMap,
|
|
676
|
+
});
|
|
677
|
+
diagnostics.push(...typenameValidationResult.diagnostics);
|
|
678
|
+
if (!typenameValidationResult.valid) {
|
|
679
|
+
continue;
|
|
680
|
+
}
|
|
681
|
+
if (typenameValidationResult.allMembersHaveTypename) {
|
|
682
|
+
resolveTypeFieldPattern = determineFieldPattern(typenameValidationResult.memberTypenames);
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
const memberNames = resolveMemberNames({
|
|
686
|
+
members: inlineUnion.members,
|
|
687
|
+
knownTypeNames,
|
|
688
|
+
generatedTypeNames,
|
|
689
|
+
enumTypeNames,
|
|
690
|
+
parentContext: inlineUnion.context,
|
|
691
|
+
unionTypeNames,
|
|
692
|
+
types,
|
|
693
|
+
diagnostics,
|
|
694
|
+
generatedTypenameTypes,
|
|
695
|
+
sourceLocation: inlineUnion.sourceLocation,
|
|
696
|
+
});
|
|
697
|
+
types.push({
|
|
698
|
+
name: typeName,
|
|
699
|
+
kind: "Union",
|
|
700
|
+
fields: null,
|
|
701
|
+
enumValues: null,
|
|
702
|
+
unionMembers: memberNames,
|
|
703
|
+
needsStringEnumMapping: false,
|
|
704
|
+
sourceLocation: inlineUnion.sourceLocation,
|
|
705
|
+
generatedFrom: buildGeneratedFromInfo(inlineUnion.context),
|
|
706
|
+
description: null,
|
|
707
|
+
resolveTypeFieldPattern,
|
|
708
|
+
});
|
|
709
|
+
unionTypeNames.set(contextKey, typeName);
|
|
710
|
+
}
|
|
711
|
+
return { types, diagnostics };
|
|
712
|
+
}
|
|
713
|
+
/**
|
|
714
|
+
* Determine the field pattern for resolveType based on the typename fields used by members.
|
|
715
|
+
*/
|
|
716
|
+
function determineFieldPattern(memberTypenames) {
|
|
717
|
+
const fieldNames = new Set();
|
|
718
|
+
for (const info of memberTypenames.values()) {
|
|
719
|
+
fieldNames.add(info.fieldName);
|
|
720
|
+
}
|
|
721
|
+
if (fieldNames.size === 0) {
|
|
722
|
+
return { usedFieldNames: createFieldNameSet(["__typename"]) };
|
|
723
|
+
}
|
|
724
|
+
return { usedFieldNames: fieldNames };
|
|
725
|
+
}
|
|
726
|
+
function processInlineUnions(params) {
|
|
727
|
+
const { inlineUnions, knownTypeNames, generatedTypeNames, enumTypeNames, unionTypeNames, extractedTypes, } = params;
|
|
728
|
+
const typeMap = new Map();
|
|
729
|
+
for (const typeInfo of extractedTypes) {
|
|
730
|
+
typeMap.set(typeInfo.metadata.name, typeInfo);
|
|
731
|
+
}
|
|
732
|
+
const inputUnions = inlineUnions.filter((u) => u.isInputContext);
|
|
733
|
+
const outputUnions = inlineUnions.filter((u) => !u.isInputContext);
|
|
734
|
+
const oneOfResult = processOneOfInputObjects({
|
|
735
|
+
inlineUnions: inputUnions,
|
|
736
|
+
knownTypeNames,
|
|
737
|
+
typeMap,
|
|
738
|
+
unionTypeNames,
|
|
739
|
+
});
|
|
740
|
+
const unionResult = processUnionTypes({
|
|
741
|
+
inlineUnions: outputUnions,
|
|
742
|
+
knownTypeNames,
|
|
743
|
+
generatedTypeNames,
|
|
744
|
+
enumTypeNames,
|
|
745
|
+
unionTypeNames,
|
|
746
|
+
typeMap,
|
|
747
|
+
});
|
|
748
|
+
return {
|
|
749
|
+
types: [...oneOfResult.types, ...unionResult.types],
|
|
750
|
+
diagnostics: [...oneOfResult.diagnostics, ...unionResult.diagnostics],
|
|
751
|
+
};
|
|
752
|
+
}
|
|
753
|
+
function generateOneOfFields(params) {
|
|
754
|
+
const { members, knownTypeNames } = params;
|
|
755
|
+
const fields = [];
|
|
756
|
+
for (const member of members) {
|
|
757
|
+
const memberType = member.memberType;
|
|
758
|
+
if (memberType.kind === "inlineObject" &&
|
|
759
|
+
memberType.inlineObjectProperties) {
|
|
760
|
+
for (const prop of memberType.inlineObjectProperties) {
|
|
761
|
+
const fieldType = convertTsTypeToGraphQLType(prop.tsType, prop.optional);
|
|
762
|
+
fields.push({
|
|
763
|
+
name: prop.name,
|
|
764
|
+
type: {
|
|
765
|
+
...fieldType,
|
|
766
|
+
nullable: true,
|
|
767
|
+
},
|
|
768
|
+
description: prop.description,
|
|
769
|
+
deprecated: prop.deprecated,
|
|
770
|
+
directives: prop.directives,
|
|
771
|
+
defaultValue: prop.defaultValue,
|
|
772
|
+
});
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
else if (memberType.kind === "reference" && memberType.name) {
|
|
776
|
+
if (knownTypeNames.has(memberType.name)) {
|
|
777
|
+
const camelCaseName = memberType.name.charAt(0).toLowerCase() + memberType.name.slice(1);
|
|
778
|
+
fields.push({
|
|
779
|
+
name: camelCaseName,
|
|
780
|
+
type: {
|
|
781
|
+
typeName: memberType.name,
|
|
782
|
+
nullable: true,
|
|
783
|
+
list: false,
|
|
784
|
+
listItemNullable: null,
|
|
785
|
+
},
|
|
786
|
+
description: null,
|
|
787
|
+
deprecated: null,
|
|
788
|
+
directives: null,
|
|
789
|
+
defaultValue: null,
|
|
790
|
+
});
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
return fields;
|
|
795
|
+
}
|
|
796
|
+
/**
|
|
797
|
+
* Extract __typename or $typeName property value from inline object properties.
|
|
798
|
+
* Returns null if neither is found or neither is a valid string literal.
|
|
799
|
+
* __typename takes priority over $typeName if both are present.
|
|
800
|
+
*/
|
|
801
|
+
function extractTypenameFromInlineObject(properties) {
|
|
802
|
+
const found = findTypenameProperty(properties, (p) => p.name);
|
|
803
|
+
if (!found) {
|
|
804
|
+
return null;
|
|
805
|
+
}
|
|
806
|
+
const { property, fieldName } = found;
|
|
807
|
+
const { tsType } = property;
|
|
808
|
+
if (tsType.kind === "literal" && tsType.name !== null) {
|
|
809
|
+
return { typeName: tsType.name, fieldName };
|
|
810
|
+
}
|
|
811
|
+
return null;
|
|
812
|
+
}
|
|
813
|
+
function resolveMemberNames(params) {
|
|
814
|
+
const { members, generatedTypeNames, parentContext, types, generatedTypenameTypes, diagnostics, sourceLocation, } = params;
|
|
815
|
+
const memberNames = [];
|
|
816
|
+
for (let i = 0; i < members.length; i++) {
|
|
817
|
+
const member = members[i];
|
|
818
|
+
const memberType = member.memberType;
|
|
819
|
+
if (memberType.kind === "reference" && memberType.name) {
|
|
820
|
+
memberNames.push(memberType.name);
|
|
821
|
+
}
|
|
822
|
+
else if (memberType.kind === "inlineObject" &&
|
|
823
|
+
memberType.inlineObjectProperties) {
|
|
824
|
+
// Only extract __typename or $typeName for resolverPayload context
|
|
825
|
+
// For other contexts (resolverArg, objectField, inputField), these fields
|
|
826
|
+
// should be treated as regular fields, not as type discriminators
|
|
827
|
+
const extractedInfo = parentContext.kind === "resolverPayload"
|
|
828
|
+
? extractTypenameFromInlineObject(memberType.inlineObjectProperties)
|
|
829
|
+
: null;
|
|
830
|
+
let memberTypeName;
|
|
831
|
+
let contextKey;
|
|
832
|
+
if (extractedInfo !== null) {
|
|
833
|
+
memberTypeName = extractedInfo.typeName;
|
|
834
|
+
const nestedContext = {
|
|
835
|
+
...parentContext,
|
|
836
|
+
fieldPath: [...parentContext.fieldPath, extractedInfo.typeName],
|
|
837
|
+
};
|
|
838
|
+
contextKey = getContextKey(nestedContext);
|
|
839
|
+
}
|
|
840
|
+
else {
|
|
841
|
+
const nestedContext = {
|
|
842
|
+
...parentContext,
|
|
843
|
+
fieldPath: [...parentContext.fieldPath, `member${i}`],
|
|
844
|
+
};
|
|
845
|
+
memberTypeName = generateAutoTypeName(nestedContext);
|
|
846
|
+
contextKey = getContextKey(nestedContext);
|
|
847
|
+
}
|
|
848
|
+
// Only filter out __typename or $typeName for resolverPayload context
|
|
849
|
+
// For other contexts, these are regular fields that should be preserved
|
|
850
|
+
const typenameFieldToFilter = extractedInfo?.fieldName ?? null;
|
|
851
|
+
const fields = memberType.inlineObjectProperties
|
|
852
|
+
.filter((prop) => parentContext.kind !== "resolverPayload" ||
|
|
853
|
+
prop.name !== typenameFieldToFilter)
|
|
854
|
+
.map((prop) => {
|
|
855
|
+
const fieldType = convertTsTypeToGraphQLType(prop.tsType, prop.optional);
|
|
856
|
+
return {
|
|
857
|
+
name: prop.name,
|
|
858
|
+
type: fieldType,
|
|
859
|
+
description: prop.description,
|
|
860
|
+
deprecated: prop.deprecated,
|
|
861
|
+
directives: prop.directives,
|
|
862
|
+
defaultValue: prop.defaultValue,
|
|
863
|
+
};
|
|
864
|
+
});
|
|
865
|
+
// Check if this typename was already seen with a different field structure
|
|
866
|
+
if (extractedInfo !== null) {
|
|
867
|
+
const existingFields = generatedTypenameTypes.get(extractedInfo.typeName);
|
|
868
|
+
if (existingFields !== undefined) {
|
|
869
|
+
// Compare field structures
|
|
870
|
+
if (!areFieldStructuresEqual(existingFields, fields)) {
|
|
871
|
+
diagnostics.push({
|
|
872
|
+
code: "TYPENAME_FIELD_STRUCTURE_MISMATCH",
|
|
873
|
+
message: `Type with ${extractedInfo.fieldName} '${extractedInfo.typeName}' has inconsistent field structures across different union members. All types with the same ${extractedInfo.fieldName} must have identical field definitions.`,
|
|
874
|
+
severity: "error",
|
|
875
|
+
location: sourceLocation,
|
|
876
|
+
});
|
|
877
|
+
}
|
|
878
|
+
// Skip generating duplicate type and avoid adding duplicate union member
|
|
879
|
+
if (!memberNames.includes(memberTypeName)) {
|
|
880
|
+
memberNames.push(memberTypeName);
|
|
881
|
+
}
|
|
882
|
+
continue;
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
const nestedContext = {
|
|
886
|
+
...parentContext,
|
|
887
|
+
fieldPath: [
|
|
888
|
+
...parentContext.fieldPath,
|
|
889
|
+
extractedInfo?.typeName ?? `member${i}`,
|
|
890
|
+
],
|
|
891
|
+
};
|
|
892
|
+
types.push({
|
|
893
|
+
name: memberTypeName,
|
|
894
|
+
kind: "Object",
|
|
895
|
+
fields,
|
|
896
|
+
enumValues: null,
|
|
897
|
+
unionMembers: null,
|
|
898
|
+
needsStringEnumMapping: false,
|
|
899
|
+
sourceLocation: {
|
|
900
|
+
file: "",
|
|
901
|
+
line: 1,
|
|
902
|
+
column: 1,
|
|
903
|
+
},
|
|
904
|
+
generatedFrom: buildGeneratedFromInfo(nestedContext),
|
|
905
|
+
description: memberType.inlineObjectDescription,
|
|
906
|
+
resolveTypeFieldPattern: null,
|
|
907
|
+
});
|
|
908
|
+
generatedTypeNames.set(contextKey, memberTypeName);
|
|
909
|
+
if (extractedInfo !== null) {
|
|
910
|
+
generatedTypenameTypes.set(extractedInfo.typeName, fields);
|
|
911
|
+
}
|
|
912
|
+
memberNames.push(memberTypeName);
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
return memberNames;
|
|
916
|
+
}
|
|
917
|
+
/**
|
|
918
|
+
* Compare two field structures for equality.
|
|
919
|
+
* Returns true if both have the same fields with the same types.
|
|
920
|
+
*/
|
|
921
|
+
function areFieldStructuresEqual(fields1, fields2) {
|
|
922
|
+
if (fields1.length !== fields2.length) {
|
|
923
|
+
return false;
|
|
924
|
+
}
|
|
925
|
+
const sorted1 = [...fields1].sort((a, b) => a.name.localeCompare(b.name));
|
|
926
|
+
const sorted2 = [...fields2].sort((a, b) => a.name.localeCompare(b.name));
|
|
927
|
+
for (let i = 0; i < sorted1.length; i++) {
|
|
928
|
+
const f1 = sorted1[i];
|
|
929
|
+
const f2 = sorted2[i];
|
|
930
|
+
if (f1.name !== f2.name) {
|
|
931
|
+
return false;
|
|
932
|
+
}
|
|
933
|
+
if (!areGraphQLTypesEqual(f1.type, f2.type)) {
|
|
934
|
+
return false;
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
return true;
|
|
938
|
+
}
|
|
939
|
+
/**
|
|
940
|
+
* Compare two GraphQL type references for equality.
|
|
941
|
+
*/
|
|
942
|
+
function areGraphQLTypesEqual(type1, type2) {
|
|
943
|
+
if (type1.typeName !== type2.typeName) {
|
|
944
|
+
return false;
|
|
945
|
+
}
|
|
946
|
+
if (type1.nullable !== type2.nullable) {
|
|
947
|
+
return false;
|
|
948
|
+
}
|
|
949
|
+
if (type1.list !== type2.list) {
|
|
950
|
+
return false;
|
|
951
|
+
}
|
|
952
|
+
if (type1.listItemNullable !== type2.listItemNullable) {
|
|
953
|
+
return false;
|
|
954
|
+
}
|
|
955
|
+
return true;
|
|
956
|
+
}
|
|
494
957
|
export function generateAutoTypes(input) {
|
|
495
958
|
const inlineObjectsFromTypes = [];
|
|
496
959
|
for (const typeInfo of input.extractedTypes) {
|
|
497
960
|
inlineObjectsFromTypes.push(...collectInlineObjectsFromType(typeInfo));
|
|
498
961
|
}
|
|
499
962
|
const inlineObjectsFromResolvers = collectInlineObjectsFromResolvers(input.resolversResult);
|
|
963
|
+
const inlinePayloadsFromResolvers = collectInlinePayloadsFromResolvers(input.resolversResult);
|
|
500
964
|
const allInlineObjects = [
|
|
501
965
|
...inlineObjectsFromTypes,
|
|
502
966
|
...inlineObjectsFromResolvers,
|
|
967
|
+
...inlinePayloadsFromResolvers,
|
|
503
968
|
];
|
|
504
969
|
const generatedTypeNames = buildGeneratedTypeNamesMap(allInlineObjects);
|
|
505
970
|
const inlineEnumsFromTypes = collectInlineEnumsFromTypes(input.extractedTypes);
|
|
506
|
-
const inlineEnumsFromResolvers = collectInlineEnumsFromResolvers(
|
|
507
|
-
|
|
971
|
+
const inlineEnumsFromResolvers = collectInlineEnumsFromResolvers({
|
|
972
|
+
resolversResult: input.resolversResult,
|
|
973
|
+
});
|
|
974
|
+
const inlineEnumsFromPayloads = collectInlineEnumsFromPayloads({
|
|
975
|
+
resolversResult: input.resolversResult,
|
|
976
|
+
});
|
|
977
|
+
const allInlineEnums = [
|
|
978
|
+
...inlineEnumsFromTypes,
|
|
979
|
+
...inlineEnumsFromResolvers,
|
|
980
|
+
...inlineEnumsFromPayloads,
|
|
981
|
+
];
|
|
508
982
|
const { enumTypeNames, uniqueInlineEnums } = buildEnumTypeNamesMap(allInlineEnums);
|
|
983
|
+
// Collect inline unions from types, resolvers, and payloads
|
|
984
|
+
const inlineUnionsFromTypes = collectInlineUnionsFromTypes({
|
|
985
|
+
extractedTypes: input.extractedTypes,
|
|
986
|
+
knownTypeNames: input.knownTypeNames,
|
|
987
|
+
});
|
|
988
|
+
const inlineUnionsFromResolvers = collectInlineUnionsFromResolvers({
|
|
989
|
+
resolversResult: input.resolversResult,
|
|
990
|
+
knownTypeNames: input.knownTypeNames,
|
|
991
|
+
});
|
|
992
|
+
const inlineUnionsFromPayloads = collectInlineUnionsFromPayloads({
|
|
993
|
+
resolversResult: input.resolversResult,
|
|
994
|
+
knownTypeNames: input.knownTypeNames,
|
|
995
|
+
});
|
|
996
|
+
const allInlineUnions = [
|
|
997
|
+
...inlineUnionsFromTypes,
|
|
998
|
+
...inlineUnionsFromResolvers,
|
|
999
|
+
...inlineUnionsFromPayloads,
|
|
1000
|
+
];
|
|
1001
|
+
// Build union type names map before generating auto types
|
|
1002
|
+
const unionTypeNames = buildUnionTypeNamesMap(allInlineUnions);
|
|
509
1003
|
const autoGeneratedTypes = [];
|
|
510
1004
|
const diagnostics = [];
|
|
511
1005
|
for (const inlineObj of allInlineObjects) {
|
|
@@ -513,6 +1007,7 @@ export function generateAutoTypes(input) {
|
|
|
513
1007
|
inlineObj,
|
|
514
1008
|
generatedTypeNames,
|
|
515
1009
|
enumTypeNames,
|
|
1010
|
+
unionTypeNames,
|
|
516
1011
|
});
|
|
517
1012
|
autoGeneratedTypes.push(result.type);
|
|
518
1013
|
diagnostics.push(...result.diagnostics);
|
|
@@ -524,9 +1019,21 @@ export function generateAutoTypes(input) {
|
|
|
524
1019
|
autoGeneratedTypes.push(result.type);
|
|
525
1020
|
diagnostics.push(...result.diagnostics);
|
|
526
1021
|
}
|
|
1022
|
+
// Process inline unions
|
|
1023
|
+
const { types: unionTypes, diagnostics: unionDiagnostics } = processInlineUnions({
|
|
1024
|
+
inlineUnions: allInlineUnions,
|
|
1025
|
+
knownTypeNames: input.knownTypeNames,
|
|
1026
|
+
generatedTypeNames,
|
|
1027
|
+
enumTypeNames,
|
|
1028
|
+
unionTypeNames,
|
|
1029
|
+
extractedTypes: input.extractedTypes,
|
|
1030
|
+
});
|
|
1031
|
+
autoGeneratedTypes.push(...unionTypes);
|
|
1032
|
+
diagnostics.push(...unionDiagnostics);
|
|
527
1033
|
const updateParams = {
|
|
528
1034
|
generatedTypeNames,
|
|
529
1035
|
enumTypeNames,
|
|
1036
|
+
unionTypeNames,
|
|
530
1037
|
};
|
|
531
1038
|
const updatedExtractedTypes = updateExtractedTypes(input.extractedTypes, updateParams);
|
|
532
1039
|
const updatedResolversResult = updateResolversResult(input.resolversResult, updateParams);
|