@ptdgrp/typedgql 1.0.0-beta.13 → 1.0.0-beta.14

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.
@@ -2,6 +2,7 @@ import { GraphQLEnumType, GraphQLInputObjectType, GraphQLInterfaceType, GraphQLL
2
2
  import { mkdir, readFile, rm, writeFile } from "fs/promises";
3
3
  import { createWriteStream } from "fs";
4
4
  import { join, resolve } from "path";
5
+ import ts from "typescript";
5
6
 
6
7
  //#region src/codegen/utils.ts
7
8
  /**
@@ -36,6 +37,132 @@ function toKebabCase(name) {
36
37
  return name.replace(/([A-Z]+)([A-Z][a-z])/g, "$1-$2").replace(/([a-z\d])([A-Z])/g, "$1-$2").toLowerCase();
37
38
  }
38
39
 
40
+ //#endregion
41
+ //#region src/codegen/imports.ts
42
+ /**
43
+ * Shared import collector for codegen writers.
44
+ *
45
+ * Responsibilities:
46
+ * - normalize imports by source
47
+ * - deduplicate symbols
48
+ * - keep emitted import statements stable (sorted)
49
+ */
50
+ var JSImportCollector = class {
51
+ typeBySource = /* @__PURE__ */ new Map();
52
+ valueBySource = /* @__PURE__ */ new Map();
53
+ sideEffects = /* @__PURE__ */ new Set();
54
+ constructor(sink, sourceMap) {
55
+ this.sink = sink;
56
+ this.sourceMap = sourceMap;
57
+ }
58
+ useMapped(symbol) {
59
+ const spec = this.sourceMap[symbol];
60
+ if (spec.kind === "type") this.useType(spec.source, symbol);
61
+ else this.useValue(spec.source, symbol);
62
+ }
63
+ useType(source, symbol) {
64
+ this.collect(this.typeBySource, source, symbol);
65
+ }
66
+ useValue(source, symbol) {
67
+ this.collect(this.valueBySource, source, symbol);
68
+ }
69
+ useSideEffect(source) {
70
+ this.sideEffects.add(source);
71
+ }
72
+ emit() {
73
+ for (const [source, symbols] of this.sorted(this.typeBySource)) this.sink(`import type { ${Array.from(symbols).sort().join(", ")} } from '${source}';`);
74
+ for (const [source, symbols] of this.sorted(this.valueBySource)) this.sink(`import { ${Array.from(symbols).sort().join(", ")} } from '${source}';`);
75
+ for (const source of Array.from(this.sideEffects).sort()) this.sink(`import '${source}';`);
76
+ }
77
+ collect(map, source, symbol) {
78
+ const set = map.get(source) ?? /* @__PURE__ */ new Set();
79
+ set.add(symbol);
80
+ map.set(source, set);
81
+ }
82
+ sorted(map) {
83
+ return Array.from(map.entries()).sort((a, b) => a[0].localeCompare(b[0]));
84
+ }
85
+ };
86
+ const RUNTIME_ENTRY_SOURCE = "../../dist/index.mjs";
87
+ const TYPE_HIERARCHY_SOURCE = "../type-hierarchy";
88
+ const ENUM_INPUT_METADATA_SOURCE = "../enum-input-metadata";
89
+ const SCALAR_TYPES_SOURCE = "../scalar-types";
90
+ const SCALAR_TYPES_NAMESPACE = "UserScalarTypes";
91
+ const CODEGEN_IMPORT_SOURCE_MAP = {
92
+ AcceptableVariables: {
93
+ source: RUNTIME_ENTRY_SOURCE,
94
+ kind: "type"
95
+ },
96
+ UnresolvedVariables: {
97
+ source: RUNTIME_ENTRY_SOURCE,
98
+ kind: "type"
99
+ },
100
+ DirectiveArgs: {
101
+ source: RUNTIME_ENTRY_SOURCE,
102
+ kind: "type"
103
+ },
104
+ Selection: {
105
+ source: RUNTIME_ENTRY_SOURCE,
106
+ kind: "type"
107
+ },
108
+ ShapeOf: {
109
+ source: RUNTIME_ENTRY_SOURCE,
110
+ kind: "type"
111
+ },
112
+ VariablesOf: {
113
+ source: RUNTIME_ENTRY_SOURCE,
114
+ kind: "type"
115
+ },
116
+ ValueOrThunk: {
117
+ source: RUNTIME_ENTRY_SOURCE,
118
+ kind: "type"
119
+ },
120
+ FragmentSpread: {
121
+ source: RUNTIME_ENTRY_SOURCE,
122
+ kind: "type"
123
+ },
124
+ createSelection: {
125
+ source: RUNTIME_ENTRY_SOURCE,
126
+ kind: "value"
127
+ },
128
+ withOperationName: {
129
+ source: RUNTIME_ENTRY_SOURCE,
130
+ kind: "value"
131
+ },
132
+ createSchemaType: {
133
+ source: RUNTIME_ENTRY_SOURCE,
134
+ kind: "value"
135
+ },
136
+ registerSchemaTypeFactory: {
137
+ source: RUNTIME_ENTRY_SOURCE,
138
+ kind: "value"
139
+ },
140
+ resolveRegisteredSchemaType: {
141
+ source: RUNTIME_ENTRY_SOURCE,
142
+ kind: "value"
143
+ },
144
+ ENUM_INPUT_METADATA: {
145
+ source: ENUM_INPUT_METADATA_SOURCE,
146
+ kind: "value"
147
+ },
148
+ SCALAR_TYPE_NAMESPACE: {
149
+ source: SCALAR_TYPES_SOURCE,
150
+ kind: "type"
151
+ },
152
+ WithTypeName: {
153
+ source: TYPE_HIERARCHY_SOURCE,
154
+ kind: "type"
155
+ },
156
+ ImplementationType: {
157
+ source: TYPE_HIERARCHY_SOURCE,
158
+ kind: "type"
159
+ },
160
+ EnumInputMetadataBuilder: {
161
+ source: "../dist/index.mjs",
162
+ kind: "value"
163
+ }
164
+ };
165
+
39
166
  //#endregion
40
167
  //#region src/codegen/writer.ts
41
168
  const SCOPE_BRACKETS = {
@@ -74,7 +201,7 @@ var Writer = class {
74
201
  needIndent = false;
75
202
  importStatements = /* @__PURE__ */ new Set();
76
203
  importedTypes = /* @__PURE__ */ new Set();
77
- importedScalarTypes = /* @__PURE__ */ new Map();
204
+ usesScalarTypeNamespaceImport = false;
78
205
  importFinalized = false;
79
206
  constructor(stream, options) {
80
207
  this.stream = stream;
@@ -117,11 +244,7 @@ var Writer = class {
117
244
  return;
118
245
  }
119
246
  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);
247
+ if (this.options.scalarTypeMap[namedType.name]) this.usesScalarTypeNamespaceImport = true;
125
248
  }
126
249
  }
127
250
  importStatement(statement) {
@@ -209,9 +332,13 @@ var Writer = class {
209
332
  return;
210
333
  }
211
334
  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);
335
+ if (this.options.scalarTypeMap?.[type.name]) {
336
+ this.text(`${SCALAR_TYPES_NAMESPACE}.${type.name}`);
337
+ return;
338
+ }
339
+ const fallback = SCALAR_MAP[type.name];
340
+ if (!fallback) throw new Error(`Unknown scalar type ${type.name}`);
341
+ this.text(fallback);
215
342
  return;
216
343
  }
