@gqlkit-ts/cli 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (234) hide show
  1. package/dist/auto-type-generator/auto-type-generator.d.ts +19 -3
  2. package/dist/auto-type-generator/auto-type-generator.d.ts.map +1 -1
  3. package/dist/auto-type-generator/auto-type-generator.js +236 -49
  4. package/dist/auto-type-generator/auto-type-generator.js.map +1 -1
  5. package/dist/auto-type-generator/index.d.ts +1 -1
  6. package/dist/auto-type-generator/index.d.ts.map +1 -1
  7. package/dist/auto-type-generator/index.js.map +1 -1
  8. package/dist/auto-type-generator/inline-enum-collector.d.ts +31 -0
  9. package/dist/auto-type-generator/inline-enum-collector.d.ts.map +1 -0
  10. package/dist/auto-type-generator/inline-enum-collector.js +157 -0
  11. package/dist/auto-type-generator/inline-enum-collector.js.map +1 -0
  12. package/dist/auto-type-generator/naming-convention.d.ts +4 -0
  13. package/dist/auto-type-generator/naming-convention.d.ts.map +1 -1
  14. package/dist/auto-type-generator/naming-convention.js +8 -0
  15. package/dist/auto-type-generator/naming-convention.js.map +1 -1
  16. package/dist/gen-orchestrator/orchestrator.d.ts.map +1 -1
  17. package/dist/gen-orchestrator/orchestrator.js +106 -8
  18. package/dist/gen-orchestrator/orchestrator.js.map +1 -1
  19. package/dist/resolver-extractor/extract-resolvers.d.ts +10 -1
  20. package/dist/resolver-extractor/extract-resolvers.d.ts.map +1 -1
  21. package/dist/resolver-extractor/extractor/define-api-extractor.d.ts +11 -1
  22. package/dist/resolver-extractor/extractor/define-api-extractor.d.ts.map +1 -1
  23. package/dist/resolver-extractor/extractor/define-api-extractor.js +88 -264
  24. package/dist/resolver-extractor/extractor/define-api-extractor.js.map +1 -1
  25. package/dist/schema-generator/emitter/code-emitter.d.ts +10 -2
  26. package/dist/schema-generator/emitter/code-emitter.d.ts.map +1 -1
  27. package/dist/schema-generator/emitter/code-emitter.js +19 -4
  28. package/dist/schema-generator/emitter/code-emitter.js.map +1 -1
  29. package/dist/schema-generator/generate-schema.d.ts.map +1 -1
  30. package/dist/schema-generator/generate-schema.js +18 -1
  31. package/dist/schema-generator/generate-schema.js.map +1 -1
  32. package/dist/schema-generator/integrator/result-integrator.d.ts +20 -0
  33. package/dist/schema-generator/integrator/result-integrator.d.ts.map +1 -1
  34. package/dist/schema-generator/integrator/result-integrator.js +42 -0
  35. package/dist/schema-generator/integrator/result-integrator.js.map +1 -1
  36. package/dist/shared/constants.d.ts +0 -16
  37. package/dist/shared/constants.d.ts.map +1 -1
  38. package/dist/shared/constants.js +0 -19
  39. package/dist/shared/constants.js.map +1 -1
  40. package/dist/shared/directive-detector.d.ts.map +1 -1
  41. package/dist/shared/directive-detector.js +8 -15
  42. package/dist/shared/directive-detector.js.map +1 -1
  43. package/dist/shared/file-scanner.d.ts.map +1 -1
  44. package/dist/shared/file-scanner.js +5 -3
  45. package/dist/shared/file-scanner.js.map +1 -1
  46. package/dist/shared/index.d.ts +1 -1
  47. package/dist/shared/index.d.ts.map +1 -1
  48. package/dist/shared/index.js +1 -3
  49. package/dist/shared/index.js.map +1 -1
  50. package/dist/shared/interface-detector.d.ts +3 -2
  51. package/dist/shared/interface-detector.d.ts.map +1 -1
  52. package/dist/shared/interface-detector.js +54 -11
  53. package/dist/shared/interface-detector.js.map +1 -1
  54. package/dist/shared/path-utils.d.ts +2 -0
  55. package/dist/shared/path-utils.d.ts.map +1 -0
  56. package/dist/shared/path-utils.js +4 -0
  57. package/dist/shared/path-utils.js.map +1 -0
  58. package/dist/shared/type-converter.d.ts.map +1 -1
  59. package/dist/shared/type-converter.js +11 -0
  60. package/dist/shared/type-converter.js.map +1 -1
  61. package/dist/shared/typescript-utils.d.ts +34 -7
  62. package/dist/shared/typescript-utils.d.ts.map +1 -1
  63. package/dist/shared/typescript-utils.js +72 -24
  64. package/dist/shared/typescript-utils.js.map +1 -1
  65. package/dist/type-extractor/collector/scalar-collector.d.ts.map +1 -1
  66. package/dist/type-extractor/collector/scalar-collector.js +4 -14
  67. package/dist/type-extractor/collector/scalar-collector.js.map +1 -1
  68. package/dist/type-extractor/converter/graphql-converter.d.ts.map +1 -1
  69. package/dist/type-extractor/converter/graphql-converter.js +42 -3
  70. package/dist/type-extractor/converter/graphql-converter.js.map +1 -1
  71. package/dist/type-extractor/extractor/field-type-resolver.d.ts +28 -0
  72. package/dist/type-extractor/extractor/field-type-resolver.d.ts.map +1 -0
  73. package/dist/type-extractor/extractor/field-type-resolver.js +394 -0
  74. package/dist/type-extractor/extractor/field-type-resolver.js.map +1 -0
  75. package/dist/type-extractor/extractor/type-extractor.d.ts +12 -3
  76. package/dist/type-extractor/extractor/type-extractor.d.ts.map +1 -1
  77. package/dist/type-extractor/extractor/type-extractor.js +176 -210
  78. package/dist/type-extractor/extractor/type-extractor.js.map +1 -1
  79. package/dist/type-extractor/extractor/type-name-collector.d.ts +24 -0
  80. package/dist/type-extractor/extractor/type-name-collector.d.ts.map +1 -0
  81. package/dist/type-extractor/extractor/type-name-collector.js +102 -0
  82. package/dist/type-extractor/extractor/type-name-collector.js.map +1 -0
  83. package/dist/type-extractor/mapper/scalar-base-type-mapper.d.ts +89 -0
  84. package/dist/type-extractor/mapper/scalar-base-type-mapper.d.ts.map +1 -0
  85. package/dist/type-extractor/mapper/scalar-base-type-mapper.js +158 -0
  86. package/dist/type-extractor/mapper/scalar-base-type-mapper.js.map +1 -0
  87. package/dist/type-extractor/types/diagnostics.d.ts +1 -1
  88. package/dist/type-extractor/types/diagnostics.d.ts.map +1 -1
  89. package/dist/type-extractor/types/graphql.d.ts +2 -0
  90. package/dist/type-extractor/types/graphql.d.ts.map +1 -1
  91. package/dist/type-extractor/types/index.d.ts +2 -1
  92. package/dist/type-extractor/types/index.d.ts.map +1 -1
  93. package/dist/type-extractor/types/index.js +1 -1
  94. package/dist/type-extractor/types/index.js.map +1 -1
  95. package/dist/type-extractor/types/ts-type-reference-factory.d.ts +39 -0
  96. package/dist/type-extractor/types/ts-type-reference-factory.d.ts.map +1 -0
  97. package/dist/type-extractor/types/ts-type-reference-factory.js +69 -0
  98. package/dist/type-extractor/types/ts-type-reference-factory.js.map +1 -0
  99. package/dist/type-extractor/types/typescript.d.ts +21 -1
  100. package/dist/type-extractor/types/typescript.d.ts.map +1 -1
  101. package/dist/type-extractor/validator/type-validator.js +1 -1
  102. package/dist/type-extractor/validator/type-validator.js.map +1 -1
  103. package/docs/index.md +1 -0
  104. package/docs/integration/drizzle.md +191 -0
  105. package/docs/schema/enums.md +208 -0
  106. package/docs/schema/fields.md +2 -0
  107. package/docs/schema/inputs.md +2 -0
  108. package/docs/schema/objects.md +2 -0
  109. package/docs/schema/queries-mutations.md +2 -0
  110. package/package.json +10 -3
  111. package/src/auto-type-generator/auto-type-generator.ts +925 -0
  112. package/src/auto-type-generator/index.ts +21 -0
  113. package/src/auto-type-generator/inline-enum-collector.ts +290 -0
  114. package/src/auto-type-generator/name-collision-validator.ts +119 -0
  115. package/src/auto-type-generator/naming-convention.ts +126 -0
  116. package/src/cli.ts +11 -0
  117. package/src/commands/gen.ts +141 -0
  118. package/src/commands/main.ts +5 -0
  119. package/src/config/define-config.ts +28 -0
  120. package/src/config/index.ts +7 -0
  121. package/src/config/types.ts +144 -0
  122. package/src/config-loader/index.ts +14 -0
  123. package/src/config-loader/loader.ts +143 -0
  124. package/src/config-loader/validator.ts +672 -0
  125. package/src/gen-orchestrator/hook-executor/hook-executor.ts +117 -0
  126. package/src/gen-orchestrator/orchestrator.ts +784 -0
  127. package/src/gen-orchestrator/reporter/diagnostic-reporter.ts +44 -0
  128. package/src/gen-orchestrator/reporter/progress-reporter.ts +61 -0
  129. package/src/gen-orchestrator/writer/file-writer.ts +38 -0
  130. package/src/index.ts +2 -0
  131. package/src/resolver-extractor/extract-resolvers.ts +63 -0
  132. package/src/resolver-extractor/extractor/define-api-extractor.ts +806 -0
  133. package/src/resolver-extractor/index.ts +19 -0
  134. package/src/resolver-extractor/validator/abstract-resolver-validator.ts +251 -0
  135. package/src/resolver-extractor/validator/only-validator.ts +158 -0
  136. package/src/schema-generator/builder/ast-builder.ts +706 -0
  137. package/src/schema-generator/emitter/code-emitter.ts +351 -0
  138. package/src/schema-generator/emitter/sdl-emitter.ts +13 -0
  139. package/src/schema-generator/generate-schema.ts +170 -0
  140. package/src/schema-generator/index.ts +19 -0
  141. package/src/schema-generator/integrator/result-integrator.ts +690 -0
  142. package/src/schema-generator/pruner/schema-pruner.ts +112 -0
  143. package/src/schema-generator/resolver-collector/resolver-collector.ts +123 -0
  144. package/src/shared/constants.ts +122 -0
  145. package/src/shared/default-value-detector.ts +172 -0
  146. package/src/shared/diagnostics.ts +35 -0
  147. package/src/shared/directive-definition-extractor.ts +564 -0
  148. package/src/shared/directive-detector.ts +556 -0
  149. package/src/shared/file-scanner.ts +170 -0
  150. package/src/shared/index.ts +32 -0
  151. package/src/shared/inline-object-extractor.ts +102 -0
  152. package/src/shared/inline-object-utils.ts +23 -0
  153. package/src/shared/interface-detector.ts +176 -0
  154. package/src/shared/interface-validator.ts +211 -0
  155. package/src/shared/metadata-detector.ts +443 -0
  156. package/src/shared/path-utils.ts +3 -0
  157. package/src/shared/program-factory.ts +51 -0
  158. package/src/shared/source-location.ts +27 -0
  159. package/src/shared/tsconfig-loader.ts +126 -0
  160. package/src/shared/tsdoc-parser.ts +155 -0
  161. package/src/shared/type-converter.ts +99 -0
  162. package/src/shared/typescript-utils.ts +246 -0
  163. package/src/type-extractor/collector/result-collector.ts +57 -0
  164. package/src/type-extractor/collector/scalar-collector.ts +254 -0
  165. package/src/type-extractor/converter/field-eligibility.ts +112 -0
  166. package/src/type-extractor/converter/graphql-converter.ts +459 -0
  167. package/src/type-extractor/extract-types.ts +1 -0
  168. package/src/type-extractor/extractor/field-type-resolver.ts +569 -0
  169. package/src/type-extractor/extractor/type-extractor.ts +1567 -0
  170. package/src/type-extractor/extractor/type-name-collector.ts +130 -0
  171. package/src/type-extractor/index.ts +20 -0
  172. package/src/type-extractor/mapper/scalar-base-type-mapper.ts +265 -0
  173. package/src/type-extractor/types/diagnostics.ts +99 -0
  174. package/src/type-extractor/types/graphql.ts +55 -0
  175. package/src/type-extractor/types/index.ts +37 -0
  176. package/src/type-extractor/types/ts-type-reference-factory.ts +137 -0
  177. package/src/type-extractor/types/typescript.ts +133 -0
  178. package/src/type-extractor/validator/type-validator.ts +77 -0
  179. package/dist/auto-type-generator/auto-type-generator.test.d.ts +0 -2
  180. package/dist/auto-type-generator/auto-type-generator.test.d.ts.map +0 -1
  181. package/dist/auto-type-generator/auto-type-generator.test.js +0 -613
  182. package/dist/auto-type-generator/auto-type-generator.test.js.map +0 -1
  183. package/dist/auto-type-generator/name-collision-validator.test.d.ts +0 -2
  184. package/dist/auto-type-generator/name-collision-validator.test.d.ts.map +0 -1
  185. package/dist/auto-type-generator/name-collision-validator.test.js +0 -358
  186. package/dist/auto-type-generator/name-collision-validator.test.js.map +0 -1
  187. package/dist/auto-type-generator/naming-convention.test.d.ts +0 -2
  188. package/dist/auto-type-generator/naming-convention.test.d.ts.map +0 -1
  189. package/dist/auto-type-generator/naming-convention.test.js +0 -132
  190. package/dist/auto-type-generator/naming-convention.test.js.map +0 -1
  191. package/dist/commands/gen.test.d.ts +0 -2
  192. package/dist/commands/gen.test.d.ts.map +0 -1
  193. package/dist/commands/gen.test.js +0 -226
  194. package/dist/commands/gen.test.js.map +0 -1
  195. package/dist/config-loader/loader.test.d.ts +0 -2
  196. package/dist/config-loader/loader.test.d.ts.map +0 -1
  197. package/dist/config-loader/loader.test.js +0 -123
  198. package/dist/config-loader/loader.test.js.map +0 -1
  199. package/dist/config-loader/validator.test.d.ts +0 -2
  200. package/dist/config-loader/validator.test.d.ts.map +0 -1
  201. package/dist/config-loader/validator.test.js +0 -846
  202. package/dist/config-loader/validator.test.js.map +0 -1
  203. package/dist/gen-orchestrator/golden.test.d.ts +0 -2
  204. package/dist/gen-orchestrator/golden.test.d.ts.map +0 -1
  205. package/dist/gen-orchestrator/golden.test.js +0 -102
  206. package/dist/gen-orchestrator/golden.test.js.map +0 -1
  207. package/dist/gen-orchestrator/hook-executor/hook-executor.test.d.ts +0 -2
  208. package/dist/gen-orchestrator/hook-executor/hook-executor.test.d.ts.map +0 -1
  209. package/dist/gen-orchestrator/hook-executor/hook-executor.test.js +0 -167
  210. package/dist/gen-orchestrator/hook-executor/hook-executor.test.js.map +0 -1
  211. package/dist/gen-orchestrator/reporter/progress-reporter.test.d.ts +0 -2
  212. package/dist/gen-orchestrator/reporter/progress-reporter.test.d.ts.map +0 -1
  213. package/dist/gen-orchestrator/reporter/progress-reporter.test.js +0 -74
  214. package/dist/gen-orchestrator/reporter/progress-reporter.test.js.map +0 -1
  215. package/dist/resolver-extractor/validator/only-validator.test.d.ts +0 -8
  216. package/dist/resolver-extractor/validator/only-validator.test.d.ts.map +0 -1
  217. package/dist/resolver-extractor/validator/only-validator.test.js +0 -352
  218. package/dist/resolver-extractor/validator/only-validator.test.js.map +0 -1
  219. package/dist/schema-generator/builder/ast-builder.test.d.ts +0 -2
  220. package/dist/schema-generator/builder/ast-builder.test.d.ts.map +0 -1
  221. package/dist/schema-generator/builder/ast-builder.test.js +0 -469
  222. package/dist/schema-generator/builder/ast-builder.test.js.map +0 -1
  223. package/dist/shared/file-scanner.test.d.ts +0 -2
  224. package/dist/shared/file-scanner.test.d.ts.map +0 -1
  225. package/dist/shared/file-scanner.test.js +0 -138
  226. package/dist/shared/file-scanner.test.js.map +0 -1
  227. package/dist/shared/interface-validator.test.d.ts +0 -2
  228. package/dist/shared/interface-validator.test.d.ts.map +0 -1
  229. package/dist/shared/interface-validator.test.js +0 -145
  230. package/dist/shared/interface-validator.test.js.map +0 -1
  231. package/dist/type-extractor/types/typescript.test.d.ts +0 -2
  232. package/dist/type-extractor/types/typescript.test.d.ts.map +0 -1
  233. package/dist/type-extractor/types/typescript.test.js +0 -287
  234. package/dist/type-extractor/types/typescript.test.js.map +0 -1
