@soda-gql/typegen 0.10.2 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +199 -116
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -20
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +4 -20
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +199 -116
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
package/dist/index.d.cts
CHANGED
|
@@ -9,7 +9,7 @@ import { ResolvedSodaGqlConfig } from "@soda-gql/config";
|
|
|
9
9
|
/**
|
|
10
10
|
* Error codes specific to typegen operations.
|
|
11
11
|
*/
|
|
12
|
-
type TypegenErrorCode = "TYPEGEN_CODEGEN_REQUIRED" | "TYPEGEN_SCHEMA_LOAD_FAILED" | "TYPEGEN_BUILD_FAILED" | "TYPEGEN_EMIT_FAILED" | "TYPEGEN_BUNDLE_FAILED"
|
|
12
|
+
type TypegenErrorCode = "TYPEGEN_CODEGEN_REQUIRED" | "TYPEGEN_SCHEMA_LOAD_FAILED" | "TYPEGEN_BUILD_FAILED" | "TYPEGEN_EMIT_FAILED" | "TYPEGEN_BUNDLE_FAILED";
|
|
13
13
|
/**
|
|
14
14
|
* Typegen-specific error type.
|
|
15
15
|
*/
|
|
@@ -36,14 +36,6 @@ type TypegenSpecificError = {
|
|
|
36
36
|
readonly message: string;
|
|
37
37
|
readonly path: string;
|
|
38
38
|
readonly cause?: unknown;
|
|
39
|
-
} | {
|
|
40
|
-
readonly code: "TYPEGEN_FRAGMENT_MISSING_KEY";
|
|
41
|
-
readonly message: string;
|
|
42
|
-
readonly fragments: readonly {
|
|
43
|
-
readonly canonicalId: string;
|
|
44
|
-
readonly typename: string;
|
|
45
|
-
readonly schemaLabel: string;
|
|
46
|
-
}[];
|
|
47
39
|
};
|
|
48
40
|
/**
|
|
49
41
|
* Union of all typegen errors (specific + builder errors).
|
|
@@ -58,11 +50,6 @@ declare const typegenErrors: {
|
|
|
58
50
|
readonly buildFailed: (message: string, cause?: unknown) => TypegenSpecificError;
|
|
59
51
|
readonly emitFailed: (path: string, message: string, cause?: unknown) => TypegenSpecificError;
|
|
60
52
|
readonly bundleFailed: (path: string, message: string, cause?: unknown) => TypegenSpecificError;
|
|
61
|
-
readonly fragmentMissingKey: (fragments: readonly {
|
|
62
|
-
canonicalId: string;
|
|
63
|
-
typename: string;
|
|
64
|
-
schemaLabel: string;
|
|
65
|
-
}[]) => TypegenSpecificError;
|
|
66
53
|
};
|
|
67
54
|
/**
|
|
68
55
|
* Format TypegenError for console output (human-readable).
|
|
@@ -160,12 +147,9 @@ type PrebuiltGeneratedModule = {
|
|
|
160
147
|
/**
|
|
161
148
|
* Generate the prebuilt index module code.
|
|
162
149
|
*
|
|
163
|
-
* Generates index.prebuilt.ts with
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
* - Adapters from _internal-injects.ts
|
|
167
|
-
* - Runtime values from _internal.ts
|
|
168
|
-
* - AnyGqlContext instead of heavy Context type inference
|
|
150
|
+
* Generates index.prebuilt.ts with builder-level type resolution.
|
|
151
|
+
* Types are resolved at the fragment/operation builder level using TKey/TName,
|
|
152
|
+
* eliminating the need for ResolvePrebuiltElement at the composer level.
|
|
169
153
|
*/
|
|
170
154
|
declare const generatePrebuiltModule: (schemas: Map<string, DocumentNode>, options: PrebuiltGeneratorOptions) => PrebuiltGeneratedModule;
|
|
171
155
|
//#endregion
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/errors.ts","../src/emitter.ts","../src/prebuilt-generator.ts","../src/types.ts","../src/runner.ts"],"sourcesContent":[],"mappings":";;;;;;;;;AAWA;
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/errors.ts","../src/emitter.ts","../src/prebuilt-generator.ts","../src/types.ts","../src/runner.ts"],"sourcesContent":[],"mappings":"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"}
|
package/dist/index.d.mts
CHANGED
|
@@ -9,7 +9,7 @@ import { ResolvedSodaGqlConfig } from "@soda-gql/config";
|
|
|
9
9
|
/**
|
|
10
10
|
* Error codes specific to typegen operations.
|
|
11
11
|
*/
|
|
12
|
-
type TypegenErrorCode = "TYPEGEN_CODEGEN_REQUIRED" | "TYPEGEN_SCHEMA_LOAD_FAILED" | "TYPEGEN_BUILD_FAILED" | "TYPEGEN_EMIT_FAILED" | "TYPEGEN_BUNDLE_FAILED"
|
|
12
|
+
type TypegenErrorCode = "TYPEGEN_CODEGEN_REQUIRED" | "TYPEGEN_SCHEMA_LOAD_FAILED" | "TYPEGEN_BUILD_FAILED" | "TYPEGEN_EMIT_FAILED" | "TYPEGEN_BUNDLE_FAILED";
|
|
13
13
|
/**
|
|
14
14
|
* Typegen-specific error type.
|
|
15
15
|
*/
|
|
@@ -36,14 +36,6 @@ type TypegenSpecificError = {
|
|
|
36
36
|
readonly message: string;
|
|
37
37
|
readonly path: string;
|
|
38
38
|
readonly cause?: unknown;
|
|
39
|
-
} | {
|
|
40
|
-
readonly code: "TYPEGEN_FRAGMENT_MISSING_KEY";
|
|
41
|
-
readonly message: string;
|
|
42
|
-
readonly fragments: readonly {
|
|
43
|
-
readonly canonicalId: string;
|
|
44
|
-
readonly typename: string;
|
|
45
|
-
readonly schemaLabel: string;
|
|
46
|
-
}[];
|
|
47
39
|
};
|
|
48
40
|
/**
|
|
49
41
|
* Union of all typegen errors (specific + builder errors).
|
|
@@ -58,11 +50,6 @@ declare const typegenErrors: {
|
|
|
58
50
|
readonly buildFailed: (message: string, cause?: unknown) => TypegenSpecificError;
|
|
59
51
|
readonly emitFailed: (path: string, message: string, cause?: unknown) => TypegenSpecificError;
|
|
60
52
|
readonly bundleFailed: (path: string, message: string, cause?: unknown) => TypegenSpecificError;
|
|
61
|
-
readonly fragmentMissingKey: (fragments: readonly {
|
|
62
|
-
canonicalId: string;
|
|
63
|
-
typename: string;
|
|
64
|
-
schemaLabel: string;
|
|
65
|
-
}[]) => TypegenSpecificError;
|
|
66
53
|
};
|
|
67
54
|
/**
|
|
68
55
|
* Format TypegenError for console output (human-readable).
|
|
@@ -160,12 +147,9 @@ type PrebuiltGeneratedModule = {
|
|
|
160
147
|
/**
|
|
161
148
|
* Generate the prebuilt index module code.
|
|
162
149
|
*
|
|
163
|
-
* Generates index.prebuilt.ts with
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
* - Adapters from _internal-injects.ts
|
|
167
|
-
* - Runtime values from _internal.ts
|
|
168
|
-
* - AnyGqlContext instead of heavy Context type inference
|
|
150
|
+
* Generates index.prebuilt.ts with builder-level type resolution.
|
|
151
|
+
* Types are resolved at the fragment/operation builder level using TKey/TName,
|
|
152
|
+
* eliminating the need for ResolvePrebuiltElement at the composer level.
|
|
169
153
|
*/
|
|
170
154
|
declare const generatePrebuiltModule: (schemas: Map<string, DocumentNode>, options: PrebuiltGeneratorOptions) => PrebuiltGeneratedModule;
|
|
171
155
|
//#endregion
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/errors.ts","../src/emitter.ts","../src/prebuilt-generator.ts","../src/types.ts","../src/runner.ts"],"sourcesContent":[],"mappings":";;;;;;;;;AAWA;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/errors.ts","../src/emitter.ts","../src/prebuilt-generator.ts","../src/types.ts","../src/runner.ts"],"sourcesContent":[],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -7,78 +7,6 @@ import { err, ok } from "neverthrow";
|
|
|
7
7
|
import { existsSync, readFileSync } from "node:fs";
|
|
8
8
|
import { build } from "esbuild";
|
|
9
9
|
|
|
10
|
-
//#region packages/typegen/src/errors.ts
|
|
11
|
-
/**
|
|
12
|
-
* Error constructor helpers for concise error creation.
|
|
13
|
-
*/
|
|
14
|
-
const typegenErrors = {
|
|
15
|
-
codegenRequired: (outdir) => ({
|
|
16
|
-
code: "TYPEGEN_CODEGEN_REQUIRED",
|
|
17
|
-
message: `Generated graphql-system module not found at '${outdir}'. Run 'soda-gql codegen' first.`,
|
|
18
|
-
outdir
|
|
19
|
-
}),
|
|
20
|
-
schemaLoadFailed: (schemaNames, cause) => ({
|
|
21
|
-
code: "TYPEGEN_SCHEMA_LOAD_FAILED",
|
|
22
|
-
message: `Failed to load schemas: ${schemaNames.join(", ")}`,
|
|
23
|
-
schemaNames,
|
|
24
|
-
cause
|
|
25
|
-
}),
|
|
26
|
-
buildFailed: (message, cause) => ({
|
|
27
|
-
code: "TYPEGEN_BUILD_FAILED",
|
|
28
|
-
message,
|
|
29
|
-
cause
|
|
30
|
-
}),
|
|
31
|
-
emitFailed: (path, message, cause) => ({
|
|
32
|
-
code: "TYPEGEN_EMIT_FAILED",
|
|
33
|
-
message,
|
|
34
|
-
path,
|
|
35
|
-
cause
|
|
36
|
-
}),
|
|
37
|
-
bundleFailed: (path, message, cause) => ({
|
|
38
|
-
code: "TYPEGEN_BUNDLE_FAILED",
|
|
39
|
-
message,
|
|
40
|
-
path,
|
|
41
|
-
cause
|
|
42
|
-
}),
|
|
43
|
-
fragmentMissingKey: (fragments) => ({
|
|
44
|
-
code: "TYPEGEN_FRAGMENT_MISSING_KEY",
|
|
45
|
-
message: `${fragments.length} fragment(s) missing required 'key' property for prebuilt types`,
|
|
46
|
-
fragments
|
|
47
|
-
})
|
|
48
|
-
};
|
|
49
|
-
/**
|
|
50
|
-
* Format TypegenError for console output (human-readable).
|
|
51
|
-
*/
|
|
52
|
-
const formatTypegenError = (error) => {
|
|
53
|
-
const lines = [];
|
|
54
|
-
lines.push(`Error [${error.code}]: ${error.message}`);
|
|
55
|
-
switch (error.code) {
|
|
56
|
-
case "TYPEGEN_CODEGEN_REQUIRED":
|
|
57
|
-
lines.push(` Output directory: ${error.outdir}`);
|
|
58
|
-
lines.push(" Hint: Run 'soda-gql codegen' to generate the graphql-system module first.");
|
|
59
|
-
break;
|
|
60
|
-
case "TYPEGEN_SCHEMA_LOAD_FAILED":
|
|
61
|
-
lines.push(` Schemas: ${error.schemaNames.join(", ")}`);
|
|
62
|
-
break;
|
|
63
|
-
case "TYPEGEN_EMIT_FAILED":
|
|
64
|
-
case "TYPEGEN_BUNDLE_FAILED":
|
|
65
|
-
lines.push(` Path: ${error.path}`);
|
|
66
|
-
break;
|
|
67
|
-
case "TYPEGEN_FRAGMENT_MISSING_KEY":
|
|
68
|
-
lines.push(" Fragments missing 'key' property:");
|
|
69
|
-
for (const fragment of error.fragments) {
|
|
70
|
-
lines.push(` - ${fragment.canonicalId} (${fragment.typename} on ${fragment.schemaLabel})`);
|
|
71
|
-
}
|
|
72
|
-
lines.push(" Hint: Add a 'key' property to each fragment for prebuilt type resolution.");
|
|
73
|
-
break;
|
|
74
|
-
}
|
|
75
|
-
if ("cause" in error && error.cause) {
|
|
76
|
-
lines.push(` Caused by: ${error.cause}`);
|
|
77
|
-
}
|
|
78
|
-
return lines.join("\n");
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
//#endregion
|
|
82
10
|
//#region packages/typegen/src/emitter.ts
|
|
83
11
|
/**
|
|
84
12
|
* Prebuilt types emitter.
|
|
@@ -108,16 +36,15 @@ const formatTypegenError = (error) => {
|
|
|
108
36
|
* Group field selections by schema.
|
|
109
37
|
* Uses the schemaLabel from each selection to group them correctly.
|
|
110
38
|
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
39
|
+
* Fragments without a 'key' property are skipped (not included in PrebuiltTypes)
|
|
40
|
+
* and a warning is added. This allows projects to use fragments without keys
|
|
41
|
+
* while still generating prebuilt types for those that have keys.
|
|
113
42
|
*
|
|
114
43
|
* @returns Result containing grouped selections and warnings, or error if schema not found
|
|
115
|
-
* or fragments are missing keys
|
|
116
44
|
*/
|
|
117
45
|
const groupBySchema = (fieldSelections, schemas) => {
|
|
118
46
|
const grouped = new Map();
|
|
119
47
|
const warnings = [];
|
|
120
|
-
const missingKeyFragments = [];
|
|
121
48
|
for (const schemaName of Object.keys(schemas)) {
|
|
122
49
|
grouped.set(schemaName, {
|
|
123
50
|
fragments: [],
|
|
@@ -139,11 +66,7 @@ const groupBySchema = (fieldSelections, schemas) => {
|
|
|
139
66
|
};
|
|
140
67
|
if (selection.type === "fragment") {
|
|
141
68
|
if (!selection.key) {
|
|
142
|
-
|
|
143
|
-
canonicalId,
|
|
144
|
-
typename: selection.typename,
|
|
145
|
-
schemaLabel: selection.schemaLabel
|
|
146
|
-
});
|
|
69
|
+
warnings.push(`[prebuilt] Fragment "${canonicalId}" skipped: missing 'key' property`);
|
|
147
70
|
continue;
|
|
148
71
|
}
|
|
149
72
|
try {
|
|
@@ -156,6 +79,7 @@ const groupBySchema = (fieldSelections, schemas) => {
|
|
|
156
79
|
const inputType = hasVariables ? generateInputTypeFromSpecifiers(schema, selection.variableDefinitions, { formatters: inputFormatters }) : "void";
|
|
157
80
|
group.fragments.push({
|
|
158
81
|
key: selection.key,
|
|
82
|
+
typename: selection.typename,
|
|
159
83
|
inputType,
|
|
160
84
|
outputType
|
|
161
85
|
});
|
|
@@ -180,9 +104,6 @@ const groupBySchema = (fieldSelections, schemas) => {
|
|
|
180
104
|
}
|
|
181
105
|
}
|
|
182
106
|
}
|
|
183
|
-
if (missingKeyFragments.length > 0) {
|
|
184
|
-
return err(typegenErrors.fragmentMissingKey(missingKeyFragments));
|
|
185
|
-
}
|
|
186
107
|
return ok({
|
|
187
108
|
grouped,
|
|
188
109
|
warnings
|
|
@@ -315,7 +236,7 @@ const generateTypesCode = (grouped, schemas, injectsModulePath) => {
|
|
|
315
236
|
lines.push(...inputTypeLines);
|
|
316
237
|
lines.push("");
|
|
317
238
|
}
|
|
318
|
-
const fragmentEntries = fragments.sort((a, b) => a.key.localeCompare(b.key)).map((f) => ` readonly "${f.key}": { readonly input: ${f.inputType}; readonly output: ${f.outputType} };`);
|
|
239
|
+
const fragmentEntries = fragments.sort((a, b) => a.key.localeCompare(b.key)).map((f) => ` readonly "${f.key}": { readonly typename: "${f.typename}"; readonly input: ${f.inputType}; readonly output: ${f.outputType} };`);
|
|
319
240
|
const operationEntries = operations.sort((a, b) => a.key.localeCompare(b.key)).map((o) => ` readonly "${o.key}": { readonly input: ${o.inputType}; readonly output: ${o.outputType} };`);
|
|
320
241
|
lines.push(`export type PrebuiltTypes_${schemaName} = {`);
|
|
321
242
|
lines.push(" readonly fragments: {");
|
|
@@ -328,7 +249,7 @@ const generateTypesCode = (grouped, schemas, injectsModulePath) => {
|
|
|
328
249
|
lines.push(...operationEntries);
|
|
329
250
|
}
|
|
330
251
|
lines.push(" };");
|
|
331
|
-
lines.push("}
|
|
252
|
+
lines.push("};");
|
|
332
253
|
lines.push("");
|
|
333
254
|
}
|
|
334
255
|
return lines.join("\n");
|
|
@@ -382,17 +303,74 @@ const emitPrebuiltTypes = async (options) => {
|
|
|
382
303
|
}
|
|
383
304
|
};
|
|
384
305
|
|
|
306
|
+
//#endregion
|
|
307
|
+
//#region packages/typegen/src/errors.ts
|
|
308
|
+
/**
|
|
309
|
+
* Error constructor helpers for concise error creation.
|
|
310
|
+
*/
|
|
311
|
+
const typegenErrors = {
|
|
312
|
+
codegenRequired: (outdir) => ({
|
|
313
|
+
code: "TYPEGEN_CODEGEN_REQUIRED",
|
|
314
|
+
message: `Generated graphql-system module not found at '${outdir}'. Run 'soda-gql codegen' first.`,
|
|
315
|
+
outdir
|
|
316
|
+
}),
|
|
317
|
+
schemaLoadFailed: (schemaNames, cause) => ({
|
|
318
|
+
code: "TYPEGEN_SCHEMA_LOAD_FAILED",
|
|
319
|
+
message: `Failed to load schemas: ${schemaNames.join(", ")}`,
|
|
320
|
+
schemaNames,
|
|
321
|
+
cause
|
|
322
|
+
}),
|
|
323
|
+
buildFailed: (message, cause) => ({
|
|
324
|
+
code: "TYPEGEN_BUILD_FAILED",
|
|
325
|
+
message,
|
|
326
|
+
cause
|
|
327
|
+
}),
|
|
328
|
+
emitFailed: (path, message, cause) => ({
|
|
329
|
+
code: "TYPEGEN_EMIT_FAILED",
|
|
330
|
+
message,
|
|
331
|
+
path,
|
|
332
|
+
cause
|
|
333
|
+
}),
|
|
334
|
+
bundleFailed: (path, message, cause) => ({
|
|
335
|
+
code: "TYPEGEN_BUNDLE_FAILED",
|
|
336
|
+
message,
|
|
337
|
+
path,
|
|
338
|
+
cause
|
|
339
|
+
})
|
|
340
|
+
};
|
|
341
|
+
/**
|
|
342
|
+
* Format TypegenError for console output (human-readable).
|
|
343
|
+
*/
|
|
344
|
+
const formatTypegenError = (error) => {
|
|
345
|
+
const lines = [];
|
|
346
|
+
lines.push(`Error [${error.code}]: ${error.message}`);
|
|
347
|
+
switch (error.code) {
|
|
348
|
+
case "TYPEGEN_CODEGEN_REQUIRED":
|
|
349
|
+
lines.push(` Output directory: ${error.outdir}`);
|
|
350
|
+
lines.push(" Hint: Run 'soda-gql codegen' to generate the graphql-system module first.");
|
|
351
|
+
break;
|
|
352
|
+
case "TYPEGEN_SCHEMA_LOAD_FAILED":
|
|
353
|
+
lines.push(` Schemas: ${error.schemaNames.join(", ")}`);
|
|
354
|
+
break;
|
|
355
|
+
case "TYPEGEN_EMIT_FAILED":
|
|
356
|
+
case "TYPEGEN_BUNDLE_FAILED":
|
|
357
|
+
lines.push(` Path: ${error.path}`);
|
|
358
|
+
break;
|
|
359
|
+
}
|
|
360
|
+
if ("cause" in error && error.cause) {
|
|
361
|
+
lines.push(` Caused by: ${error.cause}`);
|
|
362
|
+
}
|
|
363
|
+
return lines.join("\n");
|
|
364
|
+
};
|
|
365
|
+
|
|
385
366
|
//#endregion
|
|
386
367
|
//#region packages/typegen/src/prebuilt-generator.ts
|
|
387
368
|
/**
|
|
388
369
|
* Generate the prebuilt index module code.
|
|
389
370
|
*
|
|
390
|
-
* Generates index.prebuilt.ts with
|
|
391
|
-
*
|
|
392
|
-
*
|
|
393
|
-
* - Adapters from _internal-injects.ts
|
|
394
|
-
* - Runtime values from _internal.ts
|
|
395
|
-
* - AnyGqlContext instead of heavy Context type inference
|
|
371
|
+
* Generates index.prebuilt.ts with builder-level type resolution.
|
|
372
|
+
* Types are resolved at the fragment/operation builder level using TKey/TName,
|
|
373
|
+
* eliminating the need for ResolvePrebuiltElement at the composer level.
|
|
396
374
|
*/
|
|
397
375
|
const generatePrebuiltModule = (schemas, options) => {
|
|
398
376
|
const schemaNames = Array.from(schemas.keys());
|
|
@@ -409,60 +387,165 @@ const generatePrebuiltModule = (schemas, options) => {
|
|
|
409
387
|
`__inputTypeMethods_${name}`,
|
|
410
388
|
`__directiveMethods_${name}`
|
|
411
389
|
]);
|
|
390
|
+
const genericTypes = `
|
|
391
|
+
/**
|
|
392
|
+
* Generic field factory for type-erased field access.
|
|
393
|
+
* Returns a callable for nested field builders. Primitive fields can be spread directly.
|
|
394
|
+
* Runtime behavior differs but spread works for both: ...f.id() and ...f.user()(...)
|
|
395
|
+
*/
|
|
396
|
+
type GenericFieldFactory = (
|
|
397
|
+
...args: unknown[]
|
|
398
|
+
) => (nest: (tools: GenericFieldsBuilderTools) => AnyFields) => AnyFields;
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Generic tools for fields builder callbacks.
|
|
402
|
+
* Uses type-erased factory to allow any field access while maintaining strict mode compatibility.
|
|
403
|
+
*/
|
|
404
|
+
type GenericFieldsBuilderTools = {
|
|
405
|
+
readonly f: Record<string, GenericFieldFactory>;
|
|
406
|
+
readonly $: Record<string, unknown>;
|
|
407
|
+
};
|
|
408
|
+
`;
|
|
409
|
+
const contextTypes = schemaNames.map((name) => `
|
|
410
|
+
/**
|
|
411
|
+
* Resolve fragment types at builder level using TKey.
|
|
412
|
+
* If TKey is a known key in PrebuiltTypes, return resolved types.
|
|
413
|
+
* Otherwise, return PrebuiltEntryNotFound.
|
|
414
|
+
*/
|
|
415
|
+
type ResolveFragmentAtBuilder_${name}<
|
|
416
|
+
TKey extends string | undefined
|
|
417
|
+
> = TKey extends keyof PrebuiltTypes_${name}["fragments"]
|
|
418
|
+
? Fragment<
|
|
419
|
+
PrebuiltTypes_${name}["fragments"][TKey]["typename"],
|
|
420
|
+
PrebuiltTypes_${name}["fragments"][TKey]["input"] extends infer TInput
|
|
421
|
+
? TInput extends void ? void : Partial<TInput & object>
|
|
422
|
+
: void,
|
|
423
|
+
Partial<AnyFields>,
|
|
424
|
+
PrebuiltTypes_${name}["fragments"][TKey]["output"] & object
|
|
425
|
+
>
|
|
426
|
+
: TKey extends undefined
|
|
427
|
+
? Fragment<"(unknown)", PrebuiltEntryNotFound<"(undefined)", "fragment">, Partial<AnyFields>, PrebuiltEntryNotFound<"(undefined)", "fragment">>
|
|
428
|
+
: Fragment<"(unknown)", PrebuiltEntryNotFound<TKey & string, "fragment">, Partial<AnyFields>, PrebuiltEntryNotFound<TKey & string, "fragment">>;
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Resolve operation types at builder level using TName.
|
|
432
|
+
*/
|
|
433
|
+
type ResolveOperationAtBuilder_${name}<
|
|
434
|
+
TOperationType extends OperationType,
|
|
435
|
+
TName extends string
|
|
436
|
+
> = TName extends keyof PrebuiltTypes_${name}["operations"]
|
|
437
|
+
? Operation<
|
|
438
|
+
TOperationType,
|
|
439
|
+
TName,
|
|
440
|
+
string[],
|
|
441
|
+
PrebuiltTypes_${name}["operations"][TName]["input"] & AnyConstAssignableInput,
|
|
442
|
+
Partial<AnyFields>,
|
|
443
|
+
PrebuiltTypes_${name}["operations"][TName]["output"] & object
|
|
444
|
+
>
|
|
445
|
+
: Operation<
|
|
446
|
+
TOperationType,
|
|
447
|
+
TName,
|
|
448
|
+
string[],
|
|
449
|
+
PrebuiltEntryNotFound<TName, "operation">,
|
|
450
|
+
Partial<AnyFields>,
|
|
451
|
+
PrebuiltEntryNotFound<TName, "operation">
|
|
452
|
+
>;
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* Fragment builder that resolves types at builder level using TKey.
|
|
456
|
+
*/
|
|
457
|
+
type PrebuiltFragmentBuilder_${name} = <TKey extends string | undefined = undefined>(
|
|
458
|
+
options: {
|
|
459
|
+
key?: TKey;
|
|
460
|
+
fields: (tools: GenericFieldsBuilderTools) => AnyFields;
|
|
461
|
+
variables?: Record<string, unknown>;
|
|
462
|
+
metadata?: unknown;
|
|
463
|
+
}
|
|
464
|
+
) => ResolveFragmentAtBuilder_${name}<TKey>;
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* Operation builder that resolves types at builder level using TName.
|
|
468
|
+
*/
|
|
469
|
+
type PrebuiltOperationBuilder_${name}<TOperationType extends OperationType> = <TName extends string>(
|
|
470
|
+
options: {
|
|
471
|
+
name: TName;
|
|
472
|
+
fields: (tools: GenericFieldsBuilderTools) => AnyFields;
|
|
473
|
+
variables?: Record<string, unknown>;
|
|
474
|
+
metadata?: unknown;
|
|
475
|
+
}
|
|
476
|
+
) => ResolveOperationAtBuilder_${name}<TOperationType, TName>;
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* Prebuilt context with builder-level type resolution for schema "${name}".
|
|
480
|
+
*/
|
|
481
|
+
type PrebuiltContext_${name} = {
|
|
482
|
+
readonly fragment: { [K: string]: PrebuiltFragmentBuilder_${name} };
|
|
483
|
+
readonly query: { readonly operation: PrebuiltOperationBuilder_${name}<"query"> };
|
|
484
|
+
readonly mutation: { readonly operation: PrebuiltOperationBuilder_${name}<"mutation"> };
|
|
485
|
+
readonly subscription: { readonly operation: PrebuiltOperationBuilder_${name}<"subscription"> };
|
|
486
|
+
readonly $var: unknown;
|
|
487
|
+
readonly $dir: StandardDirectives;
|
|
488
|
+
readonly $colocate: unknown;
|
|
489
|
+
};`).join("\n");
|
|
412
490
|
const gqlEntries = schemaNames.map((name) => {
|
|
413
491
|
const config = injection.get(name);
|
|
414
|
-
const
|
|
415
|
-
return ` ${name}:
|
|
416
|
-
AnyGraphqlSchema,
|
|
417
|
-
PrebuiltTypes_${name},
|
|
418
|
-
Record<string, unknown>,
|
|
419
|
-
StandardDirectives,
|
|
420
|
-
AnyGqlContext
|
|
421
|
-
>(
|
|
492
|
+
const adapterLine = config?.hasAdapter ? `,\n adapter: adapter_${name}` : "";
|
|
493
|
+
return ` ${name}: createGqlElementComposer(
|
|
422
494
|
__schema_${name} as AnyGraphqlSchema,
|
|
423
495
|
{
|
|
424
496
|
inputTypeMethods: __inputTypeMethods_${name},
|
|
425
|
-
directiveMethods: __directiveMethods_${name}
|
|
426
|
-
${adapterArg}
|
|
497
|
+
directiveMethods: __directiveMethods_${name}${adapterLine}
|
|
427
498
|
}
|
|
428
|
-
)`;
|
|
499
|
+
) as unknown as GqlComposer_${name}`;
|
|
429
500
|
});
|
|
430
501
|
const injectsImportSpecifiers = adapterImports.length > 0 ? adapterImports.join(", ") : "";
|
|
431
502
|
const injectsImportLine = injectsImportSpecifiers ? `import { ${injectsImportSpecifiers} } from "${options.injectsModulePath}";` : "";
|
|
432
503
|
const indexCode = `\
|
|
433
504
|
/**
|
|
434
|
-
* Prebuilt GQL module
|
|
435
|
-
*
|
|
436
|
-
* This module creates prebuilt composers using createPrebuiltGqlElementComposer
|
|
437
|
-
* that look up types from PrebuiltTypes instead of complex inference.
|
|
505
|
+
* Prebuilt GQL module with builder-level type resolution.
|
|
438
506
|
*
|
|
439
|
-
*
|
|
440
|
-
*
|
|
441
|
-
*
|
|
442
|
-
* - AnyGqlContext instead of heavy Context type inference
|
|
507
|
+
* Types are resolved at the fragment/operation builder level using TKey/TName,
|
|
508
|
+
* not at the composer level. This enables proper typing for builder arguments
|
|
509
|
+
* and eliminates the need for ResolvePrebuiltElement.
|
|
443
510
|
*
|
|
444
511
|
* @module
|
|
445
512
|
* @generated by @soda-gql/typegen
|
|
446
513
|
*/
|
|
447
514
|
|
|
448
515
|
import {
|
|
449
|
-
|
|
450
|
-
type
|
|
516
|
+
createGqlElementComposer,
|
|
517
|
+
type AnyConstAssignableInput,
|
|
518
|
+
type AnyFields,
|
|
451
519
|
type AnyGraphqlSchema,
|
|
520
|
+
type Fragment,
|
|
521
|
+
type Operation,
|
|
522
|
+
type OperationType,
|
|
523
|
+
type PrebuiltEntryNotFound,
|
|
452
524
|
type StandardDirectives,
|
|
453
525
|
} from "@soda-gql/core";
|
|
454
526
|
${injectsImportLine}
|
|
455
527
|
import { ${internalImports.join(", ")} } from "${options.internalModulePath}";
|
|
456
528
|
import type { ${schemaNames.map((name) => `PrebuiltTypes_${name}`).join(", ")} } from "./types.prebuilt";
|
|
529
|
+
${genericTypes}
|
|
530
|
+
${contextTypes}
|
|
531
|
+
|
|
532
|
+
// Export context types for explicit annotation
|
|
533
|
+
${schemaNames.map((name) => `export type { PrebuiltContext_${name} };`).join("\n")}
|
|
534
|
+
|
|
535
|
+
// Composer type - TResult already has resolved types from builders, no ResolvePrebuiltElement needed
|
|
536
|
+
${schemaNames.map((name) => `type GqlComposer_${name} = {
|
|
537
|
+
<TResult>(composeElement: (context: PrebuiltContext_${name}) => TResult): TResult;
|
|
538
|
+
readonly $schema: AnyGraphqlSchema;
|
|
539
|
+
};`).join("\n")}
|
|
457
540
|
|
|
458
541
|
/**
|
|
459
|
-
* Prebuilt GQL composers with
|
|
542
|
+
* Prebuilt GQL composers with builder-level type resolution.
|
|
460
543
|
*
|
|
461
544
|
* These composers have the same runtime behavior as the base composers,
|
|
462
545
|
* but their return types are resolved from the prebuilt type registry
|
|
463
|
-
* instead of using
|
|
546
|
+
* at the builder level instead of using ResolvePrebuiltElement.
|
|
464
547
|
*/
|
|
465
|
-
export const gql = {
|
|
548
|
+
export const gql: { ${schemaNames.map((name) => `${name}: GqlComposer_${name}`).join("; ")} } = {
|
|
466
549
|
${gqlEntries.join(",\n")}
|
|
467
550
|
};
|
|
468
551
|
`;
|