@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
|
@@ -55,11 +55,36 @@ export interface ResolverPayloadContext {
|
|
|
55
55
|
readonly fieldPath: ReadonlyArray<string>;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
const IRREGULAR_SINGULAR_FIELD_NAMES = new Map([
|
|
59
|
+
["aliases", "alias"],
|
|
60
|
+
["analyses", "analysis"],
|
|
61
|
+
["buses", "bus"],
|
|
62
|
+
["children", "child"],
|
|
63
|
+
["cookies", "cookie"],
|
|
64
|
+
["crises", "crisis"],
|
|
65
|
+
["diagnoses", "diagnosis"],
|
|
66
|
+
["feet", "foot"],
|
|
67
|
+
["geese", "goose"],
|
|
68
|
+
["men", "man"],
|
|
69
|
+
["mice", "mouse"],
|
|
70
|
+
["movies", "movie"],
|
|
71
|
+
["people", "person"],
|
|
72
|
+
["selfies", "selfie"],
|
|
73
|
+
["statuses", "status"],
|
|
74
|
+
["teeth", "tooth"],
|
|
75
|
+
["theses", "thesis"],
|
|
76
|
+
["women", "woman"],
|
|
77
|
+
["zombies", "zombie"],
|
|
78
|
+
]);
|
|
79
|
+
|
|
80
|
+
const NON_INFLECTING_FIELD_NAMES = new Set(["news", "series", "species"]);
|
|
81
|
+
const AMBIGUOUS_PLURAL_FIELD_NAMES = new Set(["axes"]);
|
|
82
|
+
|
|
58
83
|
/**
|
|
59
84
|
* Convert a string to PascalCase.
|
|
60
85
|
* Handles camelCase, snake_case, and kebab-case inputs.
|
|
61
86
|
*/
|
|
62
|
-
function toPascalCase(str: string): string {
|
|
87
|
+
export function toPascalCase(str: string): string {
|
|
63
88
|
if (str.length === 0) return str;
|
|
64
89
|
|
|
65
90
|
return str
|
|
@@ -76,6 +101,185 @@ function toPascalCase(str: string): string {
|
|
|
76
101
|
.join("");
|
|
77
102
|
}
|
|
78
103
|
|
|
104
|
+
function isConsonant(char: string): boolean {
|
|
105
|
+
return /^[bcdfghjklmnpqrstvwxyz]$/i.test(char);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function isUppercaseLetter(char: string): boolean {
|
|
109
|
+
return char.toLowerCase() !== char && char.toUpperCase() === char;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function applyReplacementCase(params: {
|
|
113
|
+
readonly replacement: string;
|
|
114
|
+
readonly template: string;
|
|
115
|
+
}): string {
|
|
116
|
+
const { replacement, template } = params;
|
|
117
|
+
|
|
118
|
+
if (template.toUpperCase() === template) {
|
|
119
|
+
return replacement.toUpperCase();
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (isUppercaseLetter(template.charAt(0))) {
|
|
123
|
+
return `${replacement.charAt(0).toUpperCase()}${replacement.slice(1)}`;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return replacement;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function singularizeIrregularFieldName(name: string): string | null {
|
|
130
|
+
const lowerName = name.toLowerCase();
|
|
131
|
+
|
|
132
|
+
for (const [plural, singular] of IRREGULAR_SINGULAR_FIELD_NAMES) {
|
|
133
|
+
if (!lowerName.endsWith(plural)) {
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const suffixStart = name.length - plural.length;
|
|
138
|
+
if (suffixStart > 0) {
|
|
139
|
+
const previousChar = name.charAt(suffixStart - 1);
|
|
140
|
+
const suffixFirstChar = name.charAt(suffixStart);
|
|
141
|
+
const hasWordBoundary =
|
|
142
|
+
previousChar === "_" ||
|
|
143
|
+
previousChar === "-" ||
|
|
144
|
+
isUppercaseLetter(suffixFirstChar);
|
|
145
|
+
|
|
146
|
+
if (!hasWordBoundary) {
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return `${name.slice(0, suffixStart)}${applyReplacementCase({
|
|
152
|
+
replacement: singular,
|
|
153
|
+
template: name.slice(suffixStart),
|
|
154
|
+
})}`;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Singularize a plural field name conservatively for array element type naming.
|
|
162
|
+
* Falls back to the original name when the plural form is ambiguous.
|
|
163
|
+
*/
|
|
164
|
+
export function singularizeFieldName(name: string): string {
|
|
165
|
+
const irregularSingular = singularizeIrregularFieldName(name);
|
|
166
|
+
if (irregularSingular) {
|
|
167
|
+
return irregularSingular;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const lowerName = name.toLowerCase();
|
|
171
|
+
|
|
172
|
+
if (name.length <= 3 || NON_INFLECTING_FIELD_NAMES.has(lowerName)) {
|
|
173
|
+
return name;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (AMBIGUOUS_PLURAL_FIELD_NAMES.has(lowerName)) {
|
|
177
|
+
return name;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (lowerName.endsWith("ies")) {
|
|
181
|
+
if (name.length <= 4) {
|
|
182
|
+
return name.slice(0, -1);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (isConsonant(lowerName.at(-4) ?? "")) {
|
|
186
|
+
return `${name.slice(0, -3)}y`;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (
|
|
191
|
+
lowerName.endsWith("sses") ||
|
|
192
|
+
lowerName.endsWith("shes") ||
|
|
193
|
+
lowerName.endsWith("ches") ||
|
|
194
|
+
lowerName.endsWith("xes") ||
|
|
195
|
+
lowerName.endsWith("zes")
|
|
196
|
+
) {
|
|
197
|
+
return name.slice(0, -2);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (
|
|
201
|
+
lowerName.endsWith("s") &&
|
|
202
|
+
!lowerName.endsWith("ss") &&
|
|
203
|
+
!lowerName.endsWith("is") &&
|
|
204
|
+
!lowerName.endsWith("us")
|
|
205
|
+
) {
|
|
206
|
+
return name.slice(0, -1);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return name;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
interface AppendFieldPathParams {
|
|
213
|
+
readonly parentPath: ReadonlyArray<string>;
|
|
214
|
+
readonly fieldName: string;
|
|
215
|
+
readonly singularize: boolean;
|
|
216
|
+
readonly siblingFieldNames: ReadonlySet<string> | null;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function hasSiblingFieldPathCollision(params: {
|
|
220
|
+
readonly fieldName: string;
|
|
221
|
+
readonly singularFieldName: string;
|
|
222
|
+
readonly siblingFieldNames: ReadonlySet<string> | null;
|
|
223
|
+
}): boolean {
|
|
224
|
+
const { fieldName, singularFieldName, siblingFieldNames } = params;
|
|
225
|
+
|
|
226
|
+
if (!siblingFieldNames) {
|
|
227
|
+
return false;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
for (const siblingFieldName of siblingFieldNames) {
|
|
231
|
+
if (siblingFieldName === fieldName) {
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (
|
|
236
|
+
siblingFieldName === singularFieldName ||
|
|
237
|
+
singularizeFieldName(siblingFieldName) === singularFieldName
|
|
238
|
+
) {
|
|
239
|
+
return true;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return false;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function resolveFieldPathSegment(params: {
|
|
247
|
+
readonly fieldName: string;
|
|
248
|
+
readonly singularize: boolean;
|
|
249
|
+
readonly siblingFieldNames: ReadonlySet<string> | null;
|
|
250
|
+
}): string {
|
|
251
|
+
const { fieldName, singularize, siblingFieldNames } = params;
|
|
252
|
+
|
|
253
|
+
if (!singularize) {
|
|
254
|
+
return fieldName;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const singularFieldName = singularizeFieldName(fieldName);
|
|
258
|
+
if (
|
|
259
|
+
singularFieldName !== fieldName &&
|
|
260
|
+
hasSiblingFieldPathCollision({
|
|
261
|
+
fieldName,
|
|
262
|
+
singularFieldName,
|
|
263
|
+
siblingFieldNames,
|
|
264
|
+
})
|
|
265
|
+
) {
|
|
266
|
+
return fieldName;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return singularFieldName;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Append a field name to an auto-type field path.
|
|
274
|
+
*/
|
|
275
|
+
export function appendFieldPath(params: AppendFieldPathParams): string[] {
|
|
276
|
+
const { parentPath, fieldName, singularize, siblingFieldNames } = params;
|
|
277
|
+
return [
|
|
278
|
+
...parentPath,
|
|
279
|
+
resolveFieldPathSegment({ fieldName, singularize, siblingFieldNames }),
|
|
280
|
+
];
|
|
281
|
+
}
|
|
282
|
+
|
|
79
283
|
/**
|
|
80
284
|
* Remove Input suffix from type name if present.
|
|
81
285
|
*/
|
|
@@ -45,7 +45,11 @@ function extractTypenameFromFields(
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
const { tsType } = field;
|
|
48
|
-
if (
|
|
48
|
+
if (
|
|
49
|
+
tsType.nullable ||
|
|
50
|
+
tsType.kind !== "stringLiteral" ||
|
|
51
|
+
tsType.name === null
|
|
52
|
+
) {
|
|
49
53
|
return null;
|
|
50
54
|
}
|
|
51
55
|
|
|
@@ -63,7 +67,11 @@ function extractTypenameFromInlineObjectProperties(
|
|
|
63
67
|
const { property, fieldName } = found;
|
|
64
68
|
const { propertyType: tsType } = property;
|
|
65
69
|
|
|
66
|
-
if (
|
|
70
|
+
if (
|
|
71
|
+
tsType.nullable ||
|
|
72
|
+
tsType.kind !== "stringLiteral" ||
|
|
73
|
+
tsType.name === null
|
|
74
|
+
) {
|
|
67
75
|
return null;
|
|
68
76
|
}
|
|
69
77
|
|
|
@@ -206,12 +214,14 @@ function extractTypenames(
|
|
|
206
214
|
export interface CollectTypenameExtractionsParams {
|
|
207
215
|
readonly extractedTypes: ReadonlyArray<ExtractedTypeInfo>;
|
|
208
216
|
readonly typeMap: ReadonlyMap<string, ExtractedTypeInfo>;
|
|
217
|
+
/** Union names that have discriminatorFields configured; these are excluded from typename extraction. */
|
|
218
|
+
readonly discriminatorFieldUnionNames: ReadonlySet<string>;
|
|
209
219
|
}
|
|
210
220
|
|
|
211
221
|
export function collectTypenameExtractions(
|
|
212
222
|
params: CollectTypenameExtractionsParams,
|
|
213
223
|
): ReadonlyArray<TypenameExtractionResult> {
|
|
214
|
-
const { extractedTypes, typeMap } = params;
|
|
224
|
+
const { extractedTypes, typeMap, discriminatorFieldUnionNames } = params;
|
|
215
225
|
const results: TypenameExtractionResult[] = [];
|
|
216
226
|
|
|
217
227
|
for (const typeInfo of extractedTypes) {
|
|
@@ -219,6 +229,10 @@ export function collectTypenameExtractions(
|
|
|
219
229
|
typeInfo.metadata.kind === "union" ||
|
|
220
230
|
typeInfo.metadata.kind === "graphqlInterface"
|
|
221
231
|
) {
|
|
232
|
+
// Skip unions that have discriminatorFields configured; they use the discriminator pipeline instead
|
|
233
|
+
if (discriminatorFieldUnionNames.has(typeInfo.metadata.name)) {
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
222
236
|
const result = extractTypenames({ abstractType: typeInfo, typeMap });
|
|
223
237
|
if (result !== null) {
|
|
224
238
|
results.push(result);
|
|
@@ -1,12 +1,6 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
InlineObjectProperty,
|
|
5
|
-
} from "../type-extractor/types/index.js";
|
|
6
|
-
import type {
|
|
7
|
-
AutoGeneratedField,
|
|
8
|
-
AutoGeneratedType,
|
|
9
|
-
} from "./auto-type-generator.js";
|
|
1
|
+
import type { ExtractedTypeInfo } from "../type-extractor/types/index.js";
|
|
2
|
+
import type { AutoGeneratedType } from "./auto-type-generator.js";
|
|
3
|
+
import { generateObjectTypeFromInlineObject } from "./inline-object-converter.js";
|
|
10
4
|
import type { ResolveTypeFieldPattern } from "./resolve-type-generator.js";
|
|
11
5
|
import {
|
|
12
6
|
collectTypenameExtractions,
|
|
@@ -39,6 +33,8 @@ export interface CollectTypenameResolveTypesParams {
|
|
|
39
33
|
readonly extractedTypes: ReadonlyArray<ExtractedTypeInfo>;
|
|
40
34
|
readonly typeMap: ReadonlyMap<string, ExtractedTypeInfo>;
|
|
41
35
|
readonly manualResolveTypeNames: ReadonlySet<string>;
|
|
36
|
+
/** Union names that have discriminatorFields configured; these are excluded from typename processing. */
|
|
37
|
+
readonly discriminatorFieldUnionNames: ReadonlySet<string>;
|
|
42
38
|
}
|
|
43
39
|
|
|
44
40
|
export interface CollectTypenameResolveTypesResult {
|
|
@@ -83,100 +79,8 @@ function determineResolveTypePattern(
|
|
|
83
79
|
return { usedFieldNames, memberFieldMap };
|
|
84
80
|
}
|
|
85
81
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
case "string":
|
|
89
|
-
return "String";
|
|
90
|
-
case "number":
|
|
91
|
-
return "Float";
|
|
92
|
-
case "boolean":
|
|
93
|
-
return "Boolean";
|
|
94
|
-
default:
|
|
95
|
-
return "String";
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
function convertInlineObjectPropertyToField(
|
|
100
|
-
property: InlineObjectProperty,
|
|
101
|
-
): AutoGeneratedField | null {
|
|
102
|
-
if (
|
|
103
|
-
property.propertyName === "__typename" ||
|
|
104
|
-
property.propertyName === "$typeName"
|
|
105
|
-
) {
|
|
106
|
-
return null;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
const tsType = property.propertyType;
|
|
110
|
-
let typeName: string;
|
|
111
|
-
const nullable = tsType.nullable;
|
|
112
|
-
let list = false;
|
|
113
|
-
let listItemNullable: boolean | null = null;
|
|
114
|
-
|
|
115
|
-
if (tsType.kind === "array" && tsType.elementType) {
|
|
116
|
-
list = true;
|
|
117
|
-
listItemNullable = tsType.elementType.nullable;
|
|
118
|
-
const elementName = tsType.elementType.name ?? "String";
|
|
119
|
-
typeName =
|
|
120
|
-
tsType.elementType.kind === "primitive"
|
|
121
|
-
? primitiveToGraphQLScalar(elementName)
|
|
122
|
-
: elementName;
|
|
123
|
-
} else if (tsType.kind === "reference" && tsType.name) {
|
|
124
|
-
typeName = tsType.name;
|
|
125
|
-
} else if (tsType.kind === "primitive" && tsType.name) {
|
|
126
|
-
typeName = primitiveToGraphQLScalar(tsType.name);
|
|
127
|
-
} else if (tsType.kind === "scalar" && tsType.scalarInfo) {
|
|
128
|
-
typeName = tsType.scalarInfo.scalarName;
|
|
129
|
-
} else {
|
|
130
|
-
typeName = "String";
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
return {
|
|
134
|
-
name: property.propertyName,
|
|
135
|
-
type: {
|
|
136
|
-
typeName,
|
|
137
|
-
nullable,
|
|
138
|
-
list,
|
|
139
|
-
listItemNullable,
|
|
140
|
-
},
|
|
141
|
-
description: property.description,
|
|
142
|
-
deprecated: property.deprecated,
|
|
143
|
-
directives: null,
|
|
144
|
-
defaultValue: null,
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
function generateObjectTypeFromInlineObject(
|
|
149
|
-
inlineObjectMember: InlineObjectMember,
|
|
150
|
-
typeName: string,
|
|
151
|
-
abstractTypeName: string,
|
|
152
|
-
sourceFile: string,
|
|
153
|
-
): AutoGeneratedType {
|
|
154
|
-
const fields: AutoGeneratedField[] = [];
|
|
155
|
-
|
|
156
|
-
for (const property of inlineObjectMember.properties) {
|
|
157
|
-
const field = convertInlineObjectPropertyToField(property);
|
|
158
|
-
if (field !== null) {
|
|
159
|
-
fields.push(field);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
return {
|
|
164
|
-
name: typeName,
|
|
165
|
-
kind: "Object",
|
|
166
|
-
fields,
|
|
167
|
-
enumValues: null,
|
|
168
|
-
unionMembers: null,
|
|
169
|
-
needsStringEnumMapping: false,
|
|
170
|
-
sourceLocation: { file: sourceFile, line: 1, column: 1 },
|
|
171
|
-
generatedFrom: {
|
|
172
|
-
parentTypeName: abstractTypeName,
|
|
173
|
-
fieldPath: [],
|
|
174
|
-
context: "typeField",
|
|
175
|
-
},
|
|
176
|
-
description: null,
|
|
177
|
-
resolveTypeFieldPattern: null,
|
|
178
|
-
};
|
|
179
|
-
}
|
|
82
|
+
/** Typename-related properties that should be excluded from generated object types. */
|
|
83
|
+
const TYPENAME_PROPERTY_NAMES = new Set(["__typename", "$typeName"]);
|
|
180
84
|
|
|
181
85
|
function collectGeneratedObjectTypes(
|
|
182
86
|
extraction: TypenameExtractionResult,
|
|
@@ -209,12 +113,13 @@ function collectGeneratedObjectTypes(
|
|
|
209
113
|
|
|
210
114
|
const typeName = member.typenameInfo.typeName;
|
|
211
115
|
|
|
212
|
-
const objectType = generateObjectTypeFromInlineObject(
|
|
116
|
+
const objectType = generateObjectTypeFromInlineObject({
|
|
213
117
|
inlineObjectMember,
|
|
214
118
|
typeName,
|
|
215
|
-
extraction.abstractTypeName,
|
|
216
|
-
extractedType.metadata.sourceFile,
|
|
217
|
-
|
|
119
|
+
abstractTypeName: extraction.abstractTypeName,
|
|
120
|
+
sourceFile: extractedType.metadata.sourceFile,
|
|
121
|
+
skipPropertyNames: TYPENAME_PROPERTY_NAMES,
|
|
122
|
+
});
|
|
218
123
|
|
|
219
124
|
generatedObjectTypes.push(objectType);
|
|
220
125
|
generatedInlineObjectTypes.push({
|
|
@@ -230,11 +135,17 @@ function collectGeneratedObjectTypes(
|
|
|
230
135
|
export function collectTypenameResolveTypes(
|
|
231
136
|
params: CollectTypenameResolveTypesParams,
|
|
232
137
|
): CollectTypenameResolveTypesResult {
|
|
233
|
-
const {
|
|
138
|
+
const {
|
|
139
|
+
extractedTypes,
|
|
140
|
+
typeMap,
|
|
141
|
+
manualResolveTypeNames,
|
|
142
|
+
discriminatorFieldUnionNames,
|
|
143
|
+
} = params;
|
|
234
144
|
|
|
235
145
|
const extractions = collectTypenameExtractions({
|
|
236
146
|
extractedTypes,
|
|
237
147
|
typeMap,
|
|
148
|
+
discriminatorFieldUnionNames,
|
|
238
149
|
});
|
|
239
150
|
|
|
240
151
|
const autoResolveTypes: TypenameAutoResolveTypeInfo[] = [];
|
|
@@ -15,6 +15,13 @@
|
|
|
15
15
|
*/
|
|
16
16
|
export const TYPENAME_FIELD_NAMES = ["__typename", "$typeName"] as const;
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Check if a field name is a typename discrimination field.
|
|
20
|
+
*/
|
|
21
|
+
export function isTypenameFieldName(name: string): boolean {
|
|
22
|
+
return (TYPENAME_FIELD_NAMES as readonly string[]).includes(name);
|
|
23
|
+
}
|
|
24
|
+
|
|
18
25
|
/**
|
|
19
26
|
* The field name used for type discrimination.
|
|
20
27
|
*/
|
|
@@ -74,7 +74,7 @@ function analyzeInlineObjectTypename(
|
|
|
74
74
|
return {
|
|
75
75
|
exists: true,
|
|
76
76
|
fieldName,
|
|
77
|
-
isStringLiteral: tsType.kind === "
|
|
77
|
+
isStringLiteral: tsType.kind === "stringLiteral" && tsType.name !== null,
|
|
78
78
|
isNullable: tsType.nullable,
|
|
79
79
|
};
|
|
80
80
|
}
|
|
@@ -171,7 +171,8 @@ export function validateTypenames(
|
|
|
171
171
|
|
|
172
172
|
const { typeName, fieldName } = member.typenameInfo;
|
|
173
173
|
const memberTypeName =
|
|
174
|
-
member.memberTypeName ??
|
|
174
|
+
member.memberTypeName ??
|
|
175
|
+
`(anonymous member at index ${member.memberIndex})`;
|
|
175
176
|
|
|
176
177
|
const existing = typenameValueToMembers.get(typeName) ?? [];
|
|
177
178
|
existing.push({ memberTypeName, fieldName });
|
|
@@ -238,7 +239,7 @@ function extractTypenameFromObjectType(
|
|
|
238
239
|
if (
|
|
239
240
|
field.optional ||
|
|
240
241
|
tsType.nullable ||
|
|
241
|
-
tsType.kind !== "
|
|
242
|
+
tsType.kind !== "stringLiteral" ||
|
|
242
243
|
tsType.name === null
|
|
243
244
|
) {
|
|
244
245
|
return null;
|
package/src/commands/gen.ts
CHANGED
|
@@ -45,8 +45,14 @@ export async function runGenCommand(
|
|
|
45
45
|
? dirname(configResult.configPath)
|
|
46
46
|
: options.cwd;
|
|
47
47
|
|
|
48
|
-
const {
|
|
49
|
-
|
|
48
|
+
const {
|
|
49
|
+
sourceDir,
|
|
50
|
+
sourceIgnoreGlobs,
|
|
51
|
+
output,
|
|
52
|
+
scalars,
|
|
53
|
+
tsconfigPath,
|
|
54
|
+
discriminatorFields,
|
|
55
|
+
} = configResult.config;
|
|
50
56
|
|
|
51
57
|
const config: GenerationConfig = {
|
|
52
58
|
cwd: options.cwd,
|
|
@@ -56,6 +62,7 @@ export async function runGenCommand(
|
|
|
56
62
|
configDir,
|
|
57
63
|
customScalars: scalars,
|
|
58
64
|
tsconfigPath,
|
|
65
|
+
discriminatorFields,
|
|
59
66
|
};
|
|
60
67
|
|
|
61
68
|
progressReporter.startPhase("Extracting types");
|
package/src/config/types.ts
CHANGED
|
@@ -100,6 +100,16 @@ export interface GqlkitConfig {
|
|
|
100
100
|
* Hook configuration for lifecycle events.
|
|
101
101
|
*/
|
|
102
102
|
readonly hooks?: HooksConfig;
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Custom discriminator field mappings for union types.
|
|
106
|
+
* Maps GraphQL union type names to TypeScript discriminator field names.
|
|
107
|
+
* When specified, gqlkit generates __resolveType functions based on these fields
|
|
108
|
+
* instead of requiring $typeName or __typename.
|
|
109
|
+
*/
|
|
110
|
+
readonly discriminatorFields?: Readonly<
|
|
111
|
+
Record<string, string | ReadonlyArray<string>>
|
|
112
|
+
>;
|
|
103
113
|
}
|
|
104
114
|
|
|
105
115
|
/**
|
|
@@ -42,6 +42,15 @@ export interface ResolvedHooksConfig {
|
|
|
42
42
|
readonly afterAllFileWrite: ReadonlyArray<string>;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
/**
|
|
46
|
+
* Normalized discriminator fields mapping.
|
|
47
|
+
* All values are normalized to arrays (single strings are wrapped in arrays).
|
|
48
|
+
*/
|
|
49
|
+
export type ResolvedDiscriminatorFieldsMap = ReadonlyMap<
|
|
50
|
+
string,
|
|
51
|
+
ReadonlyArray<string>
|
|
52
|
+
>;
|
|
53
|
+
|
|
45
54
|
export interface ResolvedConfig {
|
|
46
55
|
readonly sourceDir: string;
|
|
47
56
|
readonly sourceIgnoreGlobs: ReadonlyArray<string>;
|
|
@@ -49,6 +58,7 @@ export interface ResolvedConfig {
|
|
|
49
58
|
readonly scalars: ReadonlyArray<ResolvedScalarMapping>;
|
|
50
59
|
readonly tsconfigPath: string | null;
|
|
51
60
|
readonly hooks: ResolvedHooksConfig;
|
|
61
|
+
readonly discriminatorFields: ResolvedDiscriminatorFieldsMap;
|
|
52
62
|
}
|
|
53
63
|
|
|
54
64
|
export interface LoadConfigResult {
|
|
@@ -82,6 +92,7 @@ const DEFAULT_RESOLVED_CONFIG: ResolvedConfig = {
|
|
|
82
92
|
scalars: [],
|
|
83
93
|
tsconfigPath: null,
|
|
84
94
|
hooks: DEFAULT_HOOKS_CONFIG,
|
|
95
|
+
discriminatorFields: new Map(),
|
|
85
96
|
};
|
|
86
97
|
|
|
87
98
|
export async function loadConfig(
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
DEFAULT_SOURCE_DIR,
|
|
7
7
|
DEFAULT_TYPEDEFS_PATH,
|
|
8
8
|
type ResolvedConfig,
|
|
9
|
+
type ResolvedDiscriminatorFieldsMap,
|
|
9
10
|
type ResolvedHooksConfig,
|
|
10
11
|
type ResolvedOutputConfig,
|
|
11
12
|
type ResolvedScalarMapping,
|
|
@@ -584,6 +585,96 @@ function validateHooksConfig(
|
|
|
584
585
|
return { resolved: undefined, diagnostics };
|
|
585
586
|
}
|
|
586
587
|
|
|
588
|
+
function validateDiscriminatorFieldsConfig(
|
|
589
|
+
value: unknown,
|
|
590
|
+
configPath: string,
|
|
591
|
+
): {
|
|
592
|
+
resolved: ResolvedDiscriminatorFieldsMap | undefined;
|
|
593
|
+
diagnostics: Diagnostic[];
|
|
594
|
+
} {
|
|
595
|
+
const diagnostics: Diagnostic[] = [];
|
|
596
|
+
|
|
597
|
+
if (value === undefined) {
|
|
598
|
+
return { resolved: new Map(), diagnostics: [] };
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
if (!isRecord(value)) {
|
|
602
|
+
diagnostics.push({
|
|
603
|
+
code: "CONFIG_INVALID_DISCRIMINATOR_FIELDS",
|
|
604
|
+
message: "discriminatorFields must be an object",
|
|
605
|
+
severity: "error",
|
|
606
|
+
location: { file: configPath, line: 1, column: 1 },
|
|
607
|
+
});
|
|
608
|
+
return { resolved: undefined, diagnostics };
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
const result = new Map<string, ReadonlyArray<string>>();
|
|
612
|
+
|
|
613
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
614
|
+
if (typeof entry === "string") {
|
|
615
|
+
if (entry === "") {
|
|
616
|
+
diagnostics.push({
|
|
617
|
+
code: "CONFIG_EMPTY_DISCRIMINATOR_FIELDS",
|
|
618
|
+
message: `discriminatorFields["${key}"] cannot be an empty string`,
|
|
619
|
+
severity: "error",
|
|
620
|
+
location: { file: configPath, line: 1, column: 1 },
|
|
621
|
+
});
|
|
622
|
+
continue;
|
|
623
|
+
}
|
|
624
|
+
result.set(key, [entry]);
|
|
625
|
+
} else if (Array.isArray(entry)) {
|
|
626
|
+
if (entry.length === 0) {
|
|
627
|
+
diagnostics.push({
|
|
628
|
+
code: "CONFIG_EMPTY_DISCRIMINATOR_FIELDS",
|
|
629
|
+
message: `discriminatorFields["${key}"] cannot be an empty array`,
|
|
630
|
+
severity: "error",
|
|
631
|
+
location: { file: configPath, line: 1, column: 1 },
|
|
632
|
+
});
|
|
633
|
+
continue;
|
|
634
|
+
}
|
|
635
|
+
let hasError = false;
|
|
636
|
+
for (const item of entry) {
|
|
637
|
+
if (typeof item !== "string") {
|
|
638
|
+
diagnostics.push({
|
|
639
|
+
code: "CONFIG_INVALID_DISCRIMINATOR_ENTRY",
|
|
640
|
+
message: `discriminatorFields["${key}"] array must contain only strings`,
|
|
641
|
+
severity: "error",
|
|
642
|
+
location: { file: configPath, line: 1, column: 1 },
|
|
643
|
+
});
|
|
644
|
+
hasError = true;
|
|
645
|
+
break;
|
|
646
|
+
}
|
|
647
|
+
if (item === "") {
|
|
648
|
+
diagnostics.push({
|
|
649
|
+
code: "CONFIG_EMPTY_DISCRIMINATOR_FIELDS",
|
|
650
|
+
message: `discriminatorFields["${key}"] array contains an empty string`,
|
|
651
|
+
severity: "error",
|
|
652
|
+
location: { file: configPath, line: 1, column: 1 },
|
|
653
|
+
});
|
|
654
|
+
hasError = true;
|
|
655
|
+
break;
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
if (!hasError) {
|
|
659
|
+
result.set(key, entry as string[]);
|
|
660
|
+
}
|
|
661
|
+
} else {
|
|
662
|
+
diagnostics.push({
|
|
663
|
+
code: "CONFIG_INVALID_DISCRIMINATOR_ENTRY",
|
|
664
|
+
message: `discriminatorFields["${key}"] must be a string or array of strings`,
|
|
665
|
+
severity: "error",
|
|
666
|
+
location: { file: configPath, line: 1, column: 1 },
|
|
667
|
+
});
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
if (diagnostics.length > 0) {
|
|
672
|
+
return { resolved: undefined, diagnostics };
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
return { resolved: result, diagnostics: [] };
|
|
676
|
+
}
|
|
677
|
+
|
|
587
678
|
export function validateConfig(
|
|
588
679
|
options: ValidateConfigOptions,
|
|
589
680
|
): ValidateConfigResult {
|
|
@@ -621,6 +712,12 @@ export function validateConfig(
|
|
|
621
712
|
const hooksResult = validateHooksConfig(config["hooks"], configPath);
|
|
622
713
|
diagnostics.push(...hooksResult.diagnostics);
|
|
623
714
|
|
|
715
|
+
const discriminatorFieldsResult = validateDiscriminatorFieldsConfig(
|
|
716
|
+
config["discriminatorFields"],
|
|
717
|
+
configPath,
|
|
718
|
+
);
|
|
719
|
+
diagnostics.push(...discriminatorFieldsResult.diagnostics);
|
|
720
|
+
|
|
624
721
|
if (config["scalars"] !== undefined && !Array.isArray(config["scalars"])) {
|
|
625
722
|
diagnostics.push({
|
|
626
723
|
code: "CONFIG_INVALID_TYPE",
|
|
@@ -685,7 +782,8 @@ export function validateConfig(
|
|
|
685
782
|
!sourceDirResult.resolved ||
|
|
686
783
|
!sourceIgnoreGlobsResult.resolved ||
|
|
687
784
|
!outputResult.resolved ||
|
|
688
|
-
!hooksResult.resolved
|
|
785
|
+
!hooksResult.resolved ||
|
|
786
|
+
!discriminatorFieldsResult.resolved
|
|
689
787
|
) {
|
|
690
788
|
return { valid: false, resolvedConfig: undefined, diagnostics };
|
|
691
789
|
}
|
|
@@ -699,6 +797,7 @@ export function validateConfig(
|
|
|
699
797
|
scalars: resolvedScalars,
|
|
700
798
|
tsconfigPath: tsconfigPathResult.resolved,
|
|
701
799
|
hooks: hooksResult.resolved,
|
|
800
|
+
discriminatorFields: discriminatorFieldsResult.resolved,
|
|
702
801
|
},
|
|
703
802
|
diagnostics: [],
|
|
704
803
|
};
|