@haddowg/json-api-codegen 1.5.0 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { r as CodegenConfig } from "./index-B0BIVXUz.mjs";
1
+ import { r as CodegenConfig } from "./index-CjNGhJJH.mjs";
2
2
 
3
3
  //#region src/cli.d.ts
4
4
  declare const USAGE = "Usage: json-api-codegen --input <url|file> --output <file> [--server <name>] [--schemas <url|file>] [--check]";
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { n as generate, r as schemasOutputPath, t as check } from "./src-G1x-BbMp.mjs";
2
+ import { n as generate, r as schemasOutputPath, t as check } from "./src-CKsM7dXw.mjs";
3
3
  import { realpathSync } from "node:fs";
4
4
  import { fileURLToPath } from "node:url";
5
5
  //#region src/cli.ts
@@ -77,12 +77,11 @@ interface OpenApiDocument {
77
77
  //#endregion
78
78
  //#region src/build-descriptor.d.ts
79
79
  declare class DescriptorBuilder {
80
- private readonly doc;
81
80
  private readonly schemas;
82
81
  private readonly paths;
83
82
  /** Lazily-built wire-type -> collection-level paginator kind (for per-relation divergence, D6a). */
84
83
  private typePaginators?;
85
- constructor(doc: OpenApiDocument);
84
+ constructor(source: OpenApiDocument);
86
85
  /**
87
86
  * The collection-level paginator kind for a WIRE type (`tracks`), memoised. Resolves each
88
87
  * resource schema's wire type (its `type.const`) to the paginator of its collection GET — the
@@ -261,7 +260,7 @@ declare function buildAtomic(doc: OpenApiDocument): AtomicDescriptor | null;
261
260
  /** Below this the document predates the structures this codegen reads. */
262
261
  declare const MINIMUM_CONTRACT = 1;
263
262
  /** Above this the document carries structures this codegen does not read. */
264
- declare const MAXIMUM_CONTRACT = 8;
263
+ declare const MAXIMUM_CONTRACT = 9;
265
264
  /**
266
265
  * Check the document's `info.x-generator.contract` against the range this codegen reads. A
267
266
  * document older than the range throws; a newer one returns a warning, because its new
@@ -282,7 +281,6 @@ interface VerbCollision {
282
281
  */
283
282
  declare function detectVerbCollisions(descriptor: ApiDescriptor): VerbCollision[];
284
283
  declare class Emitter {
285
- private readonly doc;
286
284
  private readonly descriptor;
287
285
  private readonly atomic;
288
286
  private readonly schemas;
@@ -297,6 +295,10 @@ declare class Emitter {
297
295
  * already-named attribute type. Populated as interfaces are emitted.
298
296
  */
299
297
  private readonly emittedInterfaces;
298
+ /** Enum component name -> the alias name it's emitted under. */
299
+ private readonly enumNames;
300
+ /** Type names already spoken for: the module's own, the per-type interfaces and enum aliases. */
301
+ private readonly takenNames;
300
302
  /** Component names mid-expansion in {@link tsType} — a cycle guard for self/mutually-referential `$ref`s. */
301
303
  private readonly expanding;
302
304
  /**
@@ -307,7 +309,13 @@ declare class Emitter {
307
309
  private readonly actionAliasNames;
308
310
  /** Provenance of the source document, stamped into the generated header for drift tracking. */
309
311
  private readonly provenance;
310
- constructor(doc: OpenApiDocument, descriptor: ApiDescriptor, atomic: AtomicDescriptor | null);
312
+ private readonly doc;
313
+ constructor(source: OpenApiDocument, descriptor: ApiDescriptor, atomic: AtomicDescriptor | null);
314
+ /**
315
+ * The alias an enum component is emitted under: its own name when that's a usable type name,
316
+ * else one derived from it (with a warning), kept clear of every other name in the module.
317
+ */
318
+ private enumName;
311
319
  /** Map each declared wire type back to the `Base` of its resource schema. */
312
320
  private indexBases;
313
321
  emit(): string;
@@ -503,7 +511,7 @@ declare function hashJson(value: unknown): string;
503
511
  declare function deriveProvenance(doc: OpenApiDocument): Provenance;
504
512
  /**
505
513
  * Render the provenance record as the JSDoc header lines stamped into a generated artifact
506
- * (each already prefixed with ` * `). Deterministic: no timestamp, so re-generating from the
514
+ * (each already prefixed with ` * `), with the document's text kept to one comment line. Deterministic: no timestamp, so re-generating from the
507
515
  * same spec yields byte-identical output.
508
516
  */
509
517
  declare function provenanceLines(provenance: Provenance): string[];
@@ -566,4 +574,4 @@ declare function generate(config: CodegenConfig): Promise<string>;
566
574
  declare function check(config: CodegenConfig): Promise<CheckResult>;
567
575
  //#endregion
568
576
  export { InfoObject as A, MAXIMUM_CONTRACT as C, buildAtomic as D, DescriptorBuilder as E, PathItemObject as F, RequestBodyObject as I, ResponseObject as L, OpenApiDocument as M, OperationObject as N, buildDescriptor as O, ParameterObject as P, SchemaObject as R, emit as S, checkContract as T, emitErrorCodes as _, generate as a, VerbCollision as b, deriveProvenance as c, emitSchemas as d, SchemaBundle as f, ErrorCatalogue as g, DocumentedErrorCode as h, check as i, MediaTypeObject as j, HttpMethod as k, hashJson as l, readSchemas as m, CheckResult as n, schemasOutputPath as o, readDocument as p, CodegenConfig as r, Provenance as s, ArtifactDrift as t, provenanceLines as u, readErrorCatalogue as v, MINIMUM_CONTRACT as w, detectVerbCollisions as x, Emitter as y, SchemaOrBool as z };
569
- //# sourceMappingURL=index-B0BIVXUz.d.mts.map
577
+ //# sourceMappingURL=index-CjNGhJJH.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-CjNGhJJH.d.mts","names":[],"sources":["../src/openapi.ts","../src/build-descriptor.ts","../src/contract.ts","../src/emit.ts","../src/error-codes.ts","../src/reader.ts","../src/emit-schemas.ts","../src/provenance.ts","../src/index.ts"],"mappings":"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"}
package/dist/index.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { A as InfoObject, C as MAXIMUM_CONTRACT, D as buildAtomic, E as DescriptorBuilder, F as PathItemObject, I as RequestBodyObject, L as ResponseObject, M as OpenApiDocument, N as OperationObject, O as buildDescriptor, P as ParameterObject, R as SchemaObject, S as emit, T as checkContract, _ as emitErrorCodes, a as generate, b as VerbCollision, c as deriveProvenance, d as emitSchemas, f as SchemaBundle, g as ErrorCatalogue, h as DocumentedErrorCode, i as check, j as MediaTypeObject, k as HttpMethod, l as hashJson, m as readSchemas, n as CheckResult, o as schemasOutputPath, p as readDocument, r as CodegenConfig, s as Provenance, t as ArtifactDrift, u as provenanceLines, v as readErrorCatalogue, w as MINIMUM_CONTRACT, x as detectVerbCollisions, y as Emitter, z as SchemaOrBool } from "./index-B0BIVXUz.mjs";
1
+ import { A as InfoObject, C as MAXIMUM_CONTRACT, D as buildAtomic, E as DescriptorBuilder, F as PathItemObject, I as RequestBodyObject, L as ResponseObject, M as OpenApiDocument, N as OperationObject, O as buildDescriptor, P as ParameterObject, R as SchemaObject, S as emit, T as checkContract, _ as emitErrorCodes, a as generate, b as VerbCollision, c as deriveProvenance, d as emitSchemas, f as SchemaBundle, g as ErrorCatalogue, h as DocumentedErrorCode, i as check, j as MediaTypeObject, k as HttpMethod, l as hashJson, m as readSchemas, n as CheckResult, o as schemasOutputPath, p as readDocument, r as CodegenConfig, s as Provenance, t as ArtifactDrift, u as provenanceLines, v as readErrorCatalogue, w as MINIMUM_CONTRACT, x as detectVerbCollisions, y as Emitter, z as SchemaOrBool } from "./index-CjNGhJJH.mjs";
2
2
  export { ArtifactDrift, CheckResult, CodegenConfig, DescriptorBuilder, type DocumentedErrorCode, Emitter, type ErrorCatalogue, type HttpMethod, type InfoObject, MAXIMUM_CONTRACT, MINIMUM_CONTRACT, type MediaTypeObject, type OpenApiDocument, type OperationObject, type ParameterObject, type PathItemObject, type Provenance, type RequestBodyObject, type ResponseObject, type SchemaBundle, type SchemaObject, type SchemaOrBool, type VerbCollision, buildAtomic, buildDescriptor, check, checkContract, deriveProvenance, detectVerbCollisions, emit, emitErrorCodes, emitSchemas, generate, hashJson, provenanceLines, readDocument, readErrorCatalogue, readSchemas, schemasOutputPath };
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { _ as checkContract, a as readSchemas, b as buildDescriptor, c as detectVerbCollisions, d as hashJson, f as provenanceLines, g as MINIMUM_CONTRACT, h as MAXIMUM_CONTRACT, i as readDocument, l as emit, m as readErrorCatalogue, n as generate, o as emitSchemas, p as emitErrorCodes, r as schemasOutputPath, s as Emitter, t as check, u as deriveProvenance, v as DescriptorBuilder, y as buildAtomic } from "./src-G1x-BbMp.mjs";
1
+ import { _ as checkContract, a as readSchemas, b as buildDescriptor, c as detectVerbCollisions, d as hashJson, f as provenanceLines, g as MINIMUM_CONTRACT, h as MAXIMUM_CONTRACT, i as readDocument, l as emit, m as readErrorCatalogue, n as generate, o as emitSchemas, p as emitErrorCodes, r as schemasOutputPath, s as Emitter, t as check, u as deriveProvenance, v as DescriptorBuilder, y as buildAtomic } from "./src-CKsM7dXw.mjs";
2
2
  export { DescriptorBuilder, Emitter, MAXIMUM_CONTRACT, MINIMUM_CONTRACT, buildAtomic, buildDescriptor, check, checkContract, deriveProvenance, detectVerbCollisions, emit, emitErrorCodes, emitSchemas, generate, hashJson, provenanceLines, readDocument, readErrorCatalogue, readSchemas, schemasOutputPath };
@@ -3,6 +3,64 @@ import { dirname } from "node:path";
3
3
  import { ATOMIC_EXT, CANONICAL_PAGE_KEYS, HANDLE_RESERVED } from "@haddowg/json-api-client";
4
4
  import { createHash } from "node:crypto";
5
5
  import { parse } from "yaml";
6
+ //#region src/unwrap-refs.ts
7
+ /**
8
+ * Keywords that annotate a schema without constraining it. A single-entry `allOf` wrapper is
9
+ * read as its `$ref` only when the wrapper carries nothing else, plus any `x-` extension.
10
+ */
11
+ const ANNOTATIONS = /* @__PURE__ */ new Set([
12
+ "title",
13
+ "description",
14
+ "example",
15
+ "examples",
16
+ "default",
17
+ "deprecated",
18
+ "readOnly",
19
+ "writeOnly",
20
+ "$comment"
21
+ ]);
22
+ const unwrapped = /* @__PURE__ */ new WeakMap();
23
+ /**
24
+ * The document with every `{ allOf: [{ $ref }], ...annotations }` node rewritten as
25
+ * `{ $ref, ...annotations }`. From generator contract 9 the projector wraps a `$ref` that
26
+ * carries an `example`, `examples` or `default` this way, because OAS 3.0 tooling ignores a
27
+ * `$ref`'s siblings. Reading the wrapper as its `$ref` keeps every lookup that follows a `$ref`
28
+ * working, and keeps the annotations for the TSDoc. The input is not modified.
29
+ */
30
+ function unwrapRefs(doc) {
31
+ let out = unwrapped.get(doc);
32
+ if (out === void 0) {
33
+ out = unwrapNode(doc);
34
+ unwrapped.set(doc, out);
35
+ unwrapped.set(out, out);
36
+ }
37
+ return out;
38
+ }
39
+ function unwrapNode(node) {
40
+ if (Array.isArray(node)) return node.map(unwrapNode);
41
+ if (typeof node !== "object" || node === null) return node;
42
+ const out = {};
43
+ for (const [key, value] of Object.entries(node)) out[key] = unwrapNode(value);
44
+ const ref = wrappedRef(out);
45
+ if (ref === void 0) return out;
46
+ const { allOf: _allOf, ...annotations } = out;
47
+ return {
48
+ $ref: ref,
49
+ ...annotations
50
+ };
51
+ }
52
+ /** The `$ref` a node wraps in a single-entry `allOf`, when that is all the node constrains. */
53
+ function wrappedRef(node) {
54
+ const allOf = node["allOf"];
55
+ if (!Array.isArray(allOf) || allOf.length !== 1 || "$ref" in node) return;
56
+ const entry = allOf[0];
57
+ if (typeof entry !== "object" || entry === null) return;
58
+ const keys = Object.keys(entry);
59
+ const ref = entry["$ref"];
60
+ if (keys.length !== 1 || typeof ref !== "string") return;
61
+ return Object.keys(node).every((key) => key === "allOf" || ANNOTATIONS.has(key) || key.startsWith("x-")) ? ref : void 0;
62
+ }
63
+ //#endregion
6
64
  //#region src/build-descriptor.ts
7
65
  const REF_PREFIX$2 = "#/components/schemas/";
8
66
  const JSON_API_MEDIA_TYPE$1 = "application/vnd.api+json";
@@ -33,13 +91,12 @@ function typeKeys(type) {
33
91
  return (Array.isArray(type) ? type : [type]).filter((t) => t !== "null");
34
92
  }
35
93
  var DescriptorBuilder = class {
36
- doc;
37
94
  schemas;
38
95
  paths;
39
96
  /** Lazily-built wire-type -> collection-level paginator kind (for per-relation divergence, D6a). */
40
97
  typePaginators;
41
- constructor(doc) {
42
- this.doc = doc;
98
+ constructor(source) {
99
+ const doc = unwrapRefs(source);
43
100
  this.schemas = doc.components?.schemas ?? {};
44
101
  this.paths = doc.paths ?? {};
45
102
  }
@@ -848,7 +905,7 @@ function stampedMenu(schema, stamp, warn) {
848
905
  /** Below this the document predates the structures this codegen reads. */
849
906
  const MINIMUM_CONTRACT = 1;
850
907
  /** Above this the document carries structures this codegen does not read. */
851
- const MAXIMUM_CONTRACT = 8;
908
+ const MAXIMUM_CONTRACT = 9;
852
909
  /**
853
910
  * Check the document's `info.x-generator.contract` against the range this codegen reads. A
854
911
  * document older than the range throws; a newer one returns a warning, because its new
@@ -858,8 +915,108 @@ const MAXIMUM_CONTRACT = 8;
858
915
  function checkContract(doc) {
859
916
  const contract = doc.info?.["x-generator"]?.contract;
860
917
  if (typeof contract !== "number") return;
861
- if (contract < 1) throw new Error(`the document declares contract ${contract}, which predates what this codegen reads (it supports 1 to 8). Use an older codegen release, or regenerate the document from a newer server.`);
862
- if (contract > 8) return `the document declares contract ${contract} and this codegen reads up to 8. It describes capabilities that were not generated; upgrade the codegen to pick them up.`;
918
+ if (contract < 1) throw new Error(`the document declares contract ${contract}, which predates what this codegen reads (it supports 1 to 9). Use an older codegen release, or regenerate the document from a newer server.`);
919
+ if (contract > 9) return `the document declares contract ${contract} and this codegen reads up to 9. It describes capabilities that were not generated; upgrade the codegen to pick them up.`;
920
+ }
921
+ //#endregion
922
+ //#region src/source.ts
923
+ /**
924
+ * Helpers for writing strings read from the OpenAPI document into generated TypeScript. Every
925
+ * name, literal and comment the emitters take from the document goes through one of these.
926
+ */
927
+ const IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
928
+ /** Line terminators as JavaScript counts them. */
929
+ const LINE_BREAK = /\r\n|[\n\r\u2028\u2029]/;
930
+ /** A string as a TS string literal. U+2028/U+2029 are escaped too, which JSON leaves raw. */
931
+ function stringLiteral(value) {
932
+ return JSON.stringify(value).replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
933
+ }
934
+ /** True when a string is a bare identifier. */
935
+ function isIdentifier(value) {
936
+ return IDENTIFIER.test(value);
937
+ }
938
+ /**
939
+ * A property key for an object literal or an interface: bare when it's an identifier, quoted
940
+ * otherwise. `__proto__` is written as a computed key, which a runtime literal keeps as an own
941
+ * property instead of setting the prototype.
942
+ */
943
+ function propertyKey(name) {
944
+ if (name === "__proto__") return `[${stringLiteral(name)}]`;
945
+ return isIdentifier(name) ? name : stringLiteral(name);
946
+ }
947
+ /** Text that can sit inside a block comment: any `*\/` is broken up so it can't close it. */
948
+ function commentText(text) {
949
+ return text.replace(/\*\//g, "* /");
950
+ }
951
+ /** {@link commentText} split into lines, for a multi-line block comment. */
952
+ function commentLines(text) {
953
+ return commentText(text).split(LINE_BREAK);
954
+ }
955
+ /** {@link commentText} on one line, for a single comment line such as the provenance header. */
956
+ function commentLine(text) {
957
+ return commentText(text).split(LINE_BREAK).join(" ");
958
+ }
959
+ /** Words a type alias can't be named: reserved words and the built-in type names. */
960
+ const RESERVED_TYPE_NAMES = /* @__PURE__ */ new Set([
961
+ "any",
962
+ "bigint",
963
+ "boolean",
964
+ "break",
965
+ "case",
966
+ "catch",
967
+ "class",
968
+ "const",
969
+ "continue",
970
+ "debugger",
971
+ "default",
972
+ "delete",
973
+ "do",
974
+ "else",
975
+ "enum",
976
+ "export",
977
+ "extends",
978
+ "false",
979
+ "finally",
980
+ "for",
981
+ "function",
982
+ "if",
983
+ "implements",
984
+ "import",
985
+ "in",
986
+ "instanceof",
987
+ "interface",
988
+ "let",
989
+ "never",
990
+ "new",
991
+ "null",
992
+ "number",
993
+ "object",
994
+ "package",
995
+ "private",
996
+ "protected",
997
+ "public",
998
+ "return",
999
+ "static",
1000
+ "string",
1001
+ "super",
1002
+ "switch",
1003
+ "symbol",
1004
+ "this",
1005
+ "throw",
1006
+ "true",
1007
+ "try",
1008
+ "typeof",
1009
+ "undefined",
1010
+ "unknown",
1011
+ "var",
1012
+ "void",
1013
+ "while",
1014
+ "with",
1015
+ "yield"
1016
+ ]);
1017
+ /** True when `name` can be used as is for an exported type. */
1018
+ function isTypeName(name) {
1019
+ return isIdentifier(name) && !RESERVED_TYPE_NAMES.has(name);
863
1020
  }
864
1021
  //#endregion
865
1022
  //#region src/error-codes.ts
@@ -924,24 +1081,20 @@ function readErrorCatalogue(doc) {
924
1081
  /** A TSDoc block for one code: its description, then each example detail as an `@example`. */
925
1082
  function codeDoc(entry, indent) {
926
1083
  const lines = [];
927
- if (entry.description !== void 0) lines.push(...entry.description.split("\n"));
1084
+ if (entry.description !== void 0) lines.push(...commentLines(entry.description));
928
1085
  for (const example of entry.examples) {
929
1086
  if (lines.length > 0) lines.push("");
930
1087
  const text = typeof example === "string" ? example : JSON.stringify(example);
931
- lines.push(...`@example ${text}`.split("\n"));
1088
+ lines.push(...commentLines(`@example ${text}`));
932
1089
  }
933
1090
  if (lines.length === 0) return;
934
- if (lines.length === 1) return `${indent}/** ${lines[0].replace(/\*\//g, "* /")} */`;
1091
+ if (lines.length === 1) return `${indent}/** ${lines[0]} */`;
935
1092
  return [
936
1093
  `${indent}/**`,
937
- ...lines.map((line) => `${indent} * ${line.replace(/\*\//g, "* /")}`.trimEnd()),
1094
+ ...lines.map((line) => `${indent} * ${line}`.trimEnd()),
938
1095
  `${indent} */`
939
1096
  ].join("\n");
940
1097
  }
941
- /** A bare object key when the code is a valid identifier, else a quoted one. */
942
- function codeKey(code) {
943
- return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(code) ? code : JSON.stringify(code);
944
- }
945
1098
  /**
946
1099
  * Emit `ErrorCodes`, a const object keyed by every documented code with its TSDoc on the key
947
1100
  * (editors show TSDoc on an object key, not on a string-literal union member), the `ErrorCode`
@@ -964,7 +1117,7 @@ function emitErrorCodes(catalogue) {
964
1117
  "export const ErrorCodes = {",
965
1118
  ...catalogue.codes.flatMap((entry) => {
966
1119
  const doc = codeDoc(entry, " ");
967
- const member = ` ${codeKey(entry.code)}: ${JSON.stringify(entry.code)},`;
1120
+ const member = ` ${propertyKey(entry.code)}: ${stringLiteral(entry.code)},`;
968
1121
  return doc === void 0 ? [member] : [doc, member];
969
1122
  }),
970
1123
  "} as const",
@@ -976,7 +1129,7 @@ function emitErrorCodes(catalogue) {
976
1129
  "export type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes]"
977
1130
  ].join("\n");
978
1131
  const statusLines = [...catalogue.byStatus].map(([status, codes]) => {
979
- const members = codes.map((c) => JSON.stringify(c));
1132
+ const members = codes.map((c) => stringLiteral(c));
980
1133
  const line = ` ${status}: ${members.length === 0 ? "never" : members.join(" | ")}`;
981
1134
  return line.length <= 100 ? line : ` ${status}:\n${members.map((m) => ` | ${m}`).join("\n")}`;
982
1135
  });
@@ -1033,12 +1186,12 @@ function deriveProvenance(doc) {
1033
1186
  }
1034
1187
  /**
1035
1188
  * Render the provenance record as the JSDoc header lines stamped into a generated artifact
1036
- * (each already prefixed with ` * `). Deterministic: no timestamp, so re-generating from the
1189
+ * (each already prefixed with ` * `), with the document's text kept to one comment line. Deterministic: no timestamp, so re-generating from the
1037
1190
  * same spec yields byte-identical output.
1038
1191
  */
1039
1192
  function provenanceLines(provenance) {
1040
- const lines = [` * Source spec: ${provenance.source}`, ` * Spec hash: ${provenance.hash}`];
1041
- if (provenance.server !== void 0) lines.splice(1, 0, ` * Server: ${provenance.server}`);
1193
+ const lines = [` * Source spec: ${commentLine(provenance.source)}`, ` * Spec hash: ${provenance.hash}`];
1194
+ if (provenance.server !== void 0) lines.splice(1, 0, ` * Server: ${commentLine(provenance.server)}`);
1042
1195
  return lines;
1043
1196
  }
1044
1197
  //#endregion
@@ -1083,17 +1236,25 @@ function isSchema(value) {
1083
1236
  function pascalCase(value) {
1084
1237
  return value.split(/[^a-zA-Z0-9]+/).filter((part) => part.length > 0).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
1085
1238
  }
1086
- /** Emit a JSON-string literal (used for keys that aren't bare identifiers and enum members). */
1087
- function quote(value) {
1088
- return JSON.stringify(value);
1089
- }
1090
- /** True when a string is a safe bare object-key identifier. */
1091
- function isIdentifier(value) {
1092
- return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(value);
1093
- }
1094
- function objectKey(value) {
1095
- return isIdentifier(value) ? value : quote(value);
1239
+ /** The identifier stem for a wire type's interfaces, `Type`-prefixed when it would start with a digit. */
1240
+ function typeStem(type) {
1241
+ const pascal = pascalCase(type);
1242
+ return /^[A-Za-z]/.test(pascal) ? pascal : `Type${pascal}`;
1096
1243
  }
1244
+ /** Names the generated module declares or relies on, which an enum alias must not take. */
1245
+ const MODULE_NAMES = [
1246
+ "ActionTypes",
1247
+ "ApiDescriptor",
1248
+ "Attributes",
1249
+ "ClientOptions",
1250
+ "ErrorCode",
1251
+ "ErrorCodeByStatus",
1252
+ "ErrorCodeGuard",
1253
+ "ErrorCodes",
1254
+ "Record",
1255
+ "ResourceMap",
1256
+ "WriteAttributes"
1257
+ ];
1097
1258
  /**
1098
1259
  * Render a description as a JSDoc comment at the given indent — single-line when it fits,
1099
1260
  * a block otherwise. Returns `undefined` for empty text. Neutralises any `*\/` so a
@@ -1102,7 +1263,7 @@ function objectKey(value) {
1102
1263
  function jsDoc(text, indent) {
1103
1264
  const trimmed = text?.trim();
1104
1265
  if (!trimmed) return;
1105
- const lines = trimmed.replace(/\*\//g, "* /").split("\n");
1266
+ const lines = commentLines(trimmed);
1106
1267
  if (lines.length === 1) return `${indent}/** ${lines[0]} */`;
1107
1268
  return [
1108
1269
  `${indent}/**`,
@@ -1158,7 +1319,6 @@ function memberDoc(schema) {
1158
1319
  return description ? `${description}\n\n${tags.join("\n")}` : tags.join("\n");
1159
1320
  }
1160
1321
  var Emitter = class {
1161
- doc;
1162
1322
  descriptor;
1163
1323
  atomic;
1164
1324
  schemas;
@@ -1173,6 +1333,10 @@ var Emitter = class {
1173
1333
  * already-named attribute type. Populated as interfaces are emitted.
1174
1334
  */
1175
1335
  emittedInterfaces = /* @__PURE__ */ new Set();
1336
+ /** Enum component name -> the alias name it's emitted under. */
1337
+ enumNames = /* @__PURE__ */ new Map();
1338
+ /** Type names already spoken for: the module's own, the per-type interfaces and enum aliases. */
1339
+ takenNames;
1176
1340
  /** Component names mid-expansion in {@link tsType} — a cycle guard for self/mutually-referential `$ref`s. */
1177
1341
  expanding = /* @__PURE__ */ new Set();
1178
1342
  /**
@@ -1183,13 +1347,47 @@ var Emitter = class {
1183
1347
  actionAliasNames = /* @__PURE__ */ new Map();
1184
1348
  /** Provenance of the source document, stamped into the generated header for drift tracking. */
1185
1349
  provenance;
1186
- constructor(doc, descriptor, atomic) {
1187
- this.doc = doc;
1350
+ doc;
1351
+ constructor(source, descriptor, atomic) {
1188
1352
  this.descriptor = descriptor;
1189
1353
  this.atomic = atomic;
1190
- this.schemas = doc.components?.schemas ?? {};
1354
+ this.doc = unwrapRefs(source);
1355
+ this.schemas = this.doc.components?.schemas ?? {};
1191
1356
  this.baseByType = this.indexBases();
1192
- this.provenance = deriveProvenance(doc);
1357
+ this.provenance = deriveProvenance(source);
1358
+ this.takenNames = new Set(MODULE_NAMES);
1359
+ for (const type of Object.keys(descriptor)) {
1360
+ const stem = typeStem(type);
1361
+ for (const suffix of [
1362
+ "Attributes",
1363
+ "CreateAttributes",
1364
+ "UpdateAttributes"
1365
+ ]) this.takenNames.add(`${stem}${suffix}`);
1366
+ for (const action of Object.keys(descriptor[type]?.actions ?? {})) {
1367
+ this.takenNames.add(`${stem}${pascalCase(action)}Input`);
1368
+ this.takenNames.add(`${stem}${pascalCase(action)}Output`);
1369
+ }
1370
+ }
1371
+ }
1372
+ /**
1373
+ * The alias an enum component is emitted under: its own name when that's a usable type name,
1374
+ * else one derived from it (with a warning), kept clear of every other name in the module.
1375
+ */
1376
+ enumName(component) {
1377
+ const known = this.enumNames.get(component);
1378
+ if (known !== void 0) return known;
1379
+ let name = component;
1380
+ if (!isTypeName(component) || this.takenNames.has(component)) {
1381
+ const pascal = pascalCase(component);
1382
+ let stem = /^[A-Za-z]/.test(pascal) ? pascal : `Enum${pascal}`;
1383
+ if (!isTypeName(stem) || this.takenNames.has(stem)) stem = `${stem}Enum`;
1384
+ name = stem;
1385
+ for (let n = 2; this.takenNames.has(name); n++) name = `${stem}${n}`;
1386
+ console.warn(`Enum component ${stringLiteral(component)} can't be used as a TypeScript type name; emitting it as ${name}.`);
1387
+ }
1388
+ this.takenNames.add(name);
1389
+ this.enumNames.set(component, name);
1390
+ return name;
1193
1391
  }
1194
1392
  /** Map each declared wire type back to the `Base` of its resource schema. */
1195
1393
  indexBases() {
@@ -1250,7 +1448,7 @@ var Emitter = class {
1250
1448
  const base = this.baseByType.get(type);
1251
1449
  const props = base ? this.schemas[`${base}Attributes`]?.properties : void 0;
1252
1450
  const fields = Object.keys(this.descriptor[type].attributes);
1253
- return this.renderInterface(`${pascalCase(type)}Attributes`, props, fields, () => true);
1451
+ return this.renderInterface(`${typeStem(type)}Attributes`, props, fields, () => true);
1254
1452
  }
1255
1453
  /**
1256
1454
  * The per-type WRITE attribute interfaces — `<Pascal>CreateAttributes` and
@@ -1262,7 +1460,7 @@ var Emitter = class {
1262
1460
  writeAttributeInterfaces(type) {
1263
1461
  const base = this.baseByType.get(type);
1264
1462
  if (base === void 0) return [];
1265
- const pascal = pascalCase(type);
1463
+ const pascal = typeStem(type);
1266
1464
  const out = [];
1267
1465
  const create = this.schemas[`${base}CreateAttributes`];
1268
1466
  if (create !== void 0) {
@@ -1289,7 +1487,7 @@ var Emitter = class {
1289
1487
  for (const type of Object.keys(this.descriptor)) {
1290
1488
  const actions = this.descriptor[type]?.actions;
1291
1489
  if (actions === void 0) continue;
1292
- const pascal = pascalCase(type);
1490
+ const pascal = typeStem(type);
1293
1491
  for (const [actionName, action] of Object.entries(actions)) {
1294
1492
  const member = `${pascal}${pascalCase(actionName)}`;
1295
1493
  const names = {};
@@ -1333,9 +1531,9 @@ var Emitter = class {
1333
1531
  const members = [];
1334
1532
  if (names.input !== void 0) members.push(`input: ${names.input}`);
1335
1533
  if (names.output !== void 0) members.push(`output: ${names.output}`);
1336
- actionLines.push(` ${objectKey(actionName)}: { ${members.join("; ")} }`);
1534
+ actionLines.push(` ${propertyKey(actionName)}: { ${members.join("; ")} }`);
1337
1535
  }
1338
- typeLines.push(` ${objectKey(type)}: {\n${actionLines.join("\n")}\n }`);
1536
+ typeLines.push(` ${propertyKey(type)}: {\n${actionLines.join("\n")}\n }`);
1339
1537
  }
1340
1538
  if (typeLines.length === 0) return "export interface ActionTypes {}";
1341
1539
  return `export interface ActionTypes {\n${typeLines.join("\n")}\n}`;
@@ -1383,10 +1581,10 @@ var Emitter = class {
1383
1581
  if (schema.oneOf !== void 0) for (const arm of schema.oneOf) {
1384
1582
  const kind = isSchema(arm.properties?.["kind"]) ? arm.properties["kind"].const : void 0;
1385
1583
  const members = this.pageMemberLimits(arm, " ");
1386
- if (typeof kind === "string" && members.length > 0) body.push(` ${objectKey(kind)}: {\n${members.join("\n")}\n },`);
1584
+ if (typeof kind === "string" && members.length > 0) body.push(` ${propertyKey(kind)}: {\n${members.join("\n")}\n },`);
1387
1585
  }
1388
1586
  else body = this.pageMemberLimits(schema, " ");
1389
- if (body.length > 0) typeLines.push(` ${objectKey(type)}: {\n${body.join("\n")}\n },`);
1587
+ if (body.length > 0) typeLines.push(` ${propertyKey(type)}: {\n${body.join("\n")}\n },`);
1390
1588
  }
1391
1589
  return `${[
1392
1590
  "/**",
@@ -1411,7 +1609,7 @@ var Emitter = class {
1411
1609
  if (limits.length === 0) continue;
1412
1610
  const doc = jsDoc(memberDoc(prop), indent);
1413
1611
  if (doc !== void 0) lines.push(doc);
1414
- lines.push(`${indent}${objectKey(name)}: { ${limits.join(", ")} },`);
1612
+ lines.push(`${indent}${propertyKey(name)}: { ${limits.join(", ")} },`);
1415
1613
  }
1416
1614
  return lines;
1417
1615
  }
@@ -1428,7 +1626,7 @@ var Emitter = class {
1428
1626
  const doc = isSchema(schema) ? jsDoc(memberDoc(schema), " ") : void 0;
1429
1627
  if (doc) lines.push(doc);
1430
1628
  const optional = required(field) ? "" : "?";
1431
- lines.push(` ${objectKey(field)}${optional}: ${tsType}`);
1629
+ lines.push(` ${propertyKey(field)}${optional}: ${tsType}`);
1432
1630
  }
1433
1631
  this.emittedInterfaces.add(name);
1434
1632
  if (lines.length === 0) return `export interface ${name} {}`;
@@ -1441,7 +1639,7 @@ var Emitter = class {
1441
1639
  const resolved = target ? this.schemas[target] : void 0;
1442
1640
  if (target && resolved && Array.isArray(resolved.enum)) {
1443
1641
  this.usedEnums.set(target, resolved);
1444
- return target;
1642
+ return this.enumName(target);
1445
1643
  }
1446
1644
  if (target && this.emittedInterfaces.has(target)) return target;
1447
1645
  if (resolved === void 0 || target === void 0 || this.expanding.has(target)) return "unknown";
@@ -1466,7 +1664,7 @@ var Emitter = class {
1466
1664
  }
1467
1665
  /** The non-nullable TS type for the declared JSON type(s). */
1468
1666
  baseTsType(schema, types) {
1469
- if (Array.isArray(schema.enum) && schema.enum.length > 0) return schema.enum.map((value) => quote(String(value))).join(" | ");
1667
+ if (Array.isArray(schema.enum) && schema.enum.length > 0) return schema.enum.map((value) => stringLiteral(String(value))).join(" | ");
1470
1668
  if (types.length === 0) return "unknown";
1471
1669
  const mapped = types.map((t) => this.scalarOrComposite(schema, t));
1472
1670
  return [...new Set(mapped)].join(" | ");
@@ -1491,7 +1689,7 @@ var Emitter = class {
1491
1689
  for (const [name, prop] of Object.entries(props)) {
1492
1690
  if (!isSchema(prop)) continue;
1493
1691
  const optional = required.has(name) ? "" : "?";
1494
- members.push(`${objectKey(name)}${optional}: ${this.tsType(prop)}`);
1692
+ members.push(`${propertyKey(name)}${optional}: ${this.tsType(prop)}`);
1495
1693
  }
1496
1694
  if (members.length === 0) return "Record<string, unknown>";
1497
1695
  return `{ ${members.join("; ")} }`;
@@ -1508,7 +1706,8 @@ var Emitter = class {
1508
1706
  if (this.usedEnums.size === 0) return;
1509
1707
  return [...this.usedEnums.keys()].sort().map((name) => {
1510
1708
  const schema = this.usedEnums.get(name);
1511
- const alias = `export type ${name} = ${(schema.enum ?? []).map((value) => quote(String(value))).join(" | ")}`;
1709
+ const union = (schema.enum ?? []).map((value) => stringLiteral(String(value))).join(" | ");
1710
+ const alias = `export type ${this.enumName(name)} = ${union}`;
1512
1711
  const doc = jsDoc(this.enumDoc(schema), "");
1513
1712
  return doc ? `${doc}\n${alias}` : alias;
1514
1713
  }).join("\n\n");
@@ -1531,7 +1730,7 @@ var Emitter = class {
1531
1730
  * argument to the runtime factory).
1532
1731
  */
1533
1732
  attributesMap() {
1534
- return `export interface Attributes {\n${Object.keys(this.descriptor).map((type) => ` ${objectKey(type)}: ${pascalCase(type)}Attributes`).join("\n")}\n}`;
1733
+ return `export interface Attributes {\n${Object.keys(this.descriptor).map((type) => ` ${propertyKey(type)}: ${typeStem(type)}Attributes`).join("\n")}\n}`;
1535
1734
  }
1536
1735
  /**
1537
1736
  * Emit the `WriteAttributes` interface mapping each writable wire type to its
@@ -1546,11 +1745,11 @@ var Emitter = class {
1546
1745
  const hasCreate = base !== void 0 && this.schemas[`${base}CreateAttributes`] !== void 0;
1547
1746
  const hasUpdate = base !== void 0 && this.schemas[`${base}UpdateAttributes`] !== void 0;
1548
1747
  if (!hasCreate && !hasUpdate) continue;
1549
- const pascal = pascalCase(type);
1748
+ const pascal = typeStem(type);
1550
1749
  const members = [];
1551
1750
  if (hasCreate) members.push(`create: ${pascal}CreateAttributes`);
1552
1751
  if (hasUpdate) members.push(`update: ${pascal}UpdateAttributes`);
1553
- lines.push(` ${objectKey(type)}: { ${members.join("; ")} }`);
1752
+ lines.push(` ${propertyKey(type)}: { ${members.join("; ")} }`);
1554
1753
  }
1555
1754
  if (lines.length === 0) return "export interface WriteAttributes {}";
1556
1755
  return `export interface WriteAttributes {\n${lines.join("\n")}\n}`;
@@ -1570,9 +1769,9 @@ var Emitter = class {
1570
1769
  if (value !== null && typeof value === "object") {
1571
1770
  const entries = Object.entries(value);
1572
1771
  if (entries.length === 0) return "{}";
1573
- return `{\n${entries.map(([key, v]) => `${inner}${objectKey(key)}: ${this.literal(v, depth + 1)}`).join(",\n")}\n${indent}}`;
1772
+ return `{\n${entries.map(([key, v]) => `${inner}${propertyKey(key)}: ${this.literal(v, depth + 1)}`).join(",\n")}\n${indent}}`;
1574
1773
  }
1575
- return JSON.stringify(value);
1774
+ return typeof value === "string" ? stringLiteral(value) : JSON.stringify(value);
1576
1775
  }
1577
1776
  boundFactory() {
1578
1777
  return [
@@ -1631,7 +1830,7 @@ function header(bundle) {
1631
1830
  ].join("\n");
1632
1831
  }
1633
1832
  function body(bundle) {
1634
- return `export const schemas = ${JSON.stringify(bundle, null, 2)} as const`;
1833
+ return `export const schemas = ${JSON.stringify(bundle, null, 2).replace(/^(\s*)"__proto__":/gm, "$1[\"__proto__\"]:").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029")} as const`;
1635
1834
  }
1636
1835
  //#endregion
1637
1836
  //#region src/reader.ts
@@ -1775,4 +1974,4 @@ async function check(config) {
1775
1974
  //#endregion
1776
1975
  export { checkContract as _, readSchemas as a, buildDescriptor as b, detectVerbCollisions as c, hashJson as d, provenanceLines as f, MINIMUM_CONTRACT as g, MAXIMUM_CONTRACT as h, readDocument as i, emit as l, readErrorCatalogue as m, generate as n, emitSchemas as o, emitErrorCodes as p, schemasOutputPath as r, Emitter as s, check as t, deriveProvenance as u, DescriptorBuilder as v, buildAtomic as y };
1777
1976
 
1778
- //# sourceMappingURL=src-G1x-BbMp.mjs.map
1977
+ //# sourceMappingURL=src-CKsM7dXw.mjs.map