@gqlkit-ts/cli 0.5.1 → 0.7.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 +7 -0
- package/dist/auto-type-generator/auto-type-generator.d.ts.map +1 -1
- package/dist/auto-type-generator/auto-type-generator.js +379 -56
- package/dist/auto-type-generator/auto-type-generator.js.map +1 -1
- package/dist/auto-type-generator/discriminator-field-validator.d.ts +26 -0
- package/dist/auto-type-generator/discriminator-field-validator.d.ts.map +1 -0
- package/dist/auto-type-generator/discriminator-field-validator.js +242 -0
- package/dist/auto-type-generator/discriminator-field-validator.js.map +1 -0
- package/dist/auto-type-generator/discriminator-naming.d.ts +11 -0
- package/dist/auto-type-generator/discriminator-naming.d.ts.map +1 -0
- package/dist/auto-type-generator/discriminator-naming.js +15 -0
- package/dist/auto-type-generator/discriminator-naming.js.map +1 -0
- package/dist/auto-type-generator/discriminator-resolve-type-generator.d.ts +44 -0
- package/dist/auto-type-generator/discriminator-resolve-type-generator.d.ts.map +1 -0
- package/dist/auto-type-generator/discriminator-resolve-type-generator.js +77 -0
- package/dist/auto-type-generator/discriminator-resolve-type-generator.js.map +1 -0
- package/dist/auto-type-generator/index.d.ts +3 -0
- 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.map +1 -1
- package/dist/auto-type-generator/inline-enum-collector.js +14 -7
- package/dist/auto-type-generator/inline-enum-collector.js.map +1 -1
- package/dist/auto-type-generator/inline-object-converter.d.ts +12 -0
- package/dist/auto-type-generator/inline-object-converter.d.ts.map +1 -0
- package/dist/auto-type-generator/inline-object-converter.js +72 -0
- package/dist/auto-type-generator/inline-object-converter.js.map +1 -0
- package/dist/auto-type-generator/inline-object-traverser.d.ts +2 -1
- package/dist/auto-type-generator/inline-object-traverser.d.ts.map +1 -1
- package/dist/auto-type-generator/inline-object-traverser.js +22 -4
- package/dist/auto-type-generator/inline-object-traverser.js.map +1 -1
- package/dist/auto-type-generator/inline-union-collector.d.ts.map +1 -1
- package/dist/auto-type-generator/inline-union-collector.js +20 -6
- package/dist/auto-type-generator/inline-union-collector.js.map +1 -1
- package/dist/auto-type-generator/inline-union-types.d.ts +2 -0
- package/dist/auto-type-generator/inline-union-types.d.ts.map +1 -1
- package/dist/auto-type-generator/inline-union-validator.js +3 -3
- package/dist/auto-type-generator/inline-union-validator.js.map +1 -1
- package/dist/auto-type-generator/intersection-flattener.d.ts +44 -0
- package/dist/auto-type-generator/intersection-flattener.d.ts.map +1 -0
- package/dist/auto-type-generator/intersection-flattener.js +398 -0
- package/dist/auto-type-generator/intersection-flattener.js.map +1 -0
- package/dist/auto-type-generator/naming-convention.d.ts +23 -2
- package/dist/auto-type-generator/naming-convention.d.ts.map +1 -1
- package/dist/auto-type-generator/naming-convention.js +145 -1
- package/dist/auto-type-generator/naming-convention.js.map +1 -1
- package/dist/auto-type-generator/resolver-field-iterator.d.ts +1 -1
- package/dist/auto-type-generator/resolver-field-iterator.d.ts.map +1 -1
- package/dist/auto-type-generator/resolver-field-iterator.js +3 -0
- package/dist/auto-type-generator/resolver-field-iterator.js.map +1 -1
- package/dist/auto-type-generator/typename-extractor.d.ts +2 -0
- package/dist/auto-type-generator/typename-extractor.d.ts.map +1 -1
- package/dist/auto-type-generator/typename-extractor.js +11 -3
- package/dist/auto-type-generator/typename-extractor.js.map +1 -1
- package/dist/auto-type-generator/typename-resolve-type-generator.d.ts +2 -0
- package/dist/auto-type-generator/typename-resolve-type-generator.d.ts.map +1 -1
- package/dist/auto-type-generator/typename-resolve-type-generator.js +12 -84
- package/dist/auto-type-generator/typename-resolve-type-generator.js.map +1 -1
- package/dist/auto-type-generator/typename-types.d.ts +4 -0
- package/dist/auto-type-generator/typename-types.d.ts.map +1 -1
- package/dist/auto-type-generator/typename-types.js +6 -0
- package/dist/auto-type-generator/typename-types.js.map +1 -1
- package/dist/auto-type-generator/typename-validator.d.ts.map +1 -1
- package/dist/auto-type-generator/typename-validator.js +4 -3
- package/dist/auto-type-generator/typename-validator.js.map +1 -1
- package/dist/commands/docs.d.ts +1 -0
- package/dist/commands/docs.d.ts.map +1 -1
- package/dist/commands/gen.d.ts +1 -0
- package/dist/commands/gen.d.ts.map +1 -1
- package/dist/commands/gen.js +2 -1
- package/dist/commands/gen.js.map +1 -1
- package/dist/commands/main.d.ts +1 -0
- package/dist/commands/main.d.ts.map +1 -1
- package/dist/config/types.d.ts +7 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config-loader/index.d.ts +1 -1
- package/dist/config-loader/index.d.ts.map +1 -1
- package/dist/config-loader/index.js.map +1 -1
- package/dist/config-loader/loader.d.ts +6 -0
- package/dist/config-loader/loader.d.ts.map +1 -1
- package/dist/config-loader/loader.js +1 -0
- package/dist/config-loader/loader.js.map +1 -1
- package/dist/config-loader/validator.d.ts.map +1 -1
- package/dist/config-loader/validator.js +84 -1
- package/dist/config-loader/validator.js.map +1 -1
- package/dist/gen-orchestrator/orchestrator.d.ts +2 -1
- package/dist/gen-orchestrator/orchestrator.d.ts.map +1 -1
- package/dist/gen-orchestrator/orchestrator.js +43 -3
- package/dist/gen-orchestrator/orchestrator.js.map +1 -1
- package/dist/resolver-extractor/extract-resolvers.d.ts +4 -0
- package/dist/resolver-extractor/extract-resolvers.d.ts.map +1 -1
- package/dist/resolver-extractor/extractor/define-api-extractor.d.ts +2 -1
- package/dist/resolver-extractor/extractor/define-api-extractor.d.ts.map +1 -1
- package/dist/resolver-extractor/extractor/define-api-extractor.js +35 -6
- package/dist/resolver-extractor/extractor/define-api-extractor.js.map +1 -1
- package/dist/resolver-extractor/index.d.ts +1 -1
- package/dist/resolver-extractor/index.d.ts.map +1 -1
- package/dist/resolver-extractor/validator/abstract-resolver-validator.d.ts +2 -0
- package/dist/resolver-extractor/validator/abstract-resolver-validator.d.ts.map +1 -1
- package/dist/resolver-extractor/validator/abstract-resolver-validator.js +16 -3
- 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 +24 -4
- package/dist/schema-generator/emitter/code-emitter.js.map +1 -1
- package/dist/schema-generator/emitter/discriminator-resolve-type-emitter.d.ts +18 -0
- package/dist/schema-generator/emitter/discriminator-resolve-type-emitter.d.ts.map +1 -0
- package/dist/schema-generator/emitter/discriminator-resolve-type-emitter.js +89 -0
- package/dist/schema-generator/emitter/discriminator-resolve-type-emitter.js.map +1 -0
- package/dist/schema-generator/generate-schema.d.ts +2 -0
- package/dist/schema-generator/generate-schema.d.ts.map +1 -1
- package/dist/schema-generator/generate-schema.js +69 -10
- package/dist/schema-generator/generate-schema.js.map +1 -1
- package/dist/schema-generator/integrator/result-integrator.d.ts +5 -0
- package/dist/schema-generator/integrator/result-integrator.d.ts.map +1 -1
- package/dist/schema-generator/integrator/result-integrator.js +44 -3
- 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 +4 -0
- package/dist/schema-generator/resolver-collector/resolver-collector.js.map +1 -1
- package/dist/shared/constants.d.ts.map +1 -1
- package/dist/shared/constants.js +14 -1
- package/dist/shared/constants.js.map +1 -1
- package/dist/shared/enum-prefix-detector.d.ts.map +1 -1
- package/dist/shared/enum-prefix-detector.js +78 -8
- package/dist/shared/enum-prefix-detector.js.map +1 -1
- package/dist/shared/inline-object-utils.js +1 -1
- package/dist/shared/inline-object-utils.js.map +1 -1
- package/dist/shared/type-converter.d.ts.map +1 -1
- package/dist/shared/type-converter.js +55 -0
- package/dist/shared/type-converter.js.map +1 -1
- package/dist/type-extractor/converter/graphql-converter.d.ts.map +1 -1
- package/dist/type-extractor/converter/graphql-converter.js +11 -1
- package/dist/type-extractor/converter/graphql-converter.js.map +1 -1
- package/dist/type-extractor/extractor/field-type-resolver.d.ts +18 -0
- package/dist/type-extractor/extractor/field-type-resolver.d.ts.map +1 -1
- package/dist/type-extractor/extractor/field-type-resolver.js +198 -15
- package/dist/type-extractor/extractor/field-type-resolver.js.map +1 -1
- package/dist/type-extractor/extractor/type-extractor.d.ts +1 -0
- package/dist/type-extractor/extractor/type-extractor.d.ts.map +1 -1
- package/dist/type-extractor/extractor/type-extractor.js +100 -9
- 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/index.d.ts +1 -1
- package/dist/type-extractor/types/index.d.ts.map +1 -1
- package/dist/type-extractor/types/index.js +1 -1
- package/dist/type-extractor/types/index.js.map +1 -1
- package/dist/type-extractor/types/ts-type-reference-factory.d.ts +7 -1
- package/dist/type-extractor/types/ts-type-reference-factory.d.ts.map +1 -1
- package/dist/type-extractor/types/ts-type-reference-factory.js +18 -3
- package/dist/type-extractor/types/ts-type-reference-factory.js.map +1 -1
- package/dist/type-extractor/types/typescript.d.ts +3 -1
- package/dist/type-extractor/types/typescript.d.ts.map +1 -1
- package/dist/type-extractor/validator/type-validator.d.ts.map +1 -1
- package/dist/type-extractor/validator/type-validator.js +6 -1
- package/dist/type-extractor/validator/type-validator.js.map +1 -1
- package/docs/configuration.md +19 -0
- package/docs/getting-started.md +2 -1
- package/docs/index.md +2 -0
- package/docs/integration/ai-sdk.md +189 -0
- package/docs/schema/conventions.md +7 -0
- package/docs/schema/fields.md +15 -0
- package/docs/schema/queries-mutations.md +21 -2
- package/docs/schema/subscriptions.md +173 -0
- package/docs/schema/unions.md +117 -0
- package/package.json +4 -4
- package/src/auto-type-generator/auto-type-generator.ts +588 -62
- package/src/auto-type-generator/discriminator-field-validator.ts +368 -0
- package/src/auto-type-generator/discriminator-naming.ts +24 -0
- package/src/auto-type-generator/discriminator-resolve-type-generator.ts +136 -0
- package/src/auto-type-generator/index.ts +17 -0
- package/src/auto-type-generator/inline-enum-collector.ts +19 -4
- package/src/auto-type-generator/inline-object-converter.ts +100 -0
- package/src/auto-type-generator/inline-object-traverser.ts +33 -7
- package/src/auto-type-generator/inline-union-collector.ts +26 -4
- package/src/auto-type-generator/inline-union-types.ts +2 -0
- package/src/auto-type-generator/inline-union-validator.ts +3 -3
- package/src/auto-type-generator/intersection-flattener.ts +554 -0
- package/src/auto-type-generator/naming-convention.ts +207 -3
- package/src/auto-type-generator/resolver-field-iterator.ts +5 -1
- package/src/auto-type-generator/typename-extractor.ts +17 -3
- package/src/auto-type-generator/typename-resolve-type-generator.ts +19 -108
- package/src/auto-type-generator/typename-types.ts +7 -0
- package/src/auto-type-generator/typename-validator.ts +4 -3
- package/src/commands/gen.ts +9 -2
- package/src/config/types.ts +10 -0
- package/src/config-loader/index.ts +1 -0
- package/src/config-loader/loader.ts +11 -0
- package/src/config-loader/validator.ts +100 -1
- package/src/gen-orchestrator/orchestrator.ts +50 -3
- package/src/resolver-extractor/extract-resolvers.ts +5 -0
- package/src/resolver-extractor/extractor/define-api-extractor.ts +47 -7
- package/src/resolver-extractor/index.ts +1 -0
- package/src/resolver-extractor/validator/abstract-resolver-validator.ts +20 -6
- package/src/schema-generator/emitter/code-emitter.ts +43 -5
- package/src/schema-generator/emitter/discriminator-resolve-type-emitter.ts +125 -0
- package/src/schema-generator/generate-schema.ts +100 -13
- package/src/schema-generator/integrator/result-integrator.ts +55 -2
- package/src/schema-generator/resolver-collector/resolver-collector.ts +7 -0
- package/src/shared/constants.ts +15 -1
- package/src/shared/enum-prefix-detector.ts +96 -8
- package/src/shared/inline-object-utils.ts +1 -1
- package/src/shared/type-converter.ts +63 -0
- package/src/type-extractor/converter/graphql-converter.ts +17 -1
- package/src/type-extractor/extractor/field-type-resolver.ts +241 -16
- package/src/type-extractor/extractor/type-extractor.ts +119 -5
- package/src/type-extractor/types/diagnostics.ts +10 -1
- package/src/type-extractor/types/index.ts +2 -1
- package/src/type-extractor/types/ts-type-reference-factory.ts +24 -3
- package/src/type-extractor/types/typescript.ts +6 -2
- package/src/type-extractor/validator/type-validator.ts +6 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type ts from "typescript";
|
|
2
|
+
import type { ResolvedDiscriminatorFieldsMap } from "../config-loader/index.js";
|
|
2
3
|
import type {
|
|
3
4
|
ExtractResolversResult,
|
|
4
5
|
GraphQLFieldDefinition,
|
|
@@ -25,6 +26,7 @@ import {
|
|
|
25
26
|
type InlineEnumMemberInfo,
|
|
26
27
|
type InlineObjectPropertyDef,
|
|
27
28
|
type SourceLocation,
|
|
29
|
+
type TSTypeReference,
|
|
28
30
|
} from "../type-extractor/types/index.js";
|
|
29
31
|
import {
|
|
30
32
|
collectInlineEnumsFromPayloads,
|
|
@@ -45,17 +47,26 @@ import {
|
|
|
45
47
|
validateUnionMembers,
|
|
46
48
|
validateUnionMemberTypenames,
|
|
47
49
|
} from "./inline-union-validator.js";
|
|
50
|
+
import {
|
|
51
|
+
flattenInlineUnionMembers,
|
|
52
|
+
type InlineDiscriminatorResolveType,
|
|
53
|
+
} from "./intersection-flattener.js";
|
|
48
54
|
import {
|
|
49
55
|
type AutoTypeNameContext,
|
|
56
|
+
appendFieldPath,
|
|
50
57
|
buildFieldContext,
|
|
51
58
|
generateAutoTypeName,
|
|
52
59
|
isInputTypeName,
|
|
53
60
|
} from "./naming-convention.js";
|
|
54
61
|
import type { ResolveTypeFieldPattern } from "./resolve-type-generator.js";
|
|
55
|
-
import {
|
|
62
|
+
import {
|
|
63
|
+
forEachResolverField,
|
|
64
|
+
type ResolverType,
|
|
65
|
+
} from "./resolver-field-iterator.js";
|
|
56
66
|
import {
|
|
57
67
|
createFieldNameSet,
|
|
58
68
|
findTypenameProperty,
|
|
69
|
+
isTypenameFieldName,
|
|
59
70
|
type TypenameFieldInfo,
|
|
60
71
|
type TypenameFieldName,
|
|
61
72
|
} from "./typename-types.js";
|
|
@@ -127,6 +138,7 @@ export interface AutoTypeGeneratorInput {
|
|
|
127
138
|
readonly extractedTypes: ReadonlyArray<ExtractedTypeInfo>;
|
|
128
139
|
readonly resolversResult: ExtractResolversResult;
|
|
129
140
|
readonly knownTypeNames: ReadonlySet<string>;
|
|
141
|
+
readonly discriminatorFields: ResolvedDiscriminatorFieldsMap;
|
|
130
142
|
}
|
|
131
143
|
|
|
132
144
|
export interface AutoTypeGeneratorResult {
|
|
@@ -134,6 +146,10 @@ export interface AutoTypeGeneratorResult {
|
|
|
134
146
|
readonly updatedExtractedTypes: ReadonlyArray<ExtractedTypeInfo>;
|
|
135
147
|
readonly updatedResolversResult: ExtractResolversResult;
|
|
136
148
|
readonly diagnostics: ReadonlyArray<Diagnostic>;
|
|
149
|
+
/** Mapping from TypeScript type alias names to auto-generated GraphQL union names */
|
|
150
|
+
readonly tsAliasToGraphQLNameMap: ReadonlyMap<string, string>;
|
|
151
|
+
/** Discriminator resolveType info for inline unions that were flattened by discriminator fields */
|
|
152
|
+
readonly inlineDiscriminatorResolveTypes: ReadonlyArray<InlineDiscriminatorResolveType>;
|
|
137
153
|
}
|
|
138
154
|
|
|
139
155
|
interface InlineObjectWithContext {
|
|
@@ -160,6 +176,41 @@ interface ExtractNestedInlineObjectsParams {
|
|
|
160
176
|
readonly results: InlineObjectWithContext[];
|
|
161
177
|
}
|
|
162
178
|
|
|
179
|
+
interface InlineObjectTypeInfo {
|
|
180
|
+
readonly properties: ReadonlyArray<InlineObjectPropertyDef>;
|
|
181
|
+
readonly nullable: boolean;
|
|
182
|
+
readonly description: string | null;
|
|
183
|
+
readonly deprecated: DeprecationInfo | null;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function getInlineObjectTypeInfo(
|
|
187
|
+
tsType: TSTypeReference,
|
|
188
|
+
): InlineObjectTypeInfo | null {
|
|
189
|
+
if (tsType.kind === "inlineObject" && tsType.inlineObjectProperties) {
|
|
190
|
+
return {
|
|
191
|
+
properties: tsType.inlineObjectProperties,
|
|
192
|
+
nullable: tsType.nullable,
|
|
193
|
+
description: tsType.inlineObjectDescription,
|
|
194
|
+
deprecated: tsType.inlineObjectDeprecated,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (
|
|
199
|
+
tsType.kind === "array" &&
|
|
200
|
+
tsType.elementType?.kind === "inlineObject" &&
|
|
201
|
+
tsType.elementType.inlineObjectProperties
|
|
202
|
+
) {
|
|
203
|
+
return {
|
|
204
|
+
properties: tsType.elementType.inlineObjectProperties,
|
|
205
|
+
nullable: tsType.elementType.nullable,
|
|
206
|
+
description: tsType.elementType.inlineObjectDescription,
|
|
207
|
+
deprecated: tsType.elementType.inlineObjectDeprecated,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return null;
|
|
212
|
+
}
|
|
213
|
+
|
|
163
214
|
function extractNestedInlineObjectsRecursively(
|
|
164
215
|
params: ExtractNestedInlineObjectsParams,
|
|
165
216
|
): void {
|
|
@@ -171,32 +222,37 @@ function extractNestedInlineObjectsRecursively(
|
|
|
171
222
|
preserveDocumentation,
|
|
172
223
|
results,
|
|
173
224
|
} = params;
|
|
225
|
+
const siblingFieldNames = new Set(properties.map((prop) => prop.name));
|
|
174
226
|
|
|
175
227
|
for (const prop of properties) {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
228
|
+
const inlineObjectTypeInfo = getInlineObjectTypeInfo(prop.tsType);
|
|
229
|
+
|
|
230
|
+
if (inlineObjectTypeInfo) {
|
|
231
|
+
const nestedPath = appendFieldPath({
|
|
232
|
+
parentPath: currentPath,
|
|
233
|
+
fieldName: prop.name,
|
|
234
|
+
singularize: prop.tsType.kind === "array",
|
|
235
|
+
siblingFieldNames,
|
|
236
|
+
});
|
|
181
237
|
const nestedContext = buildContext(nestedPath);
|
|
182
238
|
// Use property's source location if available for more accurate diagnostics
|
|
183
239
|
const nestedSourceLocation = prop.sourceLocation ?? sourceLocation;
|
|
184
240
|
|
|
185
241
|
results.push({
|
|
186
|
-
properties:
|
|
242
|
+
properties: inlineObjectTypeInfo.properties,
|
|
187
243
|
context: nestedContext,
|
|
188
244
|
sourceLocation: nestedSourceLocation,
|
|
189
|
-
nullable:
|
|
245
|
+
nullable: inlineObjectTypeInfo.nullable,
|
|
190
246
|
description: preserveDocumentation
|
|
191
|
-
?
|
|
247
|
+
? inlineObjectTypeInfo.description
|
|
192
248
|
: null,
|
|
193
249
|
deprecated: preserveDocumentation
|
|
194
|
-
?
|
|
250
|
+
? inlineObjectTypeInfo.deprecated
|
|
195
251
|
: null,
|
|
196
252
|
});
|
|
197
253
|
|
|
198
254
|
extractNestedInlineObjectsRecursively({
|
|
199
|
-
properties:
|
|
255
|
+
properties: inlineObjectTypeInfo.properties,
|
|
200
256
|
currentPath: nestedPath,
|
|
201
257
|
sourceLocation: nestedSourceLocation,
|
|
202
258
|
buildContext,
|
|
@@ -255,6 +311,7 @@ function collectInlineObjectsFromType(
|
|
|
255
311
|
): InlineObjectWithContext[] {
|
|
256
312
|
const results: InlineObjectWithContext[] = [];
|
|
257
313
|
const isInput = isInputTypeName(typeInfo.metadata.name);
|
|
314
|
+
const siblingFieldNames = new Set(typeInfo.fields.map((field) => field.name));
|
|
258
315
|
|
|
259
316
|
for (const field of typeInfo.fields) {
|
|
260
317
|
collectInlineObjectsFromField({
|
|
@@ -263,6 +320,7 @@ function collectInlineObjectsFromType(
|
|
|
263
320
|
parentPath: [],
|
|
264
321
|
isInput,
|
|
265
322
|
sourceFile: typeInfo.metadata.sourceFile,
|
|
323
|
+
siblingFieldNames,
|
|
266
324
|
results,
|
|
267
325
|
});
|
|
268
326
|
}
|
|
@@ -276,21 +334,34 @@ interface CollectInlineObjectsFromFieldParams {
|
|
|
276
334
|
readonly parentPath: ReadonlyArray<string>;
|
|
277
335
|
readonly isInput: boolean;
|
|
278
336
|
readonly sourceFile: string;
|
|
337
|
+
readonly siblingFieldNames: ReadonlySet<string>;
|
|
279
338
|
readonly results: InlineObjectWithContext[];
|
|
280
339
|
}
|
|
281
340
|
|
|
282
341
|
function collectInlineObjectsFromField(
|
|
283
342
|
params: CollectInlineObjectsFromFieldParams,
|
|
284
343
|
): void {
|
|
285
|
-
const {
|
|
286
|
-
|
|
287
|
-
|
|
344
|
+
const {
|
|
345
|
+
field,
|
|
346
|
+
parentTypeName,
|
|
347
|
+
parentPath,
|
|
348
|
+
isInput,
|
|
349
|
+
sourceFile,
|
|
350
|
+
siblingFieldNames,
|
|
351
|
+
results,
|
|
352
|
+
} = params;
|
|
353
|
+
const inlineObjectTypeInfo = getInlineObjectTypeInfo(field.tsType);
|
|
288
354
|
|
|
289
|
-
if (
|
|
355
|
+
if (!inlineObjectTypeInfo) {
|
|
290
356
|
return;
|
|
291
357
|
}
|
|
292
358
|
|
|
293
|
-
const fieldPath =
|
|
359
|
+
const fieldPath = appendFieldPath({
|
|
360
|
+
parentPath,
|
|
361
|
+
fieldName: field.name,
|
|
362
|
+
singularize: field.tsType.kind === "array",
|
|
363
|
+
siblingFieldNames,
|
|
364
|
+
});
|
|
294
365
|
|
|
295
366
|
const context: AutoTypeNameContext = isInput
|
|
296
367
|
? {
|
|
@@ -310,16 +381,16 @@ function collectInlineObjectsFromField(
|
|
|
310
381
|
);
|
|
311
382
|
|
|
312
383
|
results.push({
|
|
313
|
-
properties:
|
|
384
|
+
properties: inlineObjectTypeInfo.properties,
|
|
314
385
|
context,
|
|
315
386
|
sourceLocation,
|
|
316
|
-
nullable:
|
|
317
|
-
description:
|
|
318
|
-
deprecated:
|
|
387
|
+
nullable: inlineObjectTypeInfo.nullable,
|
|
388
|
+
description: inlineObjectTypeInfo.description,
|
|
389
|
+
deprecated: inlineObjectTypeInfo.deprecated,
|
|
319
390
|
});
|
|
320
391
|
|
|
321
392
|
extractNestedInlineObjectsRecursively({
|
|
322
|
-
properties:
|
|
393
|
+
properties: inlineObjectTypeInfo.properties,
|
|
323
394
|
currentPath: fieldPath,
|
|
324
395
|
sourceLocation,
|
|
325
396
|
buildContext: (nestedPath) =>
|
|
@@ -353,7 +424,7 @@ function collectInlineObjectsFromResolvers(
|
|
|
353
424
|
|
|
354
425
|
function collectInlineObjectsFromResolverArgs(
|
|
355
426
|
field: GraphQLFieldDefinition,
|
|
356
|
-
resolverType:
|
|
427
|
+
resolverType: ResolverType,
|
|
357
428
|
parentTypeName: string | null,
|
|
358
429
|
results: InlineObjectWithContext[],
|
|
359
430
|
): void {
|
|
@@ -420,7 +491,7 @@ function collectInlinePayloadsFromResolvers(
|
|
|
420
491
|
|
|
421
492
|
function collectInlinePayloadFromReturnType(
|
|
422
493
|
field: GraphQLFieldDefinition,
|
|
423
|
-
resolverType:
|
|
494
|
+
resolverType: ResolverType,
|
|
424
495
|
parentTypeName: string | null,
|
|
425
496
|
results: InlineObjectWithContext[],
|
|
426
497
|
): void {
|
|
@@ -483,8 +554,16 @@ function generateAutoType(
|
|
|
483
554
|
|
|
484
555
|
const fields: AutoGeneratedField[] = [];
|
|
485
556
|
const diagnostics: Diagnostic[] = [];
|
|
557
|
+
const siblingFieldNames = new Set(
|
|
558
|
+
inlineObj.properties.map((prop) => prop.name),
|
|
559
|
+
);
|
|
486
560
|
|
|
487
561
|
for (const prop of inlineObj.properties) {
|
|
562
|
+
// Typename discrimination fields are silently excluded from the schema
|
|
563
|
+
if (isTypenameFieldName(prop.name)) {
|
|
564
|
+
continue;
|
|
565
|
+
}
|
|
566
|
+
|
|
488
567
|
const eligibility = isEligibleField({
|
|
489
568
|
fieldName: prop.name,
|
|
490
569
|
kind: isInput ? "input" : "object",
|
|
@@ -506,7 +585,14 @@ function generateAutoType(
|
|
|
506
585
|
enumTypeNames,
|
|
507
586
|
unionTypeNames,
|
|
508
587
|
parentContext: inlineObj.context,
|
|
588
|
+
siblingFieldNames,
|
|
509
589
|
});
|
|
590
|
+
|
|
591
|
+
// Skip fields with never type — they represent impossible values
|
|
592
|
+
if (fieldType.typeName === "__NEVER__") {
|
|
593
|
+
continue;
|
|
594
|
+
}
|
|
595
|
+
|
|
510
596
|
fields.push({
|
|
511
597
|
name: prop.name,
|
|
512
598
|
type: fieldType,
|
|
@@ -540,14 +626,21 @@ interface ResolveFieldTypeParams {
|
|
|
540
626
|
readonly enumTypeNames: Map<string, string>;
|
|
541
627
|
readonly unionTypeNames: Map<string, string>;
|
|
542
628
|
readonly parentContext: AutoTypeNameContext;
|
|
629
|
+
readonly siblingFieldNames: ReadonlySet<string>;
|
|
543
630
|
}
|
|
544
631
|
|
|
545
632
|
function tryResolveNestedType(
|
|
546
633
|
prop: InlineObjectPropertyDef,
|
|
547
634
|
parentContext: AutoTypeNameContext,
|
|
548
635
|
typeNamesMap: ReadonlyMap<string, string>,
|
|
636
|
+
siblingFieldNames: ReadonlySet<string>,
|
|
549
637
|
): GraphQLFieldType | null {
|
|
550
|
-
const nestedPath =
|
|
638
|
+
const nestedPath = appendFieldPath({
|
|
639
|
+
parentPath: parentContext.fieldPath,
|
|
640
|
+
fieldName: prop.name,
|
|
641
|
+
singularize: prop.tsType.kind === "array",
|
|
642
|
+
siblingFieldNames,
|
|
643
|
+
});
|
|
551
644
|
const nestedContext: AutoTypeNameContext = {
|
|
552
645
|
...parentContext,
|
|
553
646
|
fieldPath: nestedPath,
|
|
@@ -557,10 +650,8 @@ function tryResolveNestedType(
|
|
|
557
650
|
|
|
558
651
|
if (resolvedTypeName) {
|
|
559
652
|
return {
|
|
653
|
+
...convertTsTypeToGraphQLType(prop.tsType, prop.optional),
|
|
560
654
|
typeName: resolvedTypeName,
|
|
561
|
-
nullable: prop.tsType.nullable || prop.optional,
|
|
562
|
-
list: false,
|
|
563
|
-
listItemNullable: null,
|
|
564
655
|
};
|
|
565
656
|
}
|
|
566
657
|
return null;
|
|
@@ -573,27 +664,52 @@ function resolveFieldType(params: ResolveFieldTypeParams): GraphQLFieldType {
|
|
|
573
664
|
enumTypeNames,
|
|
574
665
|
unionTypeNames,
|
|
575
666
|
parentContext,
|
|
667
|
+
siblingFieldNames,
|
|
576
668
|
} = params;
|
|
577
669
|
|
|
578
670
|
if (
|
|
579
|
-
prop.tsType.kind === "inlineObject" &&
|
|
580
|
-
|
|
671
|
+
(prop.tsType.kind === "inlineObject" &&
|
|
672
|
+
prop.tsType.inlineObjectProperties) ||
|
|
673
|
+
(prop.tsType.kind === "array" &&
|
|
674
|
+
prop.tsType.elementType?.kind === "inlineObject" &&
|
|
675
|
+
prop.tsType.elementType.inlineObjectProperties)
|
|
581
676
|
) {
|
|
582
677
|
const result = tryResolveNestedType(
|
|
583
678
|
prop,
|
|
584
679
|
parentContext,
|
|
585
680
|
generatedTypeNames,
|
|
681
|
+
siblingFieldNames,
|
|
586
682
|
);
|
|
587
683
|
if (result) return result;
|
|
588
684
|
}
|
|
589
685
|
|
|
590
|
-
if (
|
|
591
|
-
|
|
686
|
+
if (
|
|
687
|
+
(prop.tsType.kind === "inlineEnum" && prop.tsType.inlineEnumMembers) ||
|
|
688
|
+
(prop.tsType.kind === "array" &&
|
|
689
|
+
prop.tsType.elementType?.kind === "inlineEnum" &&
|
|
690
|
+
prop.tsType.elementType.inlineEnumMembers)
|
|
691
|
+
) {
|
|
692
|
+
const result = tryResolveNestedType(
|
|
693
|
+
prop,
|
|
694
|
+
parentContext,
|
|
695
|
+
enumTypeNames,
|
|
696
|
+
siblingFieldNames,
|
|
697
|
+
);
|
|
592
698
|
if (result) return result;
|
|
593
699
|
}
|
|
594
700
|
|
|
595
|
-
if (
|
|
596
|
-
|
|
701
|
+
if (
|
|
702
|
+
(prop.tsType.kind === "union" && prop.tsType.members) ||
|
|
703
|
+
(prop.tsType.kind === "array" &&
|
|
704
|
+
prop.tsType.elementType?.kind === "union" &&
|
|
705
|
+
prop.tsType.elementType.members)
|
|
706
|
+
) {
|
|
707
|
+
const result = tryResolveNestedType(
|
|
708
|
+
prop,
|
|
709
|
+
parentContext,
|
|
710
|
+
unionTypeNames,
|
|
711
|
+
siblingFieldNames,
|
|
712
|
+
);
|
|
597
713
|
if (result) return result;
|
|
598
714
|
}
|
|
599
715
|
|
|
@@ -612,10 +728,19 @@ function updateExtractedTypes(
|
|
|
612
728
|
): ExtractedTypeInfo[] {
|
|
613
729
|
return extractedTypes.map((typeInfo) => {
|
|
614
730
|
const isInput = isInputTypeName(typeInfo.metadata.name);
|
|
731
|
+
const siblingFieldNames = new Set(
|
|
732
|
+
typeInfo.fields.map((field) => field.name),
|
|
733
|
+
);
|
|
615
734
|
return {
|
|
616
735
|
...typeInfo,
|
|
617
736
|
fields: typeInfo.fields.map((field) =>
|
|
618
|
-
updateField(
|
|
737
|
+
updateField(
|
|
738
|
+
field,
|
|
739
|
+
params,
|
|
740
|
+
typeInfo.metadata.name,
|
|
741
|
+
isInput,
|
|
742
|
+
siblingFieldNames,
|
|
743
|
+
),
|
|
619
744
|
),
|
|
620
745
|
};
|
|
621
746
|
});
|
|
@@ -626,9 +751,19 @@ function updateField(
|
|
|
626
751
|
params: UpdateTypeNamesParams,
|
|
627
752
|
parentTypeName: string,
|
|
628
753
|
isInput: boolean,
|
|
754
|
+
siblingFieldNames: ReadonlySet<string>,
|
|
629
755
|
): FieldDefinition {
|
|
630
756
|
const { generatedTypeNames, enumTypeNames, unionTypeNames } = params;
|
|
631
|
-
const context = buildFieldContext(
|
|
757
|
+
const context = buildFieldContext(
|
|
758
|
+
parentTypeName,
|
|
759
|
+
appendFieldPath({
|
|
760
|
+
parentPath: [],
|
|
761
|
+
fieldName: field.name,
|
|
762
|
+
singularize: field.tsType.kind === "array",
|
|
763
|
+
siblingFieldNames,
|
|
764
|
+
}),
|
|
765
|
+
isInput,
|
|
766
|
+
);
|
|
632
767
|
const contextKey = getContextKey(context);
|
|
633
768
|
|
|
634
769
|
// Handle inline objects
|
|
@@ -648,6 +783,27 @@ function updateField(
|
|
|
648
783
|
}
|
|
649
784
|
}
|
|
650
785
|
|
|
786
|
+
// Handle array of inline objects
|
|
787
|
+
if (
|
|
788
|
+
field.tsType.kind === "array" &&
|
|
789
|
+
field.tsType.elementType?.kind === "inlineObject" &&
|
|
790
|
+
field.tsType.elementType.inlineObjectProperties
|
|
791
|
+
) {
|
|
792
|
+
const resolvedTypeName = generatedTypeNames.get(contextKey);
|
|
793
|
+
if (resolvedTypeName) {
|
|
794
|
+
return {
|
|
795
|
+
...field,
|
|
796
|
+
tsType: {
|
|
797
|
+
...field.tsType,
|
|
798
|
+
elementType: createReferenceType({
|
|
799
|
+
name: resolvedTypeName,
|
|
800
|
+
nullable: field.tsType.elementType.nullable,
|
|
801
|
+
}),
|
|
802
|
+
},
|
|
803
|
+
};
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
|
|
651
807
|
// Handle inline enums
|
|
652
808
|
if (field.tsType.kind === "inlineEnum" && field.tsType.inlineEnumMembers) {
|
|
653
809
|
const resolvedTypeName = enumTypeNames.get(contextKey);
|
|
@@ -697,6 +853,27 @@ function updateField(
|
|
|
697
853
|
}
|
|
698
854
|
}
|
|
699
855
|
|
|
856
|
+
// Handle array of inline union types
|
|
857
|
+
if (
|
|
858
|
+
field.tsType.kind === "array" &&
|
|
859
|
+
field.tsType.elementType?.kind === "union" &&
|
|
860
|
+
field.tsType.elementType.members
|
|
861
|
+
) {
|
|
862
|
+
const resolvedTypeName = unionTypeNames.get(contextKey);
|
|
863
|
+
if (resolvedTypeName) {
|
|
864
|
+
return {
|
|
865
|
+
...field,
|
|
866
|
+
tsType: {
|
|
867
|
+
...field.tsType,
|
|
868
|
+
elementType: createReferenceType({
|
|
869
|
+
name: resolvedTypeName,
|
|
870
|
+
nullable: field.tsType.elementType.nullable,
|
|
871
|
+
}),
|
|
872
|
+
},
|
|
873
|
+
};
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
|
|
700
877
|
return field;
|
|
701
878
|
}
|
|
702
879
|
|
|
@@ -716,6 +893,11 @@ function updateResolversResult(
|
|
|
716
893
|
updateResolverField(field, params, "mutation", null),
|
|
717
894
|
),
|
|
718
895
|
},
|
|
896
|
+
subscriptionFields: {
|
|
897
|
+
fields: resolversResult.subscriptionFields.fields.map((field) =>
|
|
898
|
+
updateResolverField(field, params, "subscription", null),
|
|
899
|
+
),
|
|
900
|
+
},
|
|
719
901
|
typeExtensions: resolversResult.typeExtensions.map((ext) => ({
|
|
720
902
|
...ext,
|
|
721
903
|
fields: ext.fields.map((field) =>
|
|
@@ -728,7 +910,7 @@ function updateResolversResult(
|
|
|
728
910
|
function updateResolverField(
|
|
729
911
|
field: GraphQLFieldDefinition,
|
|
730
912
|
params: UpdateTypeNamesParams,
|
|
731
|
-
resolverType: "query" | "mutation" | "field",
|
|
913
|
+
resolverType: "query" | "mutation" | "subscription" | "field",
|
|
732
914
|
parentTypeName: string | null,
|
|
733
915
|
): GraphQLFieldDefinition {
|
|
734
916
|
const { generatedTypeNames, enumTypeNames, unionTypeNames } = params;
|
|
@@ -1282,6 +1464,9 @@ function generateOneOfFields(
|
|
|
1282
1464
|
prop.tsType,
|
|
1283
1465
|
prop.optional,
|
|
1284
1466
|
);
|
|
1467
|
+
if (fieldType.typeName === "__NEVER__") {
|
|
1468
|
+
continue;
|
|
1469
|
+
}
|
|
1285
1470
|
fields.push({
|
|
1286
1471
|
name: prop.name,
|
|
1287
1472
|
type: {
|
|
@@ -1350,13 +1535,306 @@ function extractTypenameFromInlineObject(
|
|
|
1350
1535
|
const { property, fieldName } = found;
|
|
1351
1536
|
const { tsType } = property;
|
|
1352
1537
|
|
|
1353
|
-
if (tsType.kind === "
|
|
1538
|
+
if (tsType.kind === "stringLiteral" && tsType.name !== null) {
|
|
1354
1539
|
return { typeName: tsType.name, fieldName };
|
|
1355
1540
|
}
|
|
1356
1541
|
|
|
1357
1542
|
return null;
|
|
1358
1543
|
}
|
|
1359
1544
|
|
|
1545
|
+
/**
|
|
1546
|
+
* Shared parameters for resolving inline types within union member properties.
|
|
1547
|
+
*/
|
|
1548
|
+
interface MemberFieldResolutionContext {
|
|
1549
|
+
readonly types: AutoGeneratedType[];
|
|
1550
|
+
readonly generatedTypeNames: Map<string, string>;
|
|
1551
|
+
readonly diagnostics: Diagnostic[];
|
|
1552
|
+
readonly sourceLocation: SourceLocation;
|
|
1553
|
+
readonly knownTypeNames: ReadonlySet<string>;
|
|
1554
|
+
}
|
|
1555
|
+
|
|
1556
|
+
/**
|
|
1557
|
+
* Convert inline object/enum/union properties within a union member to AutoGeneratedFields.
|
|
1558
|
+
* Handles __INLINE_OBJECT__, __INLINE_ENUM__, and inline union (kind: "union") sentinels
|
|
1559
|
+
* by generating appropriate auto types and replacing sentinel type names.
|
|
1560
|
+
*/
|
|
1561
|
+
function convertMemberPropertiesToFields(
|
|
1562
|
+
properties: ReadonlyArray<InlineObjectPropertyDef>,
|
|
1563
|
+
parentTypeName: string,
|
|
1564
|
+
ctx: MemberFieldResolutionContext,
|
|
1565
|
+
): AutoGeneratedField[] {
|
|
1566
|
+
const siblingFieldNames = new Set(properties.map((prop) => prop.name));
|
|
1567
|
+
return properties.flatMap((prop) => {
|
|
1568
|
+
const fieldType = convertTsTypeToGraphQLType(prop.tsType, prop.optional);
|
|
1569
|
+
if (fieldType.typeName === "__NEVER__") {
|
|
1570
|
+
return [];
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1573
|
+
const resolvedTypeName = resolveInlineTypeInMember(
|
|
1574
|
+
prop,
|
|
1575
|
+
fieldType,
|
|
1576
|
+
parentTypeName,
|
|
1577
|
+
siblingFieldNames,
|
|
1578
|
+
ctx,
|
|
1579
|
+
);
|
|
1580
|
+
|
|
1581
|
+
return {
|
|
1582
|
+
name: prop.name,
|
|
1583
|
+
type: resolvedTypeName
|
|
1584
|
+
? { ...fieldType, typeName: resolvedTypeName }
|
|
1585
|
+
: fieldType,
|
|
1586
|
+
description: prop.description,
|
|
1587
|
+
deprecated: prop.deprecated,
|
|
1588
|
+
directives: prop.directives,
|
|
1589
|
+
defaultValue: prop.defaultValue,
|
|
1590
|
+
};
|
|
1591
|
+
});
|
|
1592
|
+
}
|
|
1593
|
+
|
|
1594
|
+
/**
|
|
1595
|
+
* Resolve an inline type (object, enum, or union) within a union member property.
|
|
1596
|
+
* Returns the generated type name if resolved, or null if no resolution is needed.
|
|
1597
|
+
*/
|
|
1598
|
+
function resolveInlineTypeInMember(
|
|
1599
|
+
prop: InlineObjectPropertyDef,
|
|
1600
|
+
fieldType: GraphQLFieldType,
|
|
1601
|
+
parentTypeName: string,
|
|
1602
|
+
siblingFieldNames: ReadonlySet<string>,
|
|
1603
|
+
ctx: MemberFieldResolutionContext,
|
|
1604
|
+
): string | null {
|
|
1605
|
+
// Determine the inline TS type (direct or array element)
|
|
1606
|
+
const inlineTsType =
|
|
1607
|
+
prop.tsType.kind === "array" ? prop.tsType.elementType : prop.tsType;
|
|
1608
|
+
const singularizeArrayFieldName = prop.tsType.kind === "array";
|
|
1609
|
+
if (!inlineTsType) return null;
|
|
1610
|
+
|
|
1611
|
+
// Resolve nested inline objects
|
|
1612
|
+
if (
|
|
1613
|
+
fieldType.typeName === "__INLINE_OBJECT__" &&
|
|
1614
|
+
inlineTsType.kind === "inlineObject" &&
|
|
1615
|
+
inlineTsType.inlineObjectProperties
|
|
1616
|
+
) {
|
|
1617
|
+
return resolveNestedInlineObjectInMember(
|
|
1618
|
+
inlineTsType.inlineObjectProperties,
|
|
1619
|
+
prop.name,
|
|
1620
|
+
singularizeArrayFieldName,
|
|
1621
|
+
parentTypeName,
|
|
1622
|
+
siblingFieldNames,
|
|
1623
|
+
ctx,
|
|
1624
|
+
inlineTsType.inlineObjectDescription,
|
|
1625
|
+
);
|
|
1626
|
+
}
|
|
1627
|
+
|
|
1628
|
+
// Resolve inline enums (string literal unions)
|
|
1629
|
+
if (
|
|
1630
|
+
fieldType.typeName === "__INLINE_ENUM__" &&
|
|
1631
|
+
inlineTsType.kind === "inlineEnum" &&
|
|
1632
|
+
inlineTsType.inlineEnumMembers
|
|
1633
|
+
) {
|
|
1634
|
+
return resolveInlineEnumInMember(
|
|
1635
|
+
inlineTsType.inlineEnumMembers,
|
|
1636
|
+
prop.name,
|
|
1637
|
+
singularizeArrayFieldName,
|
|
1638
|
+
parentTypeName,
|
|
1639
|
+
siblingFieldNames,
|
|
1640
|
+
ctx,
|
|
1641
|
+
inlineTsType.externalEnumDescription,
|
|
1642
|
+
);
|
|
1643
|
+
}
|
|
1644
|
+
|
|
1645
|
+
// Resolve inline unions (reference type unions like User | Bot)
|
|
1646
|
+
if (inlineTsType.kind === "union" && inlineTsType.members) {
|
|
1647
|
+
return resolveInlineUnionInMember(
|
|
1648
|
+
inlineTsType.members,
|
|
1649
|
+
prop.name,
|
|
1650
|
+
singularizeArrayFieldName,
|
|
1651
|
+
parentTypeName,
|
|
1652
|
+
siblingFieldNames,
|
|
1653
|
+
ctx,
|
|
1654
|
+
);
|
|
1655
|
+
}
|
|
1656
|
+
|
|
1657
|
+
return null;
|
|
1658
|
+
}
|
|
1659
|
+
|
|
1660
|
+
/**
|
|
1661
|
+
* Resolve a nested inline object within an inline union member.
|
|
1662
|
+
* Generates an AutoGeneratedType using objectField context and recurses
|
|
1663
|
+
* into deeper nesting levels.
|
|
1664
|
+
*/
|
|
1665
|
+
function resolveNestedInlineObjectInMember(
|
|
1666
|
+
properties: ReadonlyArray<InlineObjectPropertyDef>,
|
|
1667
|
+
fieldName: string,
|
|
1668
|
+
singularizeArrayFieldName: boolean,
|
|
1669
|
+
parentTypeName: string,
|
|
1670
|
+
siblingFieldNames: ReadonlySet<string>,
|
|
1671
|
+
ctx: MemberFieldResolutionContext,
|
|
1672
|
+
description: string | null,
|
|
1673
|
+
): string {
|
|
1674
|
+
const context: AutoTypeNameContext = {
|
|
1675
|
+
kind: "objectField",
|
|
1676
|
+
parentTypeName,
|
|
1677
|
+
fieldPath: appendFieldPath({
|
|
1678
|
+
parentPath: [],
|
|
1679
|
+
fieldName,
|
|
1680
|
+
singularize: singularizeArrayFieldName,
|
|
1681
|
+
siblingFieldNames,
|
|
1682
|
+
}),
|
|
1683
|
+
};
|
|
1684
|
+
const typeName = generateAutoTypeName(context);
|
|
1685
|
+
const contextKey = getContextKey(context);
|
|
1686
|
+
|
|
1687
|
+
if (ctx.generatedTypeNames.has(contextKey)) {
|
|
1688
|
+
return ctx.generatedTypeNames.get(contextKey)!;
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1691
|
+
const fields = convertMemberPropertiesToFields(properties, typeName, ctx);
|
|
1692
|
+
|
|
1693
|
+
ctx.types.push({
|
|
1694
|
+
name: typeName,
|
|
1695
|
+
kind: "Object",
|
|
1696
|
+
fields,
|
|
1697
|
+
enumValues: null,
|
|
1698
|
+
unionMembers: null,
|
|
1699
|
+
needsStringEnumMapping: false,
|
|
1700
|
+
sourceLocation: ctx.sourceLocation,
|
|
1701
|
+
generatedFrom: buildGeneratedFromInfo(context),
|
|
1702
|
+
description,
|
|
1703
|
+
resolveTypeFieldPattern: null,
|
|
1704
|
+
});
|
|
1705
|
+
|
|
1706
|
+
ctx.generatedTypeNames.set(contextKey, typeName);
|
|
1707
|
+
|
|
1708
|
+
return typeName;
|
|
1709
|
+
}
|
|
1710
|
+
|
|
1711
|
+
/**
|
|
1712
|
+
* Resolve an inline enum (string literal union) within an inline union member.
|
|
1713
|
+
*/
|
|
1714
|
+
function resolveInlineEnumInMember(
|
|
1715
|
+
members: ReadonlyArray<InlineEnumMemberInfo>,
|
|
1716
|
+
fieldName: string,
|
|
1717
|
+
singularizeArrayFieldName: boolean,
|
|
1718
|
+
parentTypeName: string,
|
|
1719
|
+
siblingFieldNames: ReadonlySet<string>,
|
|
1720
|
+
ctx: MemberFieldResolutionContext,
|
|
1721
|
+
description: string | null,
|
|
1722
|
+
): string {
|
|
1723
|
+
const context: AutoTypeNameContext = {
|
|
1724
|
+
kind: "objectField",
|
|
1725
|
+
parentTypeName,
|
|
1726
|
+
fieldPath: appendFieldPath({
|
|
1727
|
+
parentPath: [],
|
|
1728
|
+
fieldName,
|
|
1729
|
+
singularize: singularizeArrayFieldName,
|
|
1730
|
+
siblingFieldNames,
|
|
1731
|
+
}),
|
|
1732
|
+
};
|
|
1733
|
+
const typeName = generateAutoTypeName(context);
|
|
1734
|
+
const contextKey = getContextKey(context);
|
|
1735
|
+
|
|
1736
|
+
if (ctx.generatedTypeNames.has(contextKey)) {
|
|
1737
|
+
return ctx.generatedTypeNames.get(contextKey)!;
|
|
1738
|
+
}
|
|
1739
|
+
|
|
1740
|
+
const {
|
|
1741
|
+
enumValues,
|
|
1742
|
+
needsStringEnumMapping,
|
|
1743
|
+
diagnostics: enumDiagnostics,
|
|
1744
|
+
} = convertInlineEnumMembers({
|
|
1745
|
+
members,
|
|
1746
|
+
enumName: typeName,
|
|
1747
|
+
sourceLocation: ctx.sourceLocation,
|
|
1748
|
+
});
|
|
1749
|
+
|
|
1750
|
+
ctx.diagnostics.push(...enumDiagnostics);
|
|
1751
|
+
|
|
1752
|
+
ctx.types.push({
|
|
1753
|
+
name: typeName,
|
|
1754
|
+
kind: "Enum",
|
|
1755
|
+
fields: null,
|
|
1756
|
+
enumValues,
|
|
1757
|
+
unionMembers: null,
|
|
1758
|
+
needsStringEnumMapping,
|
|
1759
|
+
sourceLocation: ctx.sourceLocation,
|
|
1760
|
+
generatedFrom: buildGeneratedFromInfo(context),
|
|
1761
|
+
description,
|
|
1762
|
+
resolveTypeFieldPattern: null,
|
|
1763
|
+
});
|
|
1764
|
+
|
|
1765
|
+
ctx.generatedTypeNames.set(contextKey, typeName);
|
|
1766
|
+
|
|
1767
|
+
return typeName;
|
|
1768
|
+
}
|
|
1769
|
+
|
|
1770
|
+
/**
|
|
1771
|
+
* Resolve an inline union of reference types within an inline union member.
|
|
1772
|
+
*/
|
|
1773
|
+
function resolveInlineUnionInMember(
|
|
1774
|
+
members: ReadonlyArray<TSTypeReference>,
|
|
1775
|
+
fieldName: string,
|
|
1776
|
+
singularizeArrayFieldName: boolean,
|
|
1777
|
+
parentTypeName: string,
|
|
1778
|
+
siblingFieldNames: ReadonlySet<string>,
|
|
1779
|
+
ctx: MemberFieldResolutionContext,
|
|
1780
|
+
): string {
|
|
1781
|
+
const context: AutoTypeNameContext = {
|
|
1782
|
+
kind: "objectField",
|
|
1783
|
+
parentTypeName,
|
|
1784
|
+
fieldPath: appendFieldPath({
|
|
1785
|
+
parentPath: [],
|
|
1786
|
+
fieldName,
|
|
1787
|
+
singularize: singularizeArrayFieldName,
|
|
1788
|
+
siblingFieldNames,
|
|
1789
|
+
}),
|
|
1790
|
+
};
|
|
1791
|
+
const typeName = generateAutoTypeName(context);
|
|
1792
|
+
const contextKey = getContextKey(context);
|
|
1793
|
+
|
|
1794
|
+
if (ctx.generatedTypeNames.has(contextKey)) {
|
|
1795
|
+
return ctx.generatedTypeNames.get(contextKey)!;
|
|
1796
|
+
}
|
|
1797
|
+
|
|
1798
|
+
const memberNames: string[] = [];
|
|
1799
|
+
for (const member of members) {
|
|
1800
|
+
if (member.kind === "reference" && member.name) {
|
|
1801
|
+
if (ctx.knownTypeNames.has(member.name)) {
|
|
1802
|
+
memberNames.push(member.name);
|
|
1803
|
+
}
|
|
1804
|
+
}
|
|
1805
|
+
}
|
|
1806
|
+
|
|
1807
|
+
if (memberNames.length === 0) {
|
|
1808
|
+
const memberDescriptions = members
|
|
1809
|
+
.map((m) => m.name ?? "(anonymous)")
|
|
1810
|
+
.join(", ");
|
|
1811
|
+
ctx.diagnostics.push({
|
|
1812
|
+
code: "INLINE_UNION_UNRESOLVABLE_MEMBER",
|
|
1813
|
+
message: `Could not resolve any members of inline union '${typeName}' in '${parentTypeName}.${fieldName}'. None of the member types [${memberDescriptions}] are known schema types.`,
|
|
1814
|
+
severity: "error",
|
|
1815
|
+
location: ctx.sourceLocation,
|
|
1816
|
+
});
|
|
1817
|
+
return typeName;
|
|
1818
|
+
}
|
|
1819
|
+
|
|
1820
|
+
ctx.types.push({
|
|
1821
|
+
name: typeName,
|
|
1822
|
+
kind: "Union",
|
|
1823
|
+
fields: null,
|
|
1824
|
+
enumValues: null,
|
|
1825
|
+
unionMembers: memberNames,
|
|
1826
|
+
needsStringEnumMapping: false,
|
|
1827
|
+
sourceLocation: ctx.sourceLocation,
|
|
1828
|
+
generatedFrom: buildGeneratedFromInfo(context),
|
|
1829
|
+
description: null,
|
|
1830
|
+
resolveTypeFieldPattern: null,
|
|
1831
|
+
});
|
|
1832
|
+
|
|
1833
|
+
ctx.generatedTypeNames.set(contextKey, typeName);
|
|
1834
|
+
|
|
1835
|
+
return typeName;
|
|
1836
|
+
}
|
|
1837
|
+
|
|
1360
1838
|
function resolveMemberNames(params: ResolveMemberNamesParams): string[] {
|
|
1361
1839
|
const {
|
|
1362
1840
|
members,
|
|
@@ -1398,38 +1876,47 @@ function resolveMemberNames(params: ResolveMemberNamesParams): string[] {
|
|
|
1398
1876
|
fieldPath: [...parentContext.fieldPath, extractedInfo.typeName],
|
|
1399
1877
|
};
|
|
1400
1878
|
contextKey = getContextKey(nestedContext);
|
|
1401
|
-
} else {
|
|
1879
|
+
} else if (memberType.inlineObjectHintName !== null) {
|
|
1402
1880
|
const nestedContext: AutoTypeNameContext = {
|
|
1403
1881
|
...parentContext,
|
|
1404
|
-
fieldPath: [
|
|
1882
|
+
fieldPath: [
|
|
1883
|
+
...parentContext.fieldPath,
|
|
1884
|
+
memberType.inlineObjectHintName,
|
|
1885
|
+
],
|
|
1405
1886
|
};
|
|
1406
|
-
memberTypeName =
|
|
1887
|
+
memberTypeName = memberType.inlineObjectHintName;
|
|
1407
1888
|
contextKey = getContextKey(nestedContext);
|
|
1889
|
+
} else {
|
|
1890
|
+
diagnostics.push({
|
|
1891
|
+
code: "UNNAMEABLE_UNION_MEMBER",
|
|
1892
|
+
message: `Inline object union member at index ${i} cannot be named. Use a named type (type alias or interface) for each union member, or add a '__typename' property with a string literal type.`,
|
|
1893
|
+
severity: "error",
|
|
1894
|
+
location: sourceLocation,
|
|
1895
|
+
});
|
|
1896
|
+
continue;
|
|
1408
1897
|
}
|
|
1409
1898
|
|
|
1410
1899
|
// Only filter out __typename or $typeName for resolverPayload context
|
|
1411
1900
|
// For other contexts, these are regular fields that should be preserved
|
|
1412
1901
|
const typenameFieldToFilter = extractedInfo?.fieldName ?? null;
|
|
1413
|
-
const
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
};
|
|
1432
|
-
});
|
|
1902
|
+
const filteredProperties = memberType.inlineObjectProperties.filter(
|
|
1903
|
+
(prop) =>
|
|
1904
|
+
parentContext.kind !== "resolverPayload" ||
|
|
1905
|
+
prop.name !== typenameFieldToFilter,
|
|
1906
|
+
);
|
|
1907
|
+
|
|
1908
|
+
const fieldCtx: MemberFieldResolutionContext = {
|
|
1909
|
+
types,
|
|
1910
|
+
generatedTypeNames,
|
|
1911
|
+
diagnostics,
|
|
1912
|
+
sourceLocation,
|
|
1913
|
+
knownTypeNames: params.knownTypeNames,
|
|
1914
|
+
};
|
|
1915
|
+
const fields = convertMemberPropertiesToFields(
|
|
1916
|
+
filteredProperties,
|
|
1917
|
+
memberTypeName,
|
|
1918
|
+
fieldCtx,
|
|
1919
|
+
);
|
|
1433
1920
|
|
|
1434
1921
|
// Check if this typename was already seen with a different field structure
|
|
1435
1922
|
if (extractedInfo !== null) {
|
|
@@ -1458,7 +1945,7 @@ function resolveMemberNames(params: ResolveMemberNamesParams): string[] {
|
|
|
1458
1945
|
...parentContext,
|
|
1459
1946
|
fieldPath: [
|
|
1460
1947
|
...parentContext.fieldPath,
|
|
1461
|
-
extractedInfo?.typeName ??
|
|
1948
|
+
extractedInfo?.typeName ?? memberType.inlineObjectHintName!,
|
|
1462
1949
|
],
|
|
1463
1950
|
};
|
|
1464
1951
|
|
|
@@ -1598,12 +2085,21 @@ export function generateAutoTypes(
|
|
|
1598
2085
|
resolversResult: input.resolversResult,
|
|
1599
2086
|
knownTypeNames: input.knownTypeNames,
|
|
1600
2087
|
});
|
|
1601
|
-
const
|
|
2088
|
+
const allInlineUnionsRaw = [
|
|
1602
2089
|
...inlineUnionsFromTypes,
|
|
1603
2090
|
...inlineUnionsFromResolvers,
|
|
1604
2091
|
...inlineUnionsFromPayloads,
|
|
1605
2092
|
];
|
|
1606
2093
|
|
|
2094
|
+
// Apply discriminator-aware flattening to inline unions before processing.
|
|
2095
|
+
// This resolves the case where TypeScript distributes intersections over unions
|
|
2096
|
+
// within field types, creating many anonymous inline objects.
|
|
2097
|
+
const flattenResult = flattenInlineUnionMembers({
|
|
2098
|
+
inlineUnions: allInlineUnionsRaw,
|
|
2099
|
+
discriminatorFields: input.discriminatorFields,
|
|
2100
|
+
});
|
|
2101
|
+
const allInlineUnions = [...flattenResult.inlineUnions];
|
|
2102
|
+
|
|
1607
2103
|
// Build union type names map before generating auto types
|
|
1608
2104
|
const unionTypeNames = buildUnionTypeNamesMap(allInlineUnions);
|
|
1609
2105
|
|
|
@@ -1658,10 +2154,40 @@ export function generateAutoTypes(
|
|
|
1658
2154
|
updateParams,
|
|
1659
2155
|
);
|
|
1660
2156
|
|
|
2157
|
+
// Build mapping from TS type alias names to auto-generated GraphQL union names
|
|
2158
|
+
const tsAliasToGraphQLNameMap = buildTsAliasToGraphQLNameMap(
|
|
2159
|
+
allInlineUnions,
|
|
2160
|
+
unionTypeNames,
|
|
2161
|
+
);
|
|
2162
|
+
|
|
1661
2163
|
return {
|
|
1662
2164
|
autoGeneratedTypes,
|
|
1663
2165
|
updatedExtractedTypes,
|
|
1664
2166
|
updatedResolversResult,
|
|
1665
2167
|
diagnostics,
|
|
2168
|
+
tsAliasToGraphQLNameMap,
|
|
2169
|
+
inlineDiscriminatorResolveTypes:
|
|
2170
|
+
flattenResult.inlineDiscriminatorResolveTypes,
|
|
1666
2171
|
};
|
|
1667
2172
|
}
|
|
2173
|
+
|
|
2174
|
+
function buildTsAliasToGraphQLNameMap(
|
|
2175
|
+
inlineUnions: ReadonlyArray<InlineUnionWithContext>,
|
|
2176
|
+
unionTypeNames: ReadonlyMap<string, string>,
|
|
2177
|
+
): ReadonlyMap<string, string> {
|
|
2178
|
+
const result = new Map<string, string>();
|
|
2179
|
+
|
|
2180
|
+
for (const inlineUnion of inlineUnions) {
|
|
2181
|
+
if (inlineUnion.unionAliasName === null) {
|
|
2182
|
+
continue;
|
|
2183
|
+
}
|
|
2184
|
+
|
|
2185
|
+
const contextKey = getContextKey(inlineUnion.context);
|
|
2186
|
+
const generatedName = unionTypeNames.get(contextKey);
|
|
2187
|
+
if (generatedName !== undefined) {
|
|
2188
|
+
result.set(inlineUnion.unionAliasName, generatedName);
|
|
2189
|
+
}
|
|
2190
|
+
}
|
|
2191
|
+
|
|
2192
|
+
return result;
|
|
2193
|
+
}
|