217
344
  if (type instanceof GraphQLEnumType || type instanceof GraphQLInputObjectType) {
@@ -259,10 +386,10 @@ var Writer = class {
259
386
  }
260
387
  }
261
388
  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`);
389
+ if (!this.usesScalarTypeNamespaceImport) return;
390
+ const source = CODEGEN_IMPORT_SOURCE_MAP.SCALAR_TYPE_NAMESPACE.source;
391
+ const importSource = this.isUnderGlobalDir() ? source.replace(/^\.\.\//, "./") : source;
392
+ this.stream.write(`import type { ${SCALAR_TYPES_NAMESPACE} } from '${importSource}';\n`);
266
393
  }
267
394
  typeApplication(typeName, renderTypeArg) {
268
395
  this.text(`${typeName}<`);
@@ -307,7 +434,7 @@ var Writer = class {
307
434
  });
308
435
  }
309
436
  get hasAnyImports() {
310
- return this.importStatements.size !== 0 || this.importedTypes.size !== 0 || this.importedScalarTypes.size !== 0;
437
+ return this.importStatements.size !== 0 || this.importedTypes.size !== 0 || this.usesScalarTypeNamespaceImport;
311
438
  }
312
439
  writeUnion(members) {
313
440
  this.enter("blank");
@@ -329,126 +456,6 @@ function unwrapType(type) {
329
456
  return type;
330
457
  }
331
458
 
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
- ShapeOf: {
399
- source: RUNTIME_ENTRY_SOURCE,
400
- kind: "type"
401
- },
402
- VariablesOf: {
403
- source: RUNTIME_ENTRY_SOURCE,
404
- kind: "type"
405
- },
406
- ValueOrThunk: {
407
- source: RUNTIME_ENTRY_SOURCE,
408
- kind: "type"
409
- },
410
- FragmentSpread: {
411
- source: RUNTIME_ENTRY_SOURCE,
412
- kind: "type"
413
- },
414
- createSelection: {
415
- source: RUNTIME_ENTRY_SOURCE,
416
- kind: "value"
417
- },
418
- withOperationName: {
419
- source: RUNTIME_ENTRY_SOURCE,
420
- kind: "value"
421
- },
422
- createSchemaType: {
423
- source: RUNTIME_ENTRY_SOURCE,
424
- kind: "value"
425
- },
426
- registerSchemaTypeFactory: {
427
- source: RUNTIME_ENTRY_SOURCE,
428
- kind: "value"
429
- },
430
- resolveRegisteredSchemaType: {
431
- source: RUNTIME_ENTRY_SOURCE,
432
- kind: "value"
433
- },
434
- ENUM_INPUT_METADATA: {
435
- source: ENUM_INPUT_METADATA_SOURCE,
436
- kind: "value"
437
- },
438
- WithTypeName: {
439
- source: TYPE_HIERARCHY_SOURCE,
440
- kind: "type"
441
- },
442
- ImplementationType: {
443
- source: TYPE_HIERARCHY_SOURCE,
444
- kind: "type"
445
- },
446
- EnumInputMetadataBuilder: {
447
- source: "../dist/index.mjs",
448
- kind: "value"
449
- }
450
- };
451
-
452
459
  //#endregion
453
460
  //#region src/codegen/writers/selection.ts
454
461
  var SelectionWriter = class extends Writer {
@@ -1571,9 +1578,38 @@ var EnumInputMetadataWriter = class EnumInputMetadataWriter extends Writer {
1571
1578
  };
1572
1579
 
1573
1580
  //#endregion
1574
- //#region \0raw:/home/runner/work/typedgql/typedgql/src/codegen/templates/async-runtime.template
1581
+ //#region \0raw:/Users/ashen/Projects/typedgql/src/codegen/templates/async-runtime.template
1575
1582
  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<unknown>;\n\nexport type GraphQLSubscriber = (\n request: string,\n variables: Record<string, unknown>,\n) => AsyncIterable<unknown> | Promise<AsyncIterable<unknown>>;\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];\ntype GraphQLRawResponse = {\n readonly data?: unknown;\n readonly errors?: unknown;\n};\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 ) as GraphQLRawResponse;\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) as GraphQLRawResponse;\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: unknown) {\n super();\n this.errors = normalizeGraphQLErrors(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\nfunction normalizeGraphQLErrors(errors: unknown): readonly GraphQLSubError[] {\n if (!Array.isArray(errors)) {\n return [{ message: \"Unknown GraphQL error\", path: [] }];\n }\n return errors.map((item) => {\n if (!item || typeof item !== \"object\") {\n return { message: String(item), path: [] };\n }\n const rec = item as Record<string, unknown>;\n return {\n message: typeof rec.message === \"string\" ? rec.message : \"Unknown GraphQL error\",\n path: Array.isArray(rec.path)\n ? rec.path.filter((p): p is string => typeof p === \"string\")\n : [],\n };\n });\n}\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";
1576
1583
 
1584
+ //#endregion
1585
+ //#region src/codegen/scalar-type-declarations.ts
1586
+ function analyzeScalarTypeDeclarations(source) {
1587
+ if (!source || source.trim().length === 0) return { exportedNames: /* @__PURE__ */ new Set() };
1588
+ if ((ts.transpileModule(source, {
1589
+ reportDiagnostics: true,
1590
+ compilerOptions: {
1591
+ target: ts.ScriptTarget.ESNext,
1592
+ module: ts.ModuleKind.ESNext
1593
+ },
1594
+ fileName: "scalar-types.ts"
1595
+ }).diagnostics ?? []).some((d) => d.category === ts.DiagnosticCategory.Error)) throw new Error("scalarTypeDeclarations has TypeScript syntax errors");
1596
+ const sf = ts.createSourceFile("scalar-types.ts", source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
1597
+ const exportedNames = /* @__PURE__ */ new Set();
1598
+ for (let i = 0; i < sf.statements.length; i++) {
1599
+ const stmt = sf.statements[i];
1600
+ if (ts.isTypeAliasDeclaration(stmt) || ts.isInterfaceDeclaration(stmt)) {
1601
+ if (stmt.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword)) {
1602
+ const name = stmt.name.text;
1603
+ if (exportedNames.has(name)) throw new Error(`scalarTypeDeclarations has duplicate export '${name}'`);
1604
+ exportedNames.add(name);
1605
+ }
1606
+ continue;
1607
+ }
1608
+ throw new Error(`scalarTypeDeclarations statement[${i}] must be type/interface declaration`);
1609
+ }
1610
+ return { exportedNames };
1611
+ }
1612
+
1577
1613
  //#endregion
1578
1614
  //#region src/codegen/generator.ts
1579
1615
  /** Default output directory: node_modules/@ptdgrp/typedgql/__generated */
@@ -1609,6 +1645,7 @@ var Generator = class {
1609
1645
  async generate() {
1610
1646
  const schema = await this.options.schemaLoader();
1611
1647
  this.validateSchema(schema);
1648
+ this.validateScalarTypeDeclarations();
1612
1649
  await rm(this.targetDir, {
1613
1650
  recursive: true,
1614
1651
  force: true
@@ -1688,6 +1725,7 @@ var Generator = class {
1688
1725
  promises.push(this.generateTypeHierarchy(schema, typeHierarchy));
1689
1726
  promises.push(this.generateEnumInputMetadata(schema));
1690
1727
  promises.push(this.generateAsyncRuntime());
1728
+ if (this.hasScalarTypes()) promises.push(this.generateScalarTypes());
1691
1729
  promises.push(this.writeIndex(schema, ctx));
1692
1730
  await Promise.all(promises);
1693
1731
  if (this.options.targetDir === void 0) await this.writePackageEntrypoint(schema, ctx);
@@ -1768,6 +1806,35 @@ var Generator = class {
1768
1806
  stream.write(async_runtime_default);
1769
1807
  await endStream(stream);
1770
1808
  }
1809
+ async generateScalarTypes() {
1810
+ const stream = createStream(join(this.targetDir, "scalar-types.ts"));
1811
+ const analysis = analyzeScalarTypeDeclarations(this.options.scalarTypeDeclarations);
1812
+ const code = this.options.scalarTypeDeclarations?.trim();
1813
+ if (code && code.length !== 0) {
1814
+ const indented = code.split("\n").map((line) => line.length === 0 ? line : ` ${line}`).join("\n");
1815
+ stream.write(`export declare namespace ${SCALAR_TYPES_NAMESPACE} {\n`);
1816
+ stream.write(`${indented}\n`);
1817
+ this.writeScalarMapAliases(stream, analysis.exportedNames);
1818
+ stream.write("}\n");
1819
+ } else {
1820
+ const scalarMap = this.options.scalarTypeMap;
1821
+ if (scalarMap && Object.keys(scalarMap).length !== 0) {
1822
+ stream.write(`export declare namespace ${SCALAR_TYPES_NAMESPACE} {\n`);
1823
+ this.writeScalarMapAliases(stream, analysis.exportedNames);
1824
+ stream.write("}\n");
1825
+ } else stream.write("export {};\n");
1826
+ }
1827
+ await endStream(stream);
1828
+ }
1829
+ writeScalarMapAliases(stream, exportedNames) {
1830
+ const scalarMap = this.options.scalarTypeMap;
1831
+ if (!scalarMap) return;
1832
+ const entries = Object.entries(scalarMap).sort((a, b) => a[0].localeCompare(b[0]));
1833
+ for (const [scalarName, mappedType] of entries) {
1834
+ if (exportedNames.has(scalarName)) continue;
1835
+ stream.write(` export type ${scalarName} = ${mappedType};\n`);
1836
+ }
1837
+ }
1771
1838
  async writeIndex(schema, ctx) {
1772
1839
  const stream = createStream(join(this.targetDir, "index.ts"));
1773
1840
  const selectionSuffix = this.options.selectionSuffix ?? "Selection";
@@ -1778,6 +1845,7 @@ var Generator = class {
1778
1845
  stream.write(`import type { ${selectionTypeName} } from "./selections/${toKebabCase(selectionTypeName)}";\n`);
1779
1846
  }
1780
1847
  stream.write(`import { ENUM_INPUT_METADATA } from "./enum-input-metadata";\n\n`);
1848
+ if (this.hasScalarTypes()) stream.write(`export type { ${SCALAR_TYPES_NAMESPACE} } from "./scalar-types";\n`);
1781
1849
  stream.write(`export type { GraphQLExecutor, GraphQLSubscriber, Simplify } from "./client-runtime";\n`);
1782
1850
  stream.write(`export { setGraphQLExecutor, setGraphQLSubscriber, execute, subscribe } from "./client-runtime";\n`);
1783
1851
  stream.write("export type { ImplementationType } from './type-hierarchy';\n");
@@ -1847,6 +1915,7 @@ var Generator = class {
1847
1915
  const mutationType = typeMap["Mutation"];
1848
1916
  const subscriptionType = typeMap["Subscription"];
1849
1917
  stream.write(`export * from './__generated/index';\n`);
1918
+ if (this.hasScalarTypes()) stream.write(`export type { ${SCALAR_TYPES_NAMESPACE} } from './__generated/scalar-types';\n`);
1850
1919
  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`);
1851
1920
  stream.write(`export { FragmentSpread, FragmentRef, StringValue, runtimeOf, createSchemaType, resolveRegisteredSchemaType, registerSchemaTypeFactory, SelectionNode, createSelection, ParameterRef, EnumInputMetadataBuilder, TextBuilder, cyrb53 } from './dist/index.mjs';\n`);
1852
1921
  stream.write(`import { fragment$ } from './__generated/index';\n`);
@@ -1916,6 +1985,15 @@ var Generator = class {
1916
1985
  }
1917
1986
  }
1918
1987
  }
1988
+ validateScalarTypeDeclarations() {
1989
+ analyzeScalarTypeDeclarations(this.options.scalarTypeDeclarations);
1990
+ const scalarMap = this.options.scalarTypeMap;
1991
+ if (!scalarMap) return;
1992
+ for (const scalarName of Object.keys(scalarMap)) if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(scalarName)) throw new Error(`scalarTypeMap key '${scalarName}' is not identifier`);
1993
+ }
1994
+ hasScalarTypes() {
1995
+ return (this.options.scalarTypeDeclarations?.trim().length ?? 0) !== 0 || Object.keys(this.options.scalarTypeMap ?? {}).length !== 0;
1996
+ }
1919
1997
  };
1920
1998
  function createStream(path) {
1921
1999
  return createWriteStream(path);
@@ -1949,4 +2027,4 @@ async function loadLocalSchema(location) {
1949
2027
 
1950
2028
  //#endregion
1951
2029
  export { loadRemoteSchema as n, Generator as r, loadLocalSchema as t };
1952
- //# sourceMappingURL=schema-loader-CB4j3yYF.mjs.map
2030
+ //# sourceMappingURL=schema-loader-dqwha5aR.mjs.map