@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,6 +1,9 @@
|
|
|
1
1
|
import { resolve } from "node:path";
|
|
2
2
|
import ts from "typescript";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
isBuiltInScalar,
|
|
5
|
+
isInternalTypeSymbol,
|
|
6
|
+
} from "../../shared/constants.js";
|
|
4
7
|
import { detectDefaultValueMetadata } from "../../shared/default-value-detector.js";
|
|
5
8
|
import {
|
|
6
9
|
type DirectiveArgumentValue,
|
|
@@ -50,10 +53,11 @@ import type {
|
|
|
50
53
|
import {
|
|
51
54
|
createArrayType,
|
|
52
55
|
createInlineObjectType,
|
|
53
|
-
|
|
56
|
+
createNumericLiteralType,
|
|
54
57
|
createPrimitiveType,
|
|
55
58
|
createReferenceType,
|
|
56
59
|
createScalarType,
|
|
60
|
+
createStringLiteralType,
|
|
57
61
|
createUnionType,
|
|
58
62
|
type Diagnostic,
|
|
59
63
|
type EnumMemberInfo,
|
|
@@ -65,7 +69,11 @@ import {
|
|
|
65
69
|
type TypeKind,
|
|
66
70
|
type TypeMetadata,
|
|
67
71
|
} from "../types/index.js";
|
|
68
|
-
import {
|
|
72
|
+
import {
|
|
73
|
+
type DiscoveredTypeEntry,
|
|
74
|
+
type FieldTypeResolverDiagnostic,
|
|
75
|
+
resolveFieldType,
|
|
76
|
+
} from "./field-type-resolver.js";
|
|
69
77
|
|
|
70
78
|
/**
|
|
71
79
|
* Global type mapping configuration.
|
|
@@ -98,6 +106,7 @@ export interface ExtractionResult {
|
|
|
98
106
|
readonly diagnostics: ReadonlyArray<Diagnostic>;
|
|
99
107
|
readonly detectedScalarNames: ReadonlyArray<string>;
|
|
100
108
|
readonly detectedScalars: ReadonlyArray<ScalarMetadataInfo>;
|
|
109
|
+
readonly discoveredTypeNames: ReadonlySet<string>;
|
|
101
110
|
}
|
|
102
111
|
|
|
103
112
|
function isDefaultExport(node: ts.Node, sourceFile: ts.SourceFile): boolean {
|
|
@@ -163,6 +172,7 @@ function tryExtractAsInlineObject(
|
|
|
163
172
|
properties: inlineProperties,
|
|
164
173
|
description: null,
|
|
165
174
|
deprecated: null,
|
|
175
|
+
hintName: null,
|
|
166
176
|
}),
|
|
167
177
|
};
|
|
168
178
|
}
|
|
@@ -260,6 +270,7 @@ function convertTsTypeToReference(
|
|
|
260
270
|
tsType: createUnionType({
|
|
261
271
|
members: memberResults.map((r) => r.tsType),
|
|
262
272
|
nullable,
|
|
273
|
+
aliasName: type.aliasSymbol?.getName() ?? null,
|
|
263
274
|
}),
|
|
264
275
|
};
|
|
265
276
|
}
|
|
@@ -307,12 +318,12 @@ function convertTsTypeToReference(
|
|
|
307
318
|
}
|
|
308
319
|
if (type.flags & ts.TypeFlags.StringLiteral) {
|
|
309
320
|
return {
|
|
310
|
-
tsType:
|
|
321
|
+
tsType: createStringLiteralType(typeString.replace(/"/g, "")),
|
|
311
322
|
};
|
|
312
323
|
}
|
|
313
324
|
if (type.flags & ts.TypeFlags.NumberLiteral) {
|
|
314
325
|
return {
|
|
315
|
-
tsType:
|
|
326
|
+
tsType: createNumericLiteralType(typeString),
|
|
316
327
|
};
|
|
317
328
|
}
|
|
318
329
|
|
|
@@ -436,6 +447,7 @@ interface ExtractFieldsParams {
|
|
|
436
447
|
readonly scalarMappingTable: ScalarBaseTypeMappingTable | null;
|
|
437
448
|
readonly scalarMappingContext: ScalarMappingContext;
|
|
438
449
|
readonly ignoreFields: ReadonlySet<string> | null;
|
|
450
|
+
readonly discoveredTypes: Map<string, DiscoveredTypeEntry> | null;
|
|
439
451
|
}
|
|
440
452
|
|
|
441
453
|
function extractFieldsFromType(
|
|
@@ -452,6 +464,7 @@ function extractFieldsFromType(
|
|
|
452
464
|
scalarMappingTable,
|
|
453
465
|
scalarMappingContext,
|
|
454
466
|
ignoreFields,
|
|
467
|
+
discoveredTypes,
|
|
455
468
|
} = params;
|
|
456
469
|
const fields: FieldDefinition[] = [];
|
|
457
470
|
const diagnostics: Diagnostic[] = [];
|
|
@@ -528,6 +541,7 @@ function extractFieldsFromType(
|
|
|
528
541
|
propTypeNode = declaration.type;
|
|
529
542
|
}
|
|
530
543
|
|
|
544
|
+
const fieldDiagnostics: FieldTypeResolverDiagnostic[] = [];
|
|
531
545
|
const resolvedType = resolveFieldType(actualPropType, propTypeNode, {
|
|
532
546
|
checker,
|
|
533
547
|
knownTypeNames,
|
|
@@ -537,7 +551,22 @@ function extractFieldsFromType(
|
|
|
537
551
|
sourceFiles,
|
|
538
552
|
scalarMappingTable,
|
|
539
553
|
scalarMappingContext,
|
|
554
|
+
discoveredTypes,
|
|
555
|
+
diagnostics: fieldDiagnostics,
|
|
540
556
|
});
|
|
557
|
+
for (const d of fieldDiagnostics) {
|
|
558
|
+
diagnostics.push({
|
|
559
|
+
code: d.code,
|
|
560
|
+
message: `Field '${propName}': ${d.message}`,
|
|
561
|
+
severity: d.severity,
|
|
562
|
+
location: getSourceLocationFromNode(declaration),
|
|
563
|
+
});
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
// Skip fields with never type — they have no GraphQL representation
|
|
567
|
+
if (resolvedType.kind === "never") {
|
|
568
|
+
continue;
|
|
569
|
+
}
|
|
541
570
|
|
|
542
571
|
// Preserve nullability from original WithDirectives type
|
|
543
572
|
const tsType =
|
|
@@ -847,6 +876,7 @@ interface ProcessReexportedSymbolParams {
|
|
|
847
876
|
readonly scannedSourceFiles: ReadonlySet<string>;
|
|
848
877
|
readonly scalarMappingTable: ScalarBaseTypeMappingTable | null;
|
|
849
878
|
readonly scalarMappingContext: ScalarMappingContext;
|
|
879
|
+
readonly discoveredTypes: Map<string, DiscoveredTypeEntry> | null;
|
|
850
880
|
}
|
|
851
881
|
|
|
852
882
|
interface ProcessReexportedSymbolResult {
|
|
@@ -874,6 +904,7 @@ function processReexportedSymbol(
|
|
|
874
904
|
scannedSourceFiles,
|
|
875
905
|
scalarMappingTable,
|
|
876
906
|
scalarMappingContext,
|
|
907
|
+
discoveredTypes,
|
|
877
908
|
} = params;
|
|
878
909
|
|
|
879
910
|
const diagnostics: Diagnostic[] = [];
|
|
@@ -999,6 +1030,7 @@ function processReexportedSymbol(
|
|
|
999
1030
|
scalarMappingTable,
|
|
1000
1031
|
scalarMappingContext,
|
|
1001
1032
|
ignoreFields,
|
|
1033
|
+
discoveredTypes,
|
|
1002
1034
|
});
|
|
1003
1035
|
diagnostics.push(...fieldResult.diagnostics);
|
|
1004
1036
|
|
|
@@ -1036,16 +1068,13 @@ function processExportDeclaration(
|
|
|
1036
1068
|
underlyingSymbolToTypeName: ReadonlyMap<ts.Symbol, string>,
|
|
1037
1069
|
scannedSourceFiles: ReadonlySet<string>,
|
|
1038
1070
|
scalarMappingTable: ScalarBaseTypeMappingTable | null,
|
|
1071
|
+
discoveredTypes: Map<string, DiscoveredTypeEntry> | null,
|
|
1039
1072
|
): ProcessExportDeclarationResult {
|
|
1040
1073
|
const types: ExtractedTypeInfo[] = [];
|
|
1041
1074
|
const diagnostics: Diagnostic[] = [];
|
|
1042
1075
|
const detectedScalarNames: string[] = [];
|
|
1043
1076
|
const detectedScalars: ScalarMetadataInfo[] = [];
|
|
1044
1077
|
|
|
1045
|
-
if (!node.isTypeOnly) {
|
|
1046
|
-
return { types, diagnostics, detectedScalarNames, detectedScalars };
|
|
1047
|
-
}
|
|
1048
|
-
|
|
1049
1078
|
const exportClause = node.exportClause;
|
|
1050
1079
|
|
|
1051
1080
|
const symbolsToProcess: Array<{
|
|
@@ -1054,8 +1083,35 @@ function processExportDeclaration(
|
|
|
1054
1083
|
type: ts.Type;
|
|
1055
1084
|
}> = [];
|
|
1056
1085
|
|
|
1057
|
-
if (exportClause && ts.isNamedExports(exportClause)) {
|
|
1086
|
+
if (node.isTypeOnly && exportClause && ts.isNamedExports(exportClause)) {
|
|
1087
|
+
// Declaration-level type-only: `export type { Foo, Bar } from "..."`
|
|
1088
|
+
for (const specifier of exportClause.elements) {
|
|
1089
|
+
const exportedName = specifier.name.text;
|
|
1090
|
+
const localTargetSymbol =
|
|
1091
|
+
checker.getExportSpecifierLocalTargetSymbol(specifier);
|
|
1092
|
+
if (!localTargetSymbol) continue;
|
|
1093
|
+
|
|
1094
|
+
const originalSymbol =
|
|
1095
|
+
localTargetSymbol.flags & ts.SymbolFlags.Alias
|
|
1096
|
+
? checker.getAliasedSymbol(localTargetSymbol)
|
|
1097
|
+
: localTargetSymbol;
|
|
1098
|
+
if (!originalSymbol) continue;
|
|
1099
|
+
|
|
1100
|
+
const type = checker.getDeclaredTypeOfSymbol(originalSymbol);
|
|
1101
|
+
symbolsToProcess.push({
|
|
1102
|
+
exportedName,
|
|
1103
|
+
resolvedSymbol: originalSymbol,
|
|
1104
|
+
type,
|
|
1105
|
+
});
|
|
1106
|
+
}
|
|
1107
|
+
} else if (
|
|
1108
|
+
!node.isTypeOnly &&
|
|
1109
|
+
exportClause &&
|
|
1110
|
+
ts.isNamedExports(exportClause)
|
|
1111
|
+
) {
|
|
1112
|
+
// Specifier-level type-only: `export { type Foo, type Bar } from "..."`
|
|
1058
1113
|
for (const specifier of exportClause.elements) {
|
|
1114
|
+
if (!specifier.isTypeOnly) continue;
|
|
1059
1115
|
const exportedName = specifier.name.text;
|
|
1060
1116
|
const localTargetSymbol =
|
|
1061
1117
|
checker.getExportSpecifierLocalTargetSymbol(specifier);
|
|
@@ -1074,7 +1130,7 @@ function processExportDeclaration(
|
|
|
1074
1130
|
type,
|
|
1075
1131
|
});
|
|
1076
1132
|
}
|
|
1077
|
-
} else if (!exportClause && node.moduleSpecifier) {
|
|
1133
|
+
} else if (node.isTypeOnly && !exportClause && node.moduleSpecifier) {
|
|
1078
1134
|
const moduleSymbol = checker.getSymbolAtLocation(node.moduleSpecifier);
|
|
1079
1135
|
if (!moduleSymbol) {
|
|
1080
1136
|
const location = getSourceLocationFromNode(node)!;
|
|
@@ -1132,6 +1188,7 @@ function processExportDeclaration(
|
|
|
1132
1188
|
scannedSourceFiles,
|
|
1133
1189
|
scalarMappingTable,
|
|
1134
1190
|
scalarMappingContext: exportedName.endsWith("Input") ? "input" : "output",
|
|
1191
|
+
discoveredTypes,
|
|
1135
1192
|
});
|
|
1136
1193
|
|
|
1137
1194
|
if (result.skip) continue;
|
|
@@ -1317,6 +1374,7 @@ export function extractTypesFromProgram(
|
|
|
1317
1374
|
const diagnostics: Diagnostic[] = [];
|
|
1318
1375
|
const detectedScalarNames = new Set<string>();
|
|
1319
1376
|
const detectedScalars: ScalarMetadataInfo[] = [];
|
|
1377
|
+
const discoveredTypes = new Map<string, DiscoveredTypeEntry>();
|
|
1320
1378
|
const {
|
|
1321
1379
|
globalTypeMappings,
|
|
1322
1380
|
knownTypeNames,
|
|
@@ -1562,6 +1620,7 @@ export function extractTypesFromProgram(
|
|
|
1562
1620
|
? "input"
|
|
1563
1621
|
: "output",
|
|
1564
1622
|
ignoreFields,
|
|
1623
|
+
discoveredTypes,
|
|
1565
1624
|
});
|
|
1566
1625
|
const fields = fieldResult.fields;
|
|
1567
1626
|
diagnostics.push(...fieldResult.diagnostics);
|
|
@@ -1624,6 +1683,7 @@ export function extractTypesFromProgram(
|
|
|
1624
1683
|
underlyingSymbolToTypeName,
|
|
1625
1684
|
scannedSourceFilesSet,
|
|
1626
1685
|
scalarMappingTable,
|
|
1686
|
+
discoveredTypes,
|
|
1627
1687
|
);
|
|
1628
1688
|
types.push(...result.types);
|
|
1629
1689
|
diagnostics.push(...result.diagnostics);
|
|
@@ -1635,10 +1695,87 @@ export function extractTypesFromProgram(
|
|
|
1635
1695
|
});
|
|
1636
1696
|
}
|
|
1637
1697
|
|
|
1698
|
+
// Process transitively discovered types
|
|
1699
|
+
const processedDiscovered = new Set<string>();
|
|
1700
|
+
while (discoveredTypes.size > processedDiscovered.size) {
|
|
1701
|
+
for (const [name, entry] of discoveredTypes) {
|
|
1702
|
+
if (processedDiscovered.has(name)) continue;
|
|
1703
|
+
processedDiscovered.add(name);
|
|
1704
|
+
if (knownTypeNames.has(name)) continue;
|
|
1705
|
+
|
|
1706
|
+
const { fields } = extractFieldsFromType({
|
|
1707
|
+
type: entry.tsType,
|
|
1708
|
+
checker,
|
|
1709
|
+
globalTypeMappings,
|
|
1710
|
+
knownTypeNames,
|
|
1711
|
+
knownTypeSymbols,
|
|
1712
|
+
underlyingSymbolToTypeName,
|
|
1713
|
+
sourceFiles: scannedSourceFilesSet,
|
|
1714
|
+
scalarMappingTable,
|
|
1715
|
+
scalarMappingContext: "output",
|
|
1716
|
+
ignoreFields: null,
|
|
1717
|
+
discoveredTypes,
|
|
1718
|
+
});
|
|
1719
|
+
if (fields.length === 0) continue;
|
|
1720
|
+
|
|
1721
|
+
types.push({
|
|
1722
|
+
metadata: {
|
|
1723
|
+
name,
|
|
1724
|
+
kind: "object",
|
|
1725
|
+
sourceFile: entry.sourceFile,
|
|
1726
|
+
sourceLocation: entry.sourceLocation,
|
|
1727
|
+
exportKind: "named",
|
|
1728
|
+
description: null,
|
|
1729
|
+
deprecated: null,
|
|
1730
|
+
directives: null,
|
|
1731
|
+
},
|
|
1732
|
+
fields,
|
|
1733
|
+
enumMembers: null,
|
|
1734
|
+
unionMembers: null,
|
|
1735
|
+
implementedInterfaces: null,
|
|
1736
|
+
inlineObjectMembers: null,
|
|
1737
|
+
});
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1740
|
+
|
|
1741
|
+
// Collect scalar names from field types (e.g., unknown → Unknown scalar)
|
|
1742
|
+
for (const typeInfo of types) {
|
|
1743
|
+
for (const field of typeInfo.fields) {
|
|
1744
|
+
collectScalarNamesFromType(field.tsType, detectedScalarNames);
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1747
|
+
|
|
1638
1748
|
return {
|
|
1639
1749
|
types,
|
|
1640
1750
|
diagnostics,
|
|
1641
1751
|
detectedScalarNames: [...detectedScalarNames],
|
|
1642
1752
|
detectedScalars,
|
|
1753
|
+
discoveredTypeNames: new Set(discoveredTypes.keys()),
|
|
1643
1754
|
};
|
|
1644
1755
|
}
|
|
1756
|
+
|
|
1757
|
+
function collectScalarNamesFromType(
|
|
1758
|
+
tsType: TSTypeReference,
|
|
1759
|
+
scalarNames: Set<string>,
|
|
1760
|
+
): void {
|
|
1761
|
+
if (
|
|
1762
|
+
tsType.kind === "scalar" &&
|
|
1763
|
+
tsType.scalarInfo?.isCustom &&
|
|
1764
|
+
!isBuiltInScalar(tsType.scalarInfo.scalarName)
|
|
1765
|
+
) {
|
|
1766
|
+
scalarNames.add(tsType.scalarInfo.scalarName);
|
|
1767
|
+
}
|
|
1768
|
+
if (tsType.elementType) {
|
|
1769
|
+
collectScalarNamesFromType(tsType.elementType, scalarNames);
|
|
1770
|
+
}
|
|
1771
|
+
if (tsType.members) {
|
|
1772
|
+
for (const member of tsType.members) {
|
|
1773
|
+
collectScalarNamesFromType(member, scalarNames);
|
|
1774
|
+
}
|
|
1775
|
+
}
|
|
1776
|
+
if (tsType.inlineObjectProperties) {
|
|
1777
|
+
for (const prop of tsType.inlineObjectProperties) {
|
|
1778
|
+
collectScalarNamesFromType(prop.tsType, scalarNames);
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1781
|
+
}
|
|
@@ -142,9 +142,9 @@ export function collectDeclaredTypeNames(
|
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
// Re-exports: `export type { ... } from "..."` or `export type * from "..."`
|
|
145
|
-
if (ts.isExportDeclaration(node)
|
|
146
|
-
if (node.exportClause) {
|
|
147
|
-
//
|
|
145
|
+
if (ts.isExportDeclaration(node)) {
|
|
146
|
+
if (node.isTypeOnly && node.exportClause) {
|
|
147
|
+
// Declaration-level type-only named re-exports: `export type { Foo, Bar } from "..."`
|
|
148
148
|
if (ts.isNamedExports(node.exportClause)) {
|
|
149
149
|
for (const element of node.exportClause.elements) {
|
|
150
150
|
// Use the exported name (element.name), not the property name
|
|
@@ -154,7 +154,22 @@ export function collectDeclaredTypeNames(
|
|
|
154
154
|
registerTypeName(name, location, symbol);
|
|
155
155
|
}
|
|
156
156
|
}
|
|
157
|
-
} else if (node.
|
|
157
|
+
} else if (!node.isTypeOnly && node.exportClause) {
|
|
158
|
+
// Specifier-level type-only re-exports: `export { type Foo, type Bar } from "..."`
|
|
159
|
+
if (ts.isNamedExports(node.exportClause)) {
|
|
160
|
+
for (const element of node.exportClause.elements) {
|
|
161
|
+
if (!element.isTypeOnly) continue;
|
|
162
|
+
const name = element.name.getText(sourceFile);
|
|
163
|
+
const location = getSourceLocationFromNode(element)!;
|
|
164
|
+
const symbol = checker.getSymbolAtLocation(element.name);
|
|
165
|
+
registerTypeName(name, location, symbol);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
} else if (
|
|
169
|
+
node.isTypeOnly &&
|
|
170
|
+
!node.exportClause &&
|
|
171
|
+
node.moduleSpecifier
|
|
172
|
+
) {
|
|
158
173
|
// Wildcard re-exports: `export type * from "..."`
|
|
159
174
|
const moduleSymbol = checker.getSymbolAtLocation(
|
|
160
175
|
node.moduleSpecifier,
|
|
@@ -95,9 +95,18 @@ export type DiagnosticCode =
|
|
|
95
95
|
| "NULLABLE_TYPENAME_PROPERTY"
|
|
96
96
|
| "TYPENAME_FIELD_STRUCTURE_MISMATCH"
|
|
97
97
|
| "DUPLICATE_TYPENAME_VALUE"
|
|
98
|
+
| "UNNAMEABLE_UNION_MEMBER"
|
|
98
99
|
| "IGNORE_FIELD_NOT_FOUND"
|
|
99
100
|
| "IGNORE_ALL_FIELDS"
|
|
100
|
-
| "DUPLICATE_TYPE_EXPORT"
|
|
101
|
+
| "DUPLICATE_TYPE_EXPORT"
|
|
102
|
+
| "CONFIG_INVALID_DISCRIMINATOR_FIELDS"
|
|
103
|
+
| "CONFIG_INVALID_DISCRIMINATOR_ENTRY"
|
|
104
|
+
| "CONFIG_EMPTY_DISCRIMINATOR_FIELDS"
|
|
105
|
+
| "DISCRIMINATOR_FIELD_NOT_FOUND"
|
|
106
|
+
| "DISCRIMINATOR_FIELD_NOT_STRING_LITERAL"
|
|
107
|
+
| "DISCRIMINATOR_DUPLICATE_VALUE_TUPLE"
|
|
108
|
+
| "DISCRIMINATOR_UNKNOWN_UNION"
|
|
109
|
+
| "CYCLE_DETECTED";
|
|
101
110
|
|
|
102
111
|
export interface Diagnostic {
|
|
103
112
|
readonly code: DiagnosticCode;
|
|
@@ -15,10 +15,11 @@ export type {
|
|
|
15
15
|
export {
|
|
16
16
|
createArrayType,
|
|
17
17
|
createInlineObjectType,
|
|
18
|
-
|
|
18
|
+
createNumericLiteralType,
|
|
19
19
|
createPrimitiveType,
|
|
20
20
|
createReferenceType,
|
|
21
21
|
createScalarType,
|
|
22
|
+
createStringLiteralType,
|
|
22
23
|
createUnionType,
|
|
23
24
|
} from "./ts-type-reference-factory.js";
|
|
24
25
|
export type {
|
|
@@ -25,6 +25,7 @@ function createTSTypeReference(
|
|
|
25
25
|
inlineObjectProperties: null,
|
|
26
26
|
inlineObjectDescription: null,
|
|
27
27
|
inlineObjectDeprecated: null,
|
|
28
|
+
inlineObjectHintName: null,
|
|
28
29
|
inlineEnumMembers: null,
|
|
29
30
|
externalEnumSymbol: null,
|
|
30
31
|
externalEnumDescription: null,
|
|
@@ -68,6 +69,8 @@ export function createArrayType(elementType: TSTypeReference): TSTypeReference {
|
|
|
68
69
|
interface CreateUnionTypeParams {
|
|
69
70
|
readonly members: ReadonlyArray<TSTypeReference>;
|
|
70
71
|
readonly nullable: boolean;
|
|
72
|
+
/** The TypeScript type alias name for this union (e.g., "ItemPart" for `type ItemPart = A | B`) */
|
|
73
|
+
readonly aliasName: string | null;
|
|
71
74
|
}
|
|
72
75
|
|
|
73
76
|
export function createUnionType(
|
|
@@ -75,7 +78,11 @@ export function createUnionType(
|
|
|
75
78
|
): TSTypeReference {
|
|
76
79
|
return createTSTypeReference({
|
|
77
80
|
kind: "union",
|
|
78
|
-
overrides: {
|
|
81
|
+
overrides: {
|
|
82
|
+
members: params.members,
|
|
83
|
+
nullable: params.nullable,
|
|
84
|
+
name: params.aliasName,
|
|
85
|
+
},
|
|
79
86
|
});
|
|
80
87
|
}
|
|
81
88
|
|
|
@@ -85,6 +92,8 @@ interface CreateInlineObjectTypeParams {
|
|
|
85
92
|
readonly description: string | null;
|
|
86
93
|
/** @deprecated tag from the type alias (null for true inline objects) */
|
|
87
94
|
readonly deprecated: DeprecationInfo | null;
|
|
95
|
+
/** Original type name hint for inline objects extracted from external types */
|
|
96
|
+
readonly hintName: string | null;
|
|
88
97
|
}
|
|
89
98
|
|
|
90
99
|
export function createInlineObjectType(
|
|
@@ -96,6 +105,7 @@ export function createInlineObjectType(
|
|
|
96
105
|
inlineObjectProperties: params.properties,
|
|
97
106
|
inlineObjectDescription: params.description,
|
|
98
107
|
inlineObjectDeprecated: params.deprecated,
|
|
108
|
+
inlineObjectHintName: params.hintName,
|
|
99
109
|
},
|
|
100
110
|
});
|
|
101
111
|
}
|
|
@@ -119,8 +129,19 @@ export function createScalarType(
|
|
|
119
129
|
});
|
|
120
130
|
}
|
|
121
131
|
|
|
122
|
-
export function
|
|
123
|
-
return createTSTypeReference({ kind: "
|
|
132
|
+
export function createNeverType(): TSTypeReference {
|
|
133
|
+
return createTSTypeReference({ kind: "never", overrides: {} });
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function createStringLiteralType(name: string): TSTypeReference {
|
|
137
|
+
return createTSTypeReference({ kind: "stringLiteral", overrides: { name } });
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function createNumericLiteralType(name: string): TSTypeReference {
|
|
141
|
+
return createTSTypeReference({
|
|
142
|
+
kind: "numericLiteral",
|
|
143
|
+
overrides: { name },
|
|
144
|
+
});
|
|
124
145
|
}
|
|
125
146
|
|
|
126
147
|
interface CreateInlineEnumTypeParams {
|
|
@@ -45,10 +45,12 @@ export type TSTypeReferenceKind =
|
|
|
45
45
|
| "reference"
|
|
46
46
|
| "array"
|
|
47
47
|
| "union"
|
|
48
|
-
| "
|
|
48
|
+
| "stringLiteral"
|
|
49
|
+
| "numericLiteral"
|
|
49
50
|
| "scalar"
|
|
50
51
|
| "inlineObject"
|
|
51
|
-
| "inlineEnum"
|
|
52
|
+
| "inlineEnum"
|
|
53
|
+
| "never";
|
|
52
54
|
|
|
53
55
|
/**
|
|
54
56
|
* Information about an inline enum member (string literal union value).
|
|
@@ -76,6 +78,8 @@ export interface TSTypeReference {
|
|
|
76
78
|
readonly inlineObjectDeprecated: DeprecationInfo | null;
|
|
77
79
|
/** Inline enum members when kind is "inlineEnum" */
|
|
78
80
|
readonly inlineEnumMembers: ReadonlyArray<InlineEnumMemberInfo> | null;
|
|
81
|
+
/** Original type name hint for inline objects extracted from external types */
|
|
82
|
+
readonly inlineObjectHintName: string | null;
|
|
79
83
|
/** External TypeScript enum symbol for deduplication (Requirement 5.2) */
|
|
80
84
|
readonly externalEnumSymbol: ts.Symbol | null;
|
|
81
85
|
/** TSDoc description from the external enum type itself (Requirement 6.1) */
|
|
@@ -10,7 +10,12 @@ export interface ValidateTypesOptions {
|
|
|
10
10
|
readonly types: ReadonlyArray<GraphQLTypeInfo>;
|
|
11
11
|
readonly customScalarNames: ReadonlyArray<string> | null;
|
|
12
12
|
}
|
|
13
|
-
const PLACEHOLDER_TYPES = new Set([
|
|
13
|
+
const PLACEHOLDER_TYPES = new Set([
|
|
14
|
+
"__INLINE_OBJECT__",
|
|
15
|
+
"__INLINE_ENUM__",
|
|
16
|
+
"__INLINE_UNION__",
|
|
17
|
+
"__NEVER__",
|
|
18
|
+
]);
|
|
14
19
|
|
|
15
20
|
export function validateTypes(options: ValidateTypesOptions): ValidationResult {
|
|
16
21
|
const { types, customScalarNames } = options;
|