@@ -0,0 +1,784 @@
1
+ import { dirname, relative, resolve } from "node:path";
2
+ import type ts from "typescript";
3
+ import type {
4
+ ResolvedOutputConfig,
5
+ ResolvedScalarMapping,
6
+ } from "../config-loader/index.js";
7
+ import {
8
+ type AbstractResolverInfo,
9
+ type ArgumentDefinition,
10
+ type DefineApiResolverInfo,
11
+ extractDefineApiResolvers,
12
+ } from "../resolver-extractor/extractor/define-api-extractor.js";
13
+ import type {
14
+ GraphQLFieldDefinition,
15
+ GraphQLInputValue,
16
+ TypeExtension,
17
+ } from "../resolver-extractor/index.js";
18
+ import { generateSchema } from "../schema-generator/index.js";
19
+
20
+ import {
21
+ collectDiagnostics,
22
+ convertTsTypeToGraphQLType,
23
+ type DirectiveDefinitionInfo,
24
+ deduplicateDiagnostics,
25
+ extractDirectiveDefinitions,
26
+ scanDirectory,
27
+ toPosixPath,
28
+ } from "../shared/index.js";
29
+ import { createSharedProgram } from "../shared/program-factory.js";
30
+ import { collectResults } from "../type-extractor/collector/result-collector.js";
31
+ import {
32
+ type CollectedScalarType,
33
+ type ConfigScalarMapping,
34
+ collectScalars,
35
+ type ScalarMetadataInfo,
36
+ } from "../type-extractor/collector/scalar-collector.js";
37
+ import { convertToGraphQL } from "../type-extractor/converter/graphql-converter.js";
38
+ import {
39
+ extractTypesFromProgram,
40
+ type GlobalTypeMapping,
41
+ } from "../type-extractor/extractor/type-extractor.js";
42
+ import { collectDeclaredTypeNames } from "../type-extractor/extractor/type-name-collector.js";
43
+ import type {
44
+ Diagnostic,
45
+ Diagnostics,
46
+ ExtractedTypeInfo,
47
+ } from "../type-extractor/index.js";
48
+ import {
49
+ buildScalarMappingTable,
50
+ type ScalarBaseTypeMappingTable,
51
+ } from "../type-extractor/mapper/scalar-base-type-mapper.js";
52
+ import { validateTypes } from "../type-extractor/validator/type-validator.js";
53
+ import { writeFiles } from "./writer/file-writer.js";
54
+
55
+ export interface GenerationConfig {
56
+ readonly cwd: string;
57
+ readonly sourceDir: string;
58
+ readonly sourceIgnoreGlobs: ReadonlyArray<string>;
59
+ readonly output: ResolvedOutputConfig;
60
+ readonly configDir: string | null;
61
+ readonly customScalars: ReadonlyArray<ResolvedScalarMapping> | null;
62
+ readonly tsconfigPath: string | null;
63
+ }
64
+
65
+ export interface GeneratedFile {
66
+ readonly filePath: string;
67
+ readonly content: string;
68
+ }
69
+
70
+ export interface GenerationResult {
71
+ readonly success: boolean;
72
+ readonly files: ReadonlyArray<GeneratedFile>;
73
+ readonly diagnostics: ReadonlyArray<Diagnostic>;
74
+ }
75
+
76
+ interface TypesResult {
77
+ types: ReturnType<typeof collectResults>["types"];
78
+ extractedTypes: ReadonlyArray<ExtractedTypeInfo>;
79
+ diagnostics: Diagnostics;
80
+ detectedScalarNames: ReadonlyArray<string>;
81
+ detectedScalars: ReadonlyArray<ScalarMetadataInfo>;
82
+ collectedScalars: ReadonlyArray<CollectedScalarType>;
83
+ scalarMappingTable: ScalarBaseTypeMappingTable | null;
84
+ }
85
+
86
+ interface ResolversResult {
87
+ queryFields: { fields: ReadonlyArray<GraphQLFieldDefinition> };
88
+ mutationFields: { fields: ReadonlyArray<GraphQLFieldDefinition> };
89
+ typeExtensions: ReadonlyArray<TypeExtension>;
90
+ abstractTypeResolvers: ReadonlyArray<AbstractResolverInfo>;
91
+ diagnostics: Diagnostics;
92
+ }
93
+
94
+ interface PipelineContext {
95
+ readonly config: GenerationConfig;
96
+ readonly sourceFiles: ReadonlyArray<string>;
97
+ readonly program: ts.Program | null;
98
+ readonly knownTypeNames: ReadonlySet<string> | null;
99
+ readonly knownTypeSymbols: ReadonlyMap<string, ts.Symbol> | null;
100
+ readonly underlyingSymbolToTypeName: ReadonlyMap<ts.Symbol, string> | null;
101
+ readonly typesResult: TypesResult | null;
102
+ readonly resolversResult: ResolversResult | null;
103
+ readonly directiveDefinitions: DirectiveDefinitionInfo[] | null;
104
+ readonly diagnostics: Diagnostic[];
105
+ readonly aborted: boolean;
106
+ }
107
+
108
+ function collectAllDiagnostics(
109
+ typesResult: { diagnostics: Diagnostics },
110
+ resolversResult: { diagnostics: Diagnostics },
111
+ ): Diagnostic[] {
112
+ const diagnostics: Diagnostic[] = [];
113
+ diagnostics.push(...typesResult.diagnostics.errors);
114
+ diagnostics.push(...typesResult.diagnostics.warnings);
115
+ diagnostics.push(...resolversResult.diagnostics.errors);
116
+ diagnostics.push(...resolversResult.diagnostics.warnings);
117
+ return diagnostics;
118
+ }
119
+
120
+ function hasErrors(
121
+ typesResult: { diagnostics: { errors: ReadonlyArray<Diagnostic> } },
122
+ resolversResult: { diagnostics: { errors: ReadonlyArray<Diagnostic> } },
123
+ ): boolean {
124
+ return (
125
+ typesResult.diagnostics.errors.length > 0 ||
126
+ resolversResult.diagnostics.errors.length > 0
127
+ );
128
+ }
129
+
130
+ interface ExtractTypesCoreParams {
131
+ readonly program: ts.Program;
132
+ readonly sourceFiles: ReadonlyArray<string>;
133
+ readonly customScalarNames: ReadonlyArray<string>;
134
+ readonly globalTypeMappings: ReadonlyArray<GlobalTypeMapping>;
135
+ readonly configScalars: ReadonlyArray<ConfigScalarMapping>;
136
+ readonly sourceRoot: string | null;
137
+ readonly knownTypeNames: ReadonlySet<string>;
138
+ readonly knownTypeSymbols: ReadonlyMap<string, ts.Symbol>;
139
+ readonly underlyingSymbolToTypeName: ReadonlyMap<ts.Symbol, string>;
140
+ }
141
+
142
+ function extractTypesCore(params: ExtractTypesCoreParams): TypesResult {
143
+ const {
144
+ program,
145
+ sourceFiles,
146
+ customScalarNames,
147
+ globalTypeMappings,
148
+ configScalars,
149
+ sourceRoot,
150
+ knownTypeNames,
151
+ knownTypeSymbols,
152
+ underlyingSymbolToTypeName,
153
+ } = params;
154
+ const allDiagnostics: Diagnostic[] = [];
155
+
156
+ // Pass 1: Extract types and detect scalars (without scalar mapping table)
157
+ const pass1Result = extractTypesFromProgram(program, sourceFiles, {
158
+ globalTypeMappings,
159
+ knownTypeNames,
160
+ knownTypeSymbols,
161
+ underlyingSymbolToTypeName,
162
+ scalarMappingTable: null,
163
+ });
164
+
165
+ // Build scalar mapping table from detected scalars
166
+ const scalarMappingTable =
167
+ pass1Result.detectedScalars.length > 0
168
+ ? buildScalarMappingTable({
169
+ detectedScalars: pass1Result.detectedScalars,
170
+ checker: program.getTypeChecker(),
171
+ program,
172
+ })
173
+ : null;
174
+
175
+ // Report scalar mapping conflicts as diagnostics
176
+ if (scalarMappingTable) {
177
+ for (const [, conflict] of scalarMappingTable.conflicts) {
178
+ const baseTypeName = conflict.baseTypeSymbol.getName();
179
+ const scalarNames = conflict.conflictingScalars
180
+ .map((s) => s.scalarName)
181
+ .join(", ");
182
+ allDiagnostics.push({
183
+ code: conflict.code,
184
+ message: `Base type '${baseTypeName}' maps to multiple scalars: ${scalarNames}. Use explicit scalar type instead of the base type.`,
185
+ severity: "error",
186
+ location: null,
187
+ });
188
+ }
189
+ }
190
+
191
+ // Pass 2: Re-extract types with scalar mapping table (if we have detected scalars)
192
+ const extractionResult = scalarMappingTable
193
+ ? extractTypesFromProgram(program, sourceFiles, {
194
+ globalTypeMappings,
195
+ knownTypeNames,
196
+ knownTypeSymbols,
197
+ underlyingSymbolToTypeName,
198
+ scalarMappingTable,
199
+ })
200
+ : pass1Result;
201
+
202
+ allDiagnostics.push(...extractionResult.diagnostics);
203
+
204
+ const allCustomScalarNames = [
205
+ ...customScalarNames,
206
+ ...extractionResult.detectedScalarNames,
207
+ ];
208
+
209
+ const scalarValidationResult = collectScalars(
210
+ extractionResult.detectedScalars,
211
+ configScalars,
212
+ { sourceRoot },
213
+ );
214
+ const collectedScalars: CollectedScalarType[] = scalarValidationResult.success
215
+ ? [...scalarValidationResult.data]
216
+ : [];
217
+ if (!scalarValidationResult.success) {
218
+ for (const error of scalarValidationResult.errors) {
219
+ allDiagnostics.push({
220
+ code: error.code,
221
+ message: error.message,
222
+ severity: error.severity,
223
+ location: null,
224
+ });
225
+ }
226
+ }
227
+
228
+ const conversionResult = convertToGraphQL(extractionResult.types);
229
+ allDiagnostics.push(...conversionResult.diagnostics);
230
+
231
+ const validationResult = validateTypes({
232
+ types: conversionResult.types,
233
+ customScalarNames: allCustomScalarNames,
234
+ });
235
+ allDiagnostics.push(...validationResult.diagnostics);
236
+
237
+ const result = collectResults(conversionResult.types, allDiagnostics);
238
+ return {
239
+ ...result,
240
+ extractedTypes: extractionResult.types,
241
+ detectedScalarNames: extractionResult.detectedScalarNames,
242
+ detectedScalars: extractionResult.detectedScalars,
243
+ collectedScalars,
244
+ scalarMappingTable,
245
+ };
246
+ }
247
+
248
+ function convertArgsToInputValues(
249
+ args: ReadonlyArray<ArgumentDefinition>,
250
+ ): GraphQLInputValue[] {
251
+ return args.map((arg) => ({
252
+ name: arg.name,
253
+ type: {
254
+ ...convertTsTypeToGraphQLType(arg.tsType),
255
+ nullable: arg.tsType.nullable || arg.optional,
256
+ },
257
+ description: arg.description,
258
+ deprecated: arg.deprecated,
259
+ defaultValue: arg.defaultValue,
260
+ inlineObjectProperties: arg.tsType.inlineObjectProperties ?? null,
261
+ inlineEnumMembers: arg.tsType.inlineEnumMembers ?? null,
262
+ externalEnumSymbol: arg.tsType.externalEnumSymbol ?? null,
263
+ externalEnumDescription: arg.tsType.externalEnumDescription ?? null,
264
+ externalEnumDeprecated: arg.tsType.externalEnumDeprecated ?? null,
265
+ }));
266
+ }
267
+
268
+ function convertDefineApiToFields(
269
+ resolvers: ReadonlyArray<DefineApiResolverInfo>,
270
+ ): {
271
+ queryFields: { fields: ReadonlyArray<GraphQLFieldDefinition> };
272
+ mutationFields: { fields: ReadonlyArray<GraphQLFieldDefinition> };
273
+ typeExtensions: ReadonlyArray<TypeExtension>;
274
+ } {
275
+ const queryFields: GraphQLFieldDefinition[] = [];
276
+ const mutationFields: GraphQLFieldDefinition[] = [];
277
+ const typeExtensionMap = new Map<string, GraphQLFieldDefinition[]>();
278
+
279
+ for (const resolver of resolvers) {
280
+ const fieldDef: GraphQLFieldDefinition = {
281
+ name: resolver.fieldName,
282
+ type: convertTsTypeToGraphQLType(resolver.returnType),
283
+ args: resolver.args ? convertArgsToInputValues(resolver.args) : null,
284
+ sourceLocation: {
285
+ file: resolver.sourceFile,
286
+ line: 1,
287
+ column: 1,
288
+ },
289
+ resolverExportName: resolver.fieldName,
290
+ description: resolver.description,
291
+ deprecated: resolver.deprecated,
292
+ directives: resolver.directives,
293
+ };
294
+
295
+ if (resolver.resolverType === "query") {
296
+ queryFields.push(fieldDef);
297
+ } else if (resolver.resolverType === "mutation") {
298
+ mutationFields.push(fieldDef);
299
+ } else if (resolver.resolverType === "field" && resolver.parentTypeName) {
300
+ const existing = typeExtensionMap.get(resolver.parentTypeName) ?? [];
301
+ existing.push(fieldDef);
302
+ typeExtensionMap.set(resolver.parentTypeName, existing);
303
+ }
304
+ }
305
+
306
+ const typeExtensions: TypeExtension[] = [];
307
+ for (const [targetTypeName, fields] of typeExtensionMap) {
308
+ typeExtensions.push({ targetTypeName, fields });
309
+ }
310
+
311
+ return {
312
+ queryFields: { fields: queryFields },
313
+ mutationFields: { fields: mutationFields },
314
+ typeExtensions,
315
+ };
316
+ }
317
+
318
+ function normalizePathInMessage(message: string, sourceRoot: string): string {
319
+ const normalizedSourceRoot = toPosixPath(sourceRoot);
320
+ const normalizedMessage = message.replaceAll("\\", "/");
321
+ const escapedSourceRoot = normalizedSourceRoot.replace(
322
+ /[.*+?^${}()|[\]\\]/g,
323
+ "\\$&",
324
+ );
325
+ const pattern = new RegExp(`${escapedSourceRoot}/`, "g");
326
+ return normalizedMessage.replace(pattern, "");
327
+ }
328
+
329
+ function normalizeDiagnosticPaths(
330
+ diagnostics: ReadonlyArray<Diagnostic>,
331
+ sourceRoot: string,
332
+ ): Diagnostic[] {
333
+ const normalized = diagnostics.map((d) => {
334
+ const normalizedMessage = normalizePathInMessage(d.message, sourceRoot);
335
+
336
+ if (d.location === null) {
337
+ return {
338
+ ...d,
339
+ message: normalizedMessage,
340
+ };
341
+ }
342
+ return {
343
+ ...d,
344
+ message: normalizedMessage,
345
+ location: {
346
+ ...d.location,
347
+ file: toPosixPath(relative(sourceRoot, d.location.file)),
348
+ },
349
+ };
350
+ });
351
+ return deduplicateDiagnostics(normalized);
352
+ }
353
+
354
+ interface ExtractResolversCoreParams {
355
+ readonly program: ts.Program;
356
+ readonly sourceFiles: ReadonlyArray<string>;
357
+ readonly knownTypeNames: ReadonlySet<string>;
358
+ readonly knownTypeSymbols: ReadonlyMap<string, ts.Symbol>;
359
+ readonly underlyingSymbolToTypeName: ReadonlyMap<ts.Symbol, string>;
360
+ readonly globalTypeMappings: ReadonlyArray<GlobalTypeMapping>;
361
+ readonly scalarMappingTable: ScalarBaseTypeMappingTable | null;
362
+ }
363
+
364
+ function extractResolversCore(
365
+ params: ExtractResolversCoreParams,
366
+ ): ResolversResult {
367
+ const {
368
+ program,
369
+ sourceFiles,
370
+ knownTypeNames,
371
+ knownTypeSymbols,
372
+ underlyingSymbolToTypeName,
373
+ globalTypeMappings,
374
+ scalarMappingTable,
375
+ } = params;
376
+ const allDiagnostics: Diagnostic[] = [];
377
+
378
+ const sourceFilesSet = new Set(sourceFiles);
379
+ const defineApiExtractionResult = extractDefineApiResolvers(
380
+ program,
381
+ sourceFiles,
382
+ {
383
+ knownTypeNames,
384
+ knownTypeSymbols,
385
+ underlyingSymbolToTypeName,
386
+ globalTypeMappings,
387
+ sourceFiles: sourceFilesSet,
388
+ scalarMappingTable,
389
+ },
390
+ );
391
+ allDiagnostics.push(...defineApiExtractionResult.diagnostics);
392
+
393
+ const result = convertDefineApiToFields(defineApiExtractionResult.resolvers);
394
+ return {
395
+ queryFields: result.queryFields,
396
+ mutationFields: result.mutationFields,
397
+ typeExtensions: result.typeExtensions,
398
+ abstractTypeResolvers: defineApiExtractionResult.abstractTypeResolvers,
399
+ diagnostics: collectDiagnostics(allDiagnostics),
400
+ };
401
+ }
402
+
403
+ function buildExcludePaths(
404
+ cwd: string,
405
+ output: ResolvedOutputConfig,
406
+ ): string[] {
407
+ const paths: string[] = [];
408
+ if (output.resolversPath !== null) {
409
+ paths.push(resolve(cwd, output.resolversPath));
410
+ }
411
+ if (output.typeDefsPath !== null) {
412
+ paths.push(resolve(cwd, output.typeDefsPath));
413
+ }
414
+ if (output.schemaPath !== null) {
415
+ paths.push(resolve(cwd, output.schemaPath));
416
+ }
417
+ return paths;
418
+ }
419
+
420
+ function getOutputDir(output: ResolvedOutputConfig): string {
421
+ const path = output.resolversPath ?? output.typeDefsPath ?? output.schemaPath;
422
+ if (path !== null) {
423
+ return dirname(path);
424
+ }
425
+ return "src/gqlkit/__generated__";
426
+ }
427
+
428
+ function createInitialContext(config: GenerationConfig): PipelineContext {
429
+ return {
430
+ config,
431
+ sourceFiles: [],
432
+ program: null,
433
+ knownTypeNames: null,
434
+ knownTypeSymbols: null,
435
+ underlyingSymbolToTypeName: null,
436
+ typesResult: null,
437
+ resolversResult: null,
438
+ directiveDefinitions: null,
439
+ diagnostics: [],
440
+ aborted: false,
441
+ };
442
+ }
443
+
444
+ async function scanSourceFilesStep(
445
+ ctx: PipelineContext,
446
+ ): Promise<PipelineContext> {
447
+ const absoluteSourceDir = resolve(ctx.config.cwd, ctx.config.sourceDir);
448
+ const excludePaths = buildExcludePaths(ctx.config.cwd, ctx.config.output);
449
+
450
+ const scanResult = await scanDirectory(absoluteSourceDir, {
451
+ excludeGlobs: [
452
+ ...ctx.config.sourceIgnoreGlobs,
453
+ "**/*.test.ts",
454
+ "**/*.spec.ts",
455
+ ],
456
+ excludePaths,
457
+ });
458
+
459
+ if (scanResult.errors.length > 0) {
460
+ return {
461
+ ...ctx,
462
+ diagnostics: [...ctx.diagnostics, ...scanResult.errors],
463
+ aborted: true,
464
+ };
465
+ }
466
+
467
+ return { ...ctx, sourceFiles: scanResult.files };
468
+ }
469
+
470
+ function createProgramStep(ctx: PipelineContext): PipelineContext {
471
+ if (ctx.aborted) return ctx;
472
+
473
+ const programResult = createSharedProgram({
474
+ cwd: ctx.config.cwd,
475
+ tsconfigPath: ctx.config.tsconfigPath ?? null,
476
+ typeFiles: ctx.sourceFiles,
477
+ resolverFiles: ctx.sourceFiles,
478
+ });
479
+
480
+ if (programResult.diagnostics.length > 0 || !programResult.program) {
481
+ return {
482
+ ...ctx,
483
+ diagnostics: [...ctx.diagnostics, ...programResult.diagnostics],
484
+ aborted: true,
485
+ };
486
+ }
487
+
488
+ return { ...ctx, program: programResult.program };
489
+ }
490
+
491
+ function collectTypeNamesStep(ctx: PipelineContext): PipelineContext {
492
+ if (ctx.aborted || !ctx.program) return ctx;
493
+
494
+ const result = collectDeclaredTypeNames(ctx.program, ctx.sourceFiles);
495
+
496
+ return {
497
+ ...ctx,
498
+ knownTypeNames: result.typeNames,
499
+ knownTypeSymbols: result.typeSymbols,
500
+ underlyingSymbolToTypeName: result.underlyingSymbolToTypeName,
501
+ };
502
+ }
503
+
504
+ function prepareScalarConfig(config: GenerationConfig): {
505
+ customScalarNames: string[];
506
+ globalTypeMappings: GlobalTypeMapping[];
507
+ configScalars: ConfigScalarMapping[];
508
+ } {
509
+ const customScalarNames =
510
+ config.customScalars?.map((s) => s.graphqlName) ?? [];
511
+
512
+ const globalTypeMappings: GlobalTypeMapping[] =
513
+ config.customScalars
514
+ ?.filter((s) => s.importPath === null)
515
+ .map((s) => ({
516
+ typeName: s.typeName,
517
+ scalarName: s.graphqlName,
518
+ only: s.only,
519
+ })) ?? [];
520
+
521
+ const configScalars: ConfigScalarMapping[] =
522
+ config.customScalars?.map((s) => {
523
+ let sourceFile = "";
524
+ if (s.importPath !== null) {
525
+ if (s.importPath.startsWith(".")) {
526
+ const baseDir = config.configDir ?? config.cwd;
527
+ sourceFile = `${resolve(baseDir, s.importPath)}.ts`;
528
+ } else {
529
+ sourceFile = s.importPath;
530
+ }
531
+ }
532
+ return {
533
+ scalarName: s.graphqlName,
534
+ typeName: s.typeName,
535
+ only: s.only,
536
+ sourceFile,
537
+ line: 1,
538
+ description: s.description,
539
+ fromConfig: true,
540
+ };
541
+ }) ?? [];
542
+
543
+ return { customScalarNames, globalTypeMappings, configScalars };
544
+ }
545
+
546
+ function extractTypesStep(ctx: PipelineContext): PipelineContext {
547
+ if (
548
+ ctx.aborted ||
549
+ !ctx.program ||
550
+ !ctx.knownTypeNames ||
551
+ !ctx.knownTypeSymbols ||
552
+ !ctx.underlyingSymbolToTypeName
553
+ )
554
+ return ctx;
555
+
556
+ const { customScalarNames, globalTypeMappings, configScalars } =
557
+ prepareScalarConfig(ctx.config);
558
+
559
+ const typesResult = extractTypesCore({
560
+ program: ctx.program,
561
+ sourceFiles: ctx.sourceFiles,
562
+ customScalarNames,
563
+ globalTypeMappings,
564
+ configScalars,
565
+ sourceRoot: ctx.config.cwd,
566
+ knownTypeNames: ctx.knownTypeNames,
567
+ knownTypeSymbols: ctx.knownTypeSymbols,
568
+ underlyingSymbolToTypeName: ctx.underlyingSymbolToTypeName,
569
+ });
570
+
571
+ return { ...ctx, typesResult };
572
+ }
573
+
574
+ function extractResolversStep(ctx: PipelineContext): PipelineContext {
575
+ if (
576
+ ctx.aborted ||
577
+ !ctx.program ||
578
+ !ctx.knownTypeNames ||
579
+ !ctx.knownTypeSymbols ||
580
+ !ctx.underlyingSymbolToTypeName ||
581
+ !ctx.typesResult
582
+ )
583
+ return ctx;
584
+
585
+ const { globalTypeMappings } = prepareScalarConfig(ctx.config);
586
+
587
+ const resolversResult = extractResolversCore({
588
+ program: ctx.program,
589
+ sourceFiles: ctx.sourceFiles,
590
+ knownTypeNames: ctx.knownTypeNames,
591
+ knownTypeSymbols: ctx.knownTypeSymbols,
592
+ underlyingSymbolToTypeName: ctx.underlyingSymbolToTypeName,
593
+ globalTypeMappings,
594
+ scalarMappingTable: ctx.typesResult.scalarMappingTable,
595
+ });
596
+
597
+ return { ...ctx, resolversResult };
598
+ }
599
+
600
+ function extractDirectivesStep(ctx: PipelineContext): PipelineContext {
601
+ if (ctx.aborted || !ctx.program) return ctx;
602
+
603
+ const directiveDefinitionResult = extractDirectiveDefinitions(
604
+ ctx.program,
605
+ ctx.sourceFiles,
606
+ );
607
+
608
+ const directiveDefinitions: DirectiveDefinitionInfo[] =
609
+ directiveDefinitionResult.definitions.length > 0
610
+ ? [...directiveDefinitionResult.definitions]
611
+ : [];
612
+
613
+ const newDiagnostics = [...ctx.diagnostics];
614
+ for (const error of directiveDefinitionResult.errors) {
615
+ newDiagnostics.push({
616
+ code: error.code,
617
+ message: error.message,
618
+ severity: "error",
619
+ location: {
620
+ file: error.sourceFile,
621
+ line: error.line,
622
+ column: 1,
623
+ },
624
+ });
625
+ }
626
+
627
+ return { ...ctx, directiveDefinitions, diagnostics: newDiagnostics };
628
+ }
629
+
630
+ function validateExtractionStep(ctx: PipelineContext): PipelineContext {
631
+ if (ctx.aborted || !ctx.typesResult || !ctx.resolversResult) return ctx;
632
+
633
+ const allDiagnostics = [
634
+ ...ctx.diagnostics,
635
+ ...collectAllDiagnostics(ctx.typesResult, ctx.resolversResult),
636
+ ];
637
+
638
+ if (hasErrors(ctx.typesResult, ctx.resolversResult)) {
639
+ return {
640
+ ...ctx,
641
+ diagnostics: allDiagnostics,
642
+ aborted: true,
643
+ };
644
+ }
645
+
646
+ return { ...ctx, diagnostics: allDiagnostics };
647
+ }
648
+
649
+ function generateSchemaStep(ctx: PipelineContext): {
650
+ ctx: PipelineContext;
651
+ schemaResult: ReturnType<typeof generateSchema> | null;
652
+ } {
653
+ if (ctx.aborted || !ctx.typesResult || !ctx.resolversResult) {
654
+ return { ctx, schemaResult: null };
655
+ }
656
+
657
+ const { customScalarNames } = prepareScalarConfig(ctx.config);
658
+ const allCustomScalarNames = [
659
+ ...customScalarNames,
660
+ ...ctx.typesResult.detectedScalarNames,
661
+ ];
662
+
663
+ const schemaResult = generateSchema({
664
+ typesResult: ctx.typesResult,
665
+ extractedTypes: ctx.typesResult.extractedTypes,
666
+ resolversResult: ctx.resolversResult,
667
+ outputDir: resolve(ctx.config.cwd, getOutputDir(ctx.config.output)),
668
+ customScalarNames: allCustomScalarNames,
669
+ customScalars: ctx.typesResult.collectedScalars,
670
+ directiveDefinitions:
671
+ ctx.directiveDefinitions && ctx.directiveDefinitions.length > 0
672
+ ? ctx.directiveDefinitions
673
+ : null,
674
+ enablePruning: null,
675
+ sourceRoot: ctx.config.cwd,
676
+ });
677
+
678
+ const newDiagnostics = [...ctx.diagnostics, ...schemaResult.diagnostics];
679
+
680
+ if (schemaResult.hasErrors) {
681
+ return {
682
+ ctx: { ...ctx, diagnostics: newDiagnostics, aborted: true },
683
+ schemaResult: null,
684
+ };
685
+ }
686
+
687
+ return { ctx: { ...ctx, diagnostics: newDiagnostics }, schemaResult };
688
+ }
689
+
690
+ function generateOutputFiles(
691
+ config: GenerationConfig,
692
+ schemaResult: ReturnType<typeof generateSchema>,
693
+ ): GeneratedFile[] {
694
+ const files: GeneratedFile[] = [];
695
+
696
+ if (config.output.typeDefsPath !== null) {
697
+ files.push({
698
+ filePath: resolve(config.cwd, config.output.typeDefsPath),
699
+ content: schemaResult.typeDefsCode,
700
+ });
701
+ }
702
+
703
+ if (config.output.schemaPath !== null) {
704
+ files.push({
705
+ filePath: resolve(config.cwd, config.output.schemaPath),
706
+ content: schemaResult.sdlContent,
707
+ });
708
+ }
709
+
710
+ if (config.output.resolversPath !== null) {
711
+ files.push({
712
+ filePath: resolve(config.cwd, config.output.resolversPath),
713
+ content: schemaResult.resolversCode,
714
+ });
715
+ }
716
+
717
+ return files;
718
+ }
719
+
720
+ export async function executeGeneration(
721
+ config: GenerationConfig,
722
+ ): Promise<GenerationResult> {
723
+ let ctx = createInitialContext(config);
724
+
725
+ ctx = await scanSourceFilesStep(ctx);
726
+ ctx = createProgramStep(ctx);
727
+ ctx = collectTypeNamesStep(ctx);
728
+ ctx = extractTypesStep(ctx);
729
+ ctx = extractResolversStep(ctx);
730
+ ctx = extractDirectivesStep(ctx);
731
+ ctx = validateExtractionStep(ctx);
732
+
733
+ if (ctx.aborted) {
734
+ return {
735
+ success: false,
736
+ files: [],
737
+ diagnostics: normalizeDiagnosticPaths(ctx.diagnostics, config.cwd),
738
+ };
739
+ }
740
+
741
+ const { ctx: schemaCtx, schemaResult } = generateSchemaStep(ctx);
742
+ ctx = schemaCtx;
743
+
744
+ if (ctx.aborted || !schemaResult) {
745
+ return {
746
+ success: false,
747
+ files: [],
748
+ diagnostics: normalizeDiagnosticPaths(ctx.diagnostics, config.cwd),
749
+ };
750
+ }
751
+
752
+ const files = generateOutputFiles(config, schemaResult);
753
+
754
+ return {
755
+ success: true,
756
+ files,
757
+ diagnostics: normalizeDiagnosticPaths(ctx.diagnostics, config.cwd),
758
+ };
759
+ }
760
+
761
+ export interface WriteFilesConfig {
762
+ readonly files: ReadonlyArray<GeneratedFile>;
763
+ }
764
+
765
+ export interface WriteFilesResult {
766
+ readonly success: boolean;
767
+ readonly filesWritten: ReadonlyArray<string>;
768
+ }
769
+
770
+ export async function writeGeneratedFiles(
771
+ config: WriteFilesConfig,
772
+ ): Promise<WriteFilesResult> {
773
+ const result = await writeFiles({
774
+ files: config.files.map((f) => ({
775
+ filePath: f.filePath,
776
+ content: f.content,
777
+ })),
778
+ });
779
+
780
+ return {
781
+ success: result.success,
782
+ filesWritten: result.writtenPaths,
783
+ };
784
+ }