@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,690 @@
1
+ import type { AutoGeneratedType } from "../../auto-type-generator/index.js";
2
+ import type {
3
+ AbstractResolverInfo,
4
+ ExtractResolversResult,
5
+ GraphQLFieldDefinition,
6
+ GraphQLInputValue,
7
+ TypeExtension as ResolverTypeExtension,
8
+ } from "../../resolver-extractor/index.js";
9
+ import { validateAbstractResolvers } from "../../resolver-extractor/validator/abstract-resolver-validator.js";
10
+ import type {
11
+ DirectiveDefinitionInfo,
12
+ DirectiveLocation,
13
+ } from "../../shared/directive-definition-extractor.js";
14
+ import type {
15
+ DirectiveArgumentValue,
16
+ DirectiveInfo,
17
+ } from "../../shared/directive-detector.js";
18
+ import {
19
+ detectCircularInterfaceReferences,
20
+ validateInterfaceImplementations,
21
+ } from "../../shared/interface-validator.js";
22
+ import type { DeprecationInfo } from "../../shared/tsdoc-parser.js";
23
+ import type { CollectedScalarType } from "../../type-extractor/collector/scalar-collector.js";
24
+ import { mergeDescriptions } from "../../type-extractor/collector/scalar-collector.js";
25
+ import type { ExtractTypesResult } from "../../type-extractor/index.js";
26
+ import type {
27
+ Diagnostic,
28
+ EnumValueInfo,
29
+ GraphQLFieldType,
30
+ } from "../../type-extractor/types/index.js";
31
+
32
+ export interface BaseField {
33
+ readonly name: string;
34
+ readonly type: GraphQLFieldType;
35
+ readonly description: string | null;
36
+ readonly deprecated: DeprecationInfo | null;
37
+ readonly directives: ReadonlyArray<DirectiveInfo> | null;
38
+ readonly defaultValue: DirectiveArgumentValue | null;
39
+ }
40
+
41
+ export interface BaseType {
42
+ readonly name: string;
43
+ readonly kind: "Object" | "Interface" | "Union" | "Enum";
44
+ readonly fields: ReadonlyArray<BaseField> | null;
45
+ readonly unionMembers: ReadonlyArray<string> | null;
46
+ readonly enumValues: ReadonlyArray<EnumValueInfo> | null;
47
+ /** True if this enum uses numeric values */
48
+ readonly isNumericEnum: boolean;
49
+ /** True if this string enum needs value mapping (at least one value converted) */
50
+ readonly needsStringEnumMapping: boolean;
51
+ readonly implementedInterfaces: ReadonlyArray<string> | null;
52
+ readonly description: string | null;
53
+ readonly deprecated: DeprecationInfo | null;
54
+ readonly sourceFile: string | null;
55
+ readonly directives: ReadonlyArray<DirectiveInfo> | null;
56
+ }
57
+
58
+ export interface InputType {
59
+ readonly name: string;
60
+ readonly fields: ReadonlyArray<BaseField>;
61
+ readonly sourceFile: string;
62
+ readonly description: string | null;
63
+ readonly isOneOf: boolean;
64
+ }
65
+
66
+ export interface ExtensionField {
67
+ readonly name: string;
68
+ readonly type: GraphQLFieldType;
69
+ readonly args: ReadonlyArray<GraphQLInputValue> | null;
70
+ readonly resolverSourceFile: string;
71
+ readonly resolverExportName: string | null;
72
+ readonly description: string | null;
73
+ readonly deprecated: DeprecationInfo | null;
74
+ readonly directives: ReadonlyArray<DirectiveInfo> | null;
75
+ }
76
+
77
+ export interface TypeExtension {
78
+ readonly targetTypeName: string;
79
+ readonly fields: ReadonlyArray<ExtensionField>;
80
+ }
81
+
82
+ /**
83
+ * Custom scalar information for schema generation.
84
+ */
85
+ export interface CustomScalarInfo {
86
+ readonly scalarName: string;
87
+ readonly description: string | null;
88
+ }
89
+
90
+ /**
91
+ * Numeric enum member value mapping.
92
+ */
93
+ export interface NumericEnumMember {
94
+ readonly name: string;
95
+ readonly numericValue: number;
96
+ }
97
+
98
+ /**
99
+ * Numeric enum information for resolver generation.
100
+ */
101
+ export interface NumericEnumInfo {
102
+ readonly enumName: string;
103
+ readonly members: ReadonlyArray<NumericEnumMember>;
104
+ }
105
+
106
+ /**
107
+ * String enum member value mapping.
108
+ */
109
+ export interface StringEnumMember {
110
+ /** GraphQL enum value name (SCREAMING_SNAKE_CASE) */
111
+ readonly graphqlValue: string;
112
+ /** Original TypeScript enum value */
113
+ readonly typescriptValue: string;
114
+ }
115
+
116
+ /**
117
+ * String enum information for resolver generation.
118
+ */
119
+ export interface StringEnumMappingInfo {
120
+ readonly enumName: string;
121
+ readonly members: ReadonlyArray<StringEnumMember>;
122
+ }
123
+
124
+ export interface IntegratedResult {
125
+ readonly baseTypes: ReadonlyArray<BaseType>;
126
+ readonly inputTypes: ReadonlyArray<InputType>;
127
+ readonly typeExtensions: ReadonlyArray<TypeExtension>;
128
+ /** @deprecated Use customScalars instead */
129
+ readonly customScalarNames: ReadonlyArray<string> | null;
130
+ /** Custom scalars with description information */
131
+ readonly customScalars: ReadonlyArray<CustomScalarInfo> | null;
132
+ /** Directive definitions extracted from type aliases */
133
+ readonly directiveDefinitions: ReadonlyArray<DirectiveDefinitionInfo> | null;
134
+ /** Abstract type resolvers (resolveType and isTypeOf) */
135
+ readonly abstractTypeResolvers: ReadonlyArray<AbstractResolverInfo>;
136
+ /** Numeric enum information for resolver generation */
137
+ readonly numericEnums: ReadonlyArray<NumericEnumInfo>;
138
+ /** String enum mappings for resolver generation */
139
+ readonly stringEnumMappings: ReadonlyArray<StringEnumMappingInfo>;
140
+ readonly hasQuery: boolean;
141
+ readonly hasMutation: boolean;
142
+ readonly hasErrors: boolean;
143
+ readonly diagnostics: ReadonlyArray<Diagnostic>;
144
+ }
145
+
146
+ function convertToExtensionField(
147
+ field: GraphQLFieldDefinition,
148
+ ): ExtensionField {
149
+ return {
150
+ name: field.name,
151
+ type: field.type,
152
+ args: field.args,
153
+ resolverSourceFile: field.sourceLocation.file,
154
+ resolverExportName: field.resolverExportName,
155
+ description: field.description,
156
+ deprecated: field.deprecated,
157
+ directives: field.directives,
158
+ };
159
+ }
160
+
161
+ function convertResolverTypeExtension(
162
+ ext: ResolverTypeExtension,
163
+ ): TypeExtension {
164
+ return {
165
+ targetTypeName: ext.targetTypeName,
166
+ fields: ext.fields.map(convertToExtensionField),
167
+ };
168
+ }
169
+
170
+ const UNSUPPORTED_LOCATIONS: ReadonlySet<DirectiveLocation> = new Set([
171
+ "SCHEMA",
172
+ "SCALAR",
173
+ "INTERFACE",
174
+ "UNION",
175
+ "ENUM",
176
+ ]);
177
+
178
+ type UsageLocation =
179
+ | "OBJECT"
180
+ | "FIELD_DEFINITION"
181
+ | "INPUT_OBJECT"
182
+ | "INPUT_FIELD_DEFINITION";
183
+
184
+ interface DirectiveUsageContext {
185
+ readonly directiveName: string;
186
+ readonly usageLocation: UsageLocation;
187
+ readonly targetName: string;
188
+ readonly sourceFile: string;
189
+ readonly line: number;
190
+ }
191
+
192
+ function validateDirectiveUsage(
193
+ context: DirectiveUsageContext,
194
+ directiveDefMap: Map<string, DirectiveDefinitionInfo>,
195
+ diagnostics: Diagnostic[],
196
+ ): void {
197
+ const { directiveName, usageLocation, targetName, sourceFile, line } =
198
+ context;
199
+
200
+ const def = directiveDefMap.get(directiveName);
201
+ if (!def) {
202
+ diagnostics.push({
203
+ code: "UNDEFINED_DIRECTIVE",
204
+ message: `${targetName}: Directive '@${directiveName}' is not defined`,
205
+ severity: "error",
206
+ location: { file: sourceFile, line, column: 1 },
207
+ });
208
+ return;
209
+ }
210
+
211
+ for (const loc of def.locations) {
212
+ if (UNSUPPORTED_LOCATIONS.has(loc)) {
213
+ diagnostics.push({
214
+ code: "UNSUPPORTED_DIRECTIVE_LOCATION",
215
+ message: `${targetName}: Directive '@${directiveName}' uses unsupported location ${loc}`,
216
+ severity: "error",
217
+ location: { file: sourceFile, line, column: 1 },
218
+ });
219
+ return;
220
+ }
221
+ }
222
+
223
+ const allowedLocations = getCompatibleLocations(usageLocation);
224
+ const hasValidLocation = def.locations.some((loc) =>
225
+ allowedLocations.includes(loc),
226
+ );
227
+
228
+ if (!hasValidLocation) {
229
+ diagnostics.push({
230
+ code: "INVALID_DIRECTIVE_LOCATION",
231
+ message: `${targetName}: Directive '@${directiveName}' cannot be used on ${usageLocation} (allowed: ${def.locations.join(", ")})`,
232
+ severity: "error",
233
+ location: { file: sourceFile, line, column: 1 },
234
+ });
235
+ }
236
+ }
237
+
238
+ function getCompatibleLocations(
239
+ usageLocation: UsageLocation,
240
+ ): DirectiveLocation[] {
241
+ switch (usageLocation) {
242
+ case "OBJECT":
243
+ return ["OBJECT"];
244
+ case "FIELD_DEFINITION":
245
+ return ["FIELD_DEFINITION"];
246
+ case "INPUT_OBJECT":
247
+ return ["INPUT_OBJECT"];
248
+ case "INPUT_FIELD_DEFINITION":
249
+ return ["INPUT_FIELD_DEFINITION"];
250
+ }
251
+ }
252
+
253
+ export function integrate(
254
+ typesResult: ExtractTypesResult,
255
+ resolversResult: ExtractResolversResult,
256
+ customScalarNames: ReadonlyArray<string> | null,
257
+ collectedScalars?: ReadonlyArray<CollectedScalarType> | null,
258
+ directiveDefinitions?: ReadonlyArray<DirectiveDefinitionInfo> | null,
259
+ autoGeneratedTypes?: ReadonlyArray<AutoGeneratedType> | null,
260
+ ): IntegratedResult {
261
+ const directiveTypeAliasNames = new Set(
262
+ directiveDefinitions?.map((d) => d.typeAliasName) ?? [],
263
+ );
264
+
265
+ const diagnostics: Diagnostic[] = [];
266
+
267
+ diagnostics.push(...typesResult.diagnostics.errors);
268
+ diagnostics.push(...typesResult.diagnostics.warnings);
269
+ diagnostics.push(...resolversResult.diagnostics.errors);
270
+ diagnostics.push(...resolversResult.diagnostics.warnings);
271
+
272
+ const interfaceValidation = validateInterfaceImplementations(
273
+ typesResult.types,
274
+ );
275
+ diagnostics.push(...interfaceValidation.diagnostics);
276
+
277
+ const circularValidation = detectCircularInterfaceReferences(
278
+ typesResult.types,
279
+ );
280
+ diagnostics.push(...circularValidation.diagnostics);
281
+
282
+ const baseTypes: BaseType[] = [];
283
+ const inputTypes: InputType[] = [];
284
+
285
+ for (const autoType of autoGeneratedTypes ?? []) {
286
+ if (autoType.kind === "Object") {
287
+ baseTypes.push({
288
+ name: autoType.name,
289
+ kind: "Object",
290
+ fields: autoType.fields!.map((f) => ({
291
+ name: f.name,
292
+ type: f.type,
293
+ description: f.description,
294
+ deprecated: f.deprecated,
295
+ directives: f.directives,
296
+ defaultValue: f.defaultValue,
297
+ })),
298
+ unionMembers: null,
299
+ enumValues: null,
300
+ isNumericEnum: false,
301
+ needsStringEnumMapping: false,
302
+ implementedInterfaces: null,
303
+ description: autoType.description,
304
+ deprecated: null,
305
+ sourceFile: autoType.sourceLocation.file,
306
+ directives: null,
307
+ });
308
+ } else if (autoType.kind === "Enum") {
309
+ baseTypes.push({
310
+ name: autoType.name,
311
+ kind: "Enum",
312
+ fields: null,
313
+ unionMembers: null,
314
+ enumValues:
315
+ autoType.enumValues?.map((v) => ({
316
+ name: v.name,
317
+ originalValue: v.originalValue,
318
+ numericValue: null,
319
+ description: v.description,
320
+ deprecated: v.deprecated,
321
+ })) ?? null,
322
+ isNumericEnum: false,
323
+ needsStringEnumMapping: autoType.needsStringEnumMapping,
324
+ implementedInterfaces: null,
325
+ description: autoType.description,
326
+ deprecated: null,
327
+ sourceFile: autoType.sourceLocation.file,
328
+ directives: null,
329
+ });
330
+ } else {
331
+ inputTypes.push({
332
+ name: autoType.name,
333
+ fields: autoType.fields!.map((f) => ({
334
+ name: f.name,
335
+ type: f.type,
336
+ description: f.description,
337
+ deprecated: f.deprecated,
338
+ directives: f.directives,
339
+ defaultValue: f.defaultValue,
340
+ })),
341
+ sourceFile: autoType.sourceLocation.file,
342
+ description: autoType.description,
343
+ isOneOf: false,
344
+ });
345
+ }
346
+ }
347
+
348
+ for (const type of typesResult.types) {
349
+ if (directiveTypeAliasNames.has(type.name)) {
350
+ continue;
351
+ }
352
+
353
+ if (type.kind === "InputObject" || type.kind === "OneOfInputObject") {
354
+ inputTypes.push({
355
+ name: type.name,
356
+ fields:
357
+ type.fields?.map((field) => ({
358
+ name: field.name,
359
+ type: field.type,
360
+ description: field.description,
361
+ deprecated: field.deprecated,
362
+ directives: field.directives,
363
+ defaultValue: field.defaultValue,
364
+ })) ?? [],
365
+ sourceFile: type.sourceFile,
366
+ description: type.description,
367
+ isOneOf: type.kind === "OneOfInputObject",
368
+ });
369
+ } else if (type.kind === "Enum") {
370
+ baseTypes.push({
371
+ name: type.name,
372
+ kind: type.kind,
373
+ fields: null,
374
+ unionMembers: null,
375
+ enumValues: type.enumValues,
376
+ isNumericEnum: type.isNumericEnum,
377
+ needsStringEnumMapping: type.needsStringEnumMapping,
378
+ implementedInterfaces: null,
379
+ description: type.description,
380
+ deprecated: type.deprecated,
381
+ sourceFile: type.sourceFile,
382
+ directives: type.directives,
383
+ });
384
+ } else if (type.kind === "Interface") {
385
+ baseTypes.push({
386
+ name: type.name,
387
+ kind: type.kind,
388
+ fields:
389
+ type.fields?.map((field) => ({
390
+ name: field.name,
391
+ type: field.type,
392
+ description: field.description,
393
+ deprecated: field.deprecated,
394
+ directives: field.directives,
395
+ defaultValue: field.defaultValue,
396
+ })) ?? null,
397
+ unionMembers: null,
398
+ enumValues: null,
399
+ isNumericEnum: false,
400
+ needsStringEnumMapping: false,
401
+ implementedInterfaces: type.implementedInterfaces ?? null,
402
+ description: type.description,
403
+ deprecated: type.deprecated,
404
+ sourceFile: type.sourceFile,
405
+ directives: type.directives,
406
+ });
407
+ } else if (type.kind === "Object") {
408
+ baseTypes.push({
409
+ name: type.name,
410
+ kind: type.kind,
411
+ fields:
412
+ type.fields?.map((field) => ({
413
+ name: field.name,
414
+ type: field.type,
415
+ description: field.description,
416
+ deprecated: field.deprecated,
417
+ directives: field.directives,
418
+ defaultValue: field.defaultValue,
419
+ })) ?? null,
420
+ unionMembers: null,
421
+ enumValues: null,
422
+ isNumericEnum: false,
423
+ needsStringEnumMapping: false,
424
+ implementedInterfaces: type.implementedInterfaces ?? null,
425
+ description: type.description,
426
+ deprecated: type.deprecated,
427
+ sourceFile: type.sourceFile,
428
+ directives: type.directives,
429
+ });
430
+ } else {
431
+ baseTypes.push({
432
+ name: type.name,
433
+ kind: type.kind,
434
+ fields: null,
435
+ unionMembers: type.unionMembers,
436
+ enumValues: null,
437
+ isNumericEnum: false,
438
+ needsStringEnumMapping: false,
439
+ implementedInterfaces: null,
440
+ description: type.description,
441
+ deprecated: null,
442
+ sourceFile: type.sourceFile,
443
+ directives: type.directives,
444
+ });
445
+ }
446
+ }
447
+
448
+ const hasQuery = resolversResult.queryFields.fields.length > 0;
449
+ const hasMutation = resolversResult.mutationFields.fields.length > 0;
450
+
451
+ if (hasQuery) {
452
+ baseTypes.push({
453
+ name: "Query",
454
+ kind: "Object",
455
+ fields: [],
456
+ unionMembers: null,
457
+ enumValues: null,
458
+ isNumericEnum: false,
459
+ needsStringEnumMapping: false,
460
+ implementedInterfaces: null,
461
+ description: null,
462
+ deprecated: null,
463
+ sourceFile: null,
464
+ directives: null,
465
+ });
466
+ }
467
+ if (hasMutation) {
468
+ baseTypes.push({
469
+ name: "Mutation",
470
+ kind: "Object",
471
+ fields: [],
472
+ unionMembers: null,
473
+ enumValues: null,
474
+ isNumericEnum: false,
475
+ needsStringEnumMapping: false,
476
+ implementedInterfaces: null,
477
+ description: null,
478
+ deprecated: null,
479
+ sourceFile: null,
480
+ directives: null,
481
+ });
482
+ }
483
+
484
+ const abstractResolverValidation = validateAbstractResolvers({
485
+ abstractResolvers: resolversResult.abstractTypeResolvers,
486
+ baseTypes,
487
+ });
488
+ diagnostics.push(...abstractResolverValidation.diagnostics);
489
+
490
+ const knownTypeNames = new Set([
491
+ ...baseTypes.map((t) => t.name),
492
+ ...inputTypes.map((t) => t.name),
493
+ ]);
494
+
495
+ const typeExtensions: TypeExtension[] = [];
496
+
497
+ if (hasQuery) {
498
+ typeExtensions.push({
499
+ targetTypeName: "Query",
500
+ fields: resolversResult.queryFields.fields.map(convertToExtensionField),
501
+ });
502
+ }
503
+
504
+ if (hasMutation) {
505
+ typeExtensions.push({
506
+ targetTypeName: "Mutation",
507
+ fields: resolversResult.mutationFields.fields.map(
508
+ convertToExtensionField,
509
+ ),
510
+ });
511
+ }
512
+
513
+ for (const ext of resolversResult.typeExtensions) {
514
+ if (!knownTypeNames.has(ext.targetTypeName)) {
515
+ const firstField = ext.fields[0];
516
+ diagnostics.push({
517
+ code: "UNKNOWN_TARGET_TYPE",
518
+ message: `Type extension references unknown type '${ext.targetTypeName}'`,
519
+ severity: "error",
520
+ location: firstField
521
+ ? {
522
+ file: firstField.sourceLocation.file,
523
+ line: firstField.sourceLocation.line,
524
+ column: firstField.sourceLocation.column,
525
+ }
526
+ : null,
527
+ });
528
+ } else {
529
+ typeExtensions.push(convertResolverTypeExtension(ext));
530
+ }
531
+ }
532
+
533
+ const directiveDefMap = new Map<string, DirectiveDefinitionInfo>();
534
+ for (const def of directiveDefinitions ?? []) {
535
+ directiveDefMap.set(def.name, def);
536
+ }
537
+
538
+ for (const type of typesResult.types) {
539
+ if (directiveTypeAliasNames.has(type.name)) {
540
+ continue;
541
+ }
542
+
543
+ const usageLocation: UsageLocation =
544
+ type.kind === "InputObject" || type.kind === "OneOfInputObject"
545
+ ? "INPUT_OBJECT"
546
+ : "OBJECT";
547
+
548
+ if (type.directives) {
549
+ for (const directive of type.directives) {
550
+ validateDirectiveUsage(
551
+ {
552
+ directiveName: directive.name,
553
+ usageLocation,
554
+ targetName: `Type '${type.name}'`,
555
+ sourceFile: type.sourceFile,
556
+ line: 1,
557
+ },
558
+ directiveDefMap,
559
+ diagnostics,
560
+ );
561
+ }
562
+ }
563
+
564
+ const fieldUsageLocation: UsageLocation =
565
+ type.kind === "InputObject" || type.kind === "OneOfInputObject"
566
+ ? "INPUT_FIELD_DEFINITION"
567
+ : "FIELD_DEFINITION";
568
+
569
+ for (const field of type.fields ?? []) {
570
+ if (field.directives) {
571
+ for (const directive of field.directives) {
572
+ validateDirectiveUsage(
573
+ {
574
+ directiveName: directive.name,
575
+ usageLocation: fieldUsageLocation,
576
+ targetName: `Field '${type.name}.${field.name}'`,
577
+ sourceFile: type.sourceFile,
578
+ line: 1,
579
+ },
580
+ directiveDefMap,
581
+ diagnostics,
582
+ );
583
+ }
584
+ }
585
+ }
586
+ }
587
+
588
+ for (const ext of typeExtensions) {
589
+ for (const field of ext.fields) {
590
+ if (field.directives) {
591
+ for (const directive of field.directives) {
592
+ validateDirectiveUsage(
593
+ {
594
+ directiveName: directive.name,
595
+ usageLocation: "FIELD_DEFINITION",
596
+ targetName: `Field '${ext.targetTypeName}.${field.name}'`,
597
+ sourceFile: field.resolverSourceFile,
598
+ line: 1,
599
+ },
600
+ directiveDefMap,
601
+ diagnostics,
602
+ );
603
+ }
604
+ }
605
+ }
606
+ }
607
+
608
+ const hasErrors = diagnostics.some((d) => d.severity === "error");
609
+
610
+ const scalarDescriptionMap = new Map<string, string | null>();
611
+ if (collectedScalars) {
612
+ for (const scalar of collectedScalars) {
613
+ const description = mergeDescriptions(scalar.descriptions);
614
+ scalarDescriptionMap.set(scalar.scalarName, description);
615
+ }
616
+ }
617
+
618
+ const customScalars: CustomScalarInfo[] | null =
619
+ customScalarNames && customScalarNames.length > 0
620
+ ? customScalarNames.map((name) => ({
621
+ scalarName: name,
622
+ description: scalarDescriptionMap.get(name) ?? null,
623
+ }))
624
+ : null;
625
+
626
+ const numericEnums: NumericEnumInfo[] = baseTypes
627
+ .filter(
628
+ (
629
+ type,
630
+ ): type is BaseType & {
631
+ enumValues: NonNullable<BaseType["enumValues"]>;
632
+ } =>
633
+ type.kind === "Enum" && type.isNumericEnum && type.enumValues !== null,
634
+ )
635
+ .map((type) => ({
636
+ enumName: type.name,
637
+ members: type.enumValues
638
+ .filter(
639
+ (value): value is typeof value & { numericValue: number } =>
640
+ value.numericValue !== null,
641
+ )
642
+ .map((value) => ({
643
+ name: value.name,
644
+ numericValue: value.numericValue,
645
+ })),
646
+ }))
647
+ .filter((info) => info.members.length > 0);
648
+
649
+ const stringEnumMappings: StringEnumMappingInfo[] = baseTypes
650
+ .filter(
651
+ (
652
+ type,
653
+ ): type is BaseType & {
654
+ enumValues: NonNullable<BaseType["enumValues"]>;
655
+ } =>
656
+ type.kind === "Enum" &&
657
+ type.needsStringEnumMapping &&
658
+ type.enumValues !== null,
659
+ )
660
+ .map((type) => ({
661
+ enumName: type.name,
662
+ members: type.enumValues.map((value) => ({
663
+ graphqlValue: value.name,
664
+ typescriptValue: value.originalValue,
665
+ })),
666
+ }))
667
+ .filter((info) => info.members.length > 0);
668
+
669
+ return {
670
+ baseTypes,
671
+ inputTypes,
672
+ typeExtensions,
673
+ customScalarNames:
674
+ customScalarNames && customScalarNames.length > 0
675
+ ? customScalarNames
676
+ : null,
677
+ customScalars,
678
+ directiveDefinitions:
679
+ directiveDefinitions && directiveDefinitions.length > 0
680
+ ? directiveDefinitions
681
+ : null,
682
+ abstractTypeResolvers: resolversResult.abstractTypeResolvers,
683
+ numericEnums,
684
+ stringEnumMappings,
685
+ hasQuery,
686
+ hasMutation,
687
+ hasErrors,
688
+ diagnostics,
689
+ };
690
+ }