@gqlkit-ts/cli 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auto-type-generator/auto-type-generator.d.ts +10 -4
- package/dist/auto-type-generator/auto-type-generator.d.ts.map +1 -1
- package/dist/auto-type-generator/auto-type-generator.js +640 -133
- package/dist/auto-type-generator/auto-type-generator.js.map +1 -1
- package/dist/auto-type-generator/index.d.ts +8 -1
- 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 +13 -5
- package/dist/auto-type-generator/inline-enum-collector.d.ts.map +1 -1
- package/dist/auto-type-generator/inline-enum-collector.js +107 -71
- package/dist/auto-type-generator/inline-enum-collector.js.map +1 -1
- package/dist/auto-type-generator/inline-object-traverser.d.ts +20 -0
- package/dist/auto-type-generator/inline-object-traverser.d.ts.map +1 -0
- package/dist/auto-type-generator/inline-object-traverser.js +22 -0
- package/dist/auto-type-generator/inline-object-traverser.js.map +1 -0
- package/dist/auto-type-generator/inline-union-collector.d.ts +29 -0
- package/dist/auto-type-generator/inline-union-collector.d.ts.map +1 -0
- package/dist/auto-type-generator/inline-union-collector.js +216 -0
- package/dist/auto-type-generator/inline-union-collector.js.map +1 -0
- package/dist/auto-type-generator/inline-union-types.d.ts +29 -0
- package/dist/auto-type-generator/inline-union-types.d.ts.map +1 -0
- package/dist/auto-type-generator/inline-union-types.js +2 -0
- package/dist/auto-type-generator/inline-union-types.js.map +1 -0
- package/dist/auto-type-generator/inline-union-validator.d.ts +76 -0
- package/dist/auto-type-generator/inline-union-validator.d.ts.map +1 -0
- package/dist/auto-type-generator/inline-union-validator.js +329 -0
- package/dist/auto-type-generator/inline-union-validator.js.map +1 -0
- package/dist/auto-type-generator/naming-convention.d.ts +18 -1
- package/dist/auto-type-generator/naming-convention.d.ts.map +1 -1
- package/dist/auto-type-generator/naming-convention.js +16 -0
- package/dist/auto-type-generator/naming-convention.js.map +1 -1
- package/dist/auto-type-generator/resolve-type-generator.d.ts +20 -0
- package/dist/auto-type-generator/resolve-type-generator.d.ts.map +1 -0
- package/dist/auto-type-generator/resolve-type-generator.js +2 -0
- package/dist/auto-type-generator/resolve-type-generator.js.map +1 -0
- package/dist/auto-type-generator/resolver-field-iterator.d.ts +13 -0
- package/dist/auto-type-generator/resolver-field-iterator.d.ts.map +1 -0
- package/dist/auto-type-generator/resolver-field-iterator.js +22 -0
- package/dist/auto-type-generator/resolver-field-iterator.js.map +1 -0
- package/dist/auto-type-generator/typename-extractor.d.ts +26 -0
- package/dist/auto-type-generator/typename-extractor.d.ts.map +1 -0
- package/dist/auto-type-generator/typename-extractor.js +142 -0
- package/dist/auto-type-generator/typename-extractor.js.map +1 -0
- package/dist/auto-type-generator/typename-resolve-type-generator.d.ts +35 -0
- package/dist/auto-type-generator/typename-resolve-type-generator.d.ts.map +1 -0
- package/dist/auto-type-generator/typename-resolve-type-generator.js +177 -0
- package/dist/auto-type-generator/typename-resolve-type-generator.js.map +1 -0
- package/dist/auto-type-generator/typename-types.d.ts +43 -0
- package/dist/auto-type-generator/typename-types.d.ts.map +1 -0
- package/dist/auto-type-generator/typename-types.js +37 -0
- package/dist/auto-type-generator/typename-types.js.map +1 -0
- package/dist/auto-type-generator/typename-validator.d.ts +37 -0
- package/dist/auto-type-generator/typename-validator.d.ts.map +1 -0
- package/dist/auto-type-generator/typename-validator.js +206 -0
- package/dist/auto-type-generator/typename-validator.js.map +1 -0
- package/dist/cli.js +2 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/docs.d.ts +51 -0
- package/dist/commands/docs.d.ts.map +1 -0
- package/dist/commands/docs.js +154 -0
- package/dist/commands/docs.js.map +1 -0
- package/dist/gen-orchestrator/orchestrator.d.ts.map +1 -1
- package/dist/gen-orchestrator/orchestrator.js +13 -6
- package/dist/gen-orchestrator/orchestrator.js.map +1 -1
- package/dist/resolver-extractor/extract-resolvers.d.ts +19 -1
- package/dist/resolver-extractor/extract-resolvers.d.ts.map +1 -1
- package/dist/resolver-extractor/extractor/define-api-extractor.d.ts +5 -0
- package/dist/resolver-extractor/extractor/define-api-extractor.d.ts.map +1 -1
- package/dist/resolver-extractor/extractor/define-api-extractor.js +14 -61
- package/dist/resolver-extractor/extractor/define-api-extractor.js.map +1 -1
- package/dist/resolver-extractor/index.d.ts +0 -1
- package/dist/resolver-extractor/index.d.ts.map +1 -1
- package/dist/resolver-extractor/validator/abstract-resolver-validator.d.ts +1 -0
- package/dist/resolver-extractor/validator/abstract-resolver-validator.d.ts.map +1 -1
- package/dist/resolver-extractor/validator/abstract-resolver-validator.js +9 -5
- 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 +20 -0
- package/dist/schema-generator/emitter/code-emitter.js.map +1 -1
- package/dist/schema-generator/generate-schema.d.ts +1 -0
- package/dist/schema-generator/generate-schema.d.ts.map +1 -1
- package/dist/schema-generator/generate-schema.js +72 -3
- package/dist/schema-generator/generate-schema.js.map +1 -1
- package/dist/schema-generator/integrator/result-integrator.d.ts +14 -2
- package/dist/schema-generator/integrator/result-integrator.d.ts.map +1 -1
- package/dist/schema-generator/integrator/result-integrator.js +54 -1
- 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 +22 -0
- package/dist/schema-generator/resolver-collector/resolver-collector.js.map +1 -1
- package/dist/shared/enum-prefix-detector.d.ts +63 -0
- package/dist/shared/enum-prefix-detector.d.ts.map +1 -0
- package/dist/shared/enum-prefix-detector.js +80 -0
- package/dist/shared/enum-prefix-detector.js.map +1 -0
- package/dist/shared/ignore-fields-detector.d.ts +26 -0
- package/dist/shared/ignore-fields-detector.d.ts.map +1 -0
- package/dist/shared/ignore-fields-detector.js +83 -0
- package/dist/shared/ignore-fields-detector.js.map +1 -0
- package/dist/shared/ignore-fields-validator.d.ts +29 -0
- package/dist/shared/ignore-fields-validator.d.ts.map +1 -0
- package/dist/shared/ignore-fields-validator.js +43 -0
- package/dist/shared/ignore-fields-validator.js.map +1 -0
- package/dist/shared/index.d.ts +2 -0
- package/dist/shared/index.d.ts.map +1 -1
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/source-location.d.ts +5 -0
- package/dist/shared/source-location.d.ts.map +1 -1
- package/dist/shared/source-location.js +7 -0
- package/dist/shared/source-location.js.map +1 -1
- package/dist/type-extractor/converter/graphql-converter.d.ts.map +1 -1
- package/dist/type-extractor/converter/graphql-converter.js +21 -7
- package/dist/type-extractor/converter/graphql-converter.js.map +1 -1
- package/dist/type-extractor/extractor/field-type-resolver.js +42 -3
- package/dist/type-extractor/extractor/field-type-resolver.js.map +1 -1
- package/dist/type-extractor/extractor/type-extractor.d.ts.map +1 -1
- package/dist/type-extractor/extractor/type-extractor.js +88 -23
- package/dist/type-extractor/extractor/type-extractor.js.map +1 -1
- package/dist/type-extractor/types/diagnostics.d.ts +1 -1
- package/dist/type-extractor/types/diagnostics.d.ts.map +1 -1
- package/dist/type-extractor/types/ts-type-reference-factory.d.ts +10 -2
- package/dist/type-extractor/types/ts-type-reference-factory.d.ts.map +1 -1
- package/dist/type-extractor/types/ts-type-reference-factory.js +8 -2
- package/dist/type-extractor/types/ts-type-reference-factory.js.map +1 -1
- package/dist/type-extractor/types/typescript.d.ts +4 -0
- package/dist/type-extractor/types/typescript.d.ts.map +1 -1
- package/docs/coding-agents.md +64 -0
- package/docs/configuration.md +6 -20
- package/docs/getting-started.md +15 -12
- package/docs/index.md +36 -22
- package/docs/integration/apollo.md +8 -40
- package/docs/integration/drizzle.md +6 -10
- package/docs/integration/prisma.md +196 -0
- package/docs/integration/yoga.md +8 -40
- package/docs/schema/abstract-resolvers.md +117 -0
- package/docs/schema/directives.md +5 -0
- package/docs/schema/documentation.md +5 -0
- package/docs/schema/enums.md +99 -0
- package/docs/schema/fields.md +64 -0
- package/docs/schema/index.md +21 -0
- package/docs/schema/inputs.md +115 -15
- package/docs/schema/interfaces.md +31 -1
- package/docs/schema/objects.md +40 -0
- package/docs/schema/queries-mutations.md +136 -22
- package/docs/schema/scalars.md +5 -0
- package/docs/schema/unions.md +208 -1
- package/docs/what-is-gqlkit.md +13 -8
- package/package.json +6 -4
- package/src/auto-type-generator/auto-type-generator.ts +946 -201
- package/src/auto-type-generator/index.ts +42 -0
- package/src/auto-type-generator/inline-enum-collector.ts +187 -139
- package/src/auto-type-generator/inline-object-traverser.ts +49 -0
- package/src/auto-type-generator/inline-union-collector.ts +402 -0
- package/src/auto-type-generator/inline-union-types.ts +33 -0
- package/src/auto-type-generator/inline-union-validator.ts +482 -0
- package/src/auto-type-generator/naming-convention.ts +38 -1
- package/src/auto-type-generator/resolve-type-generator.ts +21 -0
- package/src/auto-type-generator/resolver-field-iterator.ts +39 -0
- package/src/auto-type-generator/typename-extractor.ts +230 -0
- package/src/auto-type-generator/typename-resolve-type-generator.ts +281 -0
- package/src/auto-type-generator/typename-types.ts +66 -0
- package/src/auto-type-generator/typename-validator.ts +326 -0
- package/src/cli.ts +2 -0
- package/src/commands/docs.ts +211 -0
- package/src/gen-orchestrator/orchestrator.ts +20 -6
- package/src/resolver-extractor/extract-resolvers.ts +19 -0
- package/src/resolver-extractor/extractor/define-api-extractor.ts +23 -89
- package/src/resolver-extractor/index.ts +0 -6
- package/src/resolver-extractor/validator/abstract-resolver-validator.ts +16 -8
- package/src/schema-generator/emitter/code-emitter.ts +34 -0
- package/src/schema-generator/generate-schema.ts +99 -2
- package/src/schema-generator/integrator/result-integrator.ts +70 -1
- package/src/schema-generator/resolver-collector/resolver-collector.ts +34 -0
- package/src/shared/enum-prefix-detector.ts +99 -0
- package/src/shared/ignore-fields-detector.ts +109 -0
- package/src/shared/ignore-fields-validator.ts +66 -0
- package/src/shared/index.ts +2 -0
- package/src/shared/source-location.ts +11 -0
- package/src/type-extractor/converter/graphql-converter.ts +31 -7
- package/src/type-extractor/extractor/field-type-resolver.ts +48 -3
- package/src/type-extractor/extractor/type-extractor.ts +103 -26
- package/src/type-extractor/types/diagnostics.ts +12 -2
- package/src/type-extractor/types/ts-type-reference-factory.ts +18 -5
- package/src/type-extractor/types/typescript.ts +4 -0
- package/dist/resolver-extractor/validator/only-validator.d.ts +0 -61
- package/dist/resolver-extractor/validator/only-validator.d.ts.map +0 -1
- package/dist/resolver-extractor/validator/only-validator.js +0 -76
- package/dist/resolver-extractor/validator/only-validator.js.map +0 -1
- package/src/resolver-extractor/validator/only-validator.ts +0 -158
|
@@ -62,6 +62,11 @@ export interface DefineApiResolverInfo {
|
|
|
62
62
|
readonly args: ReadonlyArray<ArgumentDefinition> | null;
|
|
63
63
|
readonly returnType: TSTypeReference;
|
|
64
64
|
readonly sourceFile: string;
|
|
65
|
+
readonly sourceLocation: {
|
|
66
|
+
readonly file: string;
|
|
67
|
+
readonly line: number;
|
|
68
|
+
readonly column: number;
|
|
69
|
+
};
|
|
65
70
|
readonly exportedInputTypes: ReadonlyArray<ExportedInputType>;
|
|
66
71
|
readonly description: string | null;
|
|
67
72
|
readonly deprecated: DeprecationInfo | null;
|
|
@@ -277,48 +282,15 @@ function shouldUnwrapAsGqlField(type: ts.Type): boolean {
|
|
|
277
282
|
return hasDirectiveMetadata(type);
|
|
278
283
|
}
|
|
279
284
|
|
|
280
|
-
/**
|
|
281
|
-
* Checks if a type is structurally equivalent to Record<string, never>.
|
|
282
|
-
* This is a special type that represents "no arguments".
|
|
283
|
-
* Detection is based on type structure, not type names.
|
|
284
|
-
*/
|
|
285
|
-
function isNoArgsType(type: ts.Type, checker: ts.TypeChecker): boolean {
|
|
286
|
-
const apparentType = checker.getApparentType(type);
|
|
287
|
-
|
|
288
|
-
// Check for string index signature with 'never' value type
|
|
289
|
-
const indexInfos = checker.getIndexInfosOfType(apparentType);
|
|
290
|
-
const hasNeverStringIndex = indexInfos.some((info) => {
|
|
291
|
-
return (
|
|
292
|
-
(info.keyType.flags & ts.TypeFlags.String) !== 0 &&
|
|
293
|
-
(info.type.flags & ts.TypeFlags.Never) !== 0
|
|
294
|
-
);
|
|
295
|
-
});
|
|
296
|
-
|
|
297
|
-
if (!hasNeverStringIndex) {
|
|
298
|
-
return false;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
// Check that there are no named properties (excluding metadata properties)
|
|
302
|
-
const properties = apparentType
|
|
303
|
-
.getProperties()
|
|
304
|
-
.filter((p) => !p.getName().startsWith("$"));
|
|
305
|
-
|
|
306
|
-
return properties.length === 0;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
285
|
/**
|
|
310
286
|
* Checks if a type has only index signatures with no named properties.
|
|
311
287
|
* Types like `{ [key: string]: number }` return true.
|
|
312
|
-
*
|
|
288
|
+
* Returns false for NoArgs type (Record<string, never>).
|
|
313
289
|
*/
|
|
314
290
|
function hasOnlyIndexSignatures(
|
|
315
291
|
type: ts.Type,
|
|
316
292
|
checker: ts.TypeChecker,
|
|
317
293
|
): boolean {
|
|
318
|
-
if (isNoArgsType(type, checker)) {
|
|
319
|
-
return false;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
294
|
const targetType = checker.getApparentType(type);
|
|
323
295
|
|
|
324
296
|
const indexInfos = checker.getIndexInfosOfType(targetType);
|
|
@@ -328,6 +300,17 @@ function hasOnlyIndexSignatures(
|
|
|
328
300
|
return false;
|
|
329
301
|
}
|
|
330
302
|
|
|
303
|
+
const hasNeverStringIndex = indexInfos.some((info) => {
|
|
304
|
+
return (
|
|
305
|
+
(info.keyType.flags & ts.TypeFlags.String) !== 0 &&
|
|
306
|
+
(info.type.flags & ts.TypeFlags.Never) !== 0
|
|
307
|
+
);
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
if (hasNeverStringIndex) {
|
|
311
|
+
return false;
|
|
312
|
+
}
|
|
313
|
+
|
|
331
314
|
const properties = targetType
|
|
332
315
|
.getProperties()
|
|
333
316
|
.filter((p) => !p.getName().startsWith(" $"));
|
|
@@ -458,37 +441,6 @@ function validateArgsType(
|
|
|
458
441
|
return diagnostics;
|
|
459
442
|
}
|
|
460
443
|
|
|
461
|
-
/**
|
|
462
|
-
* Checks if the extracted args are empty and the original type was not NoArgs.
|
|
463
|
-
* This indicates the type resolved to an empty object.
|
|
464
|
-
* Does not emit warnings for types that only have index signatures (they get INDEX_SIGNATURE_ONLY error instead).
|
|
465
|
-
*/
|
|
466
|
-
function checkEmptyArgsType(
|
|
467
|
-
argsType: ts.Type,
|
|
468
|
-
argsTypeNode: ts.TypeNode,
|
|
469
|
-
args: ArgumentDefinition[] | null,
|
|
470
|
-
checker: ts.TypeChecker,
|
|
471
|
-
): Diagnostic | null {
|
|
472
|
-
if (isNoArgsType(argsType, checker)) {
|
|
473
|
-
return null;
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
if (hasOnlyIndexSignatures(argsType, checker)) {
|
|
477
|
-
return null;
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
if (args !== null && args.length === 0) {
|
|
481
|
-
const typeName = getTypeNameForDiagnostic(argsType, checker);
|
|
482
|
-
return {
|
|
483
|
-
code: "EMPTY_TYPE_PROPERTIES",
|
|
484
|
-
message: `Type '${typeName}' has no properties. Consider adding properties or using a different type.`,
|
|
485
|
-
severity: "warning",
|
|
486
|
-
location: getSourceLocationFromNode(argsTypeNode),
|
|
487
|
-
};
|
|
488
|
-
}
|
|
489
|
-
return null;
|
|
490
|
-
}
|
|
491
|
-
|
|
492
444
|
interface ExtractTypeArgumentsFromCallParams {
|
|
493
445
|
readonly node: ts.CallExpression;
|
|
494
446
|
readonly inputContext: FieldTypeResolverContext;
|
|
@@ -538,18 +490,6 @@ function extractTypeArgumentsFromCall(
|
|
|
538
490
|
? null
|
|
539
491
|
: extractArgsFromType(argsType, inputContext, argsTypeNode);
|
|
540
492
|
|
|
541
|
-
if (!isNoArgs) {
|
|
542
|
-
const emptyDiagnostic = checkEmptyArgsType(
|
|
543
|
-
argsType,
|
|
544
|
-
argsTypeNode,
|
|
545
|
-
args,
|
|
546
|
-
checker,
|
|
547
|
-
);
|
|
548
|
-
if (emptyDiagnostic) {
|
|
549
|
-
diagnostics.push(emptyDiagnostic);
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
|
|
553
493
|
const directives = extractDirectivesFromTypeNode(
|
|
554
494
|
directiveTypeNode,
|
|
555
495
|
checker,
|
|
@@ -594,18 +534,6 @@ function extractTypeArgumentsFromCall(
|
|
|
594
534
|
? null
|
|
595
535
|
: extractArgsFromType(argsType, inputContext, argsTypeNode);
|
|
596
536
|
|
|
597
|
-
if (!isNoArgs) {
|
|
598
|
-
const emptyDiagnostic = checkEmptyArgsType(
|
|
599
|
-
argsType,
|
|
600
|
-
argsTypeNode,
|
|
601
|
-
args,
|
|
602
|
-
checker,
|
|
603
|
-
);
|
|
604
|
-
if (emptyDiagnostic) {
|
|
605
|
-
diagnostics.push(emptyDiagnostic);
|
|
606
|
-
}
|
|
607
|
-
}
|
|
608
|
-
|
|
609
537
|
const directives = extractDirectivesFromTypeNode(directiveTypeNode, checker);
|
|
610
538
|
|
|
611
539
|
return {
|
|
@@ -784,6 +712,11 @@ export function extractDefineApiResolvers(
|
|
|
784
712
|
diagnostics.push(...typeInfo.diagnostics);
|
|
785
713
|
|
|
786
714
|
const tsdocInfo = extractTsDocInfo(node, checker);
|
|
715
|
+
const sourceLocation = getSourceLocationFromNode(declaration.name) ?? {
|
|
716
|
+
file: filePath,
|
|
717
|
+
line: 1,
|
|
718
|
+
column: 1,
|
|
719
|
+
};
|
|
787
720
|
|
|
788
721
|
resolvers.push({
|
|
789
722
|
fieldName,
|
|
@@ -793,6 +726,7 @@ export function extractDefineApiResolvers(
|
|
|
793
726
|
args: typeInfo.args,
|
|
794
727
|
returnType: typeInfo.returnType,
|
|
795
728
|
sourceFile: filePath,
|
|
729
|
+
sourceLocation,
|
|
796
730
|
exportedInputTypes,
|
|
797
731
|
description: tsdocInfo.description,
|
|
798
732
|
deprecated: tsdocInfo.deprecated,
|
|
@@ -11,9 +11,3 @@ export type {
|
|
|
11
11
|
AbstractResolverInfo,
|
|
12
12
|
AbstractResolverKind,
|
|
13
13
|
} from "./extractor/define-api-extractor.js";
|
|
14
|
-
export type {
|
|
15
|
-
OnlyConstraintViolation,
|
|
16
|
-
OnlyConstraintViolationCode,
|
|
17
|
-
ValidateOnlyConstraintsOptions,
|
|
18
|
-
ValidationContext,
|
|
19
|
-
} from "./validator/only-validator.js";
|
|
@@ -16,6 +16,7 @@ import type { AbstractResolverInfo } from "../extractor/define-api-extractor.js"
|
|
|
16
16
|
export interface ValidateAbstractResolversOptions {
|
|
17
17
|
readonly abstractResolvers: ReadonlyArray<AbstractResolverInfo>;
|
|
18
18
|
readonly baseTypes: ReadonlyArray<BaseType>;
|
|
19
|
+
readonly typenameAutoResolveTypeNames?: ReadonlySet<string>;
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
export interface ValidateAbstractResolversResult {
|
|
@@ -113,21 +114,26 @@ function createMissingResolverDiagnostic(
|
|
|
113
114
|
};
|
|
114
115
|
}
|
|
115
116
|
|
|
117
|
+
interface DetectMissingAbstractTypeResolversParams {
|
|
118
|
+
readonly resolvers: ReadonlyArray<AbstractResolverInfo>;
|
|
119
|
+
readonly typeMap: Map<string, BaseType>;
|
|
120
|
+
readonly typenameAutoResolveTypeNames: ReadonlySet<string>;
|
|
121
|
+
}
|
|
122
|
+
|
|
116
123
|
/**
|
|
117
124
|
* Detects abstract types (union/interface) that have no resolveType defined
|
|
118
125
|
* and whose member/implementing types don't all have isTypeOf defined.
|
|
119
126
|
*
|
|
120
|
-
* @param
|
|
121
|
-
* @param typeMap - Map of type names to their definitions
|
|
127
|
+
* @param params - Parameters including resolvers, type map, and auto-generated typename resolveType names
|
|
122
128
|
* @returns Array of warning diagnostics for missing resolvers
|
|
123
129
|
*/
|
|
124
130
|
function detectMissingAbstractTypeResolvers(
|
|
125
|
-
|
|
126
|
-
typeMap: Map<string, BaseType>,
|
|
131
|
+
params: DetectMissingAbstractTypeResolversParams,
|
|
127
132
|
): Diagnostic[] {
|
|
133
|
+
const { resolvers, typeMap, typenameAutoResolveTypeNames } = params;
|
|
128
134
|
const diagnostics: Diagnostic[] = [];
|
|
129
135
|
|
|
130
|
-
const resolveTypeSet = new Set<string>();
|
|
136
|
+
const resolveTypeSet = new Set<string>(typenameAutoResolveTypeNames);
|
|
131
137
|
const isTypeOfSet = new Set<string>();
|
|
132
138
|
|
|
133
139
|
for (const resolver of resolvers) {
|
|
@@ -241,10 +247,12 @@ export function validateAbstractResolvers(
|
|
|
241
247
|
);
|
|
242
248
|
diagnostics.push(...duplicateDiagnostics);
|
|
243
249
|
|
|
244
|
-
const missingResolverWarnings = detectMissingAbstractTypeResolvers(
|
|
245
|
-
options.abstractResolvers,
|
|
250
|
+
const missingResolverWarnings = detectMissingAbstractTypeResolvers({
|
|
251
|
+
resolvers: options.abstractResolvers,
|
|
246
252
|
typeMap,
|
|
247
|
-
|
|
253
|
+
typenameAutoResolveTypeNames:
|
|
254
|
+
options.typenameAutoResolveTypeNames ?? new Set(),
|
|
255
|
+
});
|
|
248
256
|
diagnostics.push(...missingResolverWarnings);
|
|
249
257
|
|
|
250
258
|
return { diagnostics };
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
+
import type { AutoGeneratedResolveType } from "../../auto-type-generator/resolve-type-generator.js";
|
|
3
|
+
import { TYPENAME_FIELD_NAMES } from "../../auto-type-generator/typename-types.js";
|
|
2
4
|
import { toPosixPath } from "../../shared/index.js";
|
|
3
5
|
import type { CollectedScalarType } from "../../type-extractor/collector/scalar-collector.js";
|
|
4
6
|
import {
|
|
@@ -248,6 +250,30 @@ function buildTypeResolverEntry(
|
|
|
248
250
|
return ` ${type.typeName}: {\n${entries.join("\n")}\n },`;
|
|
249
251
|
}
|
|
250
252
|
|
|
253
|
+
function getResolveTypeExpression(
|
|
254
|
+
fieldPattern: AutoGeneratedResolveType["fieldPattern"],
|
|
255
|
+
): string {
|
|
256
|
+
const { usedFieldNames } = fieldPattern;
|
|
257
|
+
|
|
258
|
+
if (usedFieldNames.size === 1) {
|
|
259
|
+
const fieldName = [...usedFieldNames][0]!;
|
|
260
|
+
return `obj.${fieldName}`;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const expressions = TYPENAME_FIELD_NAMES.filter((name) =>
|
|
264
|
+
usedFieldNames.has(name),
|
|
265
|
+
).map((name) => `obj.${name}`);
|
|
266
|
+
|
|
267
|
+
return expressions.join(" ?? ");
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function buildAutoResolveTypeEntry(
|
|
271
|
+
autoResolveType: AutoGeneratedResolveType,
|
|
272
|
+
): string {
|
|
273
|
+
const expression = getResolveTypeExpression(autoResolveType.fieldPattern);
|
|
274
|
+
return ` ${autoResolveType.unionTypeName}: {\n __resolveType: (obj) => ${expression},\n },`;
|
|
275
|
+
}
|
|
276
|
+
|
|
251
277
|
function buildTypeEntries(
|
|
252
278
|
resolverInfo: ResolverInfo,
|
|
253
279
|
customScalars: ReadonlyArray<CollectedScalarType>,
|
|
@@ -269,15 +295,21 @@ function buildTypeEntries(
|
|
|
269
295
|
abstractResolversByType.set(abstractResolver.typeName, abstractResolver);
|
|
270
296
|
}
|
|
271
297
|
|
|
298
|
+
const autoResolveTypeByUnion = new Map<string, AutoGeneratedResolveType>(
|
|
299
|
+
resolverInfo.autoGeneratedResolveTypes.map((r) => [r.unionTypeName, r]),
|
|
300
|
+
);
|
|
301
|
+
|
|
272
302
|
const allTypeNames = new Set<string>([
|
|
273
303
|
...typesWithFields.keys(),
|
|
274
304
|
...abstractResolversByType.keys(),
|
|
305
|
+
...autoResolveTypeByUnion.keys(),
|
|
275
306
|
]);
|
|
276
307
|
const sortedTypeNames = [...allTypeNames].sort();
|
|
277
308
|
|
|
278
309
|
for (const typeName of sortedTypeNames) {
|
|
279
310
|
const typeWithFields = typesWithFields.get(typeName);
|
|
280
311
|
const abstractResolver = abstractResolversByType.get(typeName) ?? null;
|
|
312
|
+
const autoResolveType = autoResolveTypeByUnion.get(typeName);
|
|
281
313
|
|
|
282
314
|
if (typeWithFields !== undefined) {
|
|
283
315
|
typeEntries.push(
|
|
@@ -285,6 +317,8 @@ function buildTypeEntries(
|
|
|
285
317
|
);
|
|
286
318
|
} else if (abstractResolver !== null) {
|
|
287
319
|
typeEntries.push(buildAbstractOnlyTypeEntry(abstractResolver));
|
|
320
|
+
} else if (autoResolveType !== undefined) {
|
|
321
|
+
typeEntries.push(buildAutoResolveTypeEntry(autoResolveType));
|
|
288
322
|
}
|
|
289
323
|
}
|
|
290
324
|
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
|
+
collectTypenameExtractions,
|
|
3
|
+
collectTypenameResolveTypes,
|
|
2
4
|
generateAutoTypes,
|
|
3
5
|
validateNameCollisions,
|
|
6
|
+
validateSchemaTypenames,
|
|
7
|
+
validateTypenames,
|
|
4
8
|
} from "../auto-type-generator/index.js";
|
|
5
9
|
import type { ExtractResolversResult } from "../resolver-extractor/index.js";
|
|
6
10
|
import type { DirectiveDefinitionInfo } from "../shared/directive-definition-extractor.js";
|
|
@@ -28,6 +32,7 @@ export interface GenerateSchemaInput {
|
|
|
28
32
|
readonly directiveDefinitions: ReadonlyArray<DirectiveDefinitionInfo> | null;
|
|
29
33
|
readonly enablePruning: boolean | null;
|
|
30
34
|
readonly sourceRoot: string | null;
|
|
35
|
+
readonly knownTypeNames: ReadonlySet<string> | null;
|
|
31
36
|
}
|
|
32
37
|
|
|
33
38
|
export interface GenerateSchemaResult {
|
|
@@ -52,11 +57,13 @@ export function generateSchema(
|
|
|
52
57
|
directiveDefinitions,
|
|
53
58
|
enablePruning,
|
|
54
59
|
sourceRoot,
|
|
60
|
+
knownTypeNames,
|
|
55
61
|
} = input;
|
|
56
62
|
|
|
57
63
|
const autoTypeResult = generateAutoTypes({
|
|
58
64
|
extractedTypes,
|
|
59
65
|
resolversResult,
|
|
66
|
+
knownTypeNames: knownTypeNames ?? new Set(),
|
|
60
67
|
});
|
|
61
68
|
|
|
62
69
|
const autoTypeErrors = autoTypeResult.diagnostics.filter(
|
|
@@ -120,13 +127,103 @@ export function generateSchema(
|
|
|
120
127
|
},
|
|
121
128
|
};
|
|
122
129
|
|
|
130
|
+
const typeMap = new Map(
|
|
131
|
+
autoTypeResult.updatedExtractedTypes.map((t) => [t.metadata.name, t]),
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
const manualResolveTypeNames = new Set(
|
|
135
|
+
autoTypeResult.updatedResolversResult.abstractTypeResolvers
|
|
136
|
+
.filter((r) => r.kind === "resolveType")
|
|
137
|
+
.map((r) => r.targetTypeName),
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
const typenameResolveTypesResult = collectTypenameResolveTypes({
|
|
141
|
+
extractedTypes: autoTypeResult.updatedExtractedTypes,
|
|
142
|
+
typeMap,
|
|
143
|
+
manualResolveTypeNames,
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
const typenameExtractions = collectTypenameExtractions({
|
|
147
|
+
extractedTypes: autoTypeResult.updatedExtractedTypes,
|
|
148
|
+
typeMap,
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
const typenameValidationDiagnostics: Diagnostic[] = [];
|
|
152
|
+
|
|
153
|
+
for (const extraction of typenameExtractions) {
|
|
154
|
+
const abstractType = typeMap.get(extraction.abstractTypeName);
|
|
155
|
+
if (!abstractType) {
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
const validationResult = validateTypenames({
|
|
159
|
+
extractionResult: extraction,
|
|
160
|
+
sourceLocation: abstractType.metadata.sourceLocation,
|
|
161
|
+
inlineObjectMembers: abstractType.inlineObjectMembers,
|
|
162
|
+
});
|
|
163
|
+
typenameValidationDiagnostics.push(...validationResult.diagnostics);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const schemaTypenameValidationResult = validateSchemaTypenames({
|
|
167
|
+
objectTypes: autoTypeResult.updatedExtractedTypes,
|
|
168
|
+
typeMap,
|
|
169
|
+
});
|
|
170
|
+
typenameValidationDiagnostics.push(
|
|
171
|
+
...schemaTypenameValidationResult.diagnostics,
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
if (typenameValidationDiagnostics.length > 0) {
|
|
175
|
+
return {
|
|
176
|
+
typeDefsCode: "",
|
|
177
|
+
sdlContent: "",
|
|
178
|
+
resolversCode: "",
|
|
179
|
+
diagnostics: typenameValidationDiagnostics,
|
|
180
|
+
hasErrors: true,
|
|
181
|
+
prunedTypes: null,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const generatedInlineObjectTypes =
|
|
186
|
+
typenameResolveTypesResult.generatedInlineObjectTypes;
|
|
187
|
+
|
|
188
|
+
const updatedTypesForIntegration: ExtractTypesResult =
|
|
189
|
+
generatedInlineObjectTypes.length > 0
|
|
190
|
+
? {
|
|
191
|
+
types: updatedTypesResult.types.map((type) => {
|
|
192
|
+
if (type.kind !== "Union") {
|
|
193
|
+
return type;
|
|
194
|
+
}
|
|
195
|
+
const inlineTypes = generatedInlineObjectTypes.filter(
|
|
196
|
+
(g) => g.abstractTypeName === type.name,
|
|
197
|
+
);
|
|
198
|
+
if (inlineTypes.length === 0) {
|
|
199
|
+
return type;
|
|
200
|
+
}
|
|
201
|
+
const newMembers = inlineTypes.map((g) => g.typeName);
|
|
202
|
+
return {
|
|
203
|
+
...type,
|
|
204
|
+
unionMembers: [
|
|
205
|
+
...(type.unionMembers ?? []),
|
|
206
|
+
...newMembers,
|
|
207
|
+
].sort(),
|
|
208
|
+
};
|
|
209
|
+
}),
|
|
210
|
+
diagnostics: updatedTypesResult.diagnostics,
|
|
211
|
+
}
|
|
212
|
+
: updatedTypesResult;
|
|
213
|
+
|
|
214
|
+
const allAutoGeneratedTypes = [
|
|
215
|
+
...autoTypeResult.autoGeneratedTypes,
|
|
216
|
+
...typenameResolveTypesResult.generatedObjectTypes,
|
|
217
|
+
];
|
|
218
|
+
|
|
123
219
|
const integratedResult = integrate(
|
|
124
|
-
|
|
220
|
+
updatedTypesForIntegration,
|
|
125
221
|
autoTypeResult.updatedResolversResult,
|
|
126
222
|
customScalarNames,
|
|
127
223
|
customScalars,
|
|
128
224
|
directiveDefinitions,
|
|
129
|
-
|
|
225
|
+
allAutoGeneratedTypes,
|
|
226
|
+
typenameResolveTypesResult.autoResolveTypes,
|
|
130
227
|
);
|
|
131
228
|
|
|
132
229
|
let documentNode = buildDocumentNode(
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
AutoGeneratedType,
|
|
3
|
+
ResolveTypeFieldPattern,
|
|
4
|
+
} from "../../auto-type-generator/index.js";
|
|
5
|
+
import type { TypenameAutoResolveTypeInfo } from "../../auto-type-generator/typename-resolve-type-generator.js";
|
|
6
|
+
import { createFieldNameSet } from "../../auto-type-generator/typename-types.js";
|
|
2
7
|
import type {
|
|
3
8
|
AbstractResolverInfo,
|
|
4
9
|
ExtractResolversResult,
|
|
@@ -121,6 +126,12 @@ export interface StringEnumMappingInfo {
|
|
|
121
126
|
readonly members: ReadonlyArray<StringEnumMember>;
|
|
122
127
|
}
|
|
123
128
|
|
|
129
|
+
export interface AutoGeneratedUnionInfo {
|
|
130
|
+
readonly name: string;
|
|
131
|
+
readonly fieldPattern: ResolveTypeFieldPattern;
|
|
132
|
+
readonly hasAutoResolveType: boolean;
|
|
133
|
+
}
|
|
134
|
+
|
|
124
135
|
export interface IntegratedResult {
|
|
125
136
|
readonly baseTypes: ReadonlyArray<BaseType>;
|
|
126
137
|
readonly inputTypes: ReadonlyArray<InputType>;
|
|
@@ -133,6 +144,12 @@ export interface IntegratedResult {
|
|
|
133
144
|
readonly directiveDefinitions: ReadonlyArray<DirectiveDefinitionInfo> | null;
|
|
134
145
|
/** Abstract type resolvers (resolveType and isTypeOf) */
|
|
135
146
|
readonly abstractTypeResolvers: ReadonlyArray<AbstractResolverInfo>;
|
|
147
|
+
/** @deprecated Use autoGeneratedUnions instead */
|
|
148
|
+
readonly autoGeneratedUnionNames: ReadonlyArray<string>;
|
|
149
|
+
/** Auto-generated Union types that need __resolveType with field pattern info */
|
|
150
|
+
readonly autoGeneratedUnions: ReadonlyArray<AutoGeneratedUnionInfo>;
|
|
151
|
+
/** Union/Interface types that have typename-based auto resolveType */
|
|
152
|
+
readonly typenameAutoResolveTypes: ReadonlyArray<TypenameAutoResolveTypeInfo>;
|
|
136
153
|
/** Numeric enum information for resolver generation */
|
|
137
154
|
readonly numericEnums: ReadonlyArray<NumericEnumInfo>;
|
|
138
155
|
/** String enum mappings for resolver generation */
|
|
@@ -257,6 +274,7 @@ export function integrate(
|
|
|
257
274
|
collectedScalars?: ReadonlyArray<CollectedScalarType> | null,
|
|
258
275
|
directiveDefinitions?: ReadonlyArray<DirectiveDefinitionInfo> | null,
|
|
259
276
|
autoGeneratedTypes?: ReadonlyArray<AutoGeneratedType> | null,
|
|
277
|
+
typenameAutoResolveTypes?: ReadonlyArray<TypenameAutoResolveTypeInfo>,
|
|
260
278
|
): IntegratedResult {
|
|
261
279
|
const directiveTypeAliasNames = new Set(
|
|
262
280
|
directiveDefinitions?.map((d) => d.typeAliasName) ?? [],
|
|
@@ -281,6 +299,8 @@ export function integrate(
|
|
|
281
299
|
|
|
282
300
|
const baseTypes: BaseType[] = [];
|
|
283
301
|
const inputTypes: InputType[] = [];
|
|
302
|
+
const autoGeneratedUnionNames: string[] = [];
|
|
303
|
+
const autoGeneratedUnions: AutoGeneratedUnionInfo[] = [];
|
|
284
304
|
|
|
285
305
|
for (const autoType of autoGeneratedTypes ?? []) {
|
|
286
306
|
if (autoType.kind === "Object") {
|
|
@@ -327,6 +347,44 @@ export function integrate(
|
|
|
327
347
|
sourceFile: autoType.sourceLocation.file,
|
|
328
348
|
directives: null,
|
|
329
349
|
});
|
|
350
|
+
} else if (autoType.kind === "Union") {
|
|
351
|
+
baseTypes.push({
|
|
352
|
+
name: autoType.name,
|
|
353
|
+
kind: "Union",
|
|
354
|
+
fields: null,
|
|
355
|
+
unionMembers: autoType.unionMembers ?? [],
|
|
356
|
+
enumValues: null,
|
|
357
|
+
isNumericEnum: false,
|
|
358
|
+
needsStringEnumMapping: false,
|
|
359
|
+
implementedInterfaces: null,
|
|
360
|
+
description: autoType.description,
|
|
361
|
+
deprecated: null,
|
|
362
|
+
sourceFile: autoType.sourceLocation.file,
|
|
363
|
+
directives: null,
|
|
364
|
+
});
|
|
365
|
+
autoGeneratedUnionNames.push(autoType.name);
|
|
366
|
+
autoGeneratedUnions.push({
|
|
367
|
+
name: autoType.name,
|
|
368
|
+
fieldPattern: autoType.resolveTypeFieldPattern ?? {
|
|
369
|
+
usedFieldNames: createFieldNameSet(["__typename"]),
|
|
370
|
+
},
|
|
371
|
+
hasAutoResolveType: autoType.resolveTypeFieldPattern !== null,
|
|
372
|
+
});
|
|
373
|
+
} else if (autoType.kind === "OneOfInputObject") {
|
|
374
|
+
inputTypes.push({
|
|
375
|
+
name: autoType.name,
|
|
376
|
+
fields: autoType.fields!.map((f) => ({
|
|
377
|
+
name: f.name,
|
|
378
|
+
type: f.type,
|
|
379
|
+
description: f.description,
|
|
380
|
+
deprecated: f.deprecated,
|
|
381
|
+
directives: f.directives,
|
|
382
|
+
defaultValue: f.defaultValue,
|
|
383
|
+
})),
|
|
384
|
+
sourceFile: autoType.sourceLocation.file,
|
|
385
|
+
description: autoType.description,
|
|
386
|
+
isOneOf: true,
|
|
387
|
+
});
|
|
330
388
|
} else {
|
|
331
389
|
inputTypes.push({
|
|
332
390
|
name: autoType.name,
|
|
@@ -481,9 +539,17 @@ export function integrate(
|
|
|
481
539
|
});
|
|
482
540
|
}
|
|
483
541
|
|
|
542
|
+
const typenameAutoResolveTypeNames = new Set([
|
|
543
|
+
...(typenameAutoResolveTypes?.map((t) => t.abstractTypeName) ?? []),
|
|
544
|
+
...autoGeneratedUnions
|
|
545
|
+
.filter((u) => u.hasAutoResolveType)
|
|
546
|
+
.map((u) => u.name),
|
|
547
|
+
]);
|
|
548
|
+
|
|
484
549
|
const abstractResolverValidation = validateAbstractResolvers({
|
|
485
550
|
abstractResolvers: resolversResult.abstractTypeResolvers,
|
|
486
551
|
baseTypes,
|
|
552
|
+
typenameAutoResolveTypeNames,
|
|
487
553
|
});
|
|
488
554
|
diagnostics.push(...abstractResolverValidation.diagnostics);
|
|
489
555
|
|
|
@@ -680,6 +746,9 @@ export function integrate(
|
|
|
680
746
|
? directiveDefinitions
|
|
681
747
|
: null,
|
|
682
748
|
abstractTypeResolvers: resolversResult.abstractTypeResolvers,
|
|
749
|
+
autoGeneratedUnionNames,
|
|
750
|
+
autoGeneratedUnions,
|
|
751
|
+
typenameAutoResolveTypes: typenameAutoResolveTypes ?? [],
|
|
683
752
|
numericEnums,
|
|
684
753
|
stringEnumMappings,
|
|
685
754
|
hasQuery,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AutoGeneratedResolveType } from "../../auto-type-generator/resolve-type-generator.js";
|
|
1
2
|
import type { AbstractResolverInfo } from "../../resolver-extractor/extractor/define-api-extractor.js";
|
|
2
3
|
import type {
|
|
3
4
|
ExtensionField,
|
|
@@ -28,6 +29,7 @@ export interface ResolverInfo {
|
|
|
28
29
|
readonly types: ReadonlyArray<TypeResolvers>;
|
|
29
30
|
readonly sourceFiles: ReadonlyArray<string>;
|
|
30
31
|
readonly abstractTypeResolvers: ReadonlyArray<AbstractTypeResolverInfo>;
|
|
32
|
+
readonly autoGeneratedResolveTypes: ReadonlyArray<AutoGeneratedResolveType>;
|
|
31
33
|
}
|
|
32
34
|
|
|
33
35
|
function getResolverValueName(typeName: string): string {
|
|
@@ -104,6 +106,37 @@ export function collectResolverInfo(
|
|
|
104
106
|
sourceFilesSet.add(resolver.sourceFile);
|
|
105
107
|
}
|
|
106
108
|
|
|
109
|
+
const manualResolveTypeNames = new Set<string>(
|
|
110
|
+
abstractTypeResolvers
|
|
111
|
+
.filter((r) => r.resolverKey === "__resolveType")
|
|
112
|
+
.map((r) => r.typeName),
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
const inlineUnionResolveTypes: AutoGeneratedResolveType[] =
|
|
116
|
+
integratedResult.autoGeneratedUnions
|
|
117
|
+
.filter(
|
|
118
|
+
(u) => u.hasAutoResolveType && !manualResolveTypeNames.has(u.name),
|
|
119
|
+
)
|
|
120
|
+
.map((u) => ({
|
|
121
|
+
unionTypeName: u.name,
|
|
122
|
+
fieldPattern: u.fieldPattern,
|
|
123
|
+
}));
|
|
124
|
+
|
|
125
|
+
const typenameResolveTypes: AutoGeneratedResolveType[] =
|
|
126
|
+
integratedResult.typenameAutoResolveTypes
|
|
127
|
+
.filter((t) => !manualResolveTypeNames.has(t.abstractTypeName))
|
|
128
|
+
.map((t) => ({
|
|
129
|
+
unionTypeName: t.abstractTypeName,
|
|
130
|
+
fieldPattern: {
|
|
131
|
+
usedFieldNames: t.resolveTypePattern.usedFieldNames,
|
|
132
|
+
},
|
|
133
|
+
}));
|
|
134
|
+
|
|
135
|
+
const autoGeneratedResolveTypes = [
|
|
136
|
+
...inlineUnionResolveTypes,
|
|
137
|
+
...typenameResolveTypes,
|
|
138
|
+
].sort((a, b) => a.unionTypeName.localeCompare(b.unionTypeName));
|
|
139
|
+
|
|
107
140
|
const types: TypeResolvers[] = [...typeMap.entries()]
|
|
108
141
|
.map(([typeName, fields]) => ({
|
|
109
142
|
typeName,
|
|
@@ -119,5 +152,6 @@ export function collectResolverInfo(
|
|
|
119
152
|
types,
|
|
120
153
|
sourceFiles,
|
|
121
154
|
abstractTypeResolvers,
|
|
155
|
+
autoGeneratedResolveTypes,
|
|
122
156
|
};
|
|
123
157
|
}
|