@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.
Files changed (212) hide show
  1. package/dist/auto-type-generator/auto-type-generator.d.ts +7 -0
  2. package/dist/auto-type-generator/auto-type-generator.d.ts.map +1 -1
  3. package/dist/auto-type-generator/auto-type-generator.js +379 -56
  4. package/dist/auto-type-generator/auto-type-generator.js.map +1 -1
  5. package/dist/auto-type-generator/discriminator-field-validator.d.ts +26 -0
  6. package/dist/auto-type-generator/discriminator-field-validator.d.ts.map +1 -0
  7. package/dist/auto-type-generator/discriminator-field-validator.js +242 -0
  8. package/dist/auto-type-generator/discriminator-field-validator.js.map +1 -0
  9. package/dist/auto-type-generator/discriminator-naming.d.ts +11 -0
  10. package/dist/auto-type-generator/discriminator-naming.d.ts.map +1 -0
  11. package/dist/auto-type-generator/discriminator-naming.js +15 -0
  12. package/dist/auto-type-generator/discriminator-naming.js.map +1 -0
  13. package/dist/auto-type-generator/discriminator-resolve-type-generator.d.ts +44 -0
  14. package/dist/auto-type-generator/discriminator-resolve-type-generator.d.ts.map +1 -0
  15. package/dist/auto-type-generator/discriminator-resolve-type-generator.js +77 -0
  16. package/dist/auto-type-generator/discriminator-resolve-type-generator.js.map +1 -0
  17. package/dist/auto-type-generator/index.d.ts +3 -0
  18. package/dist/auto-type-generator/index.d.ts.map +1 -1
  19. package/dist/auto-type-generator/index.js +3 -0
  20. package/dist/auto-type-generator/index.js.map +1 -1
  21. package/dist/auto-type-generator/inline-enum-collector.d.ts.map +1 -1
  22. package/dist/auto-type-generator/inline-enum-collector.js +14 -7
  23. package/dist/auto-type-generator/inline-enum-collector.js.map +1 -1
  24. package/dist/auto-type-generator/inline-object-converter.d.ts +12 -0
  25. package/dist/auto-type-generator/inline-object-converter.d.ts.map +1 -0
  26. package/dist/auto-type-generator/inline-object-converter.js +72 -0
  27. package/dist/auto-type-generator/inline-object-converter.js.map +1 -0
  28. package/dist/auto-type-generator/inline-object-traverser.d.ts +2 -1
  29. package/dist/auto-type-generator/inline-object-traverser.d.ts.map +1 -1
  30. package/dist/auto-type-generator/inline-object-traverser.js +22 -4
  31. package/dist/auto-type-generator/inline-object-traverser.js.map +1 -1
  32. package/dist/auto-type-generator/inline-union-collector.d.ts.map +1 -1
  33. package/dist/auto-type-generator/inline-union-collector.js +20 -6
  34. package/dist/auto-type-generator/inline-union-collector.js.map +1 -1
  35. package/dist/auto-type-generator/inline-union-types.d.ts +2 -0
  36. package/dist/auto-type-generator/inline-union-types.d.ts.map +1 -1
  37. package/dist/auto-type-generator/inline-union-validator.js +3 -3
  38. package/dist/auto-type-generator/inline-union-validator.js.map +1 -1
  39. package/dist/auto-type-generator/intersection-flattener.d.ts +44 -0
  40. package/dist/auto-type-generator/intersection-flattener.d.ts.map +1 -0
  41. package/dist/auto-type-generator/intersection-flattener.js +398 -0
  42. package/dist/auto-type-generator/intersection-flattener.js.map +1 -0
  43. package/dist/auto-type-generator/naming-convention.d.ts +23 -2
  44. package/dist/auto-type-generator/naming-convention.d.ts.map +1 -1
  45. package/dist/auto-type-generator/naming-convention.js +145 -1
  46. package/dist/auto-type-generator/naming-convention.js.map +1 -1
  47. package/dist/auto-type-generator/resolver-field-iterator.d.ts +1 -1
  48. package/dist/auto-type-generator/resolver-field-iterator.d.ts.map +1 -1
  49. package/dist/auto-type-generator/resolver-field-iterator.js +3 -0
  50. package/dist/auto-type-generator/resolver-field-iterator.js.map +1 -1
  51. package/dist/auto-type-generator/typename-extractor.d.ts +2 -0
  52. package/dist/auto-type-generator/typename-extractor.d.ts.map +1 -1
  53. package/dist/auto-type-generator/typename-extractor.js +11 -3
  54. package/dist/auto-type-generator/typename-extractor.js.map +1 -1
  55. package/dist/auto-type-generator/typename-resolve-type-generator.d.ts +2 -0
  56. package/dist/auto-type-generator/typename-resolve-type-generator.d.ts.map +1 -1
  57. package/dist/auto-type-generator/typename-resolve-type-generator.js +12 -84
  58. package/dist/auto-type-generator/typename-resolve-type-generator.js.map +1 -1
  59. package/dist/auto-type-generator/typename-types.d.ts +4 -0
  60. package/dist/auto-type-generator/typename-types.d.ts.map +1 -1
  61. package/dist/auto-type-generator/typename-types.js +6 -0
  62. package/dist/auto-type-generator/typename-types.js.map +1 -1
  63. package/dist/auto-type-generator/typename-validator.d.ts.map +1 -1
  64. package/dist/auto-type-generator/typename-validator.js +4 -3
  65. package/dist/auto-type-generator/typename-validator.js.map +1 -1
  66. package/dist/commands/docs.d.ts +1 -0
  67. package/dist/commands/docs.d.ts.map +1 -1
  68. package/dist/commands/gen.d.ts +1 -0
  69. package/dist/commands/gen.d.ts.map +1 -1
  70. package/dist/commands/gen.js +2 -1
  71. package/dist/commands/gen.js.map +1 -1
  72. package/dist/commands/main.d.ts +1 -0
  73. package/dist/commands/main.d.ts.map +1 -1
  74. package/dist/config/types.d.ts +7 -0
  75. package/dist/config/types.d.ts.map +1 -1
  76. package/dist/config-loader/index.d.ts +1 -1
  77. package/dist/config-loader/index.d.ts.map +1 -1
  78. package/dist/config-loader/index.js.map +1 -1
  79. package/dist/config-loader/loader.d.ts +6 -0
  80. package/dist/config-loader/loader.d.ts.map +1 -1
  81. package/dist/config-loader/loader.js +1 -0
  82. package/dist/config-loader/loader.js.map +1 -1
  83. package/dist/config-loader/validator.d.ts.map +1 -1
  84. package/dist/config-loader/validator.js +84 -1
  85. package/dist/config-loader/validator.js.map +1 -1
  86. package/dist/gen-orchestrator/orchestrator.d.ts +2 -1
  87. package/dist/gen-orchestrator/orchestrator.d.ts.map +1 -1
  88. package/dist/gen-orchestrator/orchestrator.js +43 -3
  89. package/dist/gen-orchestrator/orchestrator.js.map +1 -1
  90. package/dist/resolver-extractor/extract-resolvers.d.ts +4 -0
  91. package/dist/resolver-extractor/extract-resolvers.d.ts.map +1 -1
  92. package/dist/resolver-extractor/extractor/define-api-extractor.d.ts +2 -1
  93. package/dist/resolver-extractor/extractor/define-api-extractor.d.ts.map +1 -1
  94. package/dist/resolver-extractor/extractor/define-api-extractor.js +35 -6
  95. package/dist/resolver-extractor/extractor/define-api-extractor.js.map +1 -1
  96. package/dist/resolver-extractor/index.d.ts +1 -1
  97. package/dist/resolver-extractor/index.d.ts.map +1 -1
  98. package/dist/resolver-extractor/validator/abstract-resolver-validator.d.ts +2 -0
  99. package/dist/resolver-extractor/validator/abstract-resolver-validator.d.ts.map +1 -1
  100. package/dist/resolver-extractor/validator/abstract-resolver-validator.js +16 -3
  101. package/dist/resolver-extractor/validator/abstract-resolver-validator.js.map +1 -1
  102. package/dist/schema-generator/emitter/code-emitter.d.ts.map +1 -1
  103. package/dist/schema-generator/emitter/code-emitter.js +24 -4
  104. package/dist/schema-generator/emitter/code-emitter.js.map +1 -1
  105. package/dist/schema-generator/emitter/discriminator-resolve-type-emitter.d.ts +18 -0
  106. package/dist/schema-generator/emitter/discriminator-resolve-type-emitter.d.ts.map +1 -0
  107. package/dist/schema-generator/emitter/discriminator-resolve-type-emitter.js +89 -0
  108. package/dist/schema-generator/emitter/discriminator-resolve-type-emitter.js.map +1 -0
  109. package/dist/schema-generator/generate-schema.d.ts +2 -0
  110. package/dist/schema-generator/generate-schema.d.ts.map +1 -1
  111. package/dist/schema-generator/generate-schema.js +69 -10
  112. package/dist/schema-generator/generate-schema.js.map +1 -1
  113. package/dist/schema-generator/integrator/result-integrator.d.ts +5 -0
  114. package/dist/schema-generator/integrator/result-integrator.d.ts.map +1 -1
  115. package/dist/schema-generator/integrator/result-integrator.js +44 -3
  116. package/dist/schema-generator/integrator/result-integrator.js.map +1 -1
  117. package/dist/schema-generator/resolver-collector/resolver-collector.d.ts +2 -0
  118. package/dist/schema-generator/resolver-collector/resolver-collector.d.ts.map +1 -1
  119. package/dist/schema-generator/resolver-collector/resolver-collector.js +4 -0
  120. package/dist/schema-generator/resolver-collector/resolver-collector.js.map +1 -1
  121. package/dist/shared/constants.d.ts.map +1 -1
  122. package/dist/shared/constants.js +14 -1
  123. package/dist/shared/constants.js.map +1 -1
  124. package/dist/shared/enum-prefix-detector.d.ts.map +1 -1
  125. package/dist/shared/enum-prefix-detector.js +78 -8
  126. package/dist/shared/enum-prefix-detector.js.map +1 -1
  127. package/dist/shared/inline-object-utils.js +1 -1
  128. package/dist/shared/inline-object-utils.js.map +1 -1
  129. package/dist/shared/type-converter.d.ts.map +1 -1
  130. package/dist/shared/type-converter.js +55 -0
  131. package/dist/shared/type-converter.js.map +1 -1
  132. package/dist/type-extractor/converter/graphql-converter.d.ts.map +1 -1
  133. package/dist/type-extractor/converter/graphql-converter.js +11 -1
  134. package/dist/type-extractor/converter/graphql-converter.js.map +1 -1
  135. package/dist/type-extractor/extractor/field-type-resolver.d.ts +18 -0
  136. package/dist/type-extractor/extractor/field-type-resolver.d.ts.map +1 -1
  137. package/dist/type-extractor/extractor/field-type-resolver.js +198 -15
  138. package/dist/type-extractor/extractor/field-type-resolver.js.map +1 -1
  139. package/dist/type-extractor/extractor/type-extractor.d.ts +1 -0
  140. package/dist/type-extractor/extractor/type-extractor.d.ts.map +1 -1
  141. package/dist/type-extractor/extractor/type-extractor.js +100 -9
  142. package/dist/type-extractor/extractor/type-extractor.js.map +1 -1
  143. package/dist/type-extractor/types/diagnostics.d.ts +1 -1
  144. package/dist/type-extractor/types/diagnostics.d.ts.map +1 -1
  145. package/dist/type-extractor/types/index.d.ts +1 -1
  146. package/dist/type-extractor/types/index.d.ts.map +1 -1
  147. package/dist/type-extractor/types/index.js +1 -1
  148. package/dist/type-extractor/types/index.js.map +1 -1
  149. package/dist/type-extractor/types/ts-type-reference-factory.d.ts +7 -1
  150. package/dist/type-extractor/types/ts-type-reference-factory.d.ts.map +1 -1
  151. package/dist/type-extractor/types/ts-type-reference-factory.js +18 -3
  152. package/dist/type-extractor/types/ts-type-reference-factory.js.map +1 -1
  153. package/dist/type-extractor/types/typescript.d.ts +3 -1
  154. package/dist/type-extractor/types/typescript.d.ts.map +1 -1
  155. package/dist/type-extractor/validator/type-validator.d.ts.map +1 -1
  156. package/dist/type-extractor/validator/type-validator.js +6 -1
  157. package/dist/type-extractor/validator/type-validator.js.map +1 -1
  158. package/docs/configuration.md +19 -0
  159. package/docs/getting-started.md +2 -1
  160. package/docs/index.md +2 -0
  161. package/docs/integration/ai-sdk.md +189 -0
  162. package/docs/schema/conventions.md +7 -0
  163. package/docs/schema/fields.md +15 -0
  164. package/docs/schema/queries-mutations.md +21 -2
  165. package/docs/schema/subscriptions.md +173 -0
  166. package/docs/schema/unions.md +117 -0
  167. package/package.json +4 -4
  168. package/src/auto-type-generator/auto-type-generator.ts +588 -62
  169. package/src/auto-type-generator/discriminator-field-validator.ts +368 -0
  170. package/src/auto-type-generator/discriminator-naming.ts +24 -0
  171. package/src/auto-type-generator/discriminator-resolve-type-generator.ts +136 -0
  172. package/src/auto-type-generator/index.ts +17 -0
  173. package/src/auto-type-generator/inline-enum-collector.ts +19 -4
  174. package/src/auto-type-generator/inline-object-converter.ts +100 -0
  175. package/src/auto-type-generator/inline-object-traverser.ts +33 -7
  176. package/src/auto-type-generator/inline-union-collector.ts +26 -4
  177. package/src/auto-type-generator/inline-union-types.ts +2 -0
  178. package/src/auto-type-generator/inline-union-validator.ts +3 -3
  179. package/src/auto-type-generator/intersection-flattener.ts +554 -0
  180. package/src/auto-type-generator/naming-convention.ts +207 -3
  181. package/src/auto-type-generator/resolver-field-iterator.ts +5 -1
  182. package/src/auto-type-generator/typename-extractor.ts +17 -3
  183. package/src/auto-type-generator/typename-resolve-type-generator.ts +19 -108
  184. package/src/auto-type-generator/typename-types.ts +7 -0
  185. package/src/auto-type-generator/typename-validator.ts +4 -3
  186. package/src/commands/gen.ts +9 -2
  187. package/src/config/types.ts +10 -0
  188. package/src/config-loader/index.ts +1 -0
  189. package/src/config-loader/loader.ts +11 -0
  190. package/src/config-loader/validator.ts +100 -1
  191. package/src/gen-orchestrator/orchestrator.ts +50 -3
  192. package/src/resolver-extractor/extract-resolvers.ts +5 -0
  193. package/src/resolver-extractor/extractor/define-api-extractor.ts +47 -7
  194. package/src/resolver-extractor/index.ts +1 -0
  195. package/src/resolver-extractor/validator/abstract-resolver-validator.ts +20 -6
  196. package/src/schema-generator/emitter/code-emitter.ts +43 -5
  197. package/src/schema-generator/emitter/discriminator-resolve-type-emitter.ts +125 -0
  198. package/src/schema-generator/generate-schema.ts +100 -13
  199. package/src/schema-generator/integrator/result-integrator.ts +55 -2
  200. package/src/schema-generator/resolver-collector/resolver-collector.ts +7 -0
  201. package/src/shared/constants.ts +15 -1
  202. package/src/shared/enum-prefix-detector.ts +96 -8
  203. package/src/shared/inline-object-utils.ts +1 -1
  204. package/src/shared/type-converter.ts +63 -0
  205. package/src/type-extractor/converter/graphql-converter.ts +17 -1
  206. package/src/type-extractor/extractor/field-type-resolver.ts +241 -16
  207. package/src/type-extractor/extractor/type-extractor.ts +119 -5
  208. package/src/type-extractor/types/diagnostics.ts +10 -1
  209. package/src/type-extractor/types/index.ts +2 -1
  210. package/src/type-extractor/types/ts-type-reference-factory.ts +24 -3
  211. package/src/type-extractor/types/typescript.ts +6 -2
  212. 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 { forEachResolverField } from "./resolver-field-iterator.js";
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
- if (
177
- prop.tsType.kind === "inlineObject" &&
178
- prop.tsType.inlineObjectProperties
179
- ) {
180
- const nestedPath = [...currentPath, prop.name];
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: prop.tsType.inlineObjectProperties,
242
+ properties: inlineObjectTypeInfo.properties,
187
243
  context: nestedContext,
188
244
  sourceLocation: nestedSourceLocation,
189
- nullable: prop.tsType.nullable,
245
+ nullable: inlineObjectTypeInfo.nullable,
190
246
  description: preserveDocumentation
191
- ? prop.tsType.inlineObjectDescription
247
+ ? inlineObjectTypeInfo.description
192
248
  : null,
193
249
  deprecated: preserveDocumentation
194
- ? prop.tsType.inlineObjectDeprecated
250
+ ? inlineObjectTypeInfo.deprecated
195
251
  : null,
196
252
  });
197
253
 
198
254
  extractNestedInlineObjectsRecursively({
199
- properties: prop.tsType.inlineObjectProperties,
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 { field, parentTypeName, parentPath, isInput, sourceFile, results } =
286
- params;
287
- const tsType = field.tsType;
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 (tsType.kind !== "inlineObject" || !tsType.inlineObjectProperties) {
355
+ if (!inlineObjectTypeInfo) {
290
356
  return;
291
357
  }
292
358
 
293
- const fieldPath = [...parentPath, field.name];
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: tsType.inlineObjectProperties,
384
+ properties: inlineObjectTypeInfo.properties,
314
385
  context,
315
386
  sourceLocation,
316
- nullable: tsType.nullable,
317
- description: tsType.inlineObjectDescription,
318
- deprecated: tsType.inlineObjectDeprecated,
387
+ nullable: inlineObjectTypeInfo.nullable,
388
+ description: inlineObjectTypeInfo.description,
389
+ deprecated: inlineObjectTypeInfo.deprecated,
319
390
  });
320
391
 
321
392
  extractNestedInlineObjectsRecursively({
322
- properties: tsType.inlineObjectProperties,
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: "query" | "mutation" | "field",
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: "query" | "mutation" | "field",
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 = [...parentContext.fieldPath, prop.name];
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
- prop.tsType.inlineObjectProperties
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 (prop.tsType.kind === "inlineEnum" && prop.tsType.inlineEnumMembers) {
591
- const result = tryResolveNestedType(prop, parentContext, enumTypeNames);
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 (prop.tsType.kind === "union" && prop.tsType.members) {
596
- const result = tryResolveNestedType(prop, parentContext, unionTypeNames);
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(field, params, typeInfo.metadata.name, isInput),
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(parentTypeName, [field.name], isInput);
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 === "literal" && tsType.name !== null) {
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: [...parentContext.fieldPath, `member${i}`],
1882
+ fieldPath: [
1883
+ ...parentContext.fieldPath,
1884
+ memberType.inlineObjectHintName,
1885
+ ],
1405
1886
  };
1406
- memberTypeName = generateAutoTypeName(nestedContext);
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 fields: AutoGeneratedField[] = memberType.inlineObjectProperties
1414
- .filter(
1415
- (prop) =>
1416
- parentContext.kind !== "resolverPayload" ||
1417
- prop.name !== typenameFieldToFilter,
1418
- )
1419
- .map((prop) => {
1420
- const fieldType = convertTsTypeToGraphQLType(
1421
- prop.tsType,
1422
- prop.optional,
1423
- );
1424
- return {
1425
- name: prop.name,
1426
- type: fieldType,
1427
- description: prop.description,
1428
- deprecated: prop.deprecated,
1429
- directives: prop.directives,
1430
- defaultValue: prop.defaultValue,
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 ?? `member${i}`,
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 allInlineUnions = [
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
+ }