@ptdgrp/typedgql 1.0.0-beta.10

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.
@@ -0,0 +1,1929 @@
1
+ let graphql = require("graphql");
2
+ let fs_promises = require("fs/promises");
3
+ let fs = require("fs");
4
+ let path = require("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 graphql.GraphQLNonNull) return targetTypeOf(type.ofType);
13
+ if (type instanceof graphql.GraphQLList) return targetTypeOf(type.ofType);
14
+ if (type instanceof graphql.GraphQLObjectType || type instanceof graphql.GraphQLInterfaceType || type instanceof graphql.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 graphql.GraphQLInputObjectType || namedType instanceof graphql.GraphQLEnumType) {
116
+ this.importedTypes.add(namedType);
117
+ return;
118
+ }
119
+ if (namedType instanceof graphql.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 graphql.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 graphql.GraphQLNonNull) {
200
+ this.typeRef(type.ofType, objectRender);
201
+ return;
202
+ }
203
+ if (type instanceof graphql.GraphQLList) {
204
+ const arrayType = this.options.arrayEditable ? "Array" : "ReadonlyArray";
205
+ this.typeApplication(arrayType, () => {
206
+ this.typeRef(type.ofType, objectRender);
207
+ if (!(type.ofType instanceof graphql.GraphQLNonNull)) this.text(" | undefined");
208
+ });
209
+ return;
210
+ }
211
+ if (type instanceof graphql.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 graphql.GraphQLEnumType || type instanceof graphql.GraphQLInputObjectType) {
218
+ this.text(type.name);
219
+ return;
220
+ }
221
+ if (type instanceof graphql.GraphQLObjectType || type instanceof graphql.GraphQLInterfaceType || type instanceof graphql.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 graphql.GraphQLNonNull) {
233
+ this.gqlTypeRef(type.ofType);
234
+ this.text("!");
235
+ return;
236
+ }
237
+ if (type instanceof graphql.GraphQLList) {
238
+ this.text("[");
239
+ this.gqlTypeRef(type.ofType);
240
+ this.text("]");
241
+ return;
242
+ }
243
+ if (type instanceof graphql.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 graphql.GraphQLInputObjectType) return "inputs";
279
+ if (importedType instanceof graphql.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 graphql.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 graphql.GraphQLNonNull || type instanceof graphql.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 graphql.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 graphql.GraphQLNonNull ? field.type.ofType : field.type;
526
+ if (this.ctx.embeddedTypes.has(fieldCoreType)) return "SCALAR";
527
+ if (fieldCoreType instanceof graphql.GraphQLList) {
528
+ const elementType = fieldCoreType.ofType instanceof graphql.GraphQLNonNull ? fieldCoreType.ofType.ofType : fieldCoreType.ofType;
529
+ if (elementType instanceof graphql.GraphQLObjectType || elementType instanceof graphql.GraphQLInterfaceType || elementType instanceof graphql.GraphQLUnionType) return "LIST";
530
+ return;
531
+ }
532
+ if (fieldCoreType instanceof graphql.GraphQLObjectType || fieldCoreType instanceof graphql.GraphQLInterfaceType || fieldCoreType instanceof graphql.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
+ const ensureConcreteSelectionTypeImported = (type) => {
563
+ if (type === this.modelType) return;
564
+ const selectionTypeName = this.selectionTypeNameForType(type);
565
+ const selectionModule = `./${toKebabCase(selectionTypeName)}`;
566
+ if (!importedConcreteSelectionNames.has(selectionTypeName)) {
567
+ importedConcreteSelectionNames.add(selectionTypeName);
568
+ imports.useType(selectionModule, selectionTypeName);
569
+ }
570
+ if (!importedConcreteSelectionModules.has(selectionModule)) {
571
+ importedConcreteSelectionModules.add(selectionModule);
572
+ imports.useSideEffect(selectionModule);
573
+ }
574
+ };
575
+ for (const field of Object.values(this.fieldMap)) {
576
+ const targetType = targetTypeOf(field.type);
577
+ if (targetType === void 0 || targetType === this.modelType) continue;
578
+ ensureConcreteSelectionTypeImported(targetType);
579
+ }
580
+ const downcasts = this.ctx.typeHierarchy.downcastTypeMap.get(this.modelType);
581
+ if (downcasts) for (const downcast of downcasts) ensureConcreteSelectionTypeImported(downcast);
582
+ const upcastTypes = this.ctx.typeHierarchy.upcastTypeMap.get(this.modelType);
583
+ if (upcastTypes !== void 0) for (const upcastType of upcastTypes) {
584
+ const selectionTypeName = `${upcastType.name}${this.options.selectionSuffix ?? "Selection"}`;
585
+ const importedNames = this.importedNamesForSuperType(upcastType);
586
+ if (importedNames.length === 0) continue;
587
+ const importSource = `./${toKebabCase(selectionTypeName)}`;
588
+ for (const importedName of importedNames) imports.useValue(importSource, importedName);
589
+ }
590
+ imports.emit();
591
+ }
592
+ importedNamesForSuperType(superType) {
593
+ if (isOperationRootTypeName(superType.name)) return [`${instancePrefix(superType.name)}$`];
594
+ return [];
595
+ }
596
+ importingBehavior(type) {
597
+ if (type === this.modelType) return "self";
598
+ if (type instanceof graphql.GraphQLObjectType || type instanceof graphql.GraphQLInterfaceType) return "same_dir";
599
+ return "other_dir";
600
+ }
601
+ writeCode() {
602
+ this.text(COMMENT$1);
603
+ this.writeSelectionInterface();
604
+ this.writeInstances();
605
+ this.writeArgsInterface();
606
+ }
607
+ writeSelectionInterface() {
608
+ this.writeSelectionInterfaceHeader();
609
+ this.scope({
610
+ type: "block",
611
+ multiLines: true,
612
+ suffix: "\n"
613
+ }, () => {
614
+ this.writeSelectionInterfaceBody();
615
+ });
616
+ }
617
+ writeSelectionInterfaceHeader() {
618
+ const superSelection = this.superSelectionTypeName(this.modelType);
619
+ this.text(`export interface ${this.selectionTypeName}<T extends object = {}, TVariables extends object = {}, TLastField extends string = never> extends ${superSelection}<'${this.modelType.name}', T, TVariables> `);
620
+ }
621
+ writeSelectionInterfaceBody() {
622
+ this.writeFragmentMethods();
623
+ this.writeDirectiveBuiltins();
624
+ this.write$omit();
625
+ this.write$alias();
626
+ this.writeTypeName();
627
+ const fields = Object.values(this.fieldMap);
628
+ for (const field of fields) {
629
+ this.text("\n");
630
+ this.writePositiveProp(field);
631
+ }
632
+ }
633
+ writeFragmentMethods() {
634
+ if (isOperationRootTypeName(this.modelType.name)) return;
635
+ const t = this.text.bind(this);
636
+ const modelName = this.modelType.name;
637
+ const selfSelectionType = this.selectionTypeName;
638
+ const fragmentTypeName = `ImplementationType<'${modelName}'>`;
639
+ const inlineSelectionFor = (xName, data, vars) => this.fragmentSelectionTypeForModel(xName, data, vars);
640
+ const resultDataType = `XName extends '${modelName}' ?\nT & X :\nWithTypeName<T, ${fragmentTypeName}> & (WithTypeName<X, ImplementationType<XName>> | {__typename: Exclude<${fragmentTypeName}, ImplementationType<XName>>})`;
641
+ t("\n$on<X extends object, XVariables extends object>");
642
+ this.scope({
643
+ type: "parameters",
644
+ multiLines: true
645
+ }, () => {
646
+ t(`builder: (it: ${selfSelectionType}<{}, {}>) => ${selfSelectionType}<X, XVariables>`);
647
+ });
648
+ t(`: ${this.selectionTypeName}`);
649
+ this.scope({
650
+ type: "generic",
651
+ multiLines: true
652
+ }, () => {
653
+ t("T & X");
654
+ this.separator(", ");
655
+ t("TVariables & XVariables");
656
+ });
657
+ t(";\n");
658
+ t(`\n$on<XName extends ${fragmentTypeName}, X extends object, XVariables extends object>`);
659
+ this.scope({
660
+ type: "parameters",
661
+ multiLines: true
662
+ }, () => {
663
+ t("typeName: XName");
664
+ this.separator(", ");
665
+ t(`builder: (it: ${inlineSelectionFor("XName", "{}", "{}")}) => ${inlineSelectionFor("XName", "X", "XVariables")}`);
666
+ });
667
+ t(`: ${this.selectionTypeName}`);
668
+ this.scope({
669
+ type: "generic",
670
+ multiLines: true
671
+ }, () => {
672
+ t(resultDataType);
673
+ this.separator(", ");
674
+ t("TVariables & XVariables");
675
+ });
676
+ t(";\n");
677
+ t(`\n$use<XName extends ${fragmentTypeName}, X extends object, XVariables extends object>`);
678
+ this.scope({
679
+ type: "parameters",
680
+ multiLines: true
681
+ }, () => {
682
+ t("fragment: ValueOrThunk<FragmentSpread<string, XName, X, XVariables>>");
683
+ });
684
+ t(`: ${this.selectionTypeName}`);
685
+ this.scope({
686
+ type: "generic",
687
+ multiLines: true
688
+ }, () => {
689
+ t(resultDataType);
690
+ this.separator(", ");
691
+ t("TVariables & XVariables");
692
+ });
693
+ t(";\n");
694
+ }
695
+ fragmentSelectionTypeForModel(xNameRef, dataType, variableType) {
696
+ const branches = [];
697
+ const selectionTypeByName = /* @__PURE__ */ new Map();
698
+ selectionTypeByName.set(this.modelType.name, this.selectionTypeName);
699
+ const downcasts = this.ctx.typeHierarchy.downcastTypeMap.get(this.modelType);
700
+ if (downcasts) for (const t of downcasts) selectionTypeByName.set(t.name, this.selectionTypeNameForType(t));
701
+ for (const [typeName, selectionTypeName] of selectionTypeByName) branches.push(`${xNameRef} extends '${typeName}' ? ${selectionTypeName}<${dataType}, ${variableType}> :`);
702
+ branches.push("never");
703
+ return branches.join("\n");
704
+ }
705
+ writeDirectiveBuiltins() {
706
+ const t = this.text.bind(this);
707
+ t("\n\n$directive(name: string, args?: DirectiveArgs): ");
708
+ this.writeFieldAwareSelectionReturnType();
709
+ t(";\n");
710
+ t("\n$include(condition: unknown): ");
711
+ this.writeFieldAwareSelectionReturnType();
712
+ t(";\n");
713
+ t("\n$skip(condition: unknown): ");
714
+ this.writeFieldAwareSelectionReturnType();
715
+ t(";\n");
716
+ }
717
+ writeFieldAwareSelectionReturnType() {
718
+ const t = this.text.bind(this);
719
+ t(this.selectionTypeName);
720
+ this.scope({
721
+ type: "generic",
722
+ multiLines: true
723
+ }, () => {
724
+ t("TLastField extends keyof T ? Omit<T, TLastField> & {readonly [key in TLastField]?: T[key]} : T");
725
+ this.separator(", ");
726
+ t("TVariables");
727
+ this.separator(", ");
728
+ t("TLastField");
729
+ });
730
+ }
731
+ writeTypeName() {
732
+ if (!isOperationRootTypeName(this.modelType.name)) {
733
+ const t = this.text.bind(this);
734
+ t("\n\n");
735
+ t("readonly __typename: ");
736
+ t(this.selectionTypeName);
737
+ t("<T & {__typename: ImplementationType<'");
738
+ t(this.modelType.name);
739
+ t("'>}, TVariables>;\n");
740
+ }
741
+ }
742
+ writePositiveProp(field) {
743
+ const targetType = targetTypeOf(field.type);
744
+ if (targetType !== void 0) this.writeAssociationProp(field, targetType);
745
+ else {
746
+ this.writePositivePropImpl(field, "SIMPLEST");
747
+ this.writePositivePropImpl(field, "WITH_ARGS");
748
+ }
749
+ }
750
+ writeAssociationProp(field, targetType) {
751
+ if (field.args.length === 0) {
752
+ this.writeAssociationPropImpl(field, targetType, false);
753
+ return;
754
+ }
755
+ this.writeAssociationPropImpl(field, targetType, true);
756
+ this.writeAssociationPropImpl(field, targetType, false);
757
+ }
758
+ writeAssociationPropImpl(field, targetType, withArgs) {
759
+ const t = this.text.bind(this);
760
+ const nonNull = field.type instanceof graphql.GraphQLNonNull;
761
+ const isPlural = field.type instanceof graphql.GraphQLNonNull ? field.type.ofType instanceof graphql.GraphQLList : field.type instanceof graphql.GraphQLList;
762
+ const childSelectionType = this.selectionTypeNameForType(targetType);
763
+ t("\n");
764
+ this.writeFieldDocComment(field);
765
+ t(field.name);
766
+ this.scope({
767
+ type: "generic",
768
+ multiLines: true
769
+ }, () => {
770
+ if (withArgs) {
771
+ t(`XArgs extends AcceptableVariables<${this.modelType.name}Args['${field.name}']>`);
772
+ this.separator(", ");
773
+ }
774
+ t("X extends object");
775
+ this.separator(", ");
776
+ t("XVariables extends object");
777
+ });
778
+ this.scope({
779
+ type: "parameters",
780
+ multiLines: true
781
+ }, () => {
782
+ if (withArgs) {
783
+ t("args: XArgs");
784
+ this.separator(", ");
785
+ }
786
+ t("selection: ");
787
+ this.scope({
788
+ type: "parameters",
789
+ multiLines: false
790
+ }, () => {
791
+ t(`selection: ${childSelectionType}<{}, {}>`);
792
+ });
793
+ t(` => ${childSelectionType}<X, XVariables>`);
794
+ });
795
+ t(`: ${this.selectionTypeName}`);
796
+ this.scope({
797
+ type: "generic",
798
+ multiLines: true,
799
+ suffix: ";\n"
800
+ }, () => {
801
+ t("T & {");
802
+ if (!this.options.objectEditable) t("readonly ");
803
+ t(`"${field.name}"`);
804
+ if (!nonNull) t("?");
805
+ t(": ");
806
+ if (isPlural) t("ReadonlyArray<X>");
807
+ else t("X");
808
+ t("}");
809
+ this.separator(", ");
810
+ t("TVariables & XVariables");
811
+ if (withArgs) t(` & UnresolvedVariables<XArgs, ${this.modelType.name}Args['${field.name}']>`);
812
+ else if (field.args.length !== 0) t(` & ${this.modelType.name}Args["${field.name}"]`);
813
+ this.separator(", ");
814
+ t(`"${field.name}"`);
815
+ });
816
+ }
817
+ write$omit() {
818
+ const omittableFields = [];
819
+ for (const [fieldName, field] of Object.entries(this.fieldMap)) if (field.args.length === 0 && targetTypeOf(field.type) === void 0) omittableFields.push(fieldName);
820
+ if (omittableFields.length === 0) return;
821
+ const t = this.text.bind(this);
822
+ t("\n\n$omit<XOmit extends ");
823
+ t(omittableFields.map((f) => `"${f}"`).join(" | "));
824
+ t(">");
825
+ this.scope({
826
+ type: "parameters",
827
+ multiLines: false
828
+ }, () => {
829
+ t("...fields: XOmit[]");
830
+ });
831
+ t(": ");
832
+ t(this.selectionTypeName);
833
+ t("<Omit<T, XOmit>, TVariables>;\n");
834
+ }
835
+ write$alias() {
836
+ if (this.getScalarFieldNames().length === 0) return;
837
+ const t = this.text.bind(this);
838
+ t("\n$alias<XAlias extends string>");
839
+ t("(");
840
+ t("alias: XAlias");
841
+ t("): ");
842
+ t(this.selectionTypeName);
843
+ t("<TLastField extends keyof T ? Omit<T, TLastField> & {readonly [key in XAlias]: T[TLastField]} : T, TVariables>;\n");
844
+ }
845
+ getScalarFieldNames() {
846
+ const fields = [];
847
+ for (const [fieldName, field] of Object.entries(this.fieldMap)) if (field.args.length === 0 && targetTypeOf(field.type) === void 0) fields.push(fieldName);
848
+ return fields;
849
+ }
850
+ writePositivePropImpl(field, mode) {
851
+ const withArgs = mode === "WITH_ARGS";
852
+ if (withArgs && field.args.length === 0) return;
853
+ const targetType = targetTypeOf(field.type);
854
+ const renderAsField = field.args.length === 0 && targetType === void 0;
855
+ const nonNull = field.type instanceof graphql.GraphQLNonNull;
856
+ const t = this.text.bind(this);
857
+ t("\n");
858
+ this.writeFieldDocComment(field);
859
+ if (renderAsField) {
860
+ t("readonly ");
861
+ t(field.name);
862
+ } else {
863
+ t(field.name);
864
+ if (withArgs || targetType !== void 0) this.scope({
865
+ type: "generic",
866
+ multiLines: true
867
+ }, () => {
868
+ if (withArgs) {
869
+ this.separator(", ");
870
+ t(`XArgs extends AcceptableVariables<${this.modelType.name}Args['${field.name}']>`);
871
+ }
872
+ if (targetType !== void 0) {
873
+ this.separator(", ");
874
+ t("X extends object");
875
+ this.separator(", ");
876
+ t("XVariables extends object");
877
+ }
878
+ });
879
+ this.scope({
880
+ type: "parameters",
881
+ multiLines: true
882
+ }, () => {
883
+ if (withArgs) {
884
+ this.separator(", ");
885
+ t("args: XArgs");
886
+ }
887
+ if (targetType !== void 0) {
888
+ this.separator(", ");
889
+ t("child: ");
890
+ t(this.superSelectionTypeName(targetType));
891
+ t("<'");
892
+ t(targetType.name);
893
+ t("', X, XVariables>");
894
+ }
895
+ });
896
+ }
897
+ t(": ");
898
+ t(this.selectionTypeName);
899
+ this.scope({
900
+ type: "generic",
901
+ multiLines: !renderAsField,
902
+ suffix: ";\n"
903
+ }, () => {
904
+ t("T & ");
905
+ this.writePositivePropChangedDataType(field, false, !nonNull);
906
+ this.separator(", ");
907
+ t("TVariables");
908
+ if (targetType !== void 0) t(" & XVariables");
909
+ if (field.args.length !== 0) if (withArgs) t(` & UnresolvedVariables<XArgs, ${this.modelType.name}Args['${field.name}']>`);
910
+ else t(` & ${this.modelType.name}Args["${field.name}"]`);
911
+ this.separator(", ");
912
+ t(`"${field.name}"`);
913
+ });
914
+ }
915
+ writePositivePropChangedDataType(field, withOptions, nullable) {
916
+ const t = this.text.bind(this);
917
+ t("{");
918
+ if (!this.options.objectEditable) t("readonly ");
919
+ if (withOptions) t(`[key in XAlias]`);
920
+ else t(`"${field.name}"`);
921
+ if (nullable) t("?");
922
+ t(": ");
923
+ this.typeRef(field.type, targetTypeOf(field.type) !== void 0 ? "X" : void 0);
924
+ t("}");
925
+ }
926
+ writeFieldDocComment(field) {
927
+ const description = field.description?.trim();
928
+ const deprecationReason = field.deprecationReason?.trim();
929
+ if (!description && !deprecationReason) return;
930
+ const t = this.text.bind(this);
931
+ t("/**\n");
932
+ if (description) for (const line of this.escapeJsDoc(description).split("\n")) {
933
+ t(" * ");
934
+ t(line);
935
+ t("\n");
936
+ }
937
+ if (deprecationReason) {
938
+ t(" * @deprecated ");
939
+ t(this.escapeJsDoc(deprecationReason));
940
+ t("\n");
941
+ }
942
+ t(" */\n");
943
+ }
944
+ escapeJsDoc(value) {
945
+ return value.replaceAll("*/", "*\\/");
946
+ }
947
+ writeInstances() {
948
+ const t = this.text.bind(this);
949
+ t("\nregisterSchemaTypeFactory(");
950
+ this.str(this.modelType.name);
951
+ t(", () => ");
952
+ this.writeSchemaTypeForModelType();
953
+ t(");\n");
954
+ const emptySelectionName = this.emptySelectionName;
955
+ if (!emptySelectionName) return;
956
+ const itemTypes = this.modelType instanceof graphql.GraphQLUnionType ? this.modelType.getTypes() : [];
957
+ t("\nexport function ");
958
+ t(emptySelectionName);
959
+ t("<T extends object = {}, TVariables extends object = {}>(");
960
+ t(`builder: (it: ${this.selectionTypeName}<{}, {}>) => ${this.selectionTypeName}<T, TVariables>`);
961
+ t(", operationName?: string");
962
+ t("): ");
963
+ t(this.selectionTypeName);
964
+ t("<T, TVariables> ");
965
+ this.scope({
966
+ type: "block",
967
+ multiLines: true,
968
+ suffix: "\n"
969
+ }, () => {
970
+ t("const selection = builder(");
971
+ this.scope({
972
+ type: "blank",
973
+ multiLines: true
974
+ }, () => {
975
+ t("createSelection");
976
+ this.scope({
977
+ type: "parameters",
978
+ multiLines: true
979
+ }, () => {
980
+ t(`resolveRegisteredSchemaType("${this.modelType.name}")!`);
981
+ this.separator(", ");
982
+ this.text("ENUM_INPUT_METADATA");
983
+ this.separator(", ");
984
+ if (itemTypes.length === 0) t("undefined");
985
+ else this.scope({
986
+ type: "array",
987
+ multiLines: itemTypes.length >= 2
988
+ }, () => {
989
+ for (const itemType of itemTypes) {
990
+ this.separator(", ");
991
+ this.str(itemType.name);
992
+ }
993
+ });
994
+ });
995
+ });
996
+ t(");\n");
997
+ t("return withOperationName(selection, operationName);\n");
998
+ });
999
+ if (this.defaultSelectionName !== void 0) {
1000
+ t("\nexport const ");
1001
+ t(this.defaultSelectionName);
1002
+ t(" = ");
1003
+ this.enter("blank", true);
1004
+ t(emptySelectionName);
1005
+ this.enter("blank", true);
1006
+ for (const propName of this.defaultSelectionProps) {
1007
+ t(".");
1008
+ t(propName);
1009
+ t("\n");
1010
+ }
1011
+ this.leave();
1012
+ this.leave(";\n");
1013
+ }
1014
+ }
1015
+ writeSchemaTypeForModelType() {
1016
+ const t = this.text.bind(this);
1017
+ t("createSchemaType");
1018
+ this.scope({
1019
+ type: "parameters",
1020
+ multiLines: true
1021
+ }, () => {
1022
+ t(`"${this.modelType.name}"`);
1023
+ this.separator(", ");
1024
+ t(this.schemaTypeCategory(this.modelType));
1025
+ this.separator(", ");
1026
+ this.scope({ type: "array" }, () => {
1027
+ const upcastTypes = this.ctx.typeHierarchy.upcastTypeMap.get(this.modelType);
1028
+ if (upcastTypes !== void 0) for (const upcastType of upcastTypes) {
1029
+ this.separator(", ");
1030
+ t(`resolveRegisteredSchemaType("${upcastType.name}")!`);
1031
+ }
1032
+ });
1033
+ this.separator(", ");
1034
+ this.scope({
1035
+ type: "array",
1036
+ multiLines: true
1037
+ }, () => {
1038
+ for (const fieldName of this.declaredFieldNames) {
1039
+ this.separator(", ");
1040
+ this.writeSchemaFieldDescriptor(this.fieldMap[fieldName]);
1041
+ }
1042
+ });
1043
+ });
1044
+ }
1045
+ writeSchemaFieldDescriptor(field) {
1046
+ const t = this.text.bind(this);
1047
+ const args = this.fieldArgsMap.get(field.name);
1048
+ const category = this.fieldCategoryMap.get(field.name);
1049
+ const targetType = targetTypeOf(field.type);
1050
+ if (args === void 0 && (category === void 0 || category === "SCALAR") && field.type instanceof graphql.GraphQLNonNull && targetType === void 0) {
1051
+ t(`"${field.name}"`);
1052
+ return;
1053
+ }
1054
+ this.scope({
1055
+ type: "block",
1056
+ multiLines: true
1057
+ }, () => {
1058
+ t(`category: "${category ?? "SCALAR"}"`);
1059
+ this.separator(", ");
1060
+ t(`name: "${field.name}"`);
1061
+ if (args !== void 0) {
1062
+ this.separator(", ");
1063
+ t("argGraphQLTypeMap: ");
1064
+ this.scope({
1065
+ type: "block",
1066
+ multiLines: args.length > 1
1067
+ }, () => {
1068
+ for (const arg of args) {
1069
+ this.separator(", ");
1070
+ t(arg.name);
1071
+ t(": '");
1072
+ this.gqlTypeRef(arg.type);
1073
+ t("'");
1074
+ }
1075
+ });
1076
+ }
1077
+ if (targetType !== void 0) {
1078
+ this.separator(", ");
1079
+ t(`targetTypeName: "${targetType.name}"`);
1080
+ }
1081
+ if (!(field.type instanceof graphql.GraphQLNonNull)) {
1082
+ this.separator(", ");
1083
+ t("undefinable: true");
1084
+ }
1085
+ });
1086
+ }
1087
+ schemaTypeCategory(type) {
1088
+ if (this.ctx.embeddedTypes.has(type)) return "\"EMBEDDED\"";
1089
+ return "\"OBJECT\"";
1090
+ }
1091
+ writeArgsInterface() {
1092
+ if (!this.hasArgs) return;
1093
+ const t = this.text.bind(this);
1094
+ t(`\nexport interface ${this.modelType.name}Args `);
1095
+ this.scope({
1096
+ type: "block",
1097
+ multiLines: true,
1098
+ suffix: "\n"
1099
+ }, () => {
1100
+ for (const field of Object.values(this.fieldMap)) if (field.args.length !== 0) {
1101
+ this.separator(", ");
1102
+ t(`\nreadonly ${field.name}: `);
1103
+ this.scope({
1104
+ type: "block",
1105
+ multiLines: true
1106
+ }, () => {
1107
+ for (const arg of field.args) {
1108
+ this.separator(", ");
1109
+ t("readonly ");
1110
+ t(arg.name);
1111
+ if (!(arg.type instanceof graphql.GraphQLNonNull)) t("?");
1112
+ t(": ");
1113
+ this.typeRef(arg.type);
1114
+ }
1115
+ });
1116
+ }
1117
+ });
1118
+ }
1119
+ get declaredFieldNames() {
1120
+ let set = this._declaredFieldNames;
1121
+ if (set === void 0) this._declaredFieldNames = set = this.getDeclaredFieldNames();
1122
+ return set;
1123
+ }
1124
+ getDeclaredFieldNames() {
1125
+ const fields = /* @__PURE__ */ new Set();
1126
+ if (this.modelType instanceof graphql.GraphQLObjectType || this.modelType instanceof graphql.GraphQLInterfaceType) {
1127
+ for (const field of Object.values(this.fieldMap)) fields.add(field.name);
1128
+ this.removeSuperFieldNames(fields, this.ctx.typeHierarchy.upcastTypeMap.get(this.modelType));
1129
+ } else if (this.modelType instanceof graphql.GraphQLUnionType) for (const fieldName of Object.keys(this.fieldMap)) fields.add(fieldName);
1130
+ return fields;
1131
+ }
1132
+ removeSuperFieldNames(fields, superTypes) {
1133
+ if (superTypes !== void 0) for (const superType of superTypes) {
1134
+ if (superType instanceof graphql.GraphQLObjectType || superType instanceof graphql.GraphQLInterfaceType) {
1135
+ const superFieldMap = superType.getFields();
1136
+ for (const superFieldName in superFieldMap) fields.delete(superFieldName);
1137
+ }
1138
+ this.removeSuperFieldNames(fields, this.ctx.typeHierarchy.upcastTypeMap.get(superType));
1139
+ }
1140
+ }
1141
+ superSelectionTypeName(_graphQLType) {
1142
+ return "Selection";
1143
+ }
1144
+ selectionTypeNameForType(graphQLType) {
1145
+ return `${graphQLType.name}${this.options.selectionSuffix ?? "Selection"}`;
1146
+ }
1147
+ };
1148
+ const isOperationRootTypeName = (name) => {
1149
+ return name === "Query" || name === "Mutation" || name === "Subscription";
1150
+ };
1151
+ const COMMENT$1 = `/*
1152
+ * Any instance of this interface is immutable,
1153
+ * all the properties and functions can only be used to create new instances,
1154
+ * they cannot modify the current instance.
1155
+ *
1156
+ * So any instance of this interface is reuseable.
1157
+ */
1158
+ `;
1159
+
1160
+ //#endregion
1161
+ //#region src/codegen/writers/enum.ts
1162
+ var EnumWriter = class extends Writer {
1163
+ constructor(enumType, stream, options) {
1164
+ super(stream, options);
1165
+ this.enumType = enumType;
1166
+ }
1167
+ writeCode() {
1168
+ const t = this.text.bind(this);
1169
+ const values = this.enumType.getValues();
1170
+ if (this.options.tsEnum === true || this.options.tsEnum === "number" || this.options.tsEnum === "string") {
1171
+ t("export enum ");
1172
+ t(this.enumType.name);
1173
+ this.scope({
1174
+ type: "block",
1175
+ prefix: " ",
1176
+ suffix: "\n",
1177
+ multiLines: values.length > 3
1178
+ }, () => {
1179
+ for (const value of values) {
1180
+ this.separator(", ");
1181
+ if (this.options.tsEnum === "string") {
1182
+ t(value.name);
1183
+ t(" = ");
1184
+ t("'");
1185
+ t(value.name);
1186
+ t("'");
1187
+ } else t(value.name);
1188
+ }
1189
+ });
1190
+ } else {
1191
+ t("export type ");
1192
+ t(this.enumType.name);
1193
+ t(" = ");
1194
+ this.scope({
1195
+ type: "blank",
1196
+ suffix: ";\n",
1197
+ multiLines: values.length > 3
1198
+ }, () => {
1199
+ for (const value of values) {
1200
+ this.separator(" | ");
1201
+ t("'");
1202
+ t(value.name);
1203
+ t("'");
1204
+ }
1205
+ });
1206
+ }
1207
+ }
1208
+ };
1209
+
1210
+ //#endregion
1211
+ //#region src/codegen/writers/input.ts
1212
+ var InputWriter = class extends Writer {
1213
+ constructor(inputType, stream, options) {
1214
+ super(stream, options);
1215
+ this.inputType = inputType;
1216
+ }
1217
+ prepareImports() {
1218
+ for (const field of Object.values(this.inputType.getFields())) this.importType(field.type);
1219
+ }
1220
+ importingBehavior(type) {
1221
+ if (type === this.inputType) return "self";
1222
+ if (type instanceof graphql.GraphQLInputObjectType) return "same_dir";
1223
+ return "other_dir";
1224
+ }
1225
+ writeCode() {
1226
+ this.text(COMMENT);
1227
+ this.text("export type ");
1228
+ this.text(this.inputType.name);
1229
+ this.text(" = ");
1230
+ const fieldMap = this.inputType.getFields();
1231
+ if (this.inputType.isOneOf) {
1232
+ this.writeOneOfType(fieldMap);
1233
+ return;
1234
+ }
1235
+ this.enter("block", true);
1236
+ for (const field of Object.values(fieldMap)) this.writeRegularField(field);
1237
+ this.leave("\n");
1238
+ }
1239
+ writeOneOfType(fieldMap) {
1240
+ const fieldNames = Object.keys(fieldMap);
1241
+ if (fieldNames.length === 0) {
1242
+ this.text("{}\n");
1243
+ return;
1244
+ }
1245
+ fieldNames.forEach((selectedFieldName, idx) => {
1246
+ const selectedField = fieldMap[selectedFieldName];
1247
+ if (idx > 0) this.text(" | ");
1248
+ this.enter("block", true);
1249
+ for (const fieldName of fieldNames) {
1250
+ if (!this.options.objectEditable) this.text("readonly ");
1251
+ const field = fieldMap[fieldName];
1252
+ this.text(field.name);
1253
+ if (fieldName === selectedFieldName) {
1254
+ this.text(": Exclude<");
1255
+ this.typeRef(selectedField.type);
1256
+ this.text(", undefined>;\n");
1257
+ } else this.text("?: never;\n");
1258
+ }
1259
+ this.leave();
1260
+ });
1261
+ this.text("\n");
1262
+ }
1263
+ writeRegularField(field) {
1264
+ if (!this.options.objectEditable) this.text("readonly ");
1265
+ this.text(field.name);
1266
+ if (!(field.type instanceof graphql.GraphQLNonNull)) this.text("?");
1267
+ this.text(": ");
1268
+ this.typeRef(field.type);
1269
+ this.text(";\n");
1270
+ }
1271
+ };
1272
+ const COMMENT = `/*
1273
+ * This input type is not interface, because interfaces
1274
+ * do not satisfy the constraint 'SerializableParam' of recoil
1275
+ */
1276
+ `;
1277
+
1278
+ //#endregion
1279
+ //#region src/codegen/writers/types.ts
1280
+ var TypeHierarchyWriter = class extends Writer {
1281
+ constructor(_schema, typeHierarchy, stream, options) {
1282
+ super(stream, options);
1283
+ this.typeHierarchy = typeHierarchy;
1284
+ }
1285
+ writeCode() {
1286
+ this.writeImplementationType();
1287
+ this.writeCastMethod("up");
1288
+ this.writeCastMethod("down");
1289
+ this.writeWithTypeNameType();
1290
+ }
1291
+ writeWithTypeNameType() {
1292
+ this.text(WITH_TYPE_NAME_DECLARATION);
1293
+ this.text("\n");
1294
+ }
1295
+ writeImplementationType() {
1296
+ const t = this.text.bind(this);
1297
+ const entries = [...this.typeHierarchy.downcastTypeMap.entries()];
1298
+ t(IMPLEMENTATION_TYPE_COMMENT);
1299
+ t("export type ImplementationType<T> = ");
1300
+ this.enter("blank", true);
1301
+ for (const [type, castTypes] of entries) {
1302
+ if (isExcludedTypeName(this.options, type.name)) continue;
1303
+ t(`T extends '${type.name}' ? `);
1304
+ this.enter("blank");
1305
+ if (!(type instanceof graphql.GraphQLUnionType)) t(`'${type.name}'`);
1306
+ for (const castType of castTypes) {
1307
+ if (isExcludedTypeName(this.options, castType.name)) continue;
1308
+ this.separator(" | ");
1309
+ t(`ImplementationType<'${castType.name}'>`);
1310
+ }
1311
+ this.leave();
1312
+ t(" :\n");
1313
+ }
1314
+ t("T\n");
1315
+ this.leave();
1316
+ t(";");
1317
+ }
1318
+ writeCastMethod(prefix) {
1319
+ const t = this.text.bind(this);
1320
+ const entries = [...(prefix === "up" ? this.typeHierarchy.upcastTypeMap : this.typeHierarchy.downcastTypeMap).entries()];
1321
+ t(prefix === "up" ? UPCAST_FUNC_COMMENT : DOWNCAST_FUNC_COMMENT);
1322
+ t(`\nexport function ${prefix}castTypes(typeName: string): string[] `);
1323
+ this.scope({
1324
+ type: "block",
1325
+ multiLines: true,
1326
+ suffix: "\n"
1327
+ }, () => {
1328
+ t("const typeNames: string[] = [];\n");
1329
+ t(`${prefix}castTypes0(typeName, typeNames);\n`);
1330
+ t("return typeNames;\n");
1331
+ });
1332
+ t(`\nfunction ${prefix}castTypes0(typeName: string, output: string[]) `);
1333
+ this.scope({
1334
+ type: "block",
1335
+ multiLines: true,
1336
+ suffix: "\n"
1337
+ }, () => {
1338
+ t("switch (typeName)");
1339
+ this.scope({
1340
+ type: "block",
1341
+ multiLines: true,
1342
+ suffix: "\n"
1343
+ }, () => {
1344
+ for (const [type, castTypes] of entries) {
1345
+ if (isExcludedTypeName(this.options, type.name)) continue;
1346
+ t(`case '${type.name}':`);
1347
+ this.scope({
1348
+ type: "blank",
1349
+ multiLines: true
1350
+ }, () => {
1351
+ if (!(type instanceof graphql.GraphQLUnionType)) t(`output.push('${type.name}');\n`);
1352
+ for (const castType of castTypes) {
1353
+ if (isExcludedTypeName(this.options, castType.name)) continue;
1354
+ t(`${prefix}castTypes0('${castType.name}', output);\n`);
1355
+ }
1356
+ t("break;\n");
1357
+ });
1358
+ }
1359
+ t("default:");
1360
+ this.scope({
1361
+ type: "blank",
1362
+ multiLines: true
1363
+ }, () => {
1364
+ t(`output.push(typeName);\n`);
1365
+ t("break;\n");
1366
+ });
1367
+ });
1368
+ });
1369
+ }
1370
+ };
1371
+ const IMPLEMENTATION_TYPE_COMMENT = `
1372
+ /**
1373
+ * This 'ImplementationType' is used for type hierarchy resolution.
1374
+ */
1375
+ `;
1376
+ const UPCAST_FUNC_COMMENT = `
1377
+ /**
1378
+ * This 'upcastTypes' resolves parent types in the type hierarchy.
1379
+ */
1380
+ `;
1381
+ const DOWNCAST_FUNC_COMMENT = `
1382
+ /**
1383
+ * This 'downcastTypes' resolves child types in the type hierarchy.
1384
+ */
1385
+ `;
1386
+ const WITH_TYPE_NAME_DECLARATION = `
1387
+ export type WithTypeName<T, TypeName extends string> =
1388
+ T extends {readonly __typename: string} ?
1389
+ T :
1390
+ T & {readonly __typename: TypeName};
1391
+ ;
1392
+ `;
1393
+
1394
+ //#endregion
1395
+ //#region src/codegen/type-hierarchy-graph.ts
1396
+ /** Get-or-create a Set in a Map, then add a value to it. */
1397
+ function addToSetMap(map, key, value) {
1398
+ let set = map.get(key);
1399
+ if (!set) {
1400
+ set = /* @__PURE__ */ new Set();
1401
+ map.set(key, set);
1402
+ }
1403
+ set.add(value);
1404
+ }
1405
+ /**
1406
+ * Remove transitive (indirect) entries from the downcast map so that
1407
+ * each parent only lists its *direct* children.
1408
+ *
1409
+ * For example given A → B → C, the entry for A should only contain B,
1410
+ * not C (because C is reachable through B).
1411
+ */
1412
+ function pruneTransitive(map) {
1413
+ for (const [, children] of map) removeReachable(children, children, map);
1414
+ }
1415
+ function removeReachable(target, current, map) {
1416
+ for (const type of current) {
1417
+ if (target !== current) target.delete(type);
1418
+ const deeper = map.get(type);
1419
+ if (deeper) removeReachable(target, deeper, map);
1420
+ }
1421
+ }
1422
+ /** Invert a parent→children map into a child→parents map. */
1423
+ function invertMap(map) {
1424
+ const inverted = /* @__PURE__ */ new Map();
1425
+ for (const [parent, children] of map) for (const child of children) addToSetMap(inverted, child, parent);
1426
+ return inverted;
1427
+ }
1428
+ var TypeHierarchyGraph = class {
1429
+ /** parent → direct children (interface → implementors, union → members) */
1430
+ downcastTypeMap;
1431
+ /** child → direct parents */
1432
+ upcastTypeMap;
1433
+ constructor(schema) {
1434
+ const downcast = /* @__PURE__ */ new Map();
1435
+ const typeMap = schema.getTypeMap();
1436
+ for (const typeName in typeMap) {
1437
+ if (typeName.startsWith("__")) continue;
1438
+ const type = typeMap[typeName];
1439
+ if (type instanceof graphql.GraphQLObjectType || type instanceof graphql.GraphQLInterfaceType) for (const iface of type.getInterfaces()) addToSetMap(downcast, iface, type);
1440
+ if (type instanceof graphql.GraphQLUnionType) for (const member of type.getTypes()) addToSetMap(downcast, type, member);
1441
+ }
1442
+ pruneTransitive(downcast);
1443
+ this.downcastTypeMap = downcast;
1444
+ this.upcastTypeMap = invertMap(downcast);
1445
+ }
1446
+ /** Walk ancestor types recursively, calling `callback` for each. */
1447
+ visitUpcastTypesRecursively(type, callback) {
1448
+ const parents = this.upcastTypeMap.get(type);
1449
+ if (!parents) return;
1450
+ for (const parent of parents) {
1451
+ callback(parent);
1452
+ this.visitUpcastTypesRecursively(parent, callback);
1453
+ }
1454
+ }
1455
+ };
1456
+
1457
+ //#endregion
1458
+ //#region src/codegen/writers/enum-input-metadata.ts
1459
+ var EnumInputMetadataWriter = class EnumInputMetadataWriter extends Writer {
1460
+ constructor(schema, stream, options) {
1461
+ super(stream, options);
1462
+ this.schema = schema;
1463
+ }
1464
+ prepareImports() {
1465
+ const imports = new JSImportCollector((stmt) => this.importStatement(stmt), CODEGEN_IMPORT_SOURCE_MAP);
1466
+ imports.useMapped("EnumInputMetadataBuilder");
1467
+ imports.emit();
1468
+ }
1469
+ writeCode() {
1470
+ const processedTypeNames = /* @__PURE__ */ new Set();
1471
+ const enumInputMetaTypeMap = /* @__PURE__ */ new Map();
1472
+ for (const type of Object.values(this.schema.getTypeMap())) {
1473
+ if (!(type instanceof graphql.GraphQLEnumType) && !(type instanceof graphql.GraphQLInputObjectType)) continue;
1474
+ this.collectEnumMetaTypes(type, processedTypeNames, enumInputMetaTypeMap);
1475
+ }
1476
+ this.text("const builder = new EnumInputMetadataBuilder();\n");
1477
+ for (const [typeName, fields] of enumInputMetaTypeMap) {
1478
+ this.text(`\nbuilder.add("${typeName}"`);
1479
+ if (fields !== void 0) {
1480
+ this.text(", ");
1481
+ this.scope({
1482
+ type: "array",
1483
+ multiLines: true
1484
+ }, () => {
1485
+ for (const field of fields) {
1486
+ this.separator(", ");
1487
+ this.scope({ type: "block" }, () => {
1488
+ this.text(`name: "${field.name}", typeName: "${EnumInputMetadataWriter.inputTypeName(field.type)}", graphqlTypeName: "${EnumInputMetadataWriter.graphqlTypeName(field.type)}"`);
1489
+ if (EnumInputMetadataWriter.isLeafInputType(field.type)) this.text(", isLeaf: true");
1490
+ });
1491
+ }
1492
+ });
1493
+ }
1494
+ this.text(");\n");
1495
+ }
1496
+ this.text("\nexport const ENUM_INPUT_METADATA = builder.build();\n");
1497
+ }
1498
+ collectEnumMetaTypes(type, processedTypeNames, outMap) {
1499
+ if (type instanceof graphql.GraphQLScalarType) return false;
1500
+ if (type instanceof graphql.GraphQLList || type instanceof graphql.GraphQLNonNull) return this.collectEnumMetaTypes(type.ofType, processedTypeNames, outMap);
1501
+ if (type.name.startsWith("__")) return false;
1502
+ if (outMap.has(type.name)) return true;
1503
+ if (processedTypeNames.has(type.name)) return false;
1504
+ if (type instanceof graphql.GraphQLEnumType) {
1505
+ outMap.set(type.name, void 0);
1506
+ return true;
1507
+ }
1508
+ processedTypeNames.add(type.name);
1509
+ const fieldMap = type.getFields();
1510
+ const fields = [];
1511
+ for (const field of Object.values(fieldMap)) {
1512
+ this.collectEnumMetaTypes(field.type, processedTypeNames, outMap);
1513
+ fields.push(field);
1514
+ }
1515
+ outMap.set(type.name, fields);
1516
+ return true;
1517
+ }
1518
+ static inputTypeName(type) {
1519
+ if (type instanceof graphql.GraphQLList) return EnumInputMetadataWriter.inputTypeName(type.ofType);
1520
+ if (type instanceof graphql.GraphQLNonNull) return EnumInputMetadataWriter.inputTypeName(type.ofType);
1521
+ return type.name;
1522
+ }
1523
+ static graphqlTypeName(type) {
1524
+ if (type instanceof graphql.GraphQLList) return `[${EnumInputMetadataWriter.graphqlTypeName(type.ofType)}]`;
1525
+ if (type instanceof graphql.GraphQLNonNull) return `${EnumInputMetadataWriter.graphqlTypeName(type.ofType)}!`;
1526
+ return type.name;
1527
+ }
1528
+ static isLeafInputType(type) {
1529
+ if (type instanceof graphql.GraphQLList || type instanceof graphql.GraphQLNonNull) return EnumInputMetadataWriter.isLeafInputType(type.ofType);
1530
+ return type instanceof graphql.GraphQLScalarType;
1531
+ }
1532
+ };
1533
+
1534
+ //#endregion
1535
+ //#region \0raw:/Users/ashen/Projects/typedgql/src/codegen/templates/async-runtime.template
1536
+ 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";
1537
+
1538
+ //#endregion
1539
+ //#region src/codegen/generator.ts
1540
+ /** Default output directory: node_modules/@ptdgrp/typedgql/__generated */
1541
+ const DEFAULT_TARGET_DIR = (0, path.resolve)(process.cwd(), "node_modules/@ptdgrp/typedgql/__generated");
1542
+ /** Parent package dir: node_modules/@ptdgrp/typedgql */
1543
+ const PACKAGE_DIR = (0, path.resolve)(process.cwd(), "node_modules/@ptdgrp/typedgql");
1544
+ /** Field names reserved by the runtime SelectionNode implementation. */
1545
+ const RESERVED_FIELDS = new Set([
1546
+ "constructor",
1547
+ "addField",
1548
+ "removeField",
1549
+ "addEmbeddable",
1550
+ "addDirective",
1551
+ "fieldMap",
1552
+ "directiveMap",
1553
+ "findField",
1554
+ "findFieldsByName",
1555
+ "findFieldByName",
1556
+ "schemaType",
1557
+ "variableTypeMap",
1558
+ "toString",
1559
+ "toJSON",
1560
+ "toFragmentString"
1561
+ ]);
1562
+ var Generator = class {
1563
+ constructor(options) {
1564
+ this.options = options;
1565
+ }
1566
+ /** Resolved output directory (uses default if not configured) */
1567
+ get targetDir() {
1568
+ return this.options.targetDir ?? DEFAULT_TARGET_DIR;
1569
+ }
1570
+ async generate() {
1571
+ const schema = await this.options.schemaLoader();
1572
+ this.validateSchema(schema);
1573
+ await (0, fs_promises.rm)(this.targetDir, {
1574
+ recursive: true,
1575
+ force: true
1576
+ });
1577
+ await (0, fs_promises.mkdir)(this.targetDir, { recursive: true });
1578
+ const typeHierarchy = new TypeHierarchyGraph(schema);
1579
+ const selectionTypes = [];
1580
+ const inputTypes = [];
1581
+ const enumTypes = [];
1582
+ const typeMap = schema.getTypeMap();
1583
+ for (const typeName in typeMap) {
1584
+ if (typeName.startsWith("__")) continue;
1585
+ const type = typeMap[typeName];
1586
+ if (isExcludedTypeName(this.options, type.name)) continue;
1587
+ if (type instanceof graphql.GraphQLObjectType || type instanceof graphql.GraphQLInterfaceType || type instanceof graphql.GraphQLUnionType) selectionTypes.push(type);
1588
+ else if (type instanceof graphql.GraphQLInputObjectType) inputTypes.push(type);
1589
+ else if (type instanceof graphql.GraphQLEnumType) enumTypes.push(type);
1590
+ }
1591
+ const configuredIdFieldMap = this.options.idFieldMap ?? {};
1592
+ const entityTypes = /* @__PURE__ */ new Set();
1593
+ const embeddedTypes = /* @__PURE__ */ new Set();
1594
+ const idFieldMap = /* @__PURE__ */ new Map();
1595
+ const triggerableTypes = /* @__PURE__ */ new Set();
1596
+ const typesWithParameterizedField = /* @__PURE__ */ new Set();
1597
+ for (const selectionType of selectionTypes) {
1598
+ if (!(selectionType instanceof graphql.GraphQLObjectType) && !(selectionType instanceof graphql.GraphQLInterfaceType)) continue;
1599
+ const fieldMap = selectionType.getFields();
1600
+ if (selectionType.name === "Query") {
1601
+ if (Object.keys(fieldMap).length !== 0) triggerableTypes.add(selectionType);
1602
+ } else {
1603
+ let idFieldName = configuredIdFieldMap[selectionType.name];
1604
+ if (idFieldName === void 0) {
1605
+ let configuredUpcastType = void 0;
1606
+ typeHierarchy.visitUpcastTypesRecursively(selectionType, (upcastType) => {
1607
+ const newIdFieldName = configuredIdFieldMap[upcastType.name];
1608
+ if (idFieldName === void 0) {
1609
+ configuredUpcastType = upcastType;
1610
+ idFieldName = newIdFieldName;
1611
+ } else if (idFieldName !== newIdFieldName) throw new Error(`Conflict id property configuration: ${configuredUpcastType.name}.${idFieldName} and ${selectionType.name}.${newIdFieldName}`);
1612
+ });
1613
+ }
1614
+ const idField = fieldMap[idFieldName ?? "id"];
1615
+ if (idField != null) {
1616
+ idFieldMap.set(selectionType, idField);
1617
+ entityTypes.add(selectionType);
1618
+ if (Object.keys(fieldMap).length !== 1) triggerableTypes.add(selectionType);
1619
+ } else embeddedTypes.add(selectionType);
1620
+ }
1621
+ for (const fieldName in fieldMap) if (fieldMap[fieldName].args.length !== 0) {
1622
+ typesWithParameterizedField.add(selectionType);
1623
+ break;
1624
+ }
1625
+ }
1626
+ const ctx = {
1627
+ schema,
1628
+ typeHierarchy,
1629
+ selectionTypes,
1630
+ entityTypes,
1631
+ embeddedTypes,
1632
+ triggerableTypes,
1633
+ idFieldMap,
1634
+ typesWithParameterizedField
1635
+ };
1636
+ const promises = [];
1637
+ if (selectionTypes.length !== 0) {
1638
+ await (0, fs_promises.mkdir)((0, path.join)(this.targetDir, "selections"), { recursive: true });
1639
+ promises.push(this.generateSelectionTypes(ctx));
1640
+ }
1641
+ if (inputTypes.length !== 0) {
1642
+ await (0, fs_promises.mkdir)((0, path.join)(this.targetDir, "inputs"), { recursive: true });
1643
+ promises.push(this.generateInputTypes(inputTypes));
1644
+ }
1645
+ if (enumTypes.length !== 0) {
1646
+ await (0, fs_promises.mkdir)((0, path.join)(this.targetDir, "enums"), { recursive: true });
1647
+ promises.push(this.generateEnumTypes(enumTypes));
1648
+ }
1649
+ promises.push(this.generateTypeHierarchy(schema, typeHierarchy));
1650
+ promises.push(this.generateEnumInputMetadata(schema));
1651
+ promises.push(this.generateAsyncRuntime());
1652
+ promises.push(this.writeIndex(schema, ctx));
1653
+ await Promise.all(promises);
1654
+ if (this.options.targetDir === void 0) await this.writePackageEntrypoint(schema, ctx);
1655
+ }
1656
+ createSelectionWriter(modelType, ctx, stream, options) {
1657
+ return new SelectionWriter(modelType, ctx, stream, options);
1658
+ }
1659
+ additionalExportedTypeNamesForSelection(_modelType, _ctx) {
1660
+ return [];
1661
+ }
1662
+ async generateSelectionTypes(ctx) {
1663
+ const dir = (0, path.join)(this.targetDir, "selections");
1664
+ const emptySelectionNameMap = /* @__PURE__ */ new Map();
1665
+ const defaultSelectionNameMap = /* @__PURE__ */ new Map();
1666
+ const suffix = this.options?.selectionSuffix ?? "Selection";
1667
+ const promises = ctx.selectionTypes.map(async (type) => {
1668
+ const stream = createStream((0, path.join)(dir, `${toKebabCase(`${type.name}${suffix}`)}.ts`));
1669
+ const writer = this.createSelectionWriter(type, ctx, stream, this.options);
1670
+ emptySelectionNameMap.set(type, writer.emptySelectionName);
1671
+ if (writer.defaultSelectionName !== void 0) defaultSelectionNameMap.set(type, writer.defaultSelectionName);
1672
+ writer.write();
1673
+ await endStream(stream);
1674
+ });
1675
+ await Promise.all([...promises, (async () => {
1676
+ const stream = createStream((0, path.join)(dir, "index.ts"));
1677
+ for (const type of ctx.selectionTypes) {
1678
+ const selectionTypeName = `${type.name}${suffix}`;
1679
+ const selectionFileName = toKebabCase(selectionTypeName);
1680
+ const typeExports = [
1681
+ selectionTypeName,
1682
+ (type instanceof graphql.GraphQLObjectType || type instanceof graphql.GraphQLInterfaceType) && ctx.typesWithParameterizedField.has(type) ? `${type.name}Args` : void 0,
1683
+ ...this.additionalExportedTypeNamesForSelection(type, ctx)
1684
+ ].filter(Boolean).join(", ");
1685
+ stream.write(`export type {${typeExports}} from './${selectionFileName}';\n`);
1686
+ const defaultSelectionName = defaultSelectionNameMap.get(type);
1687
+ const valueExports = [emptySelectionNameMap.get(type), defaultSelectionName].filter(Boolean).join(", ");
1688
+ if (valueExports.length !== 0) stream.write(`export {${valueExports}} from './${selectionFileName}';\n`);
1689
+ }
1690
+ await stream.end();
1691
+ })()]);
1692
+ }
1693
+ async generateInputTypes(inputTypes) {
1694
+ const dir = (0, path.join)(this.targetDir, "inputs");
1695
+ const promises = inputTypes.map(async (type) => {
1696
+ const stream = createStream((0, path.join)(dir, `${toKebabCase(type.name)}.ts`));
1697
+ new InputWriter(type, stream, this.options).write();
1698
+ await stream.end();
1699
+ });
1700
+ await Promise.all([...promises, this.writeSimpleIndex(dir, inputTypes)]);
1701
+ }
1702
+ async generateEnumTypes(enumTypes) {
1703
+ const dir = (0, path.join)(this.targetDir, "enums");
1704
+ const promises = enumTypes.map(async (type) => {
1705
+ const stream = createStream((0, path.join)(dir, `${toKebabCase(type.name)}.ts`));
1706
+ new EnumWriter(type, stream, this.options).write();
1707
+ await stream.end();
1708
+ });
1709
+ await Promise.all([...promises, this.writeSimpleIndex(dir, enumTypes, true)]);
1710
+ }
1711
+ async generateTypeHierarchy(schema, typeHierarchy) {
1712
+ const stream = createStream((0, path.join)(this.targetDir, "type-hierarchy.ts"));
1713
+ new TypeHierarchyWriter(schema, typeHierarchy, stream, this.options).write();
1714
+ await endStream(stream);
1715
+ }
1716
+ async generateEnumInputMetadata(schema) {
1717
+ const stream = createStream((0, path.join)(this.targetDir, "enum-input-metadata.ts"));
1718
+ new EnumInputMetadataWriter(schema, stream, this.options).write();
1719
+ await endStream(stream);
1720
+ }
1721
+ async writeSimpleIndex(dir, types, typeOnly = true) {
1722
+ const stream = createStream((0, path.join)(dir, "index.ts"));
1723
+ const keyword = typeOnly ? "export type" : "export";
1724
+ for (const type of types) stream.write(`${keyword} {${type.name}} from './${toKebabCase(type.name)}';\n`);
1725
+ await stream.end();
1726
+ }
1727
+ async generateAsyncRuntime() {
1728
+ const stream = createStream((0, path.join)(this.targetDir, "client-runtime.ts"));
1729
+ stream.write(async_runtime_default);
1730
+ await endStream(stream);
1731
+ }
1732
+ async writeIndex(schema, ctx) {
1733
+ const stream = createStream((0, path.join)(this.targetDir, "index.ts"));
1734
+ const selectionSuffix = this.options.selectionSuffix ?? "Selection";
1735
+ stream.write(`import type { Selection, ExecutableSelection, SchemaType, ShapeOf, VariablesOf } from "../dist/index.mjs";\n`);
1736
+ stream.write(`import { FragmentRef, createSelection, resolveRegisteredSchemaType } from "../dist/index.mjs";\n`);
1737
+ for (const type of ctx.selectionTypes) {
1738
+ const selectionTypeName = `${type.name}${selectionSuffix}`;
1739
+ stream.write(`import type { ${selectionTypeName} } from "./selections/${toKebabCase(selectionTypeName)}";\n`);
1740
+ }
1741
+ stream.write(`import { ENUM_INPUT_METADATA } from "./enum-input-metadata";\n\n`);
1742
+ stream.write(`export type { GraphQLExecutor, GraphQLSubscriber, Simplify } from "./client-runtime";\n`);
1743
+ stream.write(`export { setGraphQLExecutor, setGraphQLSubscriber, execute, subscribe } from "./client-runtime";\n`);
1744
+ stream.write("export type { ImplementationType } from './type-hierarchy';\n");
1745
+ stream.write("export { upcastTypes, downcastTypes } from './type-hierarchy';\n");
1746
+ stream.write(`export interface FragmentSelectionMap<T extends object = {}, TVariables extends object = {}> {\n`);
1747
+ for (const type of ctx.selectionTypes) {
1748
+ const selectionTypeName = `${type.name}${selectionSuffix}`;
1749
+ stream.write(` '${type.name}': ${selectionTypeName}<T, TVariables>;\n`);
1750
+ }
1751
+ stream.write("}\n");
1752
+ stream.write(`export type FragmentTypeName = keyof FragmentSelectionMap;\n`);
1753
+ stream.write(`export type FragmentSelectionFor<E extends FragmentTypeName, T extends object = {}, TVariables extends object = {}> = FragmentSelectionMap<T, TVariables>[E];\n`);
1754
+ stream.write(`\nexport function fragment$<const E extends FragmentTypeName, S extends FragmentSelectionFor<E, object, object>>(\n`);
1755
+ stream.write(` typeName: E,\n`);
1756
+ stream.write(` builder: (it: FragmentSelectionFor<E, {}, {}>) => S,\n`);
1757
+ stream.write(` fragmentName?: string,\n`);
1758
+ stream.write(`): FragmentRef<string, E, ShapeOf<S>, VariablesOf<S>> {\n`);
1759
+ stream.write(` const schemaType = resolveRegisteredSchemaType(typeName);\n`);
1760
+ stream.write(` if (!schemaType) {\n`);
1761
+ stream.write(` throw new Error(\`Cannot resolve schema type \"\${typeName}\" for fragment$\`);\n`);
1762
+ stream.write(` }\n`);
1763
+ stream.write(` const base = createSelection<E, Selection<E, {}, {}>>(\n`);
1764
+ stream.write(` schemaType as SchemaType<E>,\n`);
1765
+ stream.write(` ENUM_INPUT_METADATA,\n`);
1766
+ stream.write(` undefined,\n`);
1767
+ stream.write(` );\n`);
1768
+ stream.write(` const selection = builder(base as unknown as FragmentSelectionFor<E, {}, {}>);\n`);
1769
+ stream.write(` return new FragmentRef(\n`);
1770
+ stream.write(` fragmentName ?? \`\${typeName}Fragment\`,\n`);
1771
+ stream.write(` selection as unknown as ExecutableSelection<E, ShapeOf<S>, VariablesOf<S>>,\n`);
1772
+ stream.write(` );\n`);
1773
+ stream.write(`}\n`);
1774
+ await endStream(stream);
1775
+ }
1776
+ /**
1777
+ * Creates node_modules/@ptdgrp/typedgql/index.ts
1778
+ * so users can import generated types and the root gateway via `import { G } from '@ptdgrp/typedgql'`.
1779
+ * Also patches package.json exports for ESM/type resolution to point to the generated entry.
1780
+ */
1781
+ async writePackageEntrypoint(schema, ctx) {
1782
+ await (0, fs_promises.mkdir)(PACKAGE_DIR, { recursive: true });
1783
+ const indexStream = createStream((0, path.join)(PACKAGE_DIR, "index.ts"));
1784
+ this.writePackageIndexCode(indexStream, schema, ctx);
1785
+ await endStream(indexStream);
1786
+ await this.patchPackageJsonForGeneratedEntrypoint();
1787
+ }
1788
+ async patchPackageJsonForGeneratedEntrypoint() {
1789
+ const packageJsonPath = (0, path.join)(PACKAGE_DIR, "package.json");
1790
+ const raw = await (0, fs_promises.readFile)(packageJsonPath, "utf8");
1791
+ const pkg = JSON.parse(raw);
1792
+ const exportsMap = typeof pkg.exports === "object" && pkg.exports !== null ? pkg.exports : {};
1793
+ const rootExportRaw = exportsMap["."];
1794
+ const rootExport = typeof rootExportRaw === "object" && rootExportRaw !== null ? rootExportRaw : {};
1795
+ const importExportRaw = rootExport.import;
1796
+ const importExport = typeof importExportRaw === "object" && importExportRaw !== null ? importExportRaw : {};
1797
+ importExport.types = "./index.ts";
1798
+ importExport.default = "./index.ts";
1799
+ rootExport.import = importExport;
1800
+ exportsMap["."] = rootExport;
1801
+ pkg.exports = exportsMap;
1802
+ pkg.types = "./index.ts";
1803
+ await (0, fs_promises.writeFile)(packageJsonPath, `${JSON.stringify(pkg, null, 2)}\n`, "utf8");
1804
+ }
1805
+ writePackageIndexCode(stream, schema, _ctx) {
1806
+ const typeMap = schema.getTypeMap();
1807
+ const queryType = typeMap["Query"];
1808
+ const mutationType = typeMap["Mutation"];
1809
+ const subscriptionType = typeMap["Subscription"];
1810
+ stream.write(`export * from './__generated/index';\n`);
1811
+ 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`);
1812
+ stream.write(`export { FragmentSpread, FragmentRef, StringValue, runtimeOf, createSchemaType, resolveRegisteredSchemaType, registerSchemaTypeFactory, SelectionNode, createSelection, ParameterRef, EnumInputMetadataBuilder, TextBuilder, cyrb53 } from './dist/index.mjs';\n`);
1813
+ stream.write(`import { fragment$ } from './__generated/index';\n`);
1814
+ if (queryType instanceof graphql.GraphQLObjectType) stream.write(`import { query$ } from './__generated/selections/${toKebabCase("QuerySelection")}';\n`);
1815
+ if (mutationType instanceof graphql.GraphQLObjectType) stream.write(`import { mutation$ } from './__generated/selections/${toKebabCase("MutationSelection")}';\n`);
1816
+ if (subscriptionType instanceof graphql.GraphQLObjectType) stream.write(`import { subscription$ } from './__generated/selections/${toKebabCase("SubscriptionSelection")}';\n`);
1817
+ stream.write("\n");
1818
+ if (queryType instanceof graphql.GraphQLObjectType) stream.write("export { query$ };\n");
1819
+ if (mutationType instanceof graphql.GraphQLObjectType) stream.write("export { mutation$ };\n");
1820
+ if (subscriptionType instanceof graphql.GraphQLObjectType) stream.write("export { subscription$ };\n");
1821
+ stream.write("\n");
1822
+ stream.write("export const G = {\n");
1823
+ if (queryType instanceof graphql.GraphQLObjectType) stream.write(" query: query$,\n");
1824
+ if (mutationType instanceof graphql.GraphQLObjectType) stream.write(" mutation: mutation$,\n");
1825
+ if (subscriptionType instanceof graphql.GraphQLObjectType) stream.write(" subscription: subscription$,\n");
1826
+ stream.write(" fragment: fragment$,\n");
1827
+ stream.write("} as const;\n");
1828
+ if (this.hasGeneratedEnums(schema)) stream.write(`export * from './__generated/enums';\n`);
1829
+ if (this.hasGeneratedInputs(schema)) stream.write(`export * from './__generated/inputs';\n`);
1830
+ stream.write(`export type * from './__generated/selections';\n`);
1831
+ stream.write(`export type * from './__generated/type-hierarchy';\n`);
1832
+ }
1833
+ hasGeneratedEnums(schema) {
1834
+ const typeMap = schema.getTypeMap();
1835
+ for (const typeName in typeMap) {
1836
+ if (typeName.startsWith("__")) continue;
1837
+ const type = typeMap[typeName];
1838
+ if (type instanceof graphql.GraphQLEnumType && !isExcludedTypeName(this.options, type.name)) return true;
1839
+ }
1840
+ return false;
1841
+ }
1842
+ hasGeneratedInputs(schema) {
1843
+ const typeMap = schema.getTypeMap();
1844
+ for (const typeName in typeMap) {
1845
+ if (typeName.startsWith("__")) continue;
1846
+ const type = typeMap[typeName];
1847
+ if (type instanceof graphql.GraphQLInputObjectType && !isExcludedTypeName(this.options, type.name)) return true;
1848
+ }
1849
+ return false;
1850
+ }
1851
+ validateSchema(schema) {
1852
+ const typeMap = schema.getTypeMap();
1853
+ for (const typeName in typeMap) {
1854
+ const type = typeMap[typeName];
1855
+ if (type instanceof graphql.GraphQLObjectType || type instanceof graphql.GraphQLInterfaceType) {
1856
+ 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`);
1857
+ }
1858
+ }
1859
+ const { idFieldMap } = this.options;
1860
+ if (idFieldMap) for (const typeName in idFieldMap) {
1861
+ const type = typeMap[typeName];
1862
+ if (!(type instanceof graphql.GraphQLObjectType) && !(type instanceof graphql.GraphQLInterfaceType)) throw new Error(`config.idFieldMap contains an illegal key '${typeName}', that is neither a graphql object type nor graphql interface type`);
1863
+ const idField = type.getFields()[idFieldMap[typeName]];
1864
+ if (!idField) throw new Error(`config.idFieldMap['${typeName}'] is illegal, there is no field named '${idFieldMap[typeName]}' in the type '${typeName}'`);
1865
+ 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`);
1866
+ }
1867
+ const { defaultSelectionExcludeMap: excludeMap } = this.options;
1868
+ if (excludeMap) for (const typeName in excludeMap) {
1869
+ const type = typeMap[typeName];
1870
+ if (!(type instanceof graphql.GraphQLObjectType) && !(type instanceof graphql.GraphQLInterfaceType)) throw new Error(`config.defaultSelectionExcludeMap contains an illegal key '${typeName}' that is neither a graphql object type nor graphql interface type`);
1871
+ const fieldMap = type.getFields();
1872
+ const fieldNames = excludeMap[typeName];
1873
+ if (!Array.isArray(fieldNames)) throw new Error(`config.defaultSelectionExcludeMap['${typeName}'] is not array`);
1874
+ for (let i = 0; i < fieldNames.length; i++) {
1875
+ const fieldName = fieldNames[i];
1876
+ 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}'`);
1877
+ }
1878
+ }
1879
+ }
1880
+ };
1881
+ function createStream(path$1) {
1882
+ return (0, fs.createWriteStream)(path$1);
1883
+ }
1884
+ function endStream(stream) {
1885
+ return new Promise((resolve, reject) => {
1886
+ stream.end(() => resolve());
1887
+ stream.on("error", reject);
1888
+ });
1889
+ }
1890
+
1891
+ //#endregion
1892
+ //#region src/codegen/schema-loader.ts
1893
+ async function loadRemoteSchema(endpoint, headers) {
1894
+ const body = JSON.stringify({ query: (0, graphql.getIntrospectionQuery)({ oneOf: true }) });
1895
+ const { data, errors } = await (await fetch(endpoint, {
1896
+ method: "POST",
1897
+ body,
1898
+ headers: {
1899
+ Accept: "application/json",
1900
+ "Content-Type": "application/json",
1901
+ ...headers
1902
+ }
1903
+ })).json();
1904
+ if (errors !== void 0) throw new Error(JSON.stringify(errors));
1905
+ return (0, graphql.buildClientSchema)(data);
1906
+ }
1907
+ async function loadLocalSchema(location) {
1908
+ return (0, graphql.buildSchema)(await (0, fs_promises.readFile)(location, { encoding: "utf8" }));
1909
+ }
1910
+
1911
+ //#endregion
1912
+ Object.defineProperty(exports, 'Generator', {
1913
+ enumerable: true,
1914
+ get: function () {
1915
+ return Generator;
1916
+ }
1917
+ });
1918
+ Object.defineProperty(exports, 'loadLocalSchema', {
1919
+ enumerable: true,
1920
+ get: function () {
1921
+ return loadLocalSchema;
1922
+ }
1923
+ });
1924
+ Object.defineProperty(exports, 'loadRemoteSchema', {
1925
+ enumerable: true,
1926
+ get: function () {
1927
+ return loadRemoteSchema;
1928
+ }
1929
+ });