@gqlkit-ts/cli 0.6.0 → 0.7.1
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 +375 -55
- 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 +21 -0
- 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/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/gen.d.ts.map +1 -1
- package/dist/commands/gen.js +2 -1
- package/dist/commands/gen.js.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 +15 -2
- package/dist/gen-orchestrator/orchestrator.js.map +1 -1
- package/dist/resolver-extractor/extractor/define-api-extractor.d.ts.map +1 -1
- package/dist/resolver-extractor/extractor/define-api-extractor.js +4 -0
- package/dist/resolver-extractor/extractor/define-api-extractor.js.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 +13 -1
- 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 +4 -0
- package/dist/schema-generator/integrator/result-integrator.d.ts.map +1 -1
- package/dist/schema-generator/integrator/result-integrator.js +18 -2
- 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 +218 -16
- 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 +127 -14
- package/dist/type-extractor/extractor/type-extractor.js.map +1 -1
- package/dist/type-extractor/extractor/type-name-collector.d.ts.map +1 -1
- package/dist/type-extractor/extractor/type-name-collector.js +19 -4
- package/dist/type-extractor/extractor/type-name-collector.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/index.md +1 -0
- package/docs/integration/ai-sdk.md +189 -0
- package/docs/schema/unions.md +117 -0
- package/package.json +2 -2
- package/src/auto-type-generator/auto-type-generator.ts +576 -58
- 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 +205 -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 +19 -2
- package/src/resolver-extractor/extractor/define-api-extractor.ts +4 -0
- package/src/resolver-extractor/validator/abstract-resolver-validator.ts +20 -6
- package/src/schema-generator/emitter/code-emitter.ts +26 -1
- 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 +25 -1
- 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 +266 -16
- package/src/type-extractor/extractor/type-extractor.ts +148 -11
- package/src/type-extractor/extractor/type-name-collector.ts +19 -4
- 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,8 +47,13 @@ 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,
|
|
@@ -59,6 +66,7 @@ import {
|
|
|
59
66
|
import {
|
|
60
67
|
createFieldNameSet,
|
|
61
68
|
findTypenameProperty,
|
|
69
|
+
isTypenameFieldName,
|
|
62
70
|
type TypenameFieldInfo,
|
|
63
71
|
type TypenameFieldName,
|
|
64
72
|
} from "./typename-types.js";
|
|
@@ -130,6 +138,7 @@ export interface AutoTypeGeneratorInput {
|
|
|
130
138
|
readonly extractedTypes: ReadonlyArray<ExtractedTypeInfo>;
|
|
131
139
|
readonly resolversResult: ExtractResolversResult;
|
|
132
140
|
readonly knownTypeNames: ReadonlySet<string>;
|
|
141
|
+
readonly discriminatorFields: ResolvedDiscriminatorFieldsMap;
|
|
133
142
|
}
|
|
134
143
|
|
|
135
144
|
export interface AutoTypeGeneratorResult {
|
|
@@ -137,6 +146,10 @@ export interface AutoTypeGeneratorResult {
|
|
|
137
146
|
readonly updatedExtractedTypes: ReadonlyArray<ExtractedTypeInfo>;
|
|
138
147
|
readonly updatedResolversResult: ExtractResolversResult;
|
|
139
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>;
|
|
140
153
|
}
|
|
141
154
|
|
|
142
155
|
interface InlineObjectWithContext {
|
|
@@ -163,6 +176,41 @@ interface ExtractNestedInlineObjectsParams {
|
|
|
163
176
|
readonly results: InlineObjectWithContext[];
|
|
164
177
|
}
|
|
165
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
|
+
|
|
166
214
|
function extractNestedInlineObjectsRecursively(
|
|
167
215
|
params: ExtractNestedInlineObjectsParams,
|
|
168
216
|
): void {
|
|
@@ -174,32 +222,37 @@ function extractNestedInlineObjectsRecursively(
|
|
|
174
222
|
preserveDocumentation,
|
|
175
223
|
results,
|
|
176
224
|
} = params;
|
|
225
|
+
const siblingFieldNames = new Set(properties.map((prop) => prop.name));
|
|
177
226
|
|
|
178
227
|
for (const prop of properties) {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
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
|
+
});
|
|
184
237
|
const nestedContext = buildContext(nestedPath);
|
|
185
238
|
// Use property's source location if available for more accurate diagnostics
|
|
186
239
|
const nestedSourceLocation = prop.sourceLocation ?? sourceLocation;
|
|
187
240
|
|
|
188
241
|
results.push({
|
|
189
|
-
properties:
|
|
242
|
+
properties: inlineObjectTypeInfo.properties,
|
|
190
243
|
context: nestedContext,
|
|
191
244
|
sourceLocation: nestedSourceLocation,
|
|
192
|
-
nullable:
|
|
245
|
+
nullable: inlineObjectTypeInfo.nullable,
|
|
193
246
|
description: preserveDocumentation
|
|
194
|
-
?
|
|
247
|
+
? inlineObjectTypeInfo.description
|
|
195
248
|
: null,
|
|
196
249
|
deprecated: preserveDocumentation
|
|
197
|
-
?
|
|
250
|
+
? inlineObjectTypeInfo.deprecated
|
|
198
251
|
: null,
|
|
199
252
|
});
|
|
200
253
|
|
|
201
254
|
extractNestedInlineObjectsRecursively({
|
|
202
|
-
properties:
|
|
255
|
+
properties: inlineObjectTypeInfo.properties,
|
|
203
256
|
currentPath: nestedPath,
|
|
204
257
|
sourceLocation: nestedSourceLocation,
|
|
205
258
|
buildContext,
|
|
@@ -258,6 +311,7 @@ function collectInlineObjectsFromType(
|
|
|
258
311
|
): InlineObjectWithContext[] {
|
|
259
312
|
const results: InlineObjectWithContext[] = [];
|
|
260
313
|
const isInput = isInputTypeName(typeInfo.metadata.name);
|
|
314
|
+
const siblingFieldNames = new Set(typeInfo.fields.map((field) => field.name));
|
|
261
315
|
|
|
262
316
|
for (const field of typeInfo.fields) {
|
|
263
317
|
collectInlineObjectsFromField({
|
|
@@ -266,6 +320,7 @@ function collectInlineObjectsFromType(
|
|
|
266
320
|
parentPath: [],
|
|
267
321
|
isInput,
|
|
268
322
|
sourceFile: typeInfo.metadata.sourceFile,
|
|
323
|
+
siblingFieldNames,
|
|
269
324
|
results,
|
|
270
325
|
});
|
|
271
326
|
}
|
|
@@ -279,21 +334,34 @@ interface CollectInlineObjectsFromFieldParams {
|
|
|
279
334
|
readonly parentPath: ReadonlyArray<string>;
|
|
280
335
|
readonly isInput: boolean;
|
|
281
336
|
readonly sourceFile: string;
|
|
337
|
+
readonly siblingFieldNames: ReadonlySet<string>;
|
|
282
338
|
readonly results: InlineObjectWithContext[];
|
|
283
339
|
}
|
|
284
340
|
|
|
285
341
|
function collectInlineObjectsFromField(
|
|
286
342
|
params: CollectInlineObjectsFromFieldParams,
|
|
287
343
|
): void {
|
|
288
|
-
const {
|
|
289
|
-
|
|
290
|
-
|
|
344
|
+
const {
|
|
345
|
+
field,
|
|
346
|
+
parentTypeName,
|
|
347
|
+
parentPath,
|
|
348
|
+
isInput,
|
|
349
|
+
sourceFile,
|
|
350
|
+
siblingFieldNames,
|
|
351
|
+
results,
|
|
352
|
+
} = params;
|
|
353
|
+
const inlineObjectTypeInfo = getInlineObjectTypeInfo(field.tsType);
|
|
291
354
|
|
|
292
|
-
if (
|
|
355
|
+
if (!inlineObjectTypeInfo) {
|
|
293
356
|
return;
|
|
294
357
|
}
|
|
295
358
|
|
|
296
|
-
const fieldPath =
|
|
359
|
+
const fieldPath = appendFieldPath({
|
|
360
|
+
parentPath,
|
|
361
|
+
fieldName: field.name,
|
|
362
|
+
singularize: field.tsType.kind === "array",
|
|
363
|
+
siblingFieldNames,
|
|
364
|
+
});
|
|
297
365
|
|
|
298
366
|
const context: AutoTypeNameContext = isInput
|
|
299
367
|
? {
|
|
@@ -313,16 +381,16 @@ function collectInlineObjectsFromField(
|
|
|
313
381
|
);
|
|
314
382
|
|
|
315
383
|
results.push({
|
|
316
|
-
properties:
|
|
384
|
+
properties: inlineObjectTypeInfo.properties,
|
|
317
385
|
context,
|
|
318
386
|
sourceLocation,
|
|
319
|
-
nullable:
|
|
320
|
-
description:
|
|
321
|
-
deprecated:
|
|
387
|
+
nullable: inlineObjectTypeInfo.nullable,
|
|
388
|
+
description: inlineObjectTypeInfo.description,
|
|
389
|
+
deprecated: inlineObjectTypeInfo.deprecated,
|
|
322
390
|
});
|
|
323
391
|
|
|
324
392
|
extractNestedInlineObjectsRecursively({
|
|
325
|
-
properties:
|
|
393
|
+
properties: inlineObjectTypeInfo.properties,
|
|
326
394
|
currentPath: fieldPath,
|
|
327
395
|
sourceLocation,
|
|
328
396
|
buildContext: (nestedPath) =>
|
|
@@ -486,8 +554,16 @@ function generateAutoType(
|
|
|
486
554
|
|
|
487
555
|
const fields: AutoGeneratedField[] = [];
|
|
488
556
|
const diagnostics: Diagnostic[] = [];
|
|
557
|
+
const siblingFieldNames = new Set(
|
|
558
|
+
inlineObj.properties.map((prop) => prop.name),
|
|
559
|
+
);
|
|
489
560
|
|
|
490
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
|
+
|
|
491
567
|
const eligibility = isEligibleField({
|
|
492
568
|
fieldName: prop.name,
|
|
493
569
|
kind: isInput ? "input" : "object",
|
|
@@ -509,7 +585,14 @@ function generateAutoType(
|
|
|
509
585
|
enumTypeNames,
|
|
510
586
|
unionTypeNames,
|
|
511
587
|
parentContext: inlineObj.context,
|
|
588
|
+
siblingFieldNames,
|
|
512
589
|
});
|
|
590
|
+
|
|
591
|
+
// Skip fields with never type — they represent impossible values
|
|
592
|
+
if (fieldType.typeName === "__NEVER__") {
|
|
593
|
+
continue;
|
|
594
|
+
}
|
|
595
|
+
|
|
513
596
|
fields.push({
|
|
514
597
|
name: prop.name,
|
|
515
598
|
type: fieldType,
|
|
@@ -543,14 +626,21 @@ interface ResolveFieldTypeParams {
|
|
|
543
626
|
readonly enumTypeNames: Map<string, string>;
|
|
544
627
|
readonly unionTypeNames: Map<string, string>;
|
|
545
628
|
readonly parentContext: AutoTypeNameContext;
|
|
629
|
+
readonly siblingFieldNames: ReadonlySet<string>;
|
|
546
630
|
}
|
|
547
631
|
|
|
548
632
|
function tryResolveNestedType(
|
|
549
633
|
prop: InlineObjectPropertyDef,
|
|
550
634
|
parentContext: AutoTypeNameContext,
|
|
551
635
|
typeNamesMap: ReadonlyMap<string, string>,
|
|
636
|
+
siblingFieldNames: ReadonlySet<string>,
|
|
552
637
|
): GraphQLFieldType | null {
|
|
553
|
-
const nestedPath =
|
|
638
|
+
const nestedPath = appendFieldPath({
|
|
639
|
+
parentPath: parentContext.fieldPath,
|
|
640
|
+
fieldName: prop.name,
|
|
641
|
+
singularize: prop.tsType.kind === "array",
|
|
642
|
+
siblingFieldNames,
|
|
643
|
+
});
|
|
554
644
|
const nestedContext: AutoTypeNameContext = {
|
|
555
645
|
...parentContext,
|
|
556
646
|
fieldPath: nestedPath,
|
|
@@ -560,10 +650,8 @@ function tryResolveNestedType(
|
|
|
560
650
|
|
|
561
651
|
if (resolvedTypeName) {
|
|
562
652
|
return {
|
|
653
|
+
...convertTsTypeToGraphQLType(prop.tsType, prop.optional),
|
|
563
654
|
typeName: resolvedTypeName,
|
|
564
|
-
nullable: prop.tsType.nullable || prop.optional,
|
|
565
|
-
list: false,
|
|
566
|
-
listItemNullable: null,
|
|
567
655
|
};
|
|
568
656
|
}
|
|
569
657
|
return null;
|
|
@@ -576,27 +664,52 @@ function resolveFieldType(params: ResolveFieldTypeParams): GraphQLFieldType {
|
|
|
576
664
|
enumTypeNames,
|
|
577
665
|
unionTypeNames,
|
|
578
666
|
parentContext,
|
|
667
|
+
siblingFieldNames,
|
|
579
668
|
} = params;
|
|
580
669
|
|
|
581
670
|
if (
|
|
582
|
-
prop.tsType.kind === "inlineObject" &&
|
|
583
|
-
|
|
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)
|
|
584
676
|
) {
|
|
585
677
|
const result = tryResolveNestedType(
|
|
586
678
|
prop,
|
|
587
679
|
parentContext,
|
|
588
680
|
generatedTypeNames,
|
|
681
|
+
siblingFieldNames,
|
|
589
682
|
);
|
|
590
683
|
if (result) return result;
|
|
591
684
|
}
|
|
592
685
|
|
|
593
|
-
if (
|
|
594
|
-
|
|
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
|
+
);
|
|
595
698
|
if (result) return result;
|
|
596
699
|
}
|
|
597
700
|
|
|
598
|
-
if (
|
|
599
|
-
|
|
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
|
+
);
|
|
600
713
|
if (result) return result;
|
|
601
714
|
}
|
|
602
715
|
|
|
@@ -615,10 +728,19 @@ function updateExtractedTypes(
|
|
|
615
728
|
): ExtractedTypeInfo[] {
|
|
616
729
|
return extractedTypes.map((typeInfo) => {
|
|
617
730
|
const isInput = isInputTypeName(typeInfo.metadata.name);
|
|
731
|
+
const siblingFieldNames = new Set(
|
|
732
|
+
typeInfo.fields.map((field) => field.name),
|
|
733
|
+
);
|
|
618
734
|
return {
|
|
619
735
|
...typeInfo,
|
|
620
736
|
fields: typeInfo.fields.map((field) =>
|
|
621
|
-
updateField(
|
|
737
|
+
updateField(
|
|
738
|
+
field,
|
|
739
|
+
params,
|
|
740
|
+
typeInfo.metadata.name,
|
|
741
|
+
isInput,
|
|
742
|
+
siblingFieldNames,
|
|
743
|
+
),
|
|
622
744
|
),
|
|
623
745
|
};
|
|
624
746
|
});
|
|
@@ -629,9 +751,19 @@ function updateField(
|
|
|
629
751
|
params: UpdateTypeNamesParams,
|
|
630
752
|
parentTypeName: string,
|
|
631
753
|
isInput: boolean,
|
|
754
|
+
siblingFieldNames: ReadonlySet<string>,
|
|
632
755
|
): FieldDefinition {
|
|
633
756
|
const { generatedTypeNames, enumTypeNames, unionTypeNames } = params;
|
|
634
|
-
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
|
+
);
|
|
635
767
|
const contextKey = getContextKey(context);
|
|
636
768
|
|
|
637
769
|
// Handle inline objects
|
|
@@ -651,6 +783,27 @@ function updateField(
|
|
|
651
783
|
}
|
|
652
784
|
}
|
|
653
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
|
+
|
|
654
807
|
// Handle inline enums
|
|
655
808
|
if (field.tsType.kind === "inlineEnum" && field.tsType.inlineEnumMembers) {
|
|
656
809
|
const resolvedTypeName = enumTypeNames.get(contextKey);
|
|
@@ -700,6 +853,27 @@ function updateField(
|
|
|
700
853
|
}
|
|
701
854
|
}
|
|
702
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
|
+
|
|
703
877
|
return field;
|
|
704
878
|
}
|
|
705
879
|
|
|
@@ -1290,6 +1464,9 @@ function generateOneOfFields(
|
|
|
1290
1464
|
prop.tsType,
|
|
1291
1465
|
prop.optional,
|
|
1292
1466
|
);
|
|
1467
|
+
if (fieldType.typeName === "__NEVER__") {
|
|
1468
|
+
continue;
|
|
1469
|
+
}
|
|
1293
1470
|
fields.push({
|
|
1294
1471
|
name: prop.name,
|
|
1295
1472
|
type: {
|
|
@@ -1358,13 +1535,306 @@ function extractTypenameFromInlineObject(
|
|
|
1358
1535
|
const { property, fieldName } = found;
|
|
1359
1536
|
const { tsType } = property;
|
|
1360
1537
|
|
|
1361
|
-
if (tsType.kind === "
|
|
1538
|
+
if (tsType.kind === "stringLiteral" && tsType.name !== null) {
|
|
1362
1539
|
return { typeName: tsType.name, fieldName };
|
|
1363
1540
|
}
|
|
1364
1541
|
|
|
1365
1542
|
return null;
|
|
1366
1543
|
}
|
|
1367
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
|
+
|
|
1368
1838
|
function resolveMemberNames(params: ResolveMemberNamesParams): string[] {
|
|
1369
1839
|
const {
|
|
1370
1840
|
members,
|
|
@@ -1406,38 +1876,47 @@ function resolveMemberNames(params: ResolveMemberNamesParams): string[] {
|
|
|
1406
1876
|
fieldPath: [...parentContext.fieldPath, extractedInfo.typeName],
|
|
1407
1877
|
};
|
|
1408
1878
|
contextKey = getContextKey(nestedContext);
|
|
1409
|
-
} else {
|
|
1879
|
+
} else if (memberType.inlineObjectHintName !== null) {
|
|
1410
1880
|
const nestedContext: AutoTypeNameContext = {
|
|
1411
1881
|
...parentContext,
|
|
1412
|
-
fieldPath: [
|
|
1882
|
+
fieldPath: [
|
|
1883
|
+
...parentContext.fieldPath,
|
|
1884
|
+
memberType.inlineObjectHintName,
|
|
1885
|
+
],
|
|
1413
1886
|
};
|
|
1414
|
-
memberTypeName =
|
|
1887
|
+
memberTypeName = memberType.inlineObjectHintName;
|
|
1415
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;
|
|
1416
1897
|
}
|
|
1417
1898
|
|
|
1418
1899
|
// Only filter out __typename or $typeName for resolverPayload context
|
|
1419
1900
|
// For other contexts, these are regular fields that should be preserved
|
|
1420
1901
|
const typenameFieldToFilter = extractedInfo?.fieldName ?? null;
|
|
1421
|
-
const
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
};
|
|
1440
|
-
});
|
|
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
|
+
);
|
|
1441
1920
|
|
|
1442
1921
|
// Check if this typename was already seen with a different field structure
|
|
1443
1922
|
if (extractedInfo !== null) {
|
|
@@ -1466,7 +1945,7 @@ function resolveMemberNames(params: ResolveMemberNamesParams): string[] {
|
|
|
1466
1945
|
...parentContext,
|
|
1467
1946
|
fieldPath: [
|
|
1468
1947
|
...parentContext.fieldPath,
|
|
1469
|
-
extractedInfo?.typeName ??
|
|
1948
|
+
extractedInfo?.typeName ?? memberType.inlineObjectHintName!,
|
|
1470
1949
|
],
|
|
1471
1950
|
};
|
|
1472
1951
|
|
|
@@ -1606,12 +2085,21 @@ export function generateAutoTypes(
|
|
|
1606
2085
|
resolversResult: input.resolversResult,
|
|
1607
2086
|
knownTypeNames: input.knownTypeNames,
|
|
1608
2087
|
});
|
|
1609
|
-
const
|
|
2088
|
+
const allInlineUnionsRaw = [
|
|
1610
2089
|
...inlineUnionsFromTypes,
|
|
1611
2090
|
...inlineUnionsFromResolvers,
|
|
1612
2091
|
...inlineUnionsFromPayloads,
|
|
1613
2092
|
];
|
|
1614
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
|
+
|
|
1615
2103
|
// Build union type names map before generating auto types
|
|
1616
2104
|
const unionTypeNames = buildUnionTypeNamesMap(allInlineUnions);
|
|
1617
2105
|
|
|
@@ -1666,10 +2154,40 @@ export function generateAutoTypes(
|
|
|
1666
2154
|
updateParams,
|
|
1667
2155
|
);
|
|
1668
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
|
+
|
|
1669
2163
|
return {
|
|
1670
2164
|
autoGeneratedTypes,
|
|
1671
2165
|
updatedExtractedTypes,
|
|
1672
2166
|
updatedResolversResult,
|
|
1673
2167
|
diagnostics,
|
|
2168
|
+
tsAliasToGraphQLNameMap,
|
|
2169
|
+
inlineDiscriminatorResolveTypes:
|
|
2170
|
+
flattenResult.inlineDiscriminatorResolveTypes,
|
|
1674
2171
|
};
|
|
1675
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
|
+
}
|