@gqlkit-ts/cli 0.1.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 +26 -4
- package/dist/auto-type-generator/auto-type-generator.d.ts.map +1 -1
- package/dist/auto-type-generator/auto-type-generator.js +846 -152
- package/dist/auto-type-generator/auto-type-generator.js.map +1 -1
- package/dist/auto-type-generator/index.d.ts +9 -2
- 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 +39 -0
- package/dist/auto-type-generator/inline-enum-collector.d.ts.map +1 -0
- package/dist/auto-type-generator/inline-enum-collector.js +193 -0
- package/dist/auto-type-generator/inline-enum-collector.js.map +1 -0
- 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 +22 -1
- package/dist/auto-type-generator/naming-convention.d.ts.map +1 -1
- package/dist/auto-type-generator/naming-convention.js +24 -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 +119 -14
- package/dist/gen-orchestrator/orchestrator.js.map +1 -1
- package/dist/resolver-extractor/extract-resolvers.d.ts +28 -1
- package/dist/resolver-extractor/extract-resolvers.d.ts.map +1 -1
- package/dist/resolver-extractor/extractor/define-api-extractor.d.ts +16 -1
- package/dist/resolver-extractor/extractor/define-api-extractor.d.ts.map +1 -1
- package/dist/resolver-extractor/extractor/define-api-extractor.js +86 -309
- 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 +10 -2
- package/dist/schema-generator/emitter/code-emitter.d.ts.map +1 -1
- package/dist/schema-generator/emitter/code-emitter.js +39 -4
- 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 +90 -4
- package/dist/schema-generator/generate-schema.js.map +1 -1
- package/dist/schema-generator/integrator/result-integrator.d.ts +34 -2
- package/dist/schema-generator/integrator/result-integrator.d.ts.map +1 -1
- package/dist/schema-generator/integrator/result-integrator.js +96 -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/constants.d.ts +0 -16
- package/dist/shared/constants.d.ts.map +1 -1
- package/dist/shared/constants.js +0 -19
- package/dist/shared/constants.js.map +1 -1
- package/dist/shared/directive-detector.d.ts.map +1 -1
- package/dist/shared/directive-detector.js +8 -15
- package/dist/shared/directive-detector.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/file-scanner.d.ts.map +1 -1
- package/dist/shared/file-scanner.js +5 -3
- package/dist/shared/file-scanner.js.map +1 -1
- 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 +3 -1
- package/dist/shared/index.d.ts.map +1 -1
- package/dist/shared/index.js +1 -3
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/interface-detector.d.ts +3 -2
- package/dist/shared/interface-detector.d.ts.map +1 -1
- package/dist/shared/interface-detector.js +54 -11
- package/dist/shared/interface-detector.js.map +1 -1
- package/dist/shared/path-utils.d.ts +2 -0
- package/dist/shared/path-utils.d.ts.map +1 -0
- package/dist/shared/path-utils.js +4 -0
- package/dist/shared/path-utils.js.map +1 -0
- 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/shared/type-converter.d.ts.map +1 -1
- package/dist/shared/type-converter.js +11 -0
- package/dist/shared/type-converter.js.map +1 -1
- package/dist/shared/typescript-utils.d.ts +34 -7
- package/dist/shared/typescript-utils.d.ts.map +1 -1
- package/dist/shared/typescript-utils.js +72 -24
- package/dist/shared/typescript-utils.js.map +1 -1
- package/dist/type-extractor/collector/scalar-collector.d.ts.map +1 -1
- package/dist/type-extractor/collector/scalar-collector.js +4 -14
- package/dist/type-extractor/collector/scalar-collector.js.map +1 -1
- package/dist/type-extractor/converter/graphql-converter.d.ts.map +1 -1
- package/dist/type-extractor/converter/graphql-converter.js +57 -4
- package/dist/type-extractor/converter/graphql-converter.js.map +1 -1
- package/dist/type-extractor/extractor/field-type-resolver.d.ts +28 -0
- package/dist/type-extractor/extractor/field-type-resolver.d.ts.map +1 -0
- package/dist/type-extractor/extractor/field-type-resolver.js +433 -0
- package/dist/type-extractor/extractor/field-type-resolver.js.map +1 -0
- package/dist/type-extractor/extractor/type-extractor.d.ts +12 -3
- package/dist/type-extractor/extractor/type-extractor.d.ts.map +1 -1
- package/dist/type-extractor/extractor/type-extractor.js +260 -229
- package/dist/type-extractor/extractor/type-extractor.js.map +1 -1
- package/dist/type-extractor/extractor/type-name-collector.d.ts +24 -0
- package/dist/type-extractor/extractor/type-name-collector.d.ts.map +1 -0
- package/dist/type-extractor/extractor/type-name-collector.js +102 -0
- package/dist/type-extractor/extractor/type-name-collector.js.map +1 -0
- package/dist/type-extractor/mapper/scalar-base-type-mapper.d.ts +89 -0
- package/dist/type-extractor/mapper/scalar-base-type-mapper.d.ts.map +1 -0
- package/dist/type-extractor/mapper/scalar-base-type-mapper.js +158 -0
- package/dist/type-extractor/mapper/scalar-base-type-mapper.js.map +1 -0
- 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/graphql.d.ts +2 -0
- package/dist/type-extractor/types/graphql.d.ts.map +1 -1
- package/dist/type-extractor/types/index.d.ts +2 -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 +47 -0
- package/dist/type-extractor/types/ts-type-reference-factory.d.ts.map +1 -0
- package/dist/type-extractor/types/ts-type-reference-factory.js +75 -0
- package/dist/type-extractor/types/ts-type-reference-factory.js.map +1 -0
- package/dist/type-extractor/types/typescript.d.ts +25 -1
- package/dist/type-extractor/types/typescript.d.ts.map +1 -1
- package/dist/type-extractor/validator/type-validator.js +1 -1
- package/dist/type-extractor/validator/type-validator.js.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 -21
- package/docs/integration/apollo.md +8 -40
- package/docs/integration/drizzle.md +187 -0
- 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 +307 -0
- package/docs/schema/fields.md +66 -0
- package/docs/schema/index.md +21 -0
- package/docs/schema/inputs.md +117 -15
- package/docs/schema/interfaces.md +31 -1
- package/docs/schema/objects.md +42 -0
- package/docs/schema/queries-mutations.md +138 -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 +14 -5
- package/src/auto-type-generator/auto-type-generator.ts +1670 -0
- package/src/auto-type-generator/index.ts +63 -0
- package/src/auto-type-generator/inline-enum-collector.ts +338 -0
- 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/name-collision-validator.ts +119 -0
- package/src/auto-type-generator/naming-convention.ts +163 -0
- 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 +13 -0
- package/src/commands/docs.ts +211 -0
- package/src/commands/gen.ts +141 -0
- package/src/commands/main.ts +5 -0
- package/src/config/define-config.ts +28 -0
- package/src/config/index.ts +7 -0
- package/src/config/types.ts +144 -0
- package/src/config-loader/index.ts +14 -0
- package/src/config-loader/loader.ts +143 -0
- package/src/config-loader/validator.ts +672 -0
- package/src/gen-orchestrator/hook-executor/hook-executor.ts +117 -0
- package/src/gen-orchestrator/orchestrator.ts +798 -0
- package/src/gen-orchestrator/reporter/diagnostic-reporter.ts +44 -0
- package/src/gen-orchestrator/reporter/progress-reporter.ts +61 -0
- package/src/gen-orchestrator/writer/file-writer.ts +38 -0
- package/src/index.ts +2 -0
- package/src/resolver-extractor/extract-resolvers.ts +82 -0
- package/src/resolver-extractor/extractor/define-api-extractor.ts +740 -0
- package/src/resolver-extractor/index.ts +13 -0
- package/src/resolver-extractor/validator/abstract-resolver-validator.ts +259 -0
- package/src/schema-generator/builder/ast-builder.ts +706 -0
- package/src/schema-generator/emitter/code-emitter.ts +385 -0
- package/src/schema-generator/emitter/sdl-emitter.ts +13 -0
- package/src/schema-generator/generate-schema.ts +267 -0
- package/src/schema-generator/index.ts +19 -0
- package/src/schema-generator/integrator/result-integrator.ts +759 -0
- package/src/schema-generator/pruner/schema-pruner.ts +112 -0
- package/src/schema-generator/resolver-collector/resolver-collector.ts +157 -0
- package/src/shared/constants.ts +122 -0
- package/src/shared/default-value-detector.ts +172 -0
- package/src/shared/diagnostics.ts +35 -0
- package/src/shared/directive-definition-extractor.ts +564 -0
- package/src/shared/directive-detector.ts +556 -0
- package/src/shared/enum-prefix-detector.ts +99 -0
- package/src/shared/file-scanner.ts +170 -0
- package/src/shared/ignore-fields-detector.ts +109 -0
- package/src/shared/ignore-fields-validator.ts +66 -0
- package/src/shared/index.ts +34 -0
- package/src/shared/inline-object-extractor.ts +102 -0
- package/src/shared/inline-object-utils.ts +23 -0
- package/src/shared/interface-detector.ts +176 -0
- package/src/shared/interface-validator.ts +211 -0
- package/src/shared/metadata-detector.ts +443 -0
- package/src/shared/path-utils.ts +3 -0
- package/src/shared/program-factory.ts +51 -0
- package/src/shared/source-location.ts +38 -0
- package/src/shared/tsconfig-loader.ts +126 -0
- package/src/shared/tsdoc-parser.ts +155 -0
- package/src/shared/type-converter.ts +99 -0
- package/src/shared/typescript-utils.ts +246 -0
- package/src/type-extractor/collector/result-collector.ts +57 -0
- package/src/type-extractor/collector/scalar-collector.ts +254 -0
- package/src/type-extractor/converter/field-eligibility.ts +112 -0
- package/src/type-extractor/converter/graphql-converter.ts +483 -0
- package/src/type-extractor/extract-types.ts +1 -0
- package/src/type-extractor/extractor/field-type-resolver.ts +614 -0
- package/src/type-extractor/extractor/type-extractor.ts +1644 -0
- package/src/type-extractor/extractor/type-name-collector.ts +130 -0
- package/src/type-extractor/index.ts +20 -0
- package/src/type-extractor/mapper/scalar-base-type-mapper.ts +265 -0
- package/src/type-extractor/types/diagnostics.ts +109 -0
- package/src/type-extractor/types/graphql.ts +55 -0
- package/src/type-extractor/types/index.ts +37 -0
- package/src/type-extractor/types/ts-type-reference-factory.ts +150 -0
- package/src/type-extractor/types/typescript.ts +137 -0
- package/src/type-extractor/validator/type-validator.ts +77 -0
- package/dist/auto-type-generator/auto-type-generator.test.d.ts +0 -2
- package/dist/auto-type-generator/auto-type-generator.test.d.ts.map +0 -1
- package/dist/auto-type-generator/auto-type-generator.test.js +0 -613
- package/dist/auto-type-generator/auto-type-generator.test.js.map +0 -1
- package/dist/auto-type-generator/name-collision-validator.test.d.ts +0 -2
- package/dist/auto-type-generator/name-collision-validator.test.d.ts.map +0 -1
- package/dist/auto-type-generator/name-collision-validator.test.js +0 -358
- package/dist/auto-type-generator/name-collision-validator.test.js.map +0 -1
- package/dist/auto-type-generator/naming-convention.test.d.ts +0 -2
- package/dist/auto-type-generator/naming-convention.test.d.ts.map +0 -1
- package/dist/auto-type-generator/naming-convention.test.js +0 -132
- package/dist/auto-type-generator/naming-convention.test.js.map +0 -1
- package/dist/commands/gen.test.d.ts +0 -2
- package/dist/commands/gen.test.d.ts.map +0 -1
- package/dist/commands/gen.test.js +0 -226
- package/dist/commands/gen.test.js.map +0 -1
- package/dist/config-loader/loader.test.d.ts +0 -2
- package/dist/config-loader/loader.test.d.ts.map +0 -1
- package/dist/config-loader/loader.test.js +0 -123
- package/dist/config-loader/loader.test.js.map +0 -1
- package/dist/config-loader/validator.test.d.ts +0 -2
- package/dist/config-loader/validator.test.d.ts.map +0 -1
- package/dist/config-loader/validator.test.js +0 -846
- package/dist/config-loader/validator.test.js.map +0 -1
- package/dist/gen-orchestrator/golden.test.d.ts +0 -2
- package/dist/gen-orchestrator/golden.test.d.ts.map +0 -1
- package/dist/gen-orchestrator/golden.test.js +0 -102
- package/dist/gen-orchestrator/golden.test.js.map +0 -1
- package/dist/gen-orchestrator/hook-executor/hook-executor.test.d.ts +0 -2
- package/dist/gen-orchestrator/hook-executor/hook-executor.test.d.ts.map +0 -1
- package/dist/gen-orchestrator/hook-executor/hook-executor.test.js +0 -167
- package/dist/gen-orchestrator/hook-executor/hook-executor.test.js.map +0 -1
- package/dist/gen-orchestrator/reporter/progress-reporter.test.d.ts +0 -2
- package/dist/gen-orchestrator/reporter/progress-reporter.test.d.ts.map +0 -1
- package/dist/gen-orchestrator/reporter/progress-reporter.test.js +0 -74
- package/dist/gen-orchestrator/reporter/progress-reporter.test.js.map +0 -1
- 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/dist/resolver-extractor/validator/only-validator.test.d.ts +0 -8
- package/dist/resolver-extractor/validator/only-validator.test.d.ts.map +0 -1
- package/dist/resolver-extractor/validator/only-validator.test.js +0 -352
- package/dist/resolver-extractor/validator/only-validator.test.js.map +0 -1
- package/dist/schema-generator/builder/ast-builder.test.d.ts +0 -2
- package/dist/schema-generator/builder/ast-builder.test.d.ts.map +0 -1
- package/dist/schema-generator/builder/ast-builder.test.js +0 -469
- package/dist/schema-generator/builder/ast-builder.test.js.map +0 -1
- package/dist/shared/file-scanner.test.d.ts +0 -2
- package/dist/shared/file-scanner.test.d.ts.map +0 -1
- package/dist/shared/file-scanner.test.js +0 -138
- package/dist/shared/file-scanner.test.js.map +0 -1
- package/dist/shared/interface-validator.test.d.ts +0 -2
- package/dist/shared/interface-validator.test.d.ts.map +0 -1
- package/dist/shared/interface-validator.test.js +0 -145
- package/dist/shared/interface-validator.test.js.map +0 -1
- package/dist/type-extractor/types/typescript.test.d.ts +0 -2
- package/dist/type-extractor/types/typescript.test.d.ts.map +0 -1
- package/dist/type-extractor/types/typescript.test.js +0 -287
- package/dist/type-extractor/types/typescript.test.js.map +0 -1
|
@@ -0,0 +1,740 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
import {
|
|
3
|
+
isInternalTypeSymbol,
|
|
4
|
+
METADATA_PROPERTIES,
|
|
5
|
+
} from "../../shared/constants.js";
|
|
6
|
+
import { detectDefaultValueMetadata } from "../../shared/default-value-detector.js";
|
|
7
|
+
import {
|
|
8
|
+
type DirectiveArgumentValue,
|
|
9
|
+
type DirectiveInfo,
|
|
10
|
+
extractDirectivesFromType,
|
|
11
|
+
hasDirectiveMetadata,
|
|
12
|
+
unwrapDirectiveType,
|
|
13
|
+
} from "../../shared/directive-detector.js";
|
|
14
|
+
import { getActualMetadataType } from "../../shared/metadata-detector.js";
|
|
15
|
+
import { getSourceLocationFromNode } from "../../shared/source-location.js";
|
|
16
|
+
import {
|
|
17
|
+
type DeprecationInfo,
|
|
18
|
+
extractTsDocFromSymbol,
|
|
19
|
+
extractTsDocInfo,
|
|
20
|
+
} from "../../shared/tsdoc-parser.js";
|
|
21
|
+
import {
|
|
22
|
+
extractPropertySymbols,
|
|
23
|
+
getTypeNameFromNode,
|
|
24
|
+
hasUndefinedInType,
|
|
25
|
+
isExported,
|
|
26
|
+
} from "../../shared/typescript-utils.js";
|
|
27
|
+
import {
|
|
28
|
+
type FieldTypeResolverContext,
|
|
29
|
+
resolveFieldType,
|
|
30
|
+
} from "../../type-extractor/extractor/field-type-resolver.js";
|
|
31
|
+
import type { GlobalTypeMapping } from "../../type-extractor/extractor/type-extractor.js";
|
|
32
|
+
import type { ScalarBaseTypeMappingTable } from "../../type-extractor/mapper/scalar-base-type-mapper.js";
|
|
33
|
+
import type {
|
|
34
|
+
Diagnostic,
|
|
35
|
+
TSTypeReference,
|
|
36
|
+
} from "../../type-extractor/types/index.js";
|
|
37
|
+
|
|
38
|
+
export type DefineApiResolverType = "query" | "mutation" | "field";
|
|
39
|
+
|
|
40
|
+
export type AbstractResolverKind = "resolveType" | "isTypeOf";
|
|
41
|
+
|
|
42
|
+
export interface ExportedInputType {
|
|
43
|
+
readonly name: string;
|
|
44
|
+
readonly tsType: TSTypeReference;
|
|
45
|
+
readonly sourceFile: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface ArgumentDefinition {
|
|
49
|
+
readonly name: string;
|
|
50
|
+
readonly tsType: TSTypeReference;
|
|
51
|
+
readonly optional: boolean;
|
|
52
|
+
readonly description: string | null;
|
|
53
|
+
readonly deprecated: DeprecationInfo | null;
|
|
54
|
+
readonly defaultValue: DirectiveArgumentValue | null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface DefineApiResolverInfo {
|
|
58
|
+
readonly fieldName: string;
|
|
59
|
+
readonly resolverType: DefineApiResolverType;
|
|
60
|
+
readonly parentTypeName: string | null;
|
|
61
|
+
readonly argsType: TSTypeReference | null;
|
|
62
|
+
readonly args: ReadonlyArray<ArgumentDefinition> | null;
|
|
63
|
+
readonly returnType: TSTypeReference;
|
|
64
|
+
readonly sourceFile: string;
|
|
65
|
+
readonly sourceLocation: {
|
|
66
|
+
readonly file: string;
|
|
67
|
+
readonly line: number;
|
|
68
|
+
readonly column: number;
|
|
69
|
+
};
|
|
70
|
+
readonly exportedInputTypes: ReadonlyArray<ExportedInputType>;
|
|
71
|
+
readonly description: string | null;
|
|
72
|
+
readonly deprecated: DeprecationInfo | null;
|
|
73
|
+
readonly directives: ReadonlyArray<DirectiveInfo> | null;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export interface AbstractResolverInfo {
|
|
77
|
+
readonly kind: AbstractResolverKind;
|
|
78
|
+
readonly targetTypeName: string;
|
|
79
|
+
readonly exportName: string;
|
|
80
|
+
readonly sourceFile: string;
|
|
81
|
+
readonly sourceLocation: {
|
|
82
|
+
readonly file: string;
|
|
83
|
+
readonly line: number;
|
|
84
|
+
readonly column: number;
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export interface ExtractDefineApiResult {
|
|
89
|
+
readonly resolvers: ReadonlyArray<DefineApiResolverInfo>;
|
|
90
|
+
readonly abstractTypeResolvers: ReadonlyArray<AbstractResolverInfo>;
|
|
91
|
+
readonly diagnostics: ReadonlyArray<Diagnostic>;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export interface ExtractDefineApiOptions {
|
|
95
|
+
readonly knownTypeNames: ReadonlySet<string>;
|
|
96
|
+
readonly knownTypeSymbols: ReadonlyMap<string, ts.Symbol>;
|
|
97
|
+
readonly underlyingSymbolToTypeName: ReadonlyMap<ts.Symbol, string>;
|
|
98
|
+
readonly globalTypeMappings: ReadonlyArray<GlobalTypeMapping>;
|
|
99
|
+
readonly sourceFiles: ReadonlySet<string>;
|
|
100
|
+
readonly scalarMappingTable: ScalarBaseTypeMappingTable | null;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const RESOLVER_METADATA_PROPERTY = METADATA_PROPERTIES.RESOLVER;
|
|
104
|
+
const ABSTRACT_RESOLVER_METADATA_PROPERTY =
|
|
105
|
+
METADATA_PROPERTIES.ABSTRACT_RESOLVER;
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Detects abstract resolver kind and target type from metadata embedded in the type.
|
|
109
|
+
* Returns null if no abstract resolver metadata is found.
|
|
110
|
+
*/
|
|
111
|
+
function detectAbstractResolverFromMetadataType(
|
|
112
|
+
callExpr: ts.CallExpression,
|
|
113
|
+
checker: ts.TypeChecker,
|
|
114
|
+
): { kind: AbstractResolverKind; targetTypeName: string } | null {
|
|
115
|
+
const returnType = checker.getTypeAtLocation(callExpr);
|
|
116
|
+
|
|
117
|
+
const metadataProp = returnType.getProperty(
|
|
118
|
+
ABSTRACT_RESOLVER_METADATA_PROPERTY,
|
|
119
|
+
);
|
|
120
|
+
if (!metadataProp) {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const metadataType = checker.getTypeOfSymbol(metadataProp);
|
|
125
|
+
const actualType = getActualMetadataType(metadataType);
|
|
126
|
+
if (!actualType) {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const kindProp = actualType.getProperty("kind");
|
|
131
|
+
if (!kindProp) {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const kindType = checker.getTypeOfSymbol(kindProp);
|
|
136
|
+
if (!kindType.isStringLiteral()) {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const kind = kindType.value;
|
|
141
|
+
if (kind !== "resolveType" && kind !== "isTypeOf") {
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const targetTypeProp = actualType.getProperty("targetType");
|
|
146
|
+
if (!targetTypeProp) {
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const targetType = checker.getTypeOfSymbol(targetTypeProp);
|
|
151
|
+
const targetTypeName = extractTypeNameFromType(targetType, checker);
|
|
152
|
+
|
|
153
|
+
if (!targetTypeName) {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return { kind, targetTypeName };
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Extracts a type name from a TypeScript type.
|
|
162
|
+
* Handles internal type symbols (like __type) by falling back to typeToString.
|
|
163
|
+
* Returns null for unresolvable types (any, unknown).
|
|
164
|
+
*/
|
|
165
|
+
function extractTypeNameFromType(
|
|
166
|
+
type: ts.Type,
|
|
167
|
+
checker: ts.TypeChecker,
|
|
168
|
+
): string | null {
|
|
169
|
+
if (type.flags & ts.TypeFlags.Any) {
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (type.aliasSymbol) {
|
|
174
|
+
const aliasName = type.aliasSymbol.getName();
|
|
175
|
+
if (!isInternalTypeSymbol(aliasName)) {
|
|
176
|
+
return aliasName;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const symbol = type.getSymbol();
|
|
181
|
+
if (symbol) {
|
|
182
|
+
const symbolName = symbol.getName();
|
|
183
|
+
if (!isInternalTypeSymbol(symbolName)) {
|
|
184
|
+
return symbolName;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const typeString = checker.typeToString(type);
|
|
189
|
+
if (typeString && typeString !== "unknown" && typeString !== "any") {
|
|
190
|
+
return typeString;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Detects resolver type from metadata embedded in the type.
|
|
198
|
+
* Follows the same pattern as scalar metadata detection.
|
|
199
|
+
*/
|
|
200
|
+
function detectResolverFromMetadataType(
|
|
201
|
+
callExpr: ts.CallExpression,
|
|
202
|
+
checker: ts.TypeChecker,
|
|
203
|
+
): DefineApiResolverType | undefined {
|
|
204
|
+
const returnType = checker.getTypeAtLocation(callExpr);
|
|
205
|
+
|
|
206
|
+
const metadataProp = returnType.getProperty(RESOLVER_METADATA_PROPERTY);
|
|
207
|
+
if (!metadataProp) {
|
|
208
|
+
return undefined;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const metadataType = checker.getTypeOfSymbol(metadataProp);
|
|
212
|
+
const actualType = getActualMetadataType(metadataType);
|
|
213
|
+
if (!actualType) {
|
|
214
|
+
return undefined;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const kindProp = actualType.getProperty("kind");
|
|
218
|
+
if (!kindProp) {
|
|
219
|
+
return undefined;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const kindType = checker.getTypeOfSymbol(kindProp);
|
|
223
|
+
if (kindType.isStringLiteral()) {
|
|
224
|
+
const kind = kindType.value;
|
|
225
|
+
if (kind === "query" || kind === "mutation" || kind === "field") {
|
|
226
|
+
return kind;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return undefined;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function isInlineTypeLiteralDeclaration(declaration: ts.Declaration): boolean {
|
|
234
|
+
if (!ts.isPropertySignature(declaration)) {
|
|
235
|
+
return false;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const parent = declaration.parent;
|
|
239
|
+
if (!ts.isTypeLiteralNode(parent)) {
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const grandparent = parent.parent;
|
|
244
|
+
if (ts.isTypeAliasDeclaration(grandparent)) {
|
|
245
|
+
return false;
|
|
246
|
+
}
|
|
247
|
+
if (ts.isInterfaceDeclaration(grandparent)) {
|
|
248
|
+
return false;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return true;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function extractTSDocFromPropertyWithPriority(
|
|
255
|
+
prop: ts.Symbol,
|
|
256
|
+
checker: ts.TypeChecker,
|
|
257
|
+
): { description: string | null; deprecated: DeprecationInfo | null } {
|
|
258
|
+
const declarations = prop.getDeclarations();
|
|
259
|
+
if (!declarations || declarations.length === 0) {
|
|
260
|
+
return { description: null, deprecated: null };
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const inlineDeclaration = declarations.find(isInlineTypeLiteralDeclaration);
|
|
264
|
+
|
|
265
|
+
if (inlineDeclaration) {
|
|
266
|
+
const inlineSymbol = checker.getSymbolAtLocation(
|
|
267
|
+
(inlineDeclaration as ts.PropertySignature).name,
|
|
268
|
+
);
|
|
269
|
+
if (inlineSymbol) {
|
|
270
|
+
return extractTsDocFromSymbol(inlineSymbol, checker);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return extractTsDocFromSymbol(prop, checker);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Checks if a type should be unwrapped as a GqlField type.
|
|
279
|
+
* Detects by checking for metadata properties, not by type name.
|
|
280
|
+
*/
|
|
281
|
+
function shouldUnwrapAsGqlField(type: ts.Type): boolean {
|
|
282
|
+
return hasDirectiveMetadata(type);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Checks if a type has only index signatures with no named properties.
|
|
287
|
+
* Types like `{ [key: string]: number }` return true.
|
|
288
|
+
* Returns false for NoArgs type (Record<string, never>).
|
|
289
|
+
*/
|
|
290
|
+
function hasOnlyIndexSignatures(
|
|
291
|
+
type: ts.Type,
|
|
292
|
+
checker: ts.TypeChecker,
|
|
293
|
+
): boolean {
|
|
294
|
+
const targetType = checker.getApparentType(type);
|
|
295
|
+
|
|
296
|
+
const indexInfos = checker.getIndexInfosOfType(targetType);
|
|
297
|
+
const hasIndexSignatures = indexInfos.length > 0;
|
|
298
|
+
|
|
299
|
+
if (!hasIndexSignatures) {
|
|
300
|
+
return false;
|
|
301
|
+
}
|
|
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
|
+
|
|
314
|
+
const properties = targetType
|
|
315
|
+
.getProperties()
|
|
316
|
+
.filter((p) => !p.getName().startsWith(" $"));
|
|
317
|
+
if (properties.length > 0) {
|
|
318
|
+
return false;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
return true;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Gets the type name for error messages.
|
|
326
|
+
*/
|
|
327
|
+
function getTypeNameForDiagnostic(
|
|
328
|
+
type: ts.Type,
|
|
329
|
+
checker: ts.TypeChecker,
|
|
330
|
+
): string {
|
|
331
|
+
if (type.aliasSymbol) {
|
|
332
|
+
return type.aliasSymbol.getName();
|
|
333
|
+
}
|
|
334
|
+
if (type.symbol) {
|
|
335
|
+
return type.symbol.getName();
|
|
336
|
+
}
|
|
337
|
+
return checker.typeToString(type);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
function extractArgsFromType(
|
|
341
|
+
argsType: ts.Type,
|
|
342
|
+
ctx: FieldTypeResolverContext,
|
|
343
|
+
argsTypeNode?: ts.TypeNode,
|
|
344
|
+
): ArgumentDefinition[] {
|
|
345
|
+
const args: ArgumentDefinition[] = [];
|
|
346
|
+
const properties = extractPropertySymbols(argsType, ctx.checker);
|
|
347
|
+
|
|
348
|
+
const memberTypeNodes = new Map<string, ts.TypeNode>();
|
|
349
|
+
if (argsTypeNode && ts.isTypeLiteralNode(argsTypeNode)) {
|
|
350
|
+
for (const member of argsTypeNode.members) {
|
|
351
|
+
if (ts.isPropertySignature(member) && member.name && member.type) {
|
|
352
|
+
const name = ts.isIdentifier(member.name)
|
|
353
|
+
? member.name.text
|
|
354
|
+
: member.name.getText();
|
|
355
|
+
memberTypeNodes.set(name, member.type);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
for (const prop of properties) {
|
|
361
|
+
const propType = ctx.checker.getTypeOfSymbol(prop);
|
|
362
|
+
const optional = hasUndefinedInType(propType);
|
|
363
|
+
|
|
364
|
+
const tsdocInfo = extractTSDocFromPropertyWithPriority(prop, ctx.checker);
|
|
365
|
+
|
|
366
|
+
let defaultValue: DirectiveArgumentValue | null = null;
|
|
367
|
+
let actualPropType = propType;
|
|
368
|
+
|
|
369
|
+
if (shouldUnwrapAsGqlField(propType)) {
|
|
370
|
+
const defaultValueResult = detectDefaultValueMetadata(
|
|
371
|
+
propType,
|
|
372
|
+
ctx.checker,
|
|
373
|
+
);
|
|
374
|
+
if (defaultValueResult.defaultValue) {
|
|
375
|
+
defaultValue = defaultValueResult.defaultValue;
|
|
376
|
+
}
|
|
377
|
+
actualPropType = unwrapDirectiveType(propType, ctx.checker);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
const propTypeNode = memberTypeNodes.get(prop.getName());
|
|
381
|
+
args.push({
|
|
382
|
+
name: prop.getName(),
|
|
383
|
+
tsType: resolveFieldType(actualPropType, propTypeNode, ctx),
|
|
384
|
+
optional,
|
|
385
|
+
description: tsdocInfo.description,
|
|
386
|
+
deprecated: tsdocInfo.deprecated,
|
|
387
|
+
defaultValue,
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
return args;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
function extractDirectivesFromTypeNode(
|
|
395
|
+
typeNode: ts.TypeNode | undefined,
|
|
396
|
+
checker: ts.TypeChecker,
|
|
397
|
+
): ReadonlyArray<DirectiveInfo> | null {
|
|
398
|
+
if (!typeNode) {
|
|
399
|
+
return null;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
const type = checker.getTypeFromTypeNode(typeNode);
|
|
403
|
+
const directiveResult = extractDirectivesFromType(type, checker);
|
|
404
|
+
|
|
405
|
+
if (directiveResult.directives.length > 0) {
|
|
406
|
+
return directiveResult.directives;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
return null;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
interface TypeArgumentsResult {
|
|
413
|
+
parentTypeName: string | null;
|
|
414
|
+
argsType: TSTypeReference | null;
|
|
415
|
+
args: ArgumentDefinition[] | null;
|
|
416
|
+
returnType: TSTypeReference;
|
|
417
|
+
directives: ReadonlyArray<DirectiveInfo> | null;
|
|
418
|
+
diagnostics: Diagnostic[];
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Validates an args type and returns diagnostics for problematic types.
|
|
423
|
+
*/
|
|
424
|
+
function validateArgsType(
|
|
425
|
+
argsType: ts.Type,
|
|
426
|
+
argsTypeNode: ts.TypeNode,
|
|
427
|
+
checker: ts.TypeChecker,
|
|
428
|
+
): Diagnostic[] {
|
|
429
|
+
const diagnostics: Diagnostic[] = [];
|
|
430
|
+
|
|
431
|
+
if (hasOnlyIndexSignatures(argsType, checker)) {
|
|
432
|
+
const typeName = getTypeNameForDiagnostic(argsType, checker);
|
|
433
|
+
diagnostics.push({
|
|
434
|
+
code: "INDEX_SIGNATURE_ONLY",
|
|
435
|
+
message: `Type '${typeName}' contains only index signatures and cannot be represented as a GraphQL type. Use a concrete object type instead.`,
|
|
436
|
+
severity: "error",
|
|
437
|
+
location: getSourceLocationFromNode(argsTypeNode),
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
return diagnostics;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
interface ExtractTypeArgumentsFromCallParams {
|
|
445
|
+
readonly node: ts.CallExpression;
|
|
446
|
+
readonly inputContext: FieldTypeResolverContext;
|
|
447
|
+
readonly outputContext: FieldTypeResolverContext;
|
|
448
|
+
readonly resolverType: DefineApiResolverType;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
function extractTypeArgumentsFromCall(
|
|
452
|
+
params: ExtractTypeArgumentsFromCallParams,
|
|
453
|
+
): TypeArgumentsResult | null {
|
|
454
|
+
const { node, inputContext, outputContext, resolverType } = params;
|
|
455
|
+
const { checker } = inputContext;
|
|
456
|
+
const typeArgs = node.typeArguments;
|
|
457
|
+
if (!typeArgs) {
|
|
458
|
+
return null;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
if (resolverType === "field") {
|
|
462
|
+
if (typeArgs.length < 3) {
|
|
463
|
+
return null;
|
|
464
|
+
}
|
|
465
|
+
const parentTypeNode = typeArgs[0];
|
|
466
|
+
const argsTypeNode = typeArgs[1];
|
|
467
|
+
const returnTypeNode = typeArgs[2];
|
|
468
|
+
const directiveTypeNode = typeArgs[3];
|
|
469
|
+
|
|
470
|
+
if (!parentTypeNode || !argsTypeNode || !returnTypeNode) {
|
|
471
|
+
return null;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
const argsType = checker.getTypeFromTypeNode(argsTypeNode);
|
|
475
|
+
const returnType = checker.getTypeFromTypeNode(returnTypeNode);
|
|
476
|
+
|
|
477
|
+
const parentTypeName = getTypeNameFromNode(parentTypeNode);
|
|
478
|
+
|
|
479
|
+
const argsTypeRef = resolveFieldType(argsType, undefined, inputContext);
|
|
480
|
+
const isNoArgs =
|
|
481
|
+
argsTypeRef.kind === "reference" && argsTypeRef.name === "Record";
|
|
482
|
+
|
|
483
|
+
const diagnostics: Diagnostic[] = [];
|
|
484
|
+
|
|
485
|
+
if (!isNoArgs) {
|
|
486
|
+
diagnostics.push(...validateArgsType(argsType, argsTypeNode, checker));
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
const args = isNoArgs
|
|
490
|
+
? null
|
|
491
|
+
: extractArgsFromType(argsType, inputContext, argsTypeNode);
|
|
492
|
+
|
|
493
|
+
const directives = extractDirectivesFromTypeNode(
|
|
494
|
+
directiveTypeNode,
|
|
495
|
+
checker,
|
|
496
|
+
);
|
|
497
|
+
|
|
498
|
+
return {
|
|
499
|
+
parentTypeName: parentTypeName ?? null,
|
|
500
|
+
argsType: isNoArgs ? null : argsTypeRef,
|
|
501
|
+
args: args && args.length > 0 ? args : null,
|
|
502
|
+
returnType: resolveFieldType(returnType, returnTypeNode, outputContext),
|
|
503
|
+
directives,
|
|
504
|
+
diagnostics,
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
if (typeArgs.length < 2) {
|
|
509
|
+
return null;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
const argsTypeNode = typeArgs[0];
|
|
513
|
+
const returnTypeNode = typeArgs[1];
|
|
514
|
+
const directiveTypeNode = typeArgs[2];
|
|
515
|
+
|
|
516
|
+
if (!argsTypeNode || !returnTypeNode) {
|
|
517
|
+
return null;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
const argsType = checker.getTypeFromTypeNode(argsTypeNode);
|
|
521
|
+
const returnType = checker.getTypeFromTypeNode(returnTypeNode);
|
|
522
|
+
|
|
523
|
+
const argsTypeRef = resolveFieldType(argsType, undefined, inputContext);
|
|
524
|
+
const isNoArgs =
|
|
525
|
+
argsTypeRef.kind === "reference" && argsTypeRef.name === "Record";
|
|
526
|
+
|
|
527
|
+
const diagnostics: Diagnostic[] = [];
|
|
528
|
+
|
|
529
|
+
if (!isNoArgs) {
|
|
530
|
+
diagnostics.push(...validateArgsType(argsType, argsTypeNode, checker));
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
const args = isNoArgs
|
|
534
|
+
? null
|
|
535
|
+
: extractArgsFromType(argsType, inputContext, argsTypeNode);
|
|
536
|
+
|
|
537
|
+
const directives = extractDirectivesFromTypeNode(directiveTypeNode, checker);
|
|
538
|
+
|
|
539
|
+
return {
|
|
540
|
+
parentTypeName: null,
|
|
541
|
+
argsType: isNoArgs ? null : argsTypeRef,
|
|
542
|
+
args: args && args.length > 0 ? args : null,
|
|
543
|
+
returnType: resolveFieldType(returnType, returnTypeNode, outputContext),
|
|
544
|
+
directives,
|
|
545
|
+
diagnostics,
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
function extractExportedInputTypes(
|
|
550
|
+
sourceFile: ts.SourceFile,
|
|
551
|
+
ctx: FieldTypeResolverContext,
|
|
552
|
+
): ExportedInputType[] {
|
|
553
|
+
const exportedTypes: ExportedInputType[] = [];
|
|
554
|
+
|
|
555
|
+
ts.forEachChild(sourceFile, (node) => {
|
|
556
|
+
if (ts.isTypeAliasDeclaration(node) && isExported(node)) {
|
|
557
|
+
const name = node.name.getText(sourceFile);
|
|
558
|
+
const type = ctx.checker.getTypeAtLocation(node.name);
|
|
559
|
+
const tsType = resolveFieldType(type, undefined, ctx);
|
|
560
|
+
|
|
561
|
+
exportedTypes.push({
|
|
562
|
+
name,
|
|
563
|
+
tsType,
|
|
564
|
+
sourceFile: sourceFile.fileName,
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
return exportedTypes;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
export function extractDefineApiResolvers(
|
|
573
|
+
program: ts.Program,
|
|
574
|
+
files: ReadonlyArray<string>,
|
|
575
|
+
options: ExtractDefineApiOptions,
|
|
576
|
+
): ExtractDefineApiResult {
|
|
577
|
+
const checker = program.getTypeChecker();
|
|
578
|
+
const resolvers: DefineApiResolverInfo[] = [];
|
|
579
|
+
const abstractTypeResolvers: AbstractResolverInfo[] = [];
|
|
580
|
+
const diagnostics: Diagnostic[] = [];
|
|
581
|
+
|
|
582
|
+
const {
|
|
583
|
+
knownTypeNames,
|
|
584
|
+
knownTypeSymbols,
|
|
585
|
+
underlyingSymbolToTypeName,
|
|
586
|
+
globalTypeMappings,
|
|
587
|
+
sourceFiles,
|
|
588
|
+
scalarMappingTable,
|
|
589
|
+
} = options;
|
|
590
|
+
const inputContext: FieldTypeResolverContext = {
|
|
591
|
+
checker,
|
|
592
|
+
knownTypeNames,
|
|
593
|
+
knownTypeSymbols,
|
|
594
|
+
underlyingSymbolToTypeName,
|
|
595
|
+
globalTypeMappings,
|
|
596
|
+
sourceFiles,
|
|
597
|
+
scalarMappingTable,
|
|
598
|
+
scalarMappingContext: "input",
|
|
599
|
+
};
|
|
600
|
+
const outputContext: FieldTypeResolverContext = {
|
|
601
|
+
checker,
|
|
602
|
+
knownTypeNames,
|
|
603
|
+
knownTypeSymbols,
|
|
604
|
+
underlyingSymbolToTypeName,
|
|
605
|
+
globalTypeMappings,
|
|
606
|
+
sourceFiles,
|
|
607
|
+
scalarMappingTable,
|
|
608
|
+
scalarMappingContext: "output",
|
|
609
|
+
};
|
|
610
|
+
|
|
611
|
+
for (const filePath of files) {
|
|
612
|
+
const sourceFile = program.getSourceFile(filePath);
|
|
613
|
+
if (!sourceFile) {
|
|
614
|
+
continue;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
const exportedInputTypes = extractExportedInputTypes(
|
|
618
|
+
sourceFile,
|
|
619
|
+
inputContext,
|
|
620
|
+
);
|
|
621
|
+
|
|
622
|
+
ts.forEachChild(sourceFile, (node) => {
|
|
623
|
+
if (!ts.isVariableStatement(node)) {
|
|
624
|
+
return;
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
if (!isExported(node)) {
|
|
628
|
+
return;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
for (const declaration of node.declarationList.declarations) {
|
|
632
|
+
if (!ts.isIdentifier(declaration.name)) {
|
|
633
|
+
continue;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
const fieldName = declaration.name.getText(sourceFile);
|
|
637
|
+
const initializer = declaration.initializer;
|
|
638
|
+
|
|
639
|
+
if (!initializer) {
|
|
640
|
+
continue;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
if (!ts.isCallExpression(initializer)) {
|
|
644
|
+
if (
|
|
645
|
+
ts.isConditionalExpression(initializer) ||
|
|
646
|
+
ts.isBinaryExpression(initializer)
|
|
647
|
+
) {
|
|
648
|
+
const hasDefineCall = initializer
|
|
649
|
+
.getText(sourceFile)
|
|
650
|
+
.match(/define(Query|Mutation|Field)/);
|
|
651
|
+
if (hasDefineCall) {
|
|
652
|
+
diagnostics.push({
|
|
653
|
+
code: "INVALID_DEFINE_CALL",
|
|
654
|
+
message: `Complex expressions with define* functions are not supported. Use a simple 'export const ${fieldName} = defineXxx(...)' pattern.`,
|
|
655
|
+
severity: "error",
|
|
656
|
+
location: getSourceLocationFromNode(declaration.name),
|
|
657
|
+
});
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
continue;
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
const abstractResolverInfo = detectAbstractResolverFromMetadataType(
|
|
664
|
+
initializer,
|
|
665
|
+
checker,
|
|
666
|
+
);
|
|
667
|
+
|
|
668
|
+
if (abstractResolverInfo) {
|
|
669
|
+
const sourceLocation = getSourceLocationFromNode(declaration.name);
|
|
670
|
+
if (sourceLocation) {
|
|
671
|
+
abstractTypeResolvers.push({
|
|
672
|
+
kind: abstractResolverInfo.kind,
|
|
673
|
+
targetTypeName: abstractResolverInfo.targetTypeName,
|
|
674
|
+
exportName: fieldName,
|
|
675
|
+
sourceFile: filePath,
|
|
676
|
+
sourceLocation,
|
|
677
|
+
});
|
|
678
|
+
}
|
|
679
|
+
continue;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
const resolverType = detectResolverFromMetadataType(
|
|
683
|
+
initializer,
|
|
684
|
+
checker,
|
|
685
|
+
);
|
|
686
|
+
|
|
687
|
+
if (!resolverType) {
|
|
688
|
+
continue;
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
const funcName = ts.isIdentifier(initializer.expression)
|
|
692
|
+
? initializer.expression.text
|
|
693
|
+
: undefined;
|
|
694
|
+
|
|
695
|
+
const typeInfo = extractTypeArgumentsFromCall({
|
|
696
|
+
node: initializer,
|
|
697
|
+
inputContext,
|
|
698
|
+
outputContext,
|
|
699
|
+
resolverType,
|
|
700
|
+
});
|
|
701
|
+
|
|
702
|
+
if (!typeInfo) {
|
|
703
|
+
diagnostics.push({
|
|
704
|
+
code: "INVALID_DEFINE_CALL",
|
|
705
|
+
message: `Failed to extract type arguments from ${funcName ?? "define*"} call for '${fieldName}'`,
|
|
706
|
+
severity: "error",
|
|
707
|
+
location: getSourceLocationFromNode(declaration.name),
|
|
708
|
+
});
|
|
709
|
+
continue;
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
diagnostics.push(...typeInfo.diagnostics);
|
|
713
|
+
|
|
714
|
+
const tsdocInfo = extractTsDocInfo(node, checker);
|
|
715
|
+
const sourceLocation = getSourceLocationFromNode(declaration.name) ?? {
|
|
716
|
+
file: filePath,
|
|
717
|
+
line: 1,
|
|
718
|
+
column: 1,
|
|
719
|
+
};
|
|
720
|
+
|
|
721
|
+
resolvers.push({
|
|
722
|
+
fieldName,
|
|
723
|
+
resolverType,
|
|
724
|
+
parentTypeName: typeInfo.parentTypeName,
|
|
725
|
+
argsType: typeInfo.argsType,
|
|
726
|
+
args: typeInfo.args,
|
|
727
|
+
returnType: typeInfo.returnType,
|
|
728
|
+
sourceFile: filePath,
|
|
729
|
+
sourceLocation,
|
|
730
|
+
exportedInputTypes,
|
|
731
|
+
description: tsdocInfo.description,
|
|
732
|
+
deprecated: tsdocInfo.deprecated,
|
|
733
|
+
directives: typeInfo.directives,
|
|
734
|
+
});
|
|
735
|
+
}
|
|
736
|
+
});
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
return { resolvers, abstractTypeResolvers, diagnostics };
|
|
740
|
+
}
|