@ptdgrp/typedgql 1.0.0-beta.8
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/LICENSE +45 -0
- package/README.md +121 -0
- package/README.zh-CN.md +113 -0
- package/dist/index.cjs +911 -0
- package/dist/index.d.cts +299 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +299 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +896 -0
- package/dist/index.mjs.map +1 -0
- package/dist/node.cjs +6 -0
- package/dist/node.d.cts +41 -0
- package/dist/node.d.cts.map +1 -0
- package/dist/node.d.mts +41 -0
- package/dist/node.d.mts.map +1 -0
- package/dist/node.mjs +3 -0
- package/dist/options-CaWo97vV.d.cts +99 -0
- package/dist/options-CaWo97vV.d.cts.map +1 -0
- package/dist/options-D2L-tv7C.d.mts +99 -0
- package/dist/options-D2L-tv7C.d.mts.map +1 -0
- package/dist/schema-loader-BeukhrkU.cjs +1915 -0
- package/dist/schema-loader-CYFTxUkG.mjs +1899 -0
- package/dist/schema-loader-CYFTxUkG.mjs.map +1 -0
- package/dist/vite.cjs +148 -0
- package/dist/vite.d.cts +61 -0
- package/dist/vite.d.cts.map +1 -0
- package/dist/vite.d.mts +61 -0
- package/dist/vite.d.mts.map +1 -0
- package/dist/vite.mjs +148 -0
- package/dist/vite.mjs.map +1 -0
- package/package.json +87 -0
|
@@ -0,0 +1,1899 @@
|
|
|
1
|
+
import { GraphQLEnumType, GraphQLInputObjectType, GraphQLInterfaceType, GraphQLList, GraphQLNonNull, GraphQLObjectType, GraphQLScalarType, GraphQLUnionType, buildClientSchema, buildSchema, getIntrospectionQuery } from "graphql";
|
|
2
|
+
import { mkdir, readFile, rm, writeFile } from "fs/promises";
|
|
3
|
+
import { createWriteStream } from "fs";
|
|
4
|
+
import { join, resolve } from "path";
|
|
5
|
+
|
|
6
|
+
//#region src/codegen/utils.ts
|
|
7
|
+
/**
|
|
8
|
+
* Unwrap NonNull/List wrappers and return the underlying composite type,
|
|
9
|
+
* or `undefined` if the base type is a scalar/enum/input.
|
|
10
|
+
*/
|
|
11
|
+
function targetTypeOf(type) {
|
|
12
|
+
if (type instanceof GraphQLNonNull) return targetTypeOf(type.ofType);
|
|
13
|
+
if (type instanceof GraphQLList) return targetTypeOf(type.ofType);
|
|
14
|
+
if (type instanceof GraphQLObjectType || type instanceof GraphQLInterfaceType || type instanceof GraphQLUnionType) return type;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Lower-case the first character of a name for use as a variable/instance prefix.
|
|
18
|
+
* e.g. "QuerySelection" → "querySelection"
|
|
19
|
+
*/
|
|
20
|
+
function instancePrefix(name) {
|
|
21
|
+
return name.substring(0, 1).toLowerCase() + name.substring(1);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Check whether a type name is in the user's exclusion list.
|
|
25
|
+
*/
|
|
26
|
+
function isExcludedTypeName(options, typeName) {
|
|
27
|
+
if (typeName == void 0) return false;
|
|
28
|
+
const list = options.excludedTypes;
|
|
29
|
+
return list !== void 0 && list.findIndex((v) => v == typeName) !== -1;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Convert a PascalCase or camelCase name to kebab-case.
|
|
33
|
+
* e.g. "TaskSelection" → "task-selection", "EnumInputMetadata" → "enum-input-metadata"
|
|
34
|
+
*/
|
|
35
|
+
function toKebabCase(name) {
|
|
36
|
+
return name.replace(/([A-Z]+)([A-Z][a-z])/g, "$1-$2").replace(/([a-z\d])([A-Z])/g, "$1-$2").toLowerCase();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
//#endregion
|
|
40
|
+
//#region src/codegen/writer.ts
|
|
41
|
+
const SCOPE_BRACKETS = {
|
|
42
|
+
blank: ["", ""],
|
|
43
|
+
block: ["{", "}"],
|
|
44
|
+
parameters: ["(", ")"],
|
|
45
|
+
array: ["[", "]"],
|
|
46
|
+
generic: ["<", ">"]
|
|
47
|
+
};
|
|
48
|
+
const SCALAR_MAP = {
|
|
49
|
+
Boolean: "boolean",
|
|
50
|
+
Byte: "number",
|
|
51
|
+
Short: "number",
|
|
52
|
+
Int: "number",
|
|
53
|
+
Long: "number",
|
|
54
|
+
Float: "number",
|
|
55
|
+
Double: "number",
|
|
56
|
+
BigInteger: "number",
|
|
57
|
+
BigDecimal: "number",
|
|
58
|
+
String: "string",
|
|
59
|
+
Date: "string",
|
|
60
|
+
DateTime: "string",
|
|
61
|
+
LocalDate: "string",
|
|
62
|
+
LocalDateTime: "string",
|
|
63
|
+
ID: "string",
|
|
64
|
+
UUID: "string"
|
|
65
|
+
};
|
|
66
|
+
const GLOBAL_SCOPE = {
|
|
67
|
+
type: "blank",
|
|
68
|
+
multiLines: true,
|
|
69
|
+
dirty: true
|
|
70
|
+
};
|
|
71
|
+
var Writer = class {
|
|
72
|
+
indent;
|
|
73
|
+
scopes = [];
|
|
74
|
+
needIndent = false;
|
|
75
|
+
importStatements = /* @__PURE__ */ new Set();
|
|
76
|
+
importedTypes = /* @__PURE__ */ new Set();
|
|
77
|
+
importedScalarTypes = /* @__PURE__ */ new Map();
|
|
78
|
+
importFinalized = false;
|
|
79
|
+
constructor(stream, options) {
|
|
80
|
+
this.stream = stream;
|
|
81
|
+
this.options = options;
|
|
82
|
+
this.indent = options.indent ?? " ";
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Two-phase render lifecycle:
|
|
86
|
+
* 1) collect imports
|
|
87
|
+
* 2) flush imports and emit body
|
|
88
|
+
*/
|
|
89
|
+
write() {
|
|
90
|
+
this.prepareImports();
|
|
91
|
+
this.importFinalized = true;
|
|
92
|
+
for (const stmt of Array.from(this.importStatements).sort()) {
|
|
93
|
+
this.stream.write(stmt);
|
|
94
|
+
this.stream.write("\n");
|
|
95
|
+
}
|
|
96
|
+
this.writeNamedTypeImports();
|
|
97
|
+
this.writeMappedScalarImports();
|
|
98
|
+
if (this.hasAnyImports) this.stream.write("\n");
|
|
99
|
+
this.writeCode();
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Hook for subclasses to register all imports before body generation.
|
|
103
|
+
*/
|
|
104
|
+
prepareImports() {}
|
|
105
|
+
importFieldTypes(field) {
|
|
106
|
+
this.importType(field.type);
|
|
107
|
+
for (const arg of field.args) this.importType(arg.type);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Registers type imports by recursively unwrapping list/non-null wrappers.
|
|
111
|
+
*/
|
|
112
|
+
importType(type) {
|
|
113
|
+
if (this.importFinalized) throw new Error("Cannot import after write phase has started");
|
|
114
|
+
const namedType = unwrapType(type);
|
|
115
|
+
if (namedType instanceof GraphQLInputObjectType || namedType instanceof GraphQLEnumType) {
|
|
116
|
+
this.importedTypes.add(namedType);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (namedType instanceof GraphQLScalarType && this.options.scalarTypeMap) {
|
|
120
|
+
const mapped = this.options.scalarTypeMap[namedType.name];
|
|
121
|
+
if (typeof mapped !== "object") return;
|
|
122
|
+
const set = this.importedScalarTypes.get(mapped.importSource) ?? /* @__PURE__ */ new Set();
|
|
123
|
+
set.add(mapped.typeName);
|
|
124
|
+
this.importedScalarTypes.set(mapped.importSource, set);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
importStatement(statement) {
|
|
128
|
+
if (this.importFinalized) throw new Error("Cannot import after write phase has started");
|
|
129
|
+
let stmt = statement.trimEnd();
|
|
130
|
+
if (stmt.endsWith("\n")) stmt = stmt.slice(0, -1);
|
|
131
|
+
if (!stmt.endsWith(";")) stmt += ";";
|
|
132
|
+
this.importStatements.add(stmt);
|
|
133
|
+
}
|
|
134
|
+
importingBehavior(_type) {
|
|
135
|
+
return "other_dir";
|
|
136
|
+
}
|
|
137
|
+
enter(type, multiLines = false, prefix) {
|
|
138
|
+
if (prefix) this.text(prefix);
|
|
139
|
+
const [open] = SCOPE_BRACKETS[type];
|
|
140
|
+
if (open) this.text(open);
|
|
141
|
+
if (multiLines) this.text("\n");
|
|
142
|
+
this.scopes.push({
|
|
143
|
+
type,
|
|
144
|
+
multiLines,
|
|
145
|
+
dirty: false
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
leave(suffix) {
|
|
149
|
+
const scope = this.scopes.pop();
|
|
150
|
+
if (!scope) throw new Error("No scope to leave");
|
|
151
|
+
if (scope.multiLines && !this.needIndent) this.text("\n");
|
|
152
|
+
const [, close] = SCOPE_BRACKETS[scope.type];
|
|
153
|
+
if (close) this.text(close);
|
|
154
|
+
if (suffix) this.text(suffix);
|
|
155
|
+
}
|
|
156
|
+
scope(args, action) {
|
|
157
|
+
this.enter(args.type, args.multiLines === true, args.prefix);
|
|
158
|
+
action();
|
|
159
|
+
this.leave(args.suffix);
|
|
160
|
+
}
|
|
161
|
+
separator(value) {
|
|
162
|
+
const scope = this.currentScope;
|
|
163
|
+
if (scope.dirty) {
|
|
164
|
+
if (value) this.text(value);
|
|
165
|
+
else if (scope.type === "parameters" || scope.type === "generic") this.text(", ");
|
|
166
|
+
if (scope.multiLines) this.text("\n");
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
text(value) {
|
|
170
|
+
const lines = value.split("\n");
|
|
171
|
+
lines.forEach((line, idx) => {
|
|
172
|
+
if (line) {
|
|
173
|
+
if (this.needIndent) {
|
|
174
|
+
this.flushIndent();
|
|
175
|
+
this.needIndent = false;
|
|
176
|
+
}
|
|
177
|
+
this.stream.write(line);
|
|
178
|
+
this.currentScope.dirty = true;
|
|
179
|
+
}
|
|
180
|
+
if (idx < lines.length - 1) {
|
|
181
|
+
this.stream.write("\n");
|
|
182
|
+
this.needIndent = true;
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
str(value) {
|
|
187
|
+
this.text(`'${value}'`);
|
|
188
|
+
}
|
|
189
|
+
variableDecl(name, type, overrideObjectTypeName) {
|
|
190
|
+
this.text(name);
|
|
191
|
+
if (!(type instanceof GraphQLNonNull)) this.text("?");
|
|
192
|
+
this.text(": ");
|
|
193
|
+
this.typeRef(type, overrideObjectTypeName);
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Renders a GraphQL type as TypeScript type syntax.
|
|
197
|
+
*/
|
|
198
|
+
typeRef(type, objectRender) {
|
|
199
|
+
if (type instanceof GraphQLNonNull) {
|
|
200
|
+
this.typeRef(type.ofType, objectRender);
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
if (type instanceof GraphQLList) {
|
|
204
|
+
const arrayType = this.options.arrayEditable ? "Array" : "ReadonlyArray";
|
|
205
|
+
this.typeApplication(arrayType, () => {
|
|
206
|
+
this.typeRef(type.ofType, objectRender);
|
|
207
|
+
if (!(type.ofType instanceof GraphQLNonNull)) this.text(" | undefined");
|
|
208
|
+
});
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
if (type instanceof GraphQLScalarType) {
|
|
212
|
+
const mapped = this.options.scalarTypeMap?.[type.name] ?? SCALAR_MAP[type.name];
|
|
213
|
+
if (!mapped) throw new Error(`Unknown scalar type ${type.name}`);
|
|
214
|
+
this.text(typeof mapped === "string" ? mapped : mapped.typeName);
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
if (type instanceof GraphQLEnumType || type instanceof GraphQLInputObjectType) {
|
|
218
|
+
this.text(type.name);
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
if (type instanceof GraphQLObjectType || type instanceof GraphQLInterfaceType || type instanceof GraphQLUnionType) {
|
|
222
|
+
this.writeObjectLikeTypeRef(type, objectRender);
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
const neverType = type;
|
|
226
|
+
throw new Error(`Unsupported GraphQL type ${neverType.toString()}`);
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Renders a GraphQL type in SDL notation, e.g. `[User!]!`.
|
|
230
|
+
*/
|
|
231
|
+
gqlTypeRef(type) {
|
|
232
|
+
if (type instanceof GraphQLNonNull) {
|
|
233
|
+
this.gqlTypeRef(type.ofType);
|
|
234
|
+
this.text("!");
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
if (type instanceof GraphQLList) {
|
|
238
|
+
this.text("[");
|
|
239
|
+
this.gqlTypeRef(type.ofType);
|
|
240
|
+
this.text("]");
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
if (type instanceof GraphQLUnionType) {
|
|
244
|
+
this.writeUnion(type.getTypes().map((itemType) => itemType.name));
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
this.text(type.name);
|
|
248
|
+
}
|
|
249
|
+
isUnderGlobalDir() {
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
writeNamedTypeImports() {
|
|
253
|
+
const sortedTypes = Array.from(this.importedTypes).sort((a, b) => a.name.localeCompare(b.name));
|
|
254
|
+
for (const importedType of sortedTypes) {
|
|
255
|
+
const behavior = this.importingBehavior(importedType);
|
|
256
|
+
if (behavior === "self") continue;
|
|
257
|
+
const from = this.resolveTypeImportPath(importedType, behavior);
|
|
258
|
+
this.stream.write(`import type {${importedType.name}} from '${from}';\n`);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
writeMappedScalarImports() {
|
|
262
|
+
if (this.importedScalarTypes.size === 0) return;
|
|
263
|
+
const sourcePrefix = this.isUnderGlobalDir() ? "../" : "../../";
|
|
264
|
+
const sortedEntries = Array.from(this.importedScalarTypes.entries()).sort((a, b) => a[0].localeCompare(b[0]));
|
|
265
|
+
for (const [importSource, typeNames] of sortedEntries) this.stream.write(`import type { ${Array.from(typeNames).sort().join(", ")} } from '${sourcePrefix}${importSource}';\n`);
|
|
266
|
+
}
|
|
267
|
+
typeApplication(typeName, renderTypeArg) {
|
|
268
|
+
this.text(`${typeName}<`);
|
|
269
|
+
renderTypeArg();
|
|
270
|
+
this.text(">");
|
|
271
|
+
}
|
|
272
|
+
resolveTypeImportPath(importedType, behavior) {
|
|
273
|
+
if (behavior === "same_dir") return ".";
|
|
274
|
+
const subDir = this.typeSubDir(importedType);
|
|
275
|
+
return this.isUnderGlobalDir() ? `./${subDir}` : `../${subDir}`;
|
|
276
|
+
}
|
|
277
|
+
typeSubDir(importedType) {
|
|
278
|
+
if (importedType instanceof GraphQLInputObjectType) return "inputs";
|
|
279
|
+
if (importedType instanceof GraphQLEnumType) return "enums";
|
|
280
|
+
return "selections";
|
|
281
|
+
}
|
|
282
|
+
writeObjectLikeTypeRef(type, objectRender) {
|
|
283
|
+
if (typeof objectRender === "string") {
|
|
284
|
+
this.text(objectRender);
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
if (type instanceof GraphQLUnionType) {
|
|
288
|
+
this.writeUnion(type.getTypes().map((itemType) => itemType.name));
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
if (typeof objectRender !== "function") {
|
|
292
|
+
this.text(type.name);
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
this.scope({
|
|
296
|
+
type: "block",
|
|
297
|
+
multiLines: true
|
|
298
|
+
}, () => {
|
|
299
|
+
for (const [fieldName, field] of Object.entries(type.getFields())) {
|
|
300
|
+
if (!objectRender(type, field)) continue;
|
|
301
|
+
this.separator(", ");
|
|
302
|
+
this.text("readonly ");
|
|
303
|
+
this.text(fieldName);
|
|
304
|
+
this.text(": ");
|
|
305
|
+
this.typeRef(field.type, objectRender);
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
get hasAnyImports() {
|
|
310
|
+
return this.importStatements.size !== 0 || this.importedTypes.size !== 0 || this.importedScalarTypes.size !== 0;
|
|
311
|
+
}
|
|
312
|
+
writeUnion(members) {
|
|
313
|
+
this.enter("blank");
|
|
314
|
+
for (const member of members) {
|
|
315
|
+
this.separator(" | ");
|
|
316
|
+
this.text(member);
|
|
317
|
+
}
|
|
318
|
+
this.leave();
|
|
319
|
+
}
|
|
320
|
+
flushIndent() {
|
|
321
|
+
for (const scope of this.scopes) if (scope.multiLines) this.stream.write(this.indent);
|
|
322
|
+
}
|
|
323
|
+
get currentScope() {
|
|
324
|
+
return this.scopes.at(-1) ?? GLOBAL_SCOPE;
|
|
325
|
+
}
|
|
326
|
+
};
|
|
327
|
+
function unwrapType(type) {
|
|
328
|
+
if (type instanceof GraphQLNonNull || type instanceof GraphQLList) return unwrapType(type.ofType);
|
|
329
|
+
return type;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
//#endregion
|
|
333
|
+
//#region src/codegen/imports.ts
|
|
334
|
+
/**
|
|
335
|
+
* Shared import collector for codegen writers.
|
|
336
|
+
*
|
|
337
|
+
* Responsibilities:
|
|
338
|
+
* - normalize imports by source
|
|
339
|
+
* - deduplicate symbols
|
|
340
|
+
* - keep emitted import statements stable (sorted)
|
|
341
|
+
*/
|
|
342
|
+
var JSImportCollector = class {
|
|
343
|
+
typeBySource = /* @__PURE__ */ new Map();
|
|
344
|
+
valueBySource = /* @__PURE__ */ new Map();
|
|
345
|
+
sideEffects = /* @__PURE__ */ new Set();
|
|
346
|
+
constructor(sink, sourceMap) {
|
|
347
|
+
this.sink = sink;
|
|
348
|
+
this.sourceMap = sourceMap;
|
|
349
|
+
}
|
|
350
|
+
useMapped(symbol) {
|
|
351
|
+
const spec = this.sourceMap[symbol];
|
|
352
|
+
if (spec.kind === "type") this.useType(spec.source, symbol);
|
|
353
|
+
else this.useValue(spec.source, symbol);
|
|
354
|
+
}
|
|
355
|
+
useType(source, symbol) {
|
|
356
|
+
this.collect(this.typeBySource, source, symbol);
|
|
357
|
+
}
|
|
358
|
+
useValue(source, symbol) {
|
|
359
|
+
this.collect(this.valueBySource, source, symbol);
|
|
360
|
+
}
|
|
361
|
+
useSideEffect(source) {
|
|
362
|
+
this.sideEffects.add(source);
|
|
363
|
+
}
|
|
364
|
+
emit() {
|
|
365
|
+
for (const [source, symbols] of this.sorted(this.typeBySource)) this.sink(`import type { ${Array.from(symbols).sort().join(", ")} } from '${source}';`);
|
|
366
|
+
for (const [source, symbols] of this.sorted(this.valueBySource)) this.sink(`import { ${Array.from(symbols).sort().join(", ")} } from '${source}';`);
|
|
367
|
+
for (const source of Array.from(this.sideEffects).sort()) this.sink(`import '${source}';`);
|
|
368
|
+
}
|
|
369
|
+
collect(map, source, symbol) {
|
|
370
|
+
const set = map.get(source) ?? /* @__PURE__ */ new Set();
|
|
371
|
+
set.add(symbol);
|
|
372
|
+
map.set(source, set);
|
|
373
|
+
}
|
|
374
|
+
sorted(map) {
|
|
375
|
+
return Array.from(map.entries()).sort((a, b) => a[0].localeCompare(b[0]));
|
|
376
|
+
}
|
|
377
|
+
};
|
|
378
|
+
const RUNTIME_ENTRY_SOURCE = "../../dist/index.mjs";
|
|
379
|
+
const TYPE_HIERARCHY_SOURCE = "../type-hierarchy";
|
|
380
|
+
const ENUM_INPUT_METADATA_SOURCE = "../enum-input-metadata";
|
|
381
|
+
const CODEGEN_IMPORT_SOURCE_MAP = {
|
|
382
|
+
AcceptableVariables: {
|
|
383
|
+
source: RUNTIME_ENTRY_SOURCE,
|
|
384
|
+
kind: "type"
|
|
385
|
+
},
|
|
386
|
+
UnresolvedVariables: {
|
|
387
|
+
source: RUNTIME_ENTRY_SOURCE,
|
|
388
|
+
kind: "type"
|
|
389
|
+
},
|
|
390
|
+
DirectiveArgs: {
|
|
391
|
+
source: RUNTIME_ENTRY_SOURCE,
|
|
392
|
+
kind: "type"
|
|
393
|
+
},
|
|
394
|
+
Selection: {
|
|
395
|
+
source: RUNTIME_ENTRY_SOURCE,
|
|
396
|
+
kind: "type"
|
|
397
|
+
},
|
|
398
|
+
ValueOrThunk: {
|
|
399
|
+
source: RUNTIME_ENTRY_SOURCE,
|
|
400
|
+
kind: "type"
|
|
401
|
+
},
|
|
402
|
+
FragmentSpread: {
|
|
403
|
+
source: RUNTIME_ENTRY_SOURCE,
|
|
404
|
+
kind: "type"
|
|
405
|
+
},
|
|
406
|
+
createSelection: {
|
|
407
|
+
source: RUNTIME_ENTRY_SOURCE,
|
|
408
|
+
kind: "value"
|
|
409
|
+
},
|
|
410
|
+
withOperationName: {
|
|
411
|
+
source: RUNTIME_ENTRY_SOURCE,
|
|
412
|
+
kind: "value"
|
|
413
|
+
},
|
|
414
|
+
createSchemaType: {
|
|
415
|
+
source: RUNTIME_ENTRY_SOURCE,
|
|
416
|
+
kind: "value"
|
|
417
|
+
},
|
|
418
|
+
registerSchemaTypeFactory: {
|
|
419
|
+
source: RUNTIME_ENTRY_SOURCE,
|
|
420
|
+
kind: "value"
|
|
421
|
+
},
|
|
422
|
+
resolveRegisteredSchemaType: {
|
|
423
|
+
source: RUNTIME_ENTRY_SOURCE,
|
|
424
|
+
kind: "value"
|
|
425
|
+
},
|
|
426
|
+
ENUM_INPUT_METADATA: {
|
|
427
|
+
source: ENUM_INPUT_METADATA_SOURCE,
|
|
428
|
+
kind: "value"
|
|
429
|
+
},
|
|
430
|
+
WithTypeName: {
|
|
431
|
+
source: TYPE_HIERARCHY_SOURCE,
|
|
432
|
+
kind: "type"
|
|
433
|
+
},
|
|
434
|
+
ImplementationType: {
|
|
435
|
+
source: TYPE_HIERARCHY_SOURCE,
|
|
436
|
+
kind: "type"
|
|
437
|
+
},
|
|
438
|
+
EnumInputMetadataBuilder: {
|
|
439
|
+
source: "../dist/index.mjs",
|
|
440
|
+
kind: "value"
|
|
441
|
+
}
|
|
442
|
+
};
|
|
443
|
+
|
|
444
|
+
//#endregion
|
|
445
|
+
//#region src/codegen/writers/selection.ts
|
|
446
|
+
var SelectionWriter = class extends Writer {
|
|
447
|
+
selectionTypeName;
|
|
448
|
+
defaultSelectionProps;
|
|
449
|
+
emptySelectionName;
|
|
450
|
+
defaultSelectionName;
|
|
451
|
+
fieldMap;
|
|
452
|
+
fieldArgsMap;
|
|
453
|
+
fieldCategoryMap;
|
|
454
|
+
hasArgs;
|
|
455
|
+
_declaredFieldNames;
|
|
456
|
+
constructor(modelType, ctx, stream, options) {
|
|
457
|
+
super(stream, options);
|
|
458
|
+
this.modelType = modelType;
|
|
459
|
+
this.ctx = ctx;
|
|
460
|
+
this.selectionTypeName = `${this.modelType.name}${options.selectionSuffix ?? "Selection"}`;
|
|
461
|
+
this.fieldMap = this.resolveFieldMap(modelType, options);
|
|
462
|
+
const analysis = this.analyzeFields(this.fieldMap, modelType, options);
|
|
463
|
+
this.defaultSelectionProps = analysis.defaultSelectionProps;
|
|
464
|
+
this.fieldArgsMap = analysis.fieldArgsMap;
|
|
465
|
+
this.fieldCategoryMap = analysis.fieldCategoryMap;
|
|
466
|
+
this.hasArgs = analysis.hasArgs;
|
|
467
|
+
if (isOperationRootTypeName(this.modelType.name)) {
|
|
468
|
+
const prefix = instancePrefix(this.modelType.name);
|
|
469
|
+
this.emptySelectionName = `${prefix}$`;
|
|
470
|
+
this.defaultSelectionName = this.defaultSelectionProps.length !== 0 ? `${prefix}$$` : void 0;
|
|
471
|
+
} else {
|
|
472
|
+
this.emptySelectionName = void 0;
|
|
473
|
+
this.defaultSelectionName = void 0;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
resolveFieldMap(modelType, options) {
|
|
477
|
+
if (modelType instanceof GraphQLUnionType) return this.sharedUnionFields(modelType);
|
|
478
|
+
if (options.excludedTypes === void 0) return modelType.getFields();
|
|
479
|
+
const filteredFieldMap = {};
|
|
480
|
+
for (const [fieldName, field] of Object.entries(modelType.getFields())) {
|
|
481
|
+
const targetTypeName = targetTypeOf(field.type)?.name;
|
|
482
|
+
if (!isExcludedTypeName(options, targetTypeName)) filteredFieldMap[fieldName] = field;
|
|
483
|
+
}
|
|
484
|
+
return filteredFieldMap;
|
|
485
|
+
}
|
|
486
|
+
sharedUnionFields(unionType) {
|
|
487
|
+
const memberTypes = unionType.getTypes();
|
|
488
|
+
const memberCount = memberTypes.length;
|
|
489
|
+
if (memberCount === 0) return {};
|
|
490
|
+
const fieldCounts = /* @__PURE__ */ new Map();
|
|
491
|
+
for (const type of memberTypes) for (const fieldName of Object.keys(type.getFields())) fieldCounts.set(fieldName, (fieldCounts.get(fieldName) ?? 0) + 1);
|
|
492
|
+
const shared = {};
|
|
493
|
+
for (const [fieldName, field] of Object.entries(memberTypes[0].getFields())) if (fieldCounts.get(fieldName) === memberCount) shared[fieldName] = field;
|
|
494
|
+
return shared;
|
|
495
|
+
}
|
|
496
|
+
analyzeFields(fieldMap, modelType, options) {
|
|
497
|
+
const defaultSelectionProps = [];
|
|
498
|
+
const fieldArgsMap = /* @__PURE__ */ new Map();
|
|
499
|
+
const fieldCategoryMap = /* @__PURE__ */ new Map();
|
|
500
|
+
let hasArgs = false;
|
|
501
|
+
for (const [fieldName, field] of Object.entries(fieldMap)) {
|
|
502
|
+
if (this.isDefaultSelectionField(fieldName, field, modelType, options)) defaultSelectionProps.push(fieldName);
|
|
503
|
+
if (field.args.length !== 0) {
|
|
504
|
+
hasArgs = true;
|
|
505
|
+
fieldArgsMap.set(fieldName, [...field.args]);
|
|
506
|
+
}
|
|
507
|
+
const category = this.fieldCategory(field);
|
|
508
|
+
if (category !== void 0) fieldCategoryMap.set(fieldName, category);
|
|
509
|
+
}
|
|
510
|
+
return {
|
|
511
|
+
defaultSelectionProps,
|
|
512
|
+
fieldArgsMap,
|
|
513
|
+
fieldCategoryMap,
|
|
514
|
+
hasArgs
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
isDefaultSelectionField(fieldName, field, modelType, options) {
|
|
518
|
+
if (isOperationRootTypeName(this.modelType.name)) return false;
|
|
519
|
+
if (targetTypeOf(field.type) !== void 0) return false;
|
|
520
|
+
if (field.args.length !== 0) return false;
|
|
521
|
+
if (field.deprecationReason) return false;
|
|
522
|
+
return !(options.defaultSelectionExcludeMap?.[modelType.name])?.includes(fieldName);
|
|
523
|
+
}
|
|
524
|
+
fieldCategory(field) {
|
|
525
|
+
const fieldCoreType = field.type instanceof GraphQLNonNull ? field.type.ofType : field.type;
|
|
526
|
+
if (this.ctx.embeddedTypes.has(fieldCoreType)) return "SCALAR";
|
|
527
|
+
if (fieldCoreType instanceof GraphQLList) {
|
|
528
|
+
const elementType = fieldCoreType.ofType instanceof GraphQLNonNull ? fieldCoreType.ofType.ofType : fieldCoreType.ofType;
|
|
529
|
+
if (elementType instanceof GraphQLObjectType || elementType instanceof GraphQLInterfaceType || elementType instanceof GraphQLUnionType) return "LIST";
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
if (fieldCoreType instanceof GraphQLObjectType || fieldCoreType instanceof GraphQLInterfaceType || fieldCoreType instanceof GraphQLUnionType) return "REFERENCE";
|
|
533
|
+
if (this.ctx.idFieldMap.get(this.modelType) === field) return "ID";
|
|
534
|
+
return "SCALAR";
|
|
535
|
+
}
|
|
536
|
+
prepareImports() {
|
|
537
|
+
const imports = new JSImportCollector((stmt) => this.importStatement(stmt), CODEGEN_IMPORT_SOURCE_MAP);
|
|
538
|
+
imports.useMapped("DirectiveArgs");
|
|
539
|
+
imports.useMapped("Selection");
|
|
540
|
+
if (this.hasArgs) {
|
|
541
|
+
imports.useMapped("AcceptableVariables");
|
|
542
|
+
imports.useMapped("UnresolvedVariables");
|
|
543
|
+
}
|
|
544
|
+
imports.useMapped("createSchemaType");
|
|
545
|
+
imports.useMapped("registerSchemaTypeFactory");
|
|
546
|
+
const superTypesForResolve = this.ctx.typeHierarchy.upcastTypeMap.get(this.modelType);
|
|
547
|
+
if (isOperationRootTypeName(this.modelType.name) || superTypesForResolve?.size) imports.useMapped("resolveRegisteredSchemaType");
|
|
548
|
+
if (isOperationRootTypeName(this.modelType.name)) {
|
|
549
|
+
imports.useMapped("createSelection");
|
|
550
|
+
imports.useMapped("ENUM_INPUT_METADATA");
|
|
551
|
+
imports.useMapped("withOperationName");
|
|
552
|
+
}
|
|
553
|
+
if (!isOperationRootTypeName(this.modelType.name)) {
|
|
554
|
+
imports.useMapped("WithTypeName");
|
|
555
|
+
imports.useMapped("ImplementationType");
|
|
556
|
+
imports.useMapped("ValueOrThunk");
|
|
557
|
+
imports.useMapped("FragmentSpread");
|
|
558
|
+
}
|
|
559
|
+
for (const field of Object.values(this.fieldMap)) this.importFieldTypes(field);
|
|
560
|
+
const importedConcreteSelectionNames = /* @__PURE__ */ new Set();
|
|
561
|
+
const importedConcreteSelectionModules = /* @__PURE__ */ new Set();
|
|
562
|
+
for (const field of Object.values(this.fieldMap)) {
|
|
563
|
+
const targetType = targetTypeOf(field.type);
|
|
564
|
+
if (targetType === void 0 || targetType === this.modelType) continue;
|
|
565
|
+
const selectionTypeName = this.selectionTypeNameForType(targetType);
|
|
566
|
+
const selectionModule = `./${toKebabCase(selectionTypeName)}`;
|
|
567
|
+
if (importedConcreteSelectionNames.has(selectionTypeName)) {
|
|
568
|
+
if (!importedConcreteSelectionModules.has(selectionModule)) {
|
|
569
|
+
importedConcreteSelectionModules.add(selectionModule);
|
|
570
|
+
imports.useSideEffect(selectionModule);
|
|
571
|
+
}
|
|
572
|
+
continue;
|
|
573
|
+
}
|
|
574
|
+
importedConcreteSelectionNames.add(selectionTypeName);
|
|
575
|
+
imports.useType(selectionModule, selectionTypeName);
|
|
576
|
+
importedConcreteSelectionModules.add(selectionModule);
|
|
577
|
+
imports.useSideEffect(selectionModule);
|
|
578
|
+
}
|
|
579
|
+
const upcastTypes = this.ctx.typeHierarchy.upcastTypeMap.get(this.modelType);
|
|
580
|
+
if (upcastTypes !== void 0) for (const upcastType of upcastTypes) {
|
|
581
|
+
const selectionTypeName = `${upcastType.name}${this.options.selectionSuffix ?? "Selection"}`;
|
|
582
|
+
const importedNames = this.importedNamesForSuperType(upcastType);
|
|
583
|
+
if (importedNames.length === 0) continue;
|
|
584
|
+
const importSource = `./${toKebabCase(selectionTypeName)}`;
|
|
585
|
+
for (const importedName of importedNames) imports.useValue(importSource, importedName);
|
|
586
|
+
}
|
|
587
|
+
imports.emit();
|
|
588
|
+
}
|
|
589
|
+
importedNamesForSuperType(superType) {
|
|
590
|
+
if (isOperationRootTypeName(superType.name)) return [`${instancePrefix(superType.name)}$`];
|
|
591
|
+
return [];
|
|
592
|
+
}
|
|
593
|
+
importingBehavior(type) {
|
|
594
|
+
if (type === this.modelType) return "self";
|
|
595
|
+
if (type instanceof GraphQLObjectType || type instanceof GraphQLInterfaceType) return "same_dir";
|
|
596
|
+
return "other_dir";
|
|
597
|
+
}
|
|
598
|
+
writeCode() {
|
|
599
|
+
this.text(COMMENT$1);
|
|
600
|
+
this.writeSelectionInterface();
|
|
601
|
+
this.writeInstances();
|
|
602
|
+
this.writeArgsInterface();
|
|
603
|
+
}
|
|
604
|
+
writeSelectionInterface() {
|
|
605
|
+
this.writeSelectionInterfaceHeader();
|
|
606
|
+
this.scope({
|
|
607
|
+
type: "block",
|
|
608
|
+
multiLines: true,
|
|
609
|
+
suffix: "\n"
|
|
610
|
+
}, () => {
|
|
611
|
+
this.writeSelectionInterfaceBody();
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
writeSelectionInterfaceHeader() {
|
|
615
|
+
const superSelection = this.superSelectionTypeName(this.modelType);
|
|
616
|
+
this.text(`export interface ${this.selectionTypeName}<T extends object = {}, TVariables extends object = {}, TLastField extends string = never> extends ${superSelection}<'${this.modelType.name}', T, TVariables> `);
|
|
617
|
+
}
|
|
618
|
+
writeSelectionInterfaceBody() {
|
|
619
|
+
this.writeFragmentMethods();
|
|
620
|
+
this.writeDirectiveBuiltins();
|
|
621
|
+
this.write$omit();
|
|
622
|
+
this.write$alias();
|
|
623
|
+
this.writeTypeName();
|
|
624
|
+
const fields = Object.values(this.fieldMap);
|
|
625
|
+
for (const field of fields) {
|
|
626
|
+
this.text("\n");
|
|
627
|
+
this.writePositiveProp(field);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
writeFragmentMethods() {
|
|
631
|
+
if (isOperationRootTypeName(this.modelType.name)) return;
|
|
632
|
+
const t = this.text.bind(this);
|
|
633
|
+
const modelName = this.modelType.name;
|
|
634
|
+
const selectionSuperType = this.superSelectionTypeName(this.modelType);
|
|
635
|
+
const fragmentTypeName = `ImplementationType<'${modelName}'>`;
|
|
636
|
+
const resultDataType = `XName extends '${modelName}' ?\nT & X :\nWithTypeName<T, ${fragmentTypeName}> & (WithTypeName<X, ImplementationType<XName>> | {__typename: Exclude<${fragmentTypeName}, ImplementationType<XName>>})`;
|
|
637
|
+
t("\n$on<X extends object, XVariables extends object>");
|
|
638
|
+
this.scope({
|
|
639
|
+
type: "parameters",
|
|
640
|
+
multiLines: true
|
|
641
|
+
}, () => {
|
|
642
|
+
t(`builder: (it: ${selectionSuperType}<'${modelName}', {}, {}>) => ${selectionSuperType}<'${modelName}', X, XVariables>`);
|
|
643
|
+
});
|
|
644
|
+
t(`: ${this.selectionTypeName}`);
|
|
645
|
+
this.scope({
|
|
646
|
+
type: "generic",
|
|
647
|
+
multiLines: true
|
|
648
|
+
}, () => {
|
|
649
|
+
t("T & X");
|
|
650
|
+
this.separator(", ");
|
|
651
|
+
t("TVariables & XVariables");
|
|
652
|
+
});
|
|
653
|
+
t(";\n");
|
|
654
|
+
t(`\n$on<XName extends ${fragmentTypeName}, X extends object, XVariables extends object>`);
|
|
655
|
+
this.scope({
|
|
656
|
+
type: "parameters",
|
|
657
|
+
multiLines: true
|
|
658
|
+
}, () => {
|
|
659
|
+
t("typeName: XName");
|
|
660
|
+
this.separator(", ");
|
|
661
|
+
t(`builder: (it: ${selectionSuperType}<XName, {}, {}>) => ${selectionSuperType}<XName, X, XVariables>`);
|
|
662
|
+
});
|
|
663
|
+
t(`: ${this.selectionTypeName}`);
|
|
664
|
+
this.scope({
|
|
665
|
+
type: "generic",
|
|
666
|
+
multiLines: true
|
|
667
|
+
}, () => {
|
|
668
|
+
t(resultDataType);
|
|
669
|
+
this.separator(", ");
|
|
670
|
+
t("TVariables & XVariables");
|
|
671
|
+
});
|
|
672
|
+
t(";\n");
|
|
673
|
+
t(`\n$use<XName extends ${fragmentTypeName}, X extends object, XVariables extends object>`);
|
|
674
|
+
this.scope({
|
|
675
|
+
type: "parameters",
|
|
676
|
+
multiLines: true
|
|
677
|
+
}, () => {
|
|
678
|
+
t("fragment: ValueOrThunk<FragmentSpread<string, XName, X, XVariables>>");
|
|
679
|
+
});
|
|
680
|
+
t(`: ${this.selectionTypeName}`);
|
|
681
|
+
this.scope({
|
|
682
|
+
type: "generic",
|
|
683
|
+
multiLines: true
|
|
684
|
+
}, () => {
|
|
685
|
+
t(resultDataType);
|
|
686
|
+
this.separator(", ");
|
|
687
|
+
t("TVariables & XVariables");
|
|
688
|
+
});
|
|
689
|
+
t(";\n");
|
|
690
|
+
}
|
|
691
|
+
writeDirectiveBuiltins() {
|
|
692
|
+
const t = this.text.bind(this);
|
|
693
|
+
t("\n\n$directive(name: string, args?: DirectiveArgs): ");
|
|
694
|
+
this.writeFieldAwareSelectionReturnType();
|
|
695
|
+
t(";\n");
|
|
696
|
+
t("\n$include(condition: unknown): ");
|
|
697
|
+
this.writeFieldAwareSelectionReturnType();
|
|
698
|
+
t(";\n");
|
|
699
|
+
t("\n$skip(condition: unknown): ");
|
|
700
|
+
this.writeFieldAwareSelectionReturnType();
|
|
701
|
+
t(";\n");
|
|
702
|
+
}
|
|
703
|
+
writeFieldAwareSelectionReturnType() {
|
|
704
|
+
const t = this.text.bind(this);
|
|
705
|
+
t(this.selectionTypeName);
|
|
706
|
+
this.scope({
|
|
707
|
+
type: "generic",
|
|
708
|
+
multiLines: true
|
|
709
|
+
}, () => {
|
|
710
|
+
t("TLastField extends keyof T ? Omit<T, TLastField> & {readonly [key in TLastField]?: T[key]} : T");
|
|
711
|
+
this.separator(", ");
|
|
712
|
+
t("TVariables");
|
|
713
|
+
this.separator(", ");
|
|
714
|
+
t("TLastField");
|
|
715
|
+
});
|
|
716
|
+
}
|
|
717
|
+
writeTypeName() {
|
|
718
|
+
if (!isOperationRootTypeName(this.modelType.name)) {
|
|
719
|
+
const t = this.text.bind(this);
|
|
720
|
+
t("\n\n");
|
|
721
|
+
t("readonly __typename: ");
|
|
722
|
+
t(this.selectionTypeName);
|
|
723
|
+
t("<T & {__typename: ImplementationType<'");
|
|
724
|
+
t(this.modelType.name);
|
|
725
|
+
t("'>}, TVariables>;\n");
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
writePositiveProp(field) {
|
|
729
|
+
const targetType = targetTypeOf(field.type);
|
|
730
|
+
if (targetType !== void 0) this.writeAssociationProp(field, targetType);
|
|
731
|
+
else {
|
|
732
|
+
this.writePositivePropImpl(field, "SIMPLEST");
|
|
733
|
+
this.writePositivePropImpl(field, "WITH_ARGS");
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
writeAssociationProp(field, targetType) {
|
|
737
|
+
if (field.args.length === 0) {
|
|
738
|
+
this.writeAssociationPropImpl(field, targetType, false);
|
|
739
|
+
return;
|
|
740
|
+
}
|
|
741
|
+
this.writeAssociationPropImpl(field, targetType, true);
|
|
742
|
+
this.writeAssociationPropImpl(field, targetType, false);
|
|
743
|
+
}
|
|
744
|
+
writeAssociationPropImpl(field, targetType, withArgs) {
|
|
745
|
+
const t = this.text.bind(this);
|
|
746
|
+
const nonNull = field.type instanceof GraphQLNonNull;
|
|
747
|
+
const isPlural = field.type instanceof GraphQLNonNull ? field.type.ofType instanceof GraphQLList : field.type instanceof GraphQLList;
|
|
748
|
+
const childSelectionType = this.selectionTypeNameForType(targetType);
|
|
749
|
+
t("\n");
|
|
750
|
+
this.writeFieldDocComment(field);
|
|
751
|
+
t(field.name);
|
|
752
|
+
this.scope({
|
|
753
|
+
type: "generic",
|
|
754
|
+
multiLines: true
|
|
755
|
+
}, () => {
|
|
756
|
+
if (withArgs) {
|
|
757
|
+
t(`XArgs extends AcceptableVariables<${this.modelType.name}Args['${field.name}']>`);
|
|
758
|
+
this.separator(", ");
|
|
759
|
+
}
|
|
760
|
+
t("X extends object");
|
|
761
|
+
this.separator(", ");
|
|
762
|
+
t("XVariables extends object");
|
|
763
|
+
});
|
|
764
|
+
this.scope({
|
|
765
|
+
type: "parameters",
|
|
766
|
+
multiLines: true
|
|
767
|
+
}, () => {
|
|
768
|
+
if (withArgs) {
|
|
769
|
+
t("args: XArgs");
|
|
770
|
+
this.separator(", ");
|
|
771
|
+
}
|
|
772
|
+
t("selection: ");
|
|
773
|
+
this.scope({
|
|
774
|
+
type: "parameters",
|
|
775
|
+
multiLines: false
|
|
776
|
+
}, () => {
|
|
777
|
+
t(`selection: ${childSelectionType}<{}, {}>`);
|
|
778
|
+
});
|
|
779
|
+
t(` => ${childSelectionType}<X, XVariables>`);
|
|
780
|
+
});
|
|
781
|
+
t(`: ${this.selectionTypeName}`);
|
|
782
|
+
this.scope({
|
|
783
|
+
type: "generic",
|
|
784
|
+
multiLines: true,
|
|
785
|
+
suffix: ";\n"
|
|
786
|
+
}, () => {
|
|
787
|
+
t("T & {");
|
|
788
|
+
if (!this.options.objectEditable) t("readonly ");
|
|
789
|
+
t(`"${field.name}"`);
|
|
790
|
+
if (!nonNull) t("?");
|
|
791
|
+
t(": ");
|
|
792
|
+
if (isPlural) t("ReadonlyArray<X>");
|
|
793
|
+
else t("X");
|
|
794
|
+
t("}");
|
|
795
|
+
this.separator(", ");
|
|
796
|
+
t("TVariables & XVariables");
|
|
797
|
+
if (withArgs) t(` & UnresolvedVariables<XArgs, ${this.modelType.name}Args['${field.name}']>`);
|
|
798
|
+
else if (field.args.length !== 0) t(` & ${this.modelType.name}Args["${field.name}"]`);
|
|
799
|
+
this.separator(", ");
|
|
800
|
+
t(`"${field.name}"`);
|
|
801
|
+
});
|
|
802
|
+
}
|
|
803
|
+
write$omit() {
|
|
804
|
+
const omittableFields = [];
|
|
805
|
+
for (const [fieldName, field] of Object.entries(this.fieldMap)) if (field.args.length === 0 && targetTypeOf(field.type) === void 0) omittableFields.push(fieldName);
|
|
806
|
+
if (omittableFields.length === 0) return;
|
|
807
|
+
const t = this.text.bind(this);
|
|
808
|
+
t("\n\n$omit<XOmit extends ");
|
|
809
|
+
t(omittableFields.map((f) => `"${f}"`).join(" | "));
|
|
810
|
+
t(">");
|
|
811
|
+
this.scope({
|
|
812
|
+
type: "parameters",
|
|
813
|
+
multiLines: false
|
|
814
|
+
}, () => {
|
|
815
|
+
t("...fields: XOmit[]");
|
|
816
|
+
});
|
|
817
|
+
t(": ");
|
|
818
|
+
t(this.selectionTypeName);
|
|
819
|
+
t("<Omit<T, XOmit>, TVariables>;\n");
|
|
820
|
+
}
|
|
821
|
+
write$alias() {
|
|
822
|
+
if (this.getScalarFieldNames().length === 0) return;
|
|
823
|
+
const t = this.text.bind(this);
|
|
824
|
+
t("\n$alias<XAlias extends string>");
|
|
825
|
+
t("(");
|
|
826
|
+
t("alias: XAlias");
|
|
827
|
+
t("): ");
|
|
828
|
+
t(this.selectionTypeName);
|
|
829
|
+
t("<TLastField extends keyof T ? Omit<T, TLastField> & {readonly [key in XAlias]: T[TLastField]} : T, TVariables>;\n");
|
|
830
|
+
}
|
|
831
|
+
getScalarFieldNames() {
|
|
832
|
+
const fields = [];
|
|
833
|
+
for (const [fieldName, field] of Object.entries(this.fieldMap)) if (field.args.length === 0 && targetTypeOf(field.type) === void 0) fields.push(fieldName);
|
|
834
|
+
return fields;
|
|
835
|
+
}
|
|
836
|
+
writePositivePropImpl(field, mode) {
|
|
837
|
+
const withArgs = mode === "WITH_ARGS";
|
|
838
|
+
if (withArgs && field.args.length === 0) return;
|
|
839
|
+
const targetType = targetTypeOf(field.type);
|
|
840
|
+
const renderAsField = field.args.length === 0 && targetType === void 0;
|
|
841
|
+
const nonNull = field.type instanceof GraphQLNonNull;
|
|
842
|
+
const t = this.text.bind(this);
|
|
843
|
+
t("\n");
|
|
844
|
+
this.writeFieldDocComment(field);
|
|
845
|
+
if (renderAsField) {
|
|
846
|
+
t("readonly ");
|
|
847
|
+
t(field.name);
|
|
848
|
+
} else {
|
|
849
|
+
t(field.name);
|
|
850
|
+
if (withArgs || targetType !== void 0) this.scope({
|
|
851
|
+
type: "generic",
|
|
852
|
+
multiLines: true
|
|
853
|
+
}, () => {
|
|
854
|
+
if (withArgs) {
|
|
855
|
+
this.separator(", ");
|
|
856
|
+
t(`XArgs extends AcceptableVariables<${this.modelType.name}Args['${field.name}']>`);
|
|
857
|
+
}
|
|
858
|
+
if (targetType !== void 0) {
|
|
859
|
+
this.separator(", ");
|
|
860
|
+
t("X extends object");
|
|
861
|
+
this.separator(", ");
|
|
862
|
+
t("XVariables extends object");
|
|
863
|
+
}
|
|
864
|
+
});
|
|
865
|
+
this.scope({
|
|
866
|
+
type: "parameters",
|
|
867
|
+
multiLines: true
|
|
868
|
+
}, () => {
|
|
869
|
+
if (withArgs) {
|
|
870
|
+
this.separator(", ");
|
|
871
|
+
t("args: XArgs");
|
|
872
|
+
}
|
|
873
|
+
if (targetType !== void 0) {
|
|
874
|
+
this.separator(", ");
|
|
875
|
+
t("child: ");
|
|
876
|
+
t(this.superSelectionTypeName(targetType));
|
|
877
|
+
t("<'");
|
|
878
|
+
t(targetType.name);
|
|
879
|
+
t("', X, XVariables>");
|
|
880
|
+
}
|
|
881
|
+
});
|
|
882
|
+
}
|
|
883
|
+
t(": ");
|
|
884
|
+
t(this.selectionTypeName);
|
|
885
|
+
this.scope({
|
|
886
|
+
type: "generic",
|
|
887
|
+
multiLines: !renderAsField,
|
|
888
|
+
suffix: ";\n"
|
|
889
|
+
}, () => {
|
|
890
|
+
t("T & ");
|
|
891
|
+
this.writePositivePropChangedDataType(field, false, !nonNull);
|
|
892
|
+
this.separator(", ");
|
|
893
|
+
t("TVariables");
|
|
894
|
+
if (targetType !== void 0) t(" & XVariables");
|
|
895
|
+
if (field.args.length !== 0) if (withArgs) t(` & UnresolvedVariables<XArgs, ${this.modelType.name}Args['${field.name}']>`);
|
|
896
|
+
else t(` & ${this.modelType.name}Args["${field.name}"]`);
|
|
897
|
+
this.separator(", ");
|
|
898
|
+
t(`"${field.name}"`);
|
|
899
|
+
});
|
|
900
|
+
}
|
|
901
|
+
writePositivePropChangedDataType(field, withOptions, nullable) {
|
|
902
|
+
const t = this.text.bind(this);
|
|
903
|
+
t("{");
|
|
904
|
+
if (!this.options.objectEditable) t("readonly ");
|
|
905
|
+
if (withOptions) t(`[key in XAlias]`);
|
|
906
|
+
else t(`"${field.name}"`);
|
|
907
|
+
if (nullable) t("?");
|
|
908
|
+
t(": ");
|
|
909
|
+
this.typeRef(field.type, targetTypeOf(field.type) !== void 0 ? "X" : void 0);
|
|
910
|
+
t("}");
|
|
911
|
+
}
|
|
912
|
+
writeFieldDocComment(field) {
|
|
913
|
+
const description = field.description?.trim();
|
|
914
|
+
const deprecationReason = field.deprecationReason?.trim();
|
|
915
|
+
if (!description && !deprecationReason) return;
|
|
916
|
+
const t = this.text.bind(this);
|
|
917
|
+
t("/**\n");
|
|
918
|
+
if (description) for (const line of this.escapeJsDoc(description).split("\n")) {
|
|
919
|
+
t(" * ");
|
|
920
|
+
t(line);
|
|
921
|
+
t("\n");
|
|
922
|
+
}
|
|
923
|
+
if (deprecationReason) {
|
|
924
|
+
t(" * @deprecated ");
|
|
925
|
+
t(this.escapeJsDoc(deprecationReason));
|
|
926
|
+
t("\n");
|
|
927
|
+
}
|
|
928
|
+
t(" */\n");
|
|
929
|
+
}
|
|
930
|
+
escapeJsDoc(value) {
|
|
931
|
+
return value.replaceAll("*/", "*\\/");
|
|
932
|
+
}
|
|
933
|
+
writeInstances() {
|
|
934
|
+
const t = this.text.bind(this);
|
|
935
|
+
t("\nregisterSchemaTypeFactory(");
|
|
936
|
+
this.str(this.modelType.name);
|
|
937
|
+
t(", () => ");
|
|
938
|
+
this.writeSchemaTypeForModelType();
|
|
939
|
+
t(");\n");
|
|
940
|
+
const emptySelectionName = this.emptySelectionName;
|
|
941
|
+
if (!emptySelectionName) return;
|
|
942
|
+
const itemTypes = this.modelType instanceof GraphQLUnionType ? this.modelType.getTypes() : [];
|
|
943
|
+
t("\nexport function ");
|
|
944
|
+
t(emptySelectionName);
|
|
945
|
+
t("<T extends object = {}, TVariables extends object = {}>(");
|
|
946
|
+
t(`builder: (it: ${this.selectionTypeName}<{}, {}>) => ${this.selectionTypeName}<T, TVariables>`);
|
|
947
|
+
t(", operationName?: string");
|
|
948
|
+
t("): ");
|
|
949
|
+
t(this.selectionTypeName);
|
|
950
|
+
t("<T, TVariables> ");
|
|
951
|
+
this.scope({
|
|
952
|
+
type: "block",
|
|
953
|
+
multiLines: true,
|
|
954
|
+
suffix: "\n"
|
|
955
|
+
}, () => {
|
|
956
|
+
t("const selection = builder(");
|
|
957
|
+
this.scope({
|
|
958
|
+
type: "blank",
|
|
959
|
+
multiLines: true
|
|
960
|
+
}, () => {
|
|
961
|
+
t("createSelection");
|
|
962
|
+
this.scope({
|
|
963
|
+
type: "parameters",
|
|
964
|
+
multiLines: true
|
|
965
|
+
}, () => {
|
|
966
|
+
t(`resolveRegisteredSchemaType("${this.modelType.name}")!`);
|
|
967
|
+
this.separator(", ");
|
|
968
|
+
this.text("ENUM_INPUT_METADATA");
|
|
969
|
+
this.separator(", ");
|
|
970
|
+
if (itemTypes.length === 0) t("undefined");
|
|
971
|
+
else this.scope({
|
|
972
|
+
type: "array",
|
|
973
|
+
multiLines: itemTypes.length >= 2
|
|
974
|
+
}, () => {
|
|
975
|
+
for (const itemType of itemTypes) {
|
|
976
|
+
this.separator(", ");
|
|
977
|
+
this.str(itemType.name);
|
|
978
|
+
}
|
|
979
|
+
});
|
|
980
|
+
});
|
|
981
|
+
});
|
|
982
|
+
t(");\n");
|
|
983
|
+
t("return withOperationName(selection, operationName);\n");
|
|
984
|
+
});
|
|
985
|
+
if (this.defaultSelectionName !== void 0) {
|
|
986
|
+
t("\nexport const ");
|
|
987
|
+
t(this.defaultSelectionName);
|
|
988
|
+
t(" = ");
|
|
989
|
+
this.enter("blank", true);
|
|
990
|
+
t(emptySelectionName);
|
|
991
|
+
this.enter("blank", true);
|
|
992
|
+
for (const propName of this.defaultSelectionProps) {
|
|
993
|
+
t(".");
|
|
994
|
+
t(propName);
|
|
995
|
+
t("\n");
|
|
996
|
+
}
|
|
997
|
+
this.leave();
|
|
998
|
+
this.leave(";\n");
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
writeSchemaTypeForModelType() {
|
|
1002
|
+
const t = this.text.bind(this);
|
|
1003
|
+
t("createSchemaType");
|
|
1004
|
+
this.scope({
|
|
1005
|
+
type: "parameters",
|
|
1006
|
+
multiLines: true
|
|
1007
|
+
}, () => {
|
|
1008
|
+
t(`"${this.modelType.name}"`);
|
|
1009
|
+
this.separator(", ");
|
|
1010
|
+
t(this.schemaTypeCategory(this.modelType));
|
|
1011
|
+
this.separator(", ");
|
|
1012
|
+
this.scope({ type: "array" }, () => {
|
|
1013
|
+
const upcastTypes = this.ctx.typeHierarchy.upcastTypeMap.get(this.modelType);
|
|
1014
|
+
if (upcastTypes !== void 0) for (const upcastType of upcastTypes) {
|
|
1015
|
+
this.separator(", ");
|
|
1016
|
+
t(`resolveRegisteredSchemaType("${upcastType.name}")!`);
|
|
1017
|
+
}
|
|
1018
|
+
});
|
|
1019
|
+
this.separator(", ");
|
|
1020
|
+
this.scope({
|
|
1021
|
+
type: "array",
|
|
1022
|
+
multiLines: true
|
|
1023
|
+
}, () => {
|
|
1024
|
+
for (const fieldName of this.declaredFieldNames) {
|
|
1025
|
+
this.separator(", ");
|
|
1026
|
+
this.writeSchemaFieldDescriptor(this.fieldMap[fieldName]);
|
|
1027
|
+
}
|
|
1028
|
+
});
|
|
1029
|
+
});
|
|
1030
|
+
}
|
|
1031
|
+
writeSchemaFieldDescriptor(field) {
|
|
1032
|
+
const t = this.text.bind(this);
|
|
1033
|
+
const args = this.fieldArgsMap.get(field.name);
|
|
1034
|
+
const category = this.fieldCategoryMap.get(field.name);
|
|
1035
|
+
const targetType = targetTypeOf(field.type);
|
|
1036
|
+
if (args === void 0 && (category === void 0 || category === "SCALAR") && field.type instanceof GraphQLNonNull && targetType === void 0) {
|
|
1037
|
+
t(`"${field.name}"`);
|
|
1038
|
+
return;
|
|
1039
|
+
}
|
|
1040
|
+
this.scope({
|
|
1041
|
+
type: "block",
|
|
1042
|
+
multiLines: true
|
|
1043
|
+
}, () => {
|
|
1044
|
+
t(`category: "${category ?? "SCALAR"}"`);
|
|
1045
|
+
this.separator(", ");
|
|
1046
|
+
t(`name: "${field.name}"`);
|
|
1047
|
+
if (args !== void 0) {
|
|
1048
|
+
this.separator(", ");
|
|
1049
|
+
t("argGraphQLTypeMap: ");
|
|
1050
|
+
this.scope({
|
|
1051
|
+
type: "block",
|
|
1052
|
+
multiLines: args.length > 1
|
|
1053
|
+
}, () => {
|
|
1054
|
+
for (const arg of args) {
|
|
1055
|
+
this.separator(", ");
|
|
1056
|
+
t(arg.name);
|
|
1057
|
+
t(": '");
|
|
1058
|
+
this.gqlTypeRef(arg.type);
|
|
1059
|
+
t("'");
|
|
1060
|
+
}
|
|
1061
|
+
});
|
|
1062
|
+
}
|
|
1063
|
+
if (targetType !== void 0) {
|
|
1064
|
+
this.separator(", ");
|
|
1065
|
+
t(`targetTypeName: "${targetType.name}"`);
|
|
1066
|
+
}
|
|
1067
|
+
if (!(field.type instanceof GraphQLNonNull)) {
|
|
1068
|
+
this.separator(", ");
|
|
1069
|
+
t("undefinable: true");
|
|
1070
|
+
}
|
|
1071
|
+
});
|
|
1072
|
+
}
|
|
1073
|
+
schemaTypeCategory(type) {
|
|
1074
|
+
if (this.ctx.embeddedTypes.has(type)) return "\"EMBEDDED\"";
|
|
1075
|
+
return "\"OBJECT\"";
|
|
1076
|
+
}
|
|
1077
|
+
writeArgsInterface() {
|
|
1078
|
+
if (!this.hasArgs) return;
|
|
1079
|
+
const t = this.text.bind(this);
|
|
1080
|
+
t(`\nexport interface ${this.modelType.name}Args `);
|
|
1081
|
+
this.scope({
|
|
1082
|
+
type: "block",
|
|
1083
|
+
multiLines: true,
|
|
1084
|
+
suffix: "\n"
|
|
1085
|
+
}, () => {
|
|
1086
|
+
for (const field of Object.values(this.fieldMap)) if (field.args.length !== 0) {
|
|
1087
|
+
this.separator(", ");
|
|
1088
|
+
t(`\nreadonly ${field.name}: `);
|
|
1089
|
+
this.scope({
|
|
1090
|
+
type: "block",
|
|
1091
|
+
multiLines: true
|
|
1092
|
+
}, () => {
|
|
1093
|
+
for (const arg of field.args) {
|
|
1094
|
+
this.separator(", ");
|
|
1095
|
+
t("readonly ");
|
|
1096
|
+
t(arg.name);
|
|
1097
|
+
if (!(arg.type instanceof GraphQLNonNull)) t("?");
|
|
1098
|
+
t(": ");
|
|
1099
|
+
this.typeRef(arg.type);
|
|
1100
|
+
}
|
|
1101
|
+
});
|
|
1102
|
+
}
|
|
1103
|
+
});
|
|
1104
|
+
}
|
|
1105
|
+
get declaredFieldNames() {
|
|
1106
|
+
let set = this._declaredFieldNames;
|
|
1107
|
+
if (set === void 0) this._declaredFieldNames = set = this.getDeclaredFieldNames();
|
|
1108
|
+
return set;
|
|
1109
|
+
}
|
|
1110
|
+
getDeclaredFieldNames() {
|
|
1111
|
+
const fields = /* @__PURE__ */ new Set();
|
|
1112
|
+
if (this.modelType instanceof GraphQLObjectType || this.modelType instanceof GraphQLInterfaceType) {
|
|
1113
|
+
for (const field of Object.values(this.fieldMap)) fields.add(field.name);
|
|
1114
|
+
this.removeSuperFieldNames(fields, this.ctx.typeHierarchy.upcastTypeMap.get(this.modelType));
|
|
1115
|
+
} else if (this.modelType instanceof GraphQLUnionType) for (const fieldName of Object.keys(this.fieldMap)) fields.add(fieldName);
|
|
1116
|
+
return fields;
|
|
1117
|
+
}
|
|
1118
|
+
removeSuperFieldNames(fields, superTypes) {
|
|
1119
|
+
if (superTypes !== void 0) for (const superType of superTypes) {
|
|
1120
|
+
if (superType instanceof GraphQLObjectType || superType instanceof GraphQLInterfaceType) {
|
|
1121
|
+
const superFieldMap = superType.getFields();
|
|
1122
|
+
for (const superFieldName in superFieldMap) fields.delete(superFieldName);
|
|
1123
|
+
}
|
|
1124
|
+
this.removeSuperFieldNames(fields, this.ctx.typeHierarchy.upcastTypeMap.get(superType));
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
superSelectionTypeName(_graphQLType) {
|
|
1128
|
+
return "Selection";
|
|
1129
|
+
}
|
|
1130
|
+
selectionTypeNameForType(graphQLType) {
|
|
1131
|
+
return `${graphQLType.name}${this.options.selectionSuffix ?? "Selection"}`;
|
|
1132
|
+
}
|
|
1133
|
+
};
|
|
1134
|
+
const isOperationRootTypeName = (name) => {
|
|
1135
|
+
return name === "Query" || name === "Mutation" || name === "Subscription";
|
|
1136
|
+
};
|
|
1137
|
+
const COMMENT$1 = `/*
|
|
1138
|
+
* Any instance of this interface is immutable,
|
|
1139
|
+
* all the properties and functions can only be used to create new instances,
|
|
1140
|
+
* they cannot modify the current instance.
|
|
1141
|
+
*
|
|
1142
|
+
* So any instance of this interface is reuseable.
|
|
1143
|
+
*/
|
|
1144
|
+
`;
|
|
1145
|
+
|
|
1146
|
+
//#endregion
|
|
1147
|
+
//#region src/codegen/writers/enum.ts
|
|
1148
|
+
var EnumWriter = class extends Writer {
|
|
1149
|
+
constructor(enumType, stream, options) {
|
|
1150
|
+
super(stream, options);
|
|
1151
|
+
this.enumType = enumType;
|
|
1152
|
+
}
|
|
1153
|
+
writeCode() {
|
|
1154
|
+
const t = this.text.bind(this);
|
|
1155
|
+
const values = this.enumType.getValues();
|
|
1156
|
+
if (this.options.tsEnum === true || this.options.tsEnum === "number" || this.options.tsEnum === "string") {
|
|
1157
|
+
t("export enum ");
|
|
1158
|
+
t(this.enumType.name);
|
|
1159
|
+
this.scope({
|
|
1160
|
+
type: "block",
|
|
1161
|
+
prefix: " ",
|
|
1162
|
+
suffix: "\n",
|
|
1163
|
+
multiLines: values.length > 3
|
|
1164
|
+
}, () => {
|
|
1165
|
+
for (const value of values) {
|
|
1166
|
+
this.separator(", ");
|
|
1167
|
+
if (this.options.tsEnum === "string") {
|
|
1168
|
+
t(value.name);
|
|
1169
|
+
t(" = ");
|
|
1170
|
+
t("'");
|
|
1171
|
+
t(value.name);
|
|
1172
|
+
t("'");
|
|
1173
|
+
} else t(value.name);
|
|
1174
|
+
}
|
|
1175
|
+
});
|
|
1176
|
+
} else {
|
|
1177
|
+
t("export type ");
|
|
1178
|
+
t(this.enumType.name);
|
|
1179
|
+
t(" = ");
|
|
1180
|
+
this.scope({
|
|
1181
|
+
type: "blank",
|
|
1182
|
+
suffix: ";\n",
|
|
1183
|
+
multiLines: values.length > 3
|
|
1184
|
+
}, () => {
|
|
1185
|
+
for (const value of values) {
|
|
1186
|
+
this.separator(" | ");
|
|
1187
|
+
t("'");
|
|
1188
|
+
t(value.name);
|
|
1189
|
+
t("'");
|
|
1190
|
+
}
|
|
1191
|
+
});
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
};
|
|
1195
|
+
|
|
1196
|
+
//#endregion
|
|
1197
|
+
//#region src/codegen/writers/input.ts
|
|
1198
|
+
var InputWriter = class extends Writer {
|
|
1199
|
+
constructor(inputType, stream, options) {
|
|
1200
|
+
super(stream, options);
|
|
1201
|
+
this.inputType = inputType;
|
|
1202
|
+
}
|
|
1203
|
+
prepareImports() {
|
|
1204
|
+
for (const field of Object.values(this.inputType.getFields())) this.importType(field.type);
|
|
1205
|
+
}
|
|
1206
|
+
importingBehavior(type) {
|
|
1207
|
+
if (type === this.inputType) return "self";
|
|
1208
|
+
if (type instanceof GraphQLInputObjectType) return "same_dir";
|
|
1209
|
+
return "other_dir";
|
|
1210
|
+
}
|
|
1211
|
+
writeCode() {
|
|
1212
|
+
this.text(COMMENT);
|
|
1213
|
+
this.text("export type ");
|
|
1214
|
+
this.text(this.inputType.name);
|
|
1215
|
+
this.text(" = ");
|
|
1216
|
+
const fieldMap = this.inputType.getFields();
|
|
1217
|
+
if (this.inputType.isOneOf) {
|
|
1218
|
+
this.writeOneOfType(fieldMap);
|
|
1219
|
+
return;
|
|
1220
|
+
}
|
|
1221
|
+
this.enter("block", true);
|
|
1222
|
+
for (const field of Object.values(fieldMap)) this.writeRegularField(field);
|
|
1223
|
+
this.leave("\n");
|
|
1224
|
+
}
|
|
1225
|
+
writeOneOfType(fieldMap) {
|
|
1226
|
+
const fieldNames = Object.keys(fieldMap);
|
|
1227
|
+
if (fieldNames.length === 0) {
|
|
1228
|
+
this.text("{}\n");
|
|
1229
|
+
return;
|
|
1230
|
+
}
|
|
1231
|
+
fieldNames.forEach((selectedFieldName, idx) => {
|
|
1232
|
+
const selectedField = fieldMap[selectedFieldName];
|
|
1233
|
+
if (idx > 0) this.text(" | ");
|
|
1234
|
+
this.enter("block", true);
|
|
1235
|
+
for (const fieldName of fieldNames) {
|
|
1236
|
+
if (!this.options.objectEditable) this.text("readonly ");
|
|
1237
|
+
const field = fieldMap[fieldName];
|
|
1238
|
+
this.text(field.name);
|
|
1239
|
+
if (fieldName === selectedFieldName) {
|
|
1240
|
+
this.text(": Exclude<");
|
|
1241
|
+
this.typeRef(selectedField.type);
|
|
1242
|
+
this.text(", undefined>;\n");
|
|
1243
|
+
} else this.text("?: never;\n");
|
|
1244
|
+
}
|
|
1245
|
+
this.leave();
|
|
1246
|
+
});
|
|
1247
|
+
this.text("\n");
|
|
1248
|
+
}
|
|
1249
|
+
writeRegularField(field) {
|
|
1250
|
+
if (!this.options.objectEditable) this.text("readonly ");
|
|
1251
|
+
this.text(field.name);
|
|
1252
|
+
if (!(field.type instanceof GraphQLNonNull)) this.text("?");
|
|
1253
|
+
this.text(": ");
|
|
1254
|
+
this.typeRef(field.type);
|
|
1255
|
+
this.text(";\n");
|
|
1256
|
+
}
|
|
1257
|
+
};
|
|
1258
|
+
const COMMENT = `/*
|
|
1259
|
+
* This input type is not interface, because interfaces
|
|
1260
|
+
* do not satisfy the constraint 'SerializableParam' of recoil
|
|
1261
|
+
*/
|
|
1262
|
+
`;
|
|
1263
|
+
|
|
1264
|
+
//#endregion
|
|
1265
|
+
//#region src/codegen/writers/types.ts
|
|
1266
|
+
var TypeHierarchyWriter = class extends Writer {
|
|
1267
|
+
constructor(_schema, typeHierarchy, stream, options) {
|
|
1268
|
+
super(stream, options);
|
|
1269
|
+
this.typeHierarchy = typeHierarchy;
|
|
1270
|
+
}
|
|
1271
|
+
writeCode() {
|
|
1272
|
+
this.writeImplementationType();
|
|
1273
|
+
this.writeCastMethod("up");
|
|
1274
|
+
this.writeCastMethod("down");
|
|
1275
|
+
this.writeWithTypeNameType();
|
|
1276
|
+
}
|
|
1277
|
+
writeWithTypeNameType() {
|
|
1278
|
+
this.text(WITH_TYPE_NAME_DECLARATION);
|
|
1279
|
+
this.text("\n");
|
|
1280
|
+
}
|
|
1281
|
+
writeImplementationType() {
|
|
1282
|
+
const t = this.text.bind(this);
|
|
1283
|
+
const entries = [...this.typeHierarchy.downcastTypeMap.entries()];
|
|
1284
|
+
t(IMPLEMENTATION_TYPE_COMMENT);
|
|
1285
|
+
t("export type ImplementationType<T> = ");
|
|
1286
|
+
this.enter("blank", true);
|
|
1287
|
+
for (const [type, castTypes] of entries) {
|
|
1288
|
+
if (isExcludedTypeName(this.options, type.name)) continue;
|
|
1289
|
+
t(`T extends '${type.name}' ? `);
|
|
1290
|
+
this.enter("blank");
|
|
1291
|
+
if (!(type instanceof GraphQLUnionType)) t(`'${type.name}'`);
|
|
1292
|
+
for (const castType of castTypes) {
|
|
1293
|
+
if (isExcludedTypeName(this.options, castType.name)) continue;
|
|
1294
|
+
this.separator(" | ");
|
|
1295
|
+
t(`ImplementationType<'${castType.name}'>`);
|
|
1296
|
+
}
|
|
1297
|
+
this.leave();
|
|
1298
|
+
t(" :\n");
|
|
1299
|
+
}
|
|
1300
|
+
t("T\n");
|
|
1301
|
+
this.leave();
|
|
1302
|
+
t(";");
|
|
1303
|
+
}
|
|
1304
|
+
writeCastMethod(prefix) {
|
|
1305
|
+
const t = this.text.bind(this);
|
|
1306
|
+
const entries = [...(prefix === "up" ? this.typeHierarchy.upcastTypeMap : this.typeHierarchy.downcastTypeMap).entries()];
|
|
1307
|
+
t(prefix === "up" ? UPCAST_FUNC_COMMENT : DOWNCAST_FUNC_COMMENT);
|
|
1308
|
+
t(`\nexport function ${prefix}castTypes(typeName: string): string[] `);
|
|
1309
|
+
this.scope({
|
|
1310
|
+
type: "block",
|
|
1311
|
+
multiLines: true,
|
|
1312
|
+
suffix: "\n"
|
|
1313
|
+
}, () => {
|
|
1314
|
+
t("const typeNames: string[] = [];\n");
|
|
1315
|
+
t(`${prefix}castTypes0(typeName, typeNames);\n`);
|
|
1316
|
+
t("return typeNames;\n");
|
|
1317
|
+
});
|
|
1318
|
+
t(`\nfunction ${prefix}castTypes0(typeName: string, output: string[]) `);
|
|
1319
|
+
this.scope({
|
|
1320
|
+
type: "block",
|
|
1321
|
+
multiLines: true,
|
|
1322
|
+
suffix: "\n"
|
|
1323
|
+
}, () => {
|
|
1324
|
+
t("switch (typeName)");
|
|
1325
|
+
this.scope({
|
|
1326
|
+
type: "block",
|
|
1327
|
+
multiLines: true,
|
|
1328
|
+
suffix: "\n"
|
|
1329
|
+
}, () => {
|
|
1330
|
+
for (const [type, castTypes] of entries) {
|
|
1331
|
+
if (isExcludedTypeName(this.options, type.name)) continue;
|
|
1332
|
+
t(`case '${type.name}':`);
|
|
1333
|
+
this.scope({
|
|
1334
|
+
type: "blank",
|
|
1335
|
+
multiLines: true
|
|
1336
|
+
}, () => {
|
|
1337
|
+
if (!(type instanceof GraphQLUnionType)) t(`output.push('${type.name}');\n`);
|
|
1338
|
+
for (const castType of castTypes) {
|
|
1339
|
+
if (isExcludedTypeName(this.options, castType.name)) continue;
|
|
1340
|
+
t(`${prefix}castTypes0('${castType.name}', output);\n`);
|
|
1341
|
+
}
|
|
1342
|
+
t("break;\n");
|
|
1343
|
+
});
|
|
1344
|
+
}
|
|
1345
|
+
t("default:");
|
|
1346
|
+
this.scope({
|
|
1347
|
+
type: "blank",
|
|
1348
|
+
multiLines: true
|
|
1349
|
+
}, () => {
|
|
1350
|
+
t(`output.push(typeName);\n`);
|
|
1351
|
+
t("break;\n");
|
|
1352
|
+
});
|
|
1353
|
+
});
|
|
1354
|
+
});
|
|
1355
|
+
}
|
|
1356
|
+
};
|
|
1357
|
+
const IMPLEMENTATION_TYPE_COMMENT = `
|
|
1358
|
+
/**
|
|
1359
|
+
* This 'ImplementationType' is used for type hierarchy resolution.
|
|
1360
|
+
*/
|
|
1361
|
+
`;
|
|
1362
|
+
const UPCAST_FUNC_COMMENT = `
|
|
1363
|
+
/**
|
|
1364
|
+
* This 'upcastTypes' resolves parent types in the type hierarchy.
|
|
1365
|
+
*/
|
|
1366
|
+
`;
|
|
1367
|
+
const DOWNCAST_FUNC_COMMENT = `
|
|
1368
|
+
/**
|
|
1369
|
+
* This 'downcastTypes' resolves child types in the type hierarchy.
|
|
1370
|
+
*/
|
|
1371
|
+
`;
|
|
1372
|
+
const WITH_TYPE_NAME_DECLARATION = `
|
|
1373
|
+
export type WithTypeName<T, TypeName extends string> =
|
|
1374
|
+
T extends {readonly __typename: string} ?
|
|
1375
|
+
T :
|
|
1376
|
+
T & {readonly __typename: TypeName};
|
|
1377
|
+
;
|
|
1378
|
+
`;
|
|
1379
|
+
|
|
1380
|
+
//#endregion
|
|
1381
|
+
//#region src/codegen/type-hierarchy-graph.ts
|
|
1382
|
+
/** Get-or-create a Set in a Map, then add a value to it. */
|
|
1383
|
+
function addToSetMap(map, key, value) {
|
|
1384
|
+
let set = map.get(key);
|
|
1385
|
+
if (!set) {
|
|
1386
|
+
set = /* @__PURE__ */ new Set();
|
|
1387
|
+
map.set(key, set);
|
|
1388
|
+
}
|
|
1389
|
+
set.add(value);
|
|
1390
|
+
}
|
|
1391
|
+
/**
|
|
1392
|
+
* Remove transitive (indirect) entries from the downcast map so that
|
|
1393
|
+
* each parent only lists its *direct* children.
|
|
1394
|
+
*
|
|
1395
|
+
* For example given A → B → C, the entry for A should only contain B,
|
|
1396
|
+
* not C (because C is reachable through B).
|
|
1397
|
+
*/
|
|
1398
|
+
function pruneTransitive(map) {
|
|
1399
|
+
for (const [, children] of map) removeReachable(children, children, map);
|
|
1400
|
+
}
|
|
1401
|
+
function removeReachable(target, current, map) {
|
|
1402
|
+
for (const type of current) {
|
|
1403
|
+
if (target !== current) target.delete(type);
|
|
1404
|
+
const deeper = map.get(type);
|
|
1405
|
+
if (deeper) removeReachable(target, deeper, map);
|
|
1406
|
+
}
|
|
1407
|
+
}
|
|
1408
|
+
/** Invert a parent→children map into a child→parents map. */
|
|
1409
|
+
function invertMap(map) {
|
|
1410
|
+
const inverted = /* @__PURE__ */ new Map();
|
|
1411
|
+
for (const [parent, children] of map) for (const child of children) addToSetMap(inverted, child, parent);
|
|
1412
|
+
return inverted;
|
|
1413
|
+
}
|
|
1414
|
+
var TypeHierarchyGraph = class {
|
|
1415
|
+
/** parent → direct children (interface → implementors, union → members) */
|
|
1416
|
+
downcastTypeMap;
|
|
1417
|
+
/** child → direct parents */
|
|
1418
|
+
upcastTypeMap;
|
|
1419
|
+
constructor(schema) {
|
|
1420
|
+
const downcast = /* @__PURE__ */ new Map();
|
|
1421
|
+
const typeMap = schema.getTypeMap();
|
|
1422
|
+
for (const typeName in typeMap) {
|
|
1423
|
+
if (typeName.startsWith("__")) continue;
|
|
1424
|
+
const type = typeMap[typeName];
|
|
1425
|
+
if (type instanceof GraphQLObjectType || type instanceof GraphQLInterfaceType) for (const iface of type.getInterfaces()) addToSetMap(downcast, iface, type);
|
|
1426
|
+
if (type instanceof GraphQLUnionType) for (const member of type.getTypes()) addToSetMap(downcast, type, member);
|
|
1427
|
+
}
|
|
1428
|
+
pruneTransitive(downcast);
|
|
1429
|
+
this.downcastTypeMap = downcast;
|
|
1430
|
+
this.upcastTypeMap = invertMap(downcast);
|
|
1431
|
+
}
|
|
1432
|
+
/** Walk ancestor types recursively, calling `callback` for each. */
|
|
1433
|
+
visitUpcastTypesRecursively(type, callback) {
|
|
1434
|
+
const parents = this.upcastTypeMap.get(type);
|
|
1435
|
+
if (!parents) return;
|
|
1436
|
+
for (const parent of parents) {
|
|
1437
|
+
callback(parent);
|
|
1438
|
+
this.visitUpcastTypesRecursively(parent, callback);
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
};
|
|
1442
|
+
|
|
1443
|
+
//#endregion
|
|
1444
|
+
//#region src/codegen/writers/enum-input-metadata.ts
|
|
1445
|
+
var EnumInputMetadataWriter = class EnumInputMetadataWriter extends Writer {
|
|
1446
|
+
constructor(schema, stream, options) {
|
|
1447
|
+
super(stream, options);
|
|
1448
|
+
this.schema = schema;
|
|
1449
|
+
}
|
|
1450
|
+
prepareImports() {
|
|
1451
|
+
const imports = new JSImportCollector((stmt) => this.importStatement(stmt), CODEGEN_IMPORT_SOURCE_MAP);
|
|
1452
|
+
imports.useMapped("EnumInputMetadataBuilder");
|
|
1453
|
+
imports.emit();
|
|
1454
|
+
}
|
|
1455
|
+
writeCode() {
|
|
1456
|
+
const processedTypeNames = /* @__PURE__ */ new Set();
|
|
1457
|
+
const enumInputMetaTypeMap = /* @__PURE__ */ new Map();
|
|
1458
|
+
for (const type of Object.values(this.schema.getTypeMap())) {
|
|
1459
|
+
if (!(type instanceof GraphQLEnumType) && !(type instanceof GraphQLInputObjectType)) continue;
|
|
1460
|
+
this.collectEnumMetaTypes(type, processedTypeNames, enumInputMetaTypeMap);
|
|
1461
|
+
}
|
|
1462
|
+
this.text("const builder = new EnumInputMetadataBuilder();\n");
|
|
1463
|
+
for (const [typeName, fields] of enumInputMetaTypeMap) {
|
|
1464
|
+
this.text(`\nbuilder.add("${typeName}"`);
|
|
1465
|
+
if (fields !== void 0) {
|
|
1466
|
+
this.text(", ");
|
|
1467
|
+
this.scope({
|
|
1468
|
+
type: "array",
|
|
1469
|
+
multiLines: true
|
|
1470
|
+
}, () => {
|
|
1471
|
+
for (const field of fields) {
|
|
1472
|
+
this.separator(", ");
|
|
1473
|
+
this.scope({ type: "block" }, () => {
|
|
1474
|
+
this.text(`name: "${field.name}", typeName: "${EnumInputMetadataWriter.inputTypeName(field.type)}", graphqlTypeName: "${EnumInputMetadataWriter.graphqlTypeName(field.type)}"`);
|
|
1475
|
+
if (EnumInputMetadataWriter.isLeafInputType(field.type)) this.text(", isLeaf: true");
|
|
1476
|
+
});
|
|
1477
|
+
}
|
|
1478
|
+
});
|
|
1479
|
+
}
|
|
1480
|
+
this.text(");\n");
|
|
1481
|
+
}
|
|
1482
|
+
this.text("\nexport const ENUM_INPUT_METADATA = builder.build();\n");
|
|
1483
|
+
}
|
|
1484
|
+
collectEnumMetaTypes(type, processedTypeNames, outMap) {
|
|
1485
|
+
if (type instanceof GraphQLScalarType) return false;
|
|
1486
|
+
if (type instanceof GraphQLList || type instanceof GraphQLNonNull) return this.collectEnumMetaTypes(type.ofType, processedTypeNames, outMap);
|
|
1487
|
+
if (type.name.startsWith("__")) return false;
|
|
1488
|
+
if (outMap.has(type.name)) return true;
|
|
1489
|
+
if (processedTypeNames.has(type.name)) return false;
|
|
1490
|
+
if (type instanceof GraphQLEnumType) {
|
|
1491
|
+
outMap.set(type.name, void 0);
|
|
1492
|
+
return true;
|
|
1493
|
+
}
|
|
1494
|
+
processedTypeNames.add(type.name);
|
|
1495
|
+
const fieldMap = type.getFields();
|
|
1496
|
+
const fields = [];
|
|
1497
|
+
for (const field of Object.values(fieldMap)) {
|
|
1498
|
+
this.collectEnumMetaTypes(field.type, processedTypeNames, outMap);
|
|
1499
|
+
fields.push(field);
|
|
1500
|
+
}
|
|
1501
|
+
outMap.set(type.name, fields);
|
|
1502
|
+
return true;
|
|
1503
|
+
}
|
|
1504
|
+
static inputTypeName(type) {
|
|
1505
|
+
if (type instanceof GraphQLList) return EnumInputMetadataWriter.inputTypeName(type.ofType);
|
|
1506
|
+
if (type instanceof GraphQLNonNull) return EnumInputMetadataWriter.inputTypeName(type.ofType);
|
|
1507
|
+
return type.name;
|
|
1508
|
+
}
|
|
1509
|
+
static graphqlTypeName(type) {
|
|
1510
|
+
if (type instanceof GraphQLList) return `[${EnumInputMetadataWriter.graphqlTypeName(type.ofType)}]`;
|
|
1511
|
+
if (type instanceof GraphQLNonNull) return `${EnumInputMetadataWriter.graphqlTypeName(type.ofType)}!`;
|
|
1512
|
+
return type.name;
|
|
1513
|
+
}
|
|
1514
|
+
static isLeafInputType(type) {
|
|
1515
|
+
if (type instanceof GraphQLList || type instanceof GraphQLNonNull) return EnumInputMetadataWriter.isLeafInputType(type.ofType);
|
|
1516
|
+
return type instanceof GraphQLScalarType;
|
|
1517
|
+
}
|
|
1518
|
+
};
|
|
1519
|
+
|
|
1520
|
+
//#endregion
|
|
1521
|
+
//#region \0raw:/Users/ashen/Projects/typedgql/src/codegen/templates/async-runtime.template
|
|
1522
|
+
var async_runtime_default = "import type { Selection } from \"../dist/index.mjs\";\nimport { TextBuilder, runtimeOf } from \"../dist/index.mjs\";\n\nexport type GraphQLExecutor = (\n request: string,\n variables: Record<string, unknown>,\n) => Promise<any>;\n\nexport type GraphQLSubscriber = (\n request: string,\n variables: Record<string, unknown>,\n) => AsyncIterable<any> | Promise<AsyncIterable<any>>;\n\n// Set global fallback executor used by `execute(...)`.\nexport function setGraphQLExecutor(executor: GraphQLExecutor) {\n graphQLExecutor = executor;\n}\n\n// Set global fallback subscriber used by `subscribe(...)`.\nexport function setGraphQLSubscriber(subscriber: GraphQLSubscriber) {\n graphQLSubscriber = subscriber;\n}\nexport type Simplify<T> = SimplifyDepth<T>;\ntype Primitive = string | number | boolean | bigint | symbol | null | undefined;\ntype Dec = [0,0,1,2,3,4,5,6,7,8,9];\nexport type SimplifyDepth<T, D extends number = 5> =\n D extends 0 ? T :\n T extends Primitive | Function ? T :\n T extends readonly (infer U)[] ? readonly SimplifyDepth<U, Dec[D]>[] :\n T extends object ? { [K in keyof T]: SimplifyDepth<T[K], Dec[D]> } & {} :\n T;\n\nexport async function execute<\n TData extends object,\n TVariables extends Record<string, unknown>,\n>(\n selection: Selection<\"Query\" | \"Mutation\", TData, TVariables>,\n options?: {\n readonly operationName?: string;\n readonly variables?: TVariables;\n readonly executor?: GraphQLExecutor;\n },\n): Promise<Simplify<TData>> {\n // Per-call override has priority over the globally registered executor.\n const executor = options?.executor ?? graphQLExecutor;\n if (executor === undefined) {\n throw new Error(\n \"Executor not set. Call 'setGraphQLExecutor' first or pass executor in options.\",\n );\n }\n\n const request = buildRequest(selection, options?.operationName);\n const rawResponse = exceptNullValues(\n await executor(request, options?.variables ?? {}),\n );\n // GraphQL transport errors are surfaced as exceptions.\n if (rawResponse.errors) {\n throw new GraphQLError(rawResponse.errors);\n }\n return rawResponse.data as unknown as Simplify<TData>;\n}\n\nexport async function* subscribe<\n TData extends object,\n TVariables extends Record<string, unknown>,\n>(\n selection: Selection<\"Subscription\", TData, TVariables>,\n options?: {\n readonly operationName?: string;\n readonly variables?: TVariables;\n readonly subscriber?: GraphQLSubscriber;\n },\n): AsyncIterable<Simplify<TData>> {\n // Per-call override has priority over the globally registered subscriber.\n const subscriber = options?.subscriber ?? graphQLSubscriber;\n if (subscriber === undefined) {\n throw new Error(\n \"Subscriber not set. Call 'setGraphQLSubscriber' first or pass subscriber in options.\",\n );\n }\n\n const request = buildRequest(selection, options?.operationName);\n const stream = await subscriber(request, options?.variables ?? {});\n // Stream payloads follow standard GraphQL response shape.\n for await (const payload of stream) {\n const rawResponse = exceptNullValues(payload);\n if (rawResponse.errors) {\n throw new GraphQLError(rawResponse.errors);\n }\n yield rawResponse.data as unknown as Simplify<TData>;\n }\n}\n\nexport interface Response<TData> {\n readonly data?: TData;\n readonly error?: Error;\n}\n\nexport class GraphQLError extends Error {\n readonly errors: readonly GraphQLSubError[];\n\n constructor(errors: any) {\n super();\n this.errors = errors;\n }\n}\n\nexport interface GraphQLSubError {\n readonly message: string;\n readonly path: string[];\n}\n\nlet graphQLExecutor: GraphQLExecutor | undefined = undefined;\nlet graphQLSubscriber: GraphQLSubscriber | undefined = undefined;\n\n// Build GraphQL document from selection tree and inferred variable declarations.\nfunction buildRequest<\n TData extends object,\n TVariables extends Record<string, unknown>,\n>(\n selection: Selection<\"Query\" | \"Mutation\" | \"Subscription\", TData, TVariables>,\n operationName?: string,\n): string {\n const runtime = runtimeOf(selection);\n const writer = new TextBuilder();\n writer.text(`${runtime.schemaType.name.toLowerCase()} ${operationName ?? runtime.operationName ?? \"\"}`);\n if (runtime.variableTypeMap.size !== 0) {\n writer.scope(\n {\n type: \"arguments\",\n multiLines: runtime.variableTypeMap.size > 2,\n suffix: \" \",\n },\n () => {\n for (const [name, type] of runtime.variableTypeMap) {\n writer.separator();\n writer.text(`$${name}: ${type}`);\n }\n },\n );\n }\n writer.text(selection.toString());\n writer.text(selection.toFragmentString());\n return writer.toString();\n}\n\n// Convert all nullable fields to `undefined` for easier TS optional-field ergonomics.\nfunction exceptNullValues<T>(value: T): T {\n if (value == null) return undefined as any;\n if (typeof value !== \"object\") return value;\n if (Array.isArray(value)) {\n return value.map((el) => el == null ? undefined : exceptNullValues(el)) as any;\n }\n const out: any = {};\n for (const k in value) {\n const v = value[k];\n out[k] = v != null ? exceptNullValues(v) : undefined;\n }\n return out;\n}\n";
|
|
1523
|
+
|
|
1524
|
+
//#endregion
|
|
1525
|
+
//#region src/codegen/generator.ts
|
|
1526
|
+
/** Default output directory: node_modules/@ptdgrp/typedgql/__generated */
|
|
1527
|
+
const DEFAULT_TARGET_DIR = resolve(process.cwd(), "node_modules/@ptdgrp/typedgql/__generated");
|
|
1528
|
+
/** Parent package dir: node_modules/@ptdgrp/typedgql */
|
|
1529
|
+
const PACKAGE_DIR = resolve(process.cwd(), "node_modules/@ptdgrp/typedgql");
|
|
1530
|
+
/** Field names reserved by the runtime SelectionNode implementation. */
|
|
1531
|
+
const RESERVED_FIELDS = new Set([
|
|
1532
|
+
"constructor",
|
|
1533
|
+
"addField",
|
|
1534
|
+
"removeField",
|
|
1535
|
+
"addEmbeddable",
|
|
1536
|
+
"addDirective",
|
|
1537
|
+
"fieldMap",
|
|
1538
|
+
"directiveMap",
|
|
1539
|
+
"findField",
|
|
1540
|
+
"findFieldsByName",
|
|
1541
|
+
"findFieldByName",
|
|
1542
|
+
"schemaType",
|
|
1543
|
+
"variableTypeMap",
|
|
1544
|
+
"toString",
|
|
1545
|
+
"toJSON",
|
|
1546
|
+
"toFragmentString"
|
|
1547
|
+
]);
|
|
1548
|
+
var Generator = class {
|
|
1549
|
+
constructor(options) {
|
|
1550
|
+
this.options = options;
|
|
1551
|
+
}
|
|
1552
|
+
/** Resolved output directory (uses default if not configured) */
|
|
1553
|
+
get targetDir() {
|
|
1554
|
+
return this.options.targetDir ?? DEFAULT_TARGET_DIR;
|
|
1555
|
+
}
|
|
1556
|
+
async generate() {
|
|
1557
|
+
const schema = await this.options.schemaLoader();
|
|
1558
|
+
this.validateSchema(schema);
|
|
1559
|
+
await rm(this.targetDir, {
|
|
1560
|
+
recursive: true,
|
|
1561
|
+
force: true
|
|
1562
|
+
});
|
|
1563
|
+
await mkdir(this.targetDir, { recursive: true });
|
|
1564
|
+
const typeHierarchy = new TypeHierarchyGraph(schema);
|
|
1565
|
+
const selectionTypes = [];
|
|
1566
|
+
const inputTypes = [];
|
|
1567
|
+
const enumTypes = [];
|
|
1568
|
+
const typeMap = schema.getTypeMap();
|
|
1569
|
+
for (const typeName in typeMap) {
|
|
1570
|
+
if (typeName.startsWith("__")) continue;
|
|
1571
|
+
const type = typeMap[typeName];
|
|
1572
|
+
if (isExcludedTypeName(this.options, type.name)) continue;
|
|
1573
|
+
if (type instanceof GraphQLObjectType || type instanceof GraphQLInterfaceType || type instanceof GraphQLUnionType) selectionTypes.push(type);
|
|
1574
|
+
else if (type instanceof GraphQLInputObjectType) inputTypes.push(type);
|
|
1575
|
+
else if (type instanceof GraphQLEnumType) enumTypes.push(type);
|
|
1576
|
+
}
|
|
1577
|
+
const configuredIdFieldMap = this.options.idFieldMap ?? {};
|
|
1578
|
+
const entityTypes = /* @__PURE__ */ new Set();
|
|
1579
|
+
const embeddedTypes = /* @__PURE__ */ new Set();
|
|
1580
|
+
const idFieldMap = /* @__PURE__ */ new Map();
|
|
1581
|
+
const triggerableTypes = /* @__PURE__ */ new Set();
|
|
1582
|
+
const typesWithParameterizedField = /* @__PURE__ */ new Set();
|
|
1583
|
+
for (const selectionType of selectionTypes) {
|
|
1584
|
+
if (!(selectionType instanceof GraphQLObjectType) && !(selectionType instanceof GraphQLInterfaceType)) continue;
|
|
1585
|
+
const fieldMap = selectionType.getFields();
|
|
1586
|
+
if (selectionType.name === "Query") {
|
|
1587
|
+
if (Object.keys(fieldMap).length !== 0) triggerableTypes.add(selectionType);
|
|
1588
|
+
} else {
|
|
1589
|
+
let idFieldName = configuredIdFieldMap[selectionType.name];
|
|
1590
|
+
if (idFieldName === void 0) {
|
|
1591
|
+
let configuredUpcastType = void 0;
|
|
1592
|
+
typeHierarchy.visitUpcastTypesRecursively(selectionType, (upcastType) => {
|
|
1593
|
+
const newIdFieldName = configuredIdFieldMap[upcastType.name];
|
|
1594
|
+
if (idFieldName === void 0) {
|
|
1595
|
+
configuredUpcastType = upcastType;
|
|
1596
|
+
idFieldName = newIdFieldName;
|
|
1597
|
+
} else if (idFieldName !== newIdFieldName) throw new Error(`Conflict id property configuration: ${configuredUpcastType.name}.${idFieldName} and ${selectionType.name}.${newIdFieldName}`);
|
|
1598
|
+
});
|
|
1599
|
+
}
|
|
1600
|
+
const idField = fieldMap[idFieldName ?? "id"];
|
|
1601
|
+
if (idField != null) {
|
|
1602
|
+
idFieldMap.set(selectionType, idField);
|
|
1603
|
+
entityTypes.add(selectionType);
|
|
1604
|
+
if (Object.keys(fieldMap).length !== 1) triggerableTypes.add(selectionType);
|
|
1605
|
+
} else embeddedTypes.add(selectionType);
|
|
1606
|
+
}
|
|
1607
|
+
for (const fieldName in fieldMap) if (fieldMap[fieldName].args.length !== 0) {
|
|
1608
|
+
typesWithParameterizedField.add(selectionType);
|
|
1609
|
+
break;
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1612
|
+
const ctx = {
|
|
1613
|
+
schema,
|
|
1614
|
+
typeHierarchy,
|
|
1615
|
+
selectionTypes,
|
|
1616
|
+
entityTypes,
|
|
1617
|
+
embeddedTypes,
|
|
1618
|
+
triggerableTypes,
|
|
1619
|
+
idFieldMap,
|
|
1620
|
+
typesWithParameterizedField
|
|
1621
|
+
};
|
|
1622
|
+
const promises = [];
|
|
1623
|
+
if (selectionTypes.length !== 0) {
|
|
1624
|
+
await mkdir(join(this.targetDir, "selections"), { recursive: true });
|
|
1625
|
+
promises.push(this.generateSelectionTypes(ctx));
|
|
1626
|
+
}
|
|
1627
|
+
if (inputTypes.length !== 0) {
|
|
1628
|
+
await mkdir(join(this.targetDir, "inputs"), { recursive: true });
|
|
1629
|
+
promises.push(this.generateInputTypes(inputTypes));
|
|
1630
|
+
}
|
|
1631
|
+
if (enumTypes.length !== 0) {
|
|
1632
|
+
await mkdir(join(this.targetDir, "enums"), { recursive: true });
|
|
1633
|
+
promises.push(this.generateEnumTypes(enumTypes));
|
|
1634
|
+
}
|
|
1635
|
+
promises.push(this.generateTypeHierarchy(schema, typeHierarchy));
|
|
1636
|
+
promises.push(this.generateEnumInputMetadata(schema));
|
|
1637
|
+
promises.push(this.generateAsyncRuntime());
|
|
1638
|
+
promises.push(this.writeIndex(schema, ctx));
|
|
1639
|
+
await Promise.all(promises);
|
|
1640
|
+
if (this.options.targetDir === void 0) await this.writePackageEntrypoint(schema, ctx);
|
|
1641
|
+
}
|
|
1642
|
+
createSelectionWriter(modelType, ctx, stream, options) {
|
|
1643
|
+
return new SelectionWriter(modelType, ctx, stream, options);
|
|
1644
|
+
}
|
|
1645
|
+
additionalExportedTypeNamesForSelection(_modelType, _ctx) {
|
|
1646
|
+
return [];
|
|
1647
|
+
}
|
|
1648
|
+
async generateSelectionTypes(ctx) {
|
|
1649
|
+
const dir = join(this.targetDir, "selections");
|
|
1650
|
+
const emptySelectionNameMap = /* @__PURE__ */ new Map();
|
|
1651
|
+
const defaultSelectionNameMap = /* @__PURE__ */ new Map();
|
|
1652
|
+
const suffix = this.options?.selectionSuffix ?? "Selection";
|
|
1653
|
+
const promises = ctx.selectionTypes.map(async (type) => {
|
|
1654
|
+
const stream = createStream(join(dir, `${toKebabCase(`${type.name}${suffix}`)}.ts`));
|
|
1655
|
+
const writer = this.createSelectionWriter(type, ctx, stream, this.options);
|
|
1656
|
+
emptySelectionNameMap.set(type, writer.emptySelectionName);
|
|
1657
|
+
if (writer.defaultSelectionName !== void 0) defaultSelectionNameMap.set(type, writer.defaultSelectionName);
|
|
1658
|
+
writer.write();
|
|
1659
|
+
await endStream(stream);
|
|
1660
|
+
});
|
|
1661
|
+
await Promise.all([...promises, (async () => {
|
|
1662
|
+
const stream = createStream(join(dir, "index.ts"));
|
|
1663
|
+
for (const type of ctx.selectionTypes) {
|
|
1664
|
+
const selectionTypeName = `${type.name}${suffix}`;
|
|
1665
|
+
const selectionFileName = toKebabCase(selectionTypeName);
|
|
1666
|
+
const typeExports = [
|
|
1667
|
+
selectionTypeName,
|
|
1668
|
+
(type instanceof GraphQLObjectType || type instanceof GraphQLInterfaceType) && ctx.typesWithParameterizedField.has(type) ? `${type.name}Args` : void 0,
|
|
1669
|
+
...this.additionalExportedTypeNamesForSelection(type, ctx)
|
|
1670
|
+
].filter(Boolean).join(", ");
|
|
1671
|
+
stream.write(`export type {${typeExports}} from './${selectionFileName}';\n`);
|
|
1672
|
+
const defaultSelectionName = defaultSelectionNameMap.get(type);
|
|
1673
|
+
const valueExports = [emptySelectionNameMap.get(type), defaultSelectionName].filter(Boolean).join(", ");
|
|
1674
|
+
if (valueExports.length !== 0) stream.write(`export {${valueExports}} from './${selectionFileName}';\n`);
|
|
1675
|
+
}
|
|
1676
|
+
await stream.end();
|
|
1677
|
+
})()]);
|
|
1678
|
+
}
|
|
1679
|
+
async generateInputTypes(inputTypes) {
|
|
1680
|
+
const dir = join(this.targetDir, "inputs");
|
|
1681
|
+
const promises = inputTypes.map(async (type) => {
|
|
1682
|
+
const stream = createStream(join(dir, `${toKebabCase(type.name)}.ts`));
|
|
1683
|
+
new InputWriter(type, stream, this.options).write();
|
|
1684
|
+
await stream.end();
|
|
1685
|
+
});
|
|
1686
|
+
await Promise.all([...promises, this.writeSimpleIndex(dir, inputTypes)]);
|
|
1687
|
+
}
|
|
1688
|
+
async generateEnumTypes(enumTypes) {
|
|
1689
|
+
const dir = join(this.targetDir, "enums");
|
|
1690
|
+
const promises = enumTypes.map(async (type) => {
|
|
1691
|
+
const stream = createStream(join(dir, `${toKebabCase(type.name)}.ts`));
|
|
1692
|
+
new EnumWriter(type, stream, this.options).write();
|
|
1693
|
+
await stream.end();
|
|
1694
|
+
});
|
|
1695
|
+
await Promise.all([...promises, this.writeSimpleIndex(dir, enumTypes, true)]);
|
|
1696
|
+
}
|
|
1697
|
+
async generateTypeHierarchy(schema, typeHierarchy) {
|
|
1698
|
+
const stream = createStream(join(this.targetDir, "type-hierarchy.ts"));
|
|
1699
|
+
new TypeHierarchyWriter(schema, typeHierarchy, stream, this.options).write();
|
|
1700
|
+
await endStream(stream);
|
|
1701
|
+
}
|
|
1702
|
+
async generateEnumInputMetadata(schema) {
|
|
1703
|
+
const stream = createStream(join(this.targetDir, "enum-input-metadata.ts"));
|
|
1704
|
+
new EnumInputMetadataWriter(schema, stream, this.options).write();
|
|
1705
|
+
await endStream(stream);
|
|
1706
|
+
}
|
|
1707
|
+
async writeSimpleIndex(dir, types, typeOnly = true) {
|
|
1708
|
+
const stream = createStream(join(dir, "index.ts"));
|
|
1709
|
+
const keyword = typeOnly ? "export type" : "export";
|
|
1710
|
+
for (const type of types) stream.write(`${keyword} {${type.name}} from './${toKebabCase(type.name)}';\n`);
|
|
1711
|
+
await stream.end();
|
|
1712
|
+
}
|
|
1713
|
+
async generateAsyncRuntime() {
|
|
1714
|
+
const stream = createStream(join(this.targetDir, "client-runtime.ts"));
|
|
1715
|
+
stream.write(async_runtime_default);
|
|
1716
|
+
await endStream(stream);
|
|
1717
|
+
}
|
|
1718
|
+
async writeIndex(schema, ctx) {
|
|
1719
|
+
const stream = createStream(join(this.targetDir, "index.ts"));
|
|
1720
|
+
const selectionSuffix = this.options.selectionSuffix ?? "Selection";
|
|
1721
|
+
stream.write(`import type { Selection } from "../dist/index.mjs";\n`);
|
|
1722
|
+
stream.write(`import { FragmentRef, createSelection, resolveRegisteredSchemaType } from "../dist/index.mjs";\n`);
|
|
1723
|
+
for (const type of ctx.selectionTypes) {
|
|
1724
|
+
const selectionTypeName = `${type.name}${selectionSuffix}`;
|
|
1725
|
+
stream.write(`import type { ${selectionTypeName} } from "./selections/${toKebabCase(selectionTypeName)}";\n`);
|
|
1726
|
+
}
|
|
1727
|
+
stream.write(`import { ENUM_INPUT_METADATA } from "./enum-input-metadata";\n\n`);
|
|
1728
|
+
stream.write(`export type { GraphQLExecutor, GraphQLSubscriber, Simplify } from "./client-runtime";\n`);
|
|
1729
|
+
stream.write(`export { setGraphQLExecutor, setGraphQLSubscriber, execute, subscribe } from "./client-runtime";\n`);
|
|
1730
|
+
stream.write("export type { ImplementationType } from './type-hierarchy';\n");
|
|
1731
|
+
stream.write("export { upcastTypes, downcastTypes } from './type-hierarchy';\n");
|
|
1732
|
+
const fragmentTypeNames = ctx.selectionTypes.length === 0 ? "never" : ctx.selectionTypes.map((t) => `'${t.name}'`).join(" | ");
|
|
1733
|
+
stream.write(`export type FragmentTypeName = ${fragmentTypeNames};\n`);
|
|
1734
|
+
stream.write(`export type FragmentSelectionFor<E extends FragmentTypeName, T extends object = {}, TVariables extends object = {}> =\n`);
|
|
1735
|
+
if (ctx.selectionTypes.length === 0) stream.write(" never;\n");
|
|
1736
|
+
else {
|
|
1737
|
+
for (const type of ctx.selectionTypes) {
|
|
1738
|
+
const selectionTypeName = `${type.name}${selectionSuffix}`;
|
|
1739
|
+
stream.write(` E extends '${type.name}' ? ${selectionTypeName}<T, TVariables> :\n`);
|
|
1740
|
+
}
|
|
1741
|
+
stream.write(" never;\n");
|
|
1742
|
+
}
|
|
1743
|
+
stream.write(`\nexport function fragment$<E extends FragmentTypeName, T extends object, TVariables extends object>(\n`);
|
|
1744
|
+
stream.write(` typeName: E,\n`);
|
|
1745
|
+
stream.write(` builder: (it: FragmentSelectionFor<E, {}, {}>) => FragmentSelectionFor<E, T, TVariables>,\n`);
|
|
1746
|
+
stream.write(` fragmentName?: string,\n`);
|
|
1747
|
+
stream.write(`): FragmentRef<string, E, T, TVariables> {\n`);
|
|
1748
|
+
stream.write(` const schemaType = resolveRegisteredSchemaType(typeName);\n`);
|
|
1749
|
+
stream.write(` if (!schemaType) {\n`);
|
|
1750
|
+
stream.write(` throw new Error(\`Cannot resolve schema type \"\${typeName}\" for fragment$\`);\n`);
|
|
1751
|
+
stream.write(` }\n`);
|
|
1752
|
+
stream.write(` const base = createSelection<E, Selection<E, {}, {}>>(\n`);
|
|
1753
|
+
stream.write(` schemaType as any,\n`);
|
|
1754
|
+
stream.write(` ENUM_INPUT_METADATA,\n`);
|
|
1755
|
+
stream.write(` undefined,\n`);
|
|
1756
|
+
stream.write(` );\n`);
|
|
1757
|
+
stream.write(` const selection = builder(base as unknown as FragmentSelectionFor<E, {}, {}>);\n`);
|
|
1758
|
+
stream.write(` return new FragmentRef(fragmentName ?? \`\${typeName}Fragment\`, selection as any);\n`);
|
|
1759
|
+
stream.write(`}\n`);
|
|
1760
|
+
await endStream(stream);
|
|
1761
|
+
}
|
|
1762
|
+
/**
|
|
1763
|
+
* Creates node_modules/@ptdgrp/typedgql/index.ts
|
|
1764
|
+
* so users can import generated types and the root gateway via `import { G } from '@ptdgrp/typedgql'`.
|
|
1765
|
+
* Also patches package.json exports for ESM/type resolution to point to the generated entry.
|
|
1766
|
+
*/
|
|
1767
|
+
async writePackageEntrypoint(schema, ctx) {
|
|
1768
|
+
await mkdir(PACKAGE_DIR, { recursive: true });
|
|
1769
|
+
const indexStream = createStream(join(PACKAGE_DIR, "index.ts"));
|
|
1770
|
+
this.writePackageIndexCode(indexStream, schema, ctx);
|
|
1771
|
+
await endStream(indexStream);
|
|
1772
|
+
await this.patchPackageJsonForGeneratedEntrypoint();
|
|
1773
|
+
}
|
|
1774
|
+
async patchPackageJsonForGeneratedEntrypoint() {
|
|
1775
|
+
const packageJsonPath = join(PACKAGE_DIR, "package.json");
|
|
1776
|
+
const raw = await readFile(packageJsonPath, "utf8");
|
|
1777
|
+
const pkg = JSON.parse(raw);
|
|
1778
|
+
const exportsMap = typeof pkg.exports === "object" && pkg.exports !== null ? pkg.exports : {};
|
|
1779
|
+
const rootExportRaw = exportsMap["."];
|
|
1780
|
+
const rootExport = typeof rootExportRaw === "object" && rootExportRaw !== null ? rootExportRaw : {};
|
|
1781
|
+
const importExportRaw = rootExport.import;
|
|
1782
|
+
const importExport = typeof importExportRaw === "object" && importExportRaw !== null ? importExportRaw : {};
|
|
1783
|
+
importExport.types = "./index.ts";
|
|
1784
|
+
importExport.default = "./index.ts";
|
|
1785
|
+
rootExport.import = importExport;
|
|
1786
|
+
exportsMap["."] = rootExport;
|
|
1787
|
+
pkg.exports = exportsMap;
|
|
1788
|
+
pkg.types = "./index.ts";
|
|
1789
|
+
await writeFile(packageJsonPath, `${JSON.stringify(pkg, null, 2)}\n`, "utf8");
|
|
1790
|
+
}
|
|
1791
|
+
writePackageIndexCode(stream, schema, _ctx) {
|
|
1792
|
+
const typeMap = schema.getTypeMap();
|
|
1793
|
+
const queryType = typeMap["Query"];
|
|
1794
|
+
const mutationType = typeMap["Mutation"];
|
|
1795
|
+
const subscriptionType = typeMap["Subscription"];
|
|
1796
|
+
stream.write(`export * from './__generated/index';\n`);
|
|
1797
|
+
stream.write(`export type { Selection, ExecutableSelection, ShapeOf, VariablesOf, Expand, FieldSelection, DirectiveArgs, EnumInputMetadata, EnumInputMetaType, AcceptableVariables, UnresolvedVariables, ValueOrThunk, SchemaType, SchemaField, SchemaTypeCategory, SchemaFieldCategory, FieldOptions } from './dist/index.mjs';\n`);
|
|
1798
|
+
stream.write(`export { FragmentSpread, FragmentRef, StringValue, runtimeOf, createSchemaType, resolveRegisteredSchemaType, registerSchemaTypeFactory, SelectionNode, createSelection, ParameterRef, EnumInputMetadataBuilder, TextBuilder, cyrb53 } from './dist/index.mjs';\n`);
|
|
1799
|
+
stream.write(`import { fragment$ } from './__generated/index';\n`);
|
|
1800
|
+
if (queryType instanceof GraphQLObjectType) stream.write(`import { query$ } from './__generated/selections/${toKebabCase("QuerySelection")}';\n`);
|
|
1801
|
+
if (mutationType instanceof GraphQLObjectType) stream.write(`import { mutation$ } from './__generated/selections/${toKebabCase("MutationSelection")}';\n`);
|
|
1802
|
+
if (subscriptionType instanceof GraphQLObjectType) stream.write(`import { subscription$ } from './__generated/selections/${toKebabCase("SubscriptionSelection")}';\n`);
|
|
1803
|
+
stream.write("\n");
|
|
1804
|
+
if (queryType instanceof GraphQLObjectType) stream.write("export { query$ };\n");
|
|
1805
|
+
if (mutationType instanceof GraphQLObjectType) stream.write("export { mutation$ };\n");
|
|
1806
|
+
if (subscriptionType instanceof GraphQLObjectType) stream.write("export { subscription$ };\n");
|
|
1807
|
+
stream.write("\n");
|
|
1808
|
+
stream.write("export const G = {\n");
|
|
1809
|
+
if (queryType instanceof GraphQLObjectType) stream.write(" query: query$,\n");
|
|
1810
|
+
if (mutationType instanceof GraphQLObjectType) stream.write(" mutation: mutation$,\n");
|
|
1811
|
+
if (subscriptionType instanceof GraphQLObjectType) stream.write(" subscription: subscription$,\n");
|
|
1812
|
+
stream.write(" fragment: fragment$,\n");
|
|
1813
|
+
stream.write("} as const;\n");
|
|
1814
|
+
if (this.hasGeneratedEnums(schema)) stream.write(`export * from './__generated/enums';\n`);
|
|
1815
|
+
if (this.hasGeneratedInputs(schema)) stream.write(`export * from './__generated/inputs';\n`);
|
|
1816
|
+
stream.write(`export type * from './__generated/selections';\n`);
|
|
1817
|
+
stream.write(`export type * from './__generated/type-hierarchy';\n`);
|
|
1818
|
+
}
|
|
1819
|
+
hasGeneratedEnums(schema) {
|
|
1820
|
+
const typeMap = schema.getTypeMap();
|
|
1821
|
+
for (const typeName in typeMap) {
|
|
1822
|
+
if (typeName.startsWith("__")) continue;
|
|
1823
|
+
const type = typeMap[typeName];
|
|
1824
|
+
if (type instanceof GraphQLEnumType && !isExcludedTypeName(this.options, type.name)) return true;
|
|
1825
|
+
}
|
|
1826
|
+
return false;
|
|
1827
|
+
}
|
|
1828
|
+
hasGeneratedInputs(schema) {
|
|
1829
|
+
const typeMap = schema.getTypeMap();
|
|
1830
|
+
for (const typeName in typeMap) {
|
|
1831
|
+
if (typeName.startsWith("__")) continue;
|
|
1832
|
+
const type = typeMap[typeName];
|
|
1833
|
+
if (type instanceof GraphQLInputObjectType && !isExcludedTypeName(this.options, type.name)) return true;
|
|
1834
|
+
}
|
|
1835
|
+
return false;
|
|
1836
|
+
}
|
|
1837
|
+
validateSchema(schema) {
|
|
1838
|
+
const typeMap = schema.getTypeMap();
|
|
1839
|
+
for (const typeName in typeMap) {
|
|
1840
|
+
const type = typeMap[typeName];
|
|
1841
|
+
if (type instanceof GraphQLObjectType || type instanceof GraphQLInterfaceType) {
|
|
1842
|
+
for (const fieldName in type.getFields()) if (RESERVED_FIELDS.has(fieldName)) throw new Error(`Illegal field '${fieldName}' of type '${typeName}', it's name is protected by '@ptdgrp/typedgql', please change the server-side app`);
|
|
1843
|
+
}
|
|
1844
|
+
}
|
|
1845
|
+
const { idFieldMap } = this.options;
|
|
1846
|
+
if (idFieldMap) for (const typeName in idFieldMap) {
|
|
1847
|
+
const type = typeMap[typeName];
|
|
1848
|
+
if (!(type instanceof GraphQLObjectType) && !(type instanceof GraphQLInterfaceType)) throw new Error(`config.idFieldMap contains an illegal key '${typeName}', that is neither a graphql object type nor graphql interface type`);
|
|
1849
|
+
const idField = type.getFields()[idFieldMap[typeName]];
|
|
1850
|
+
if (!idField) throw new Error(`config.idFieldMap['${typeName}'] is illegal, there is no field named '${idFieldMap[typeName]}' in the type '${typeName}'`);
|
|
1851
|
+
if (targetTypeOf(idField.type) !== void 0) throw new Error(`config.idFieldMap['${typeName}'] is illegal, the field '${idFieldMap[typeName]}' of the type '${typeName}' is not scalar`);
|
|
1852
|
+
}
|
|
1853
|
+
const { defaultSelectionExcludeMap: excludeMap } = this.options;
|
|
1854
|
+
if (excludeMap) for (const typeName in excludeMap) {
|
|
1855
|
+
const type = typeMap[typeName];
|
|
1856
|
+
if (!(type instanceof GraphQLObjectType) && !(type instanceof GraphQLInterfaceType)) throw new Error(`config.defaultSelectionExcludeMap contains an illegal key '${typeName}' that is neither a graphql object type nor graphql interface type`);
|
|
1857
|
+
const fieldMap = type.getFields();
|
|
1858
|
+
const fieldNames = excludeMap[typeName];
|
|
1859
|
+
if (!Array.isArray(fieldNames)) throw new Error(`config.defaultSelectionExcludeMap['${typeName}'] is not array`);
|
|
1860
|
+
for (let i = 0; i < fieldNames.length; i++) {
|
|
1861
|
+
const fieldName = fieldNames[i];
|
|
1862
|
+
if (fieldMap[fieldName] === void 0) throw new Error(`config.defaultSelectionExcludeMap['${typeName}'][${i}] is illegal, its value '${fieldName}' is not a field of graphql type '${typeName}'`);
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
}
|
|
1866
|
+
};
|
|
1867
|
+
function createStream(path) {
|
|
1868
|
+
return createWriteStream(path);
|
|
1869
|
+
}
|
|
1870
|
+
function endStream(stream) {
|
|
1871
|
+
return new Promise((resolve, reject) => {
|
|
1872
|
+
stream.end(() => resolve());
|
|
1873
|
+
stream.on("error", reject);
|
|
1874
|
+
});
|
|
1875
|
+
}
|
|
1876
|
+
|
|
1877
|
+
//#endregion
|
|
1878
|
+
//#region src/codegen/schema-loader.ts
|
|
1879
|
+
async function loadRemoteSchema(endpoint, headers) {
|
|
1880
|
+
const body = JSON.stringify({ query: getIntrospectionQuery({ oneOf: true }) });
|
|
1881
|
+
const { data, errors } = await (await fetch(endpoint, {
|
|
1882
|
+
method: "POST",
|
|
1883
|
+
body,
|
|
1884
|
+
headers: {
|
|
1885
|
+
Accept: "application/json",
|
|
1886
|
+
"Content-Type": "application/json",
|
|
1887
|
+
...headers
|
|
1888
|
+
}
|
|
1889
|
+
})).json();
|
|
1890
|
+
if (errors !== void 0) throw new Error(JSON.stringify(errors));
|
|
1891
|
+
return buildClientSchema(data);
|
|
1892
|
+
}
|
|
1893
|
+
async function loadLocalSchema(location) {
|
|
1894
|
+
return buildSchema(await readFile(location, { encoding: "utf8" }));
|
|
1895
|
+
}
|
|
1896
|
+
|
|
1897
|
+
//#endregion
|
|
1898
|
+
export { loadRemoteSchema as n, Generator as r, loadLocalSchema as t };
|
|
1899
|
+
//# sourceMappingURL=schema-loader-CYFTxUkG.mjs.map
|