@haddowg/json-api-codegen 1.5.0 → 1.6.0

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-CU-kUx70.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-C2INS1Wd.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;
@@ -307,7 +305,8 @@ declare class Emitter {
307
305
  private readonly actionAliasNames;
308
306
  /** Provenance of the source document, stamped into the generated header for drift tracking. */
309
307
  private readonly provenance;
310
- constructor(doc: OpenApiDocument, descriptor: ApiDescriptor, atomic: AtomicDescriptor | null);
308
+ private readonly doc;
309
+ constructor(source: OpenApiDocument, descriptor: ApiDescriptor, atomic: AtomicDescriptor | null);
311
310
  /** Map each declared wire type back to the `Base` of its resource schema. */
312
311
  private indexBases;
313
312
  emit(): string;
@@ -566,4 +565,4 @@ declare function generate(config: CodegenConfig): Promise<string>;
566
565
  declare function check(config: CodegenConfig): Promise<CheckResult>;
567
566
  //#endregion
568
567
  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
568
+ //# sourceMappingURL=index-CU-kUx70.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-CU-kUx70.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-CU-kUx70.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-C2INS1Wd.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,8 @@ 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.`;
863
920
  }
864
921
  //#endregion
865
922
  //#region src/error-codes.ts
@@ -1158,7 +1215,6 @@ function memberDoc(schema) {
1158
1215
  return description ? `${description}\n\n${tags.join("\n")}` : tags.join("\n");
1159
1216
  }
1160
1217
  var Emitter = class {
1161
- doc;
1162
1218
  descriptor;
1163
1219
  atomic;
1164
1220
  schemas;
@@ -1183,13 +1239,14 @@ var Emitter = class {
1183
1239
  actionAliasNames = /* @__PURE__ */ new Map();
1184
1240
  /** Provenance of the source document, stamped into the generated header for drift tracking. */
1185
1241
  provenance;
1186
- constructor(doc, descriptor, atomic) {
1187
- this.doc = doc;
1242
+ doc;
1243
+ constructor(source, descriptor, atomic) {
1188
1244
  this.descriptor = descriptor;
1189
1245
  this.atomic = atomic;
1190
- this.schemas = doc.components?.schemas ?? {};
1246
+ this.doc = unwrapRefs(source);
1247
+ this.schemas = this.doc.components?.schemas ?? {};
1191
1248
  this.baseByType = this.indexBases();
1192
- this.provenance = deriveProvenance(doc);
1249
+ this.provenance = deriveProvenance(source);
1193
1250
  }
1194
1251
  /** Map each declared wire type back to the `Base` of its resource schema. */
1195
1252
  indexBases() {
@@ -1775,4 +1832,4 @@ async function check(config) {
1775
1832
  //#endregion
1776
1833
  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
1834
 
1778
- //# sourceMappingURL=src-G1x-BbMp.mjs.map
1835
+ //# sourceMappingURL=src-C2INS1Wd.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"src-C2INS1Wd.mjs","names":["REF_PREFIX","JSON_API_MEDIA_TYPE","refName","isSchema","REF_PREFIX","isSchema","parse","parseYaml"],"sources":["../src/unwrap-refs.ts","../src/build-descriptor.ts","../src/contract.ts","../src/error-codes.ts","../src/provenance.ts","../src/emit.ts","../src/emit-schemas.ts","../src/reader.ts","../src/index.ts"],"sourcesContent":["import type { OpenApiDocument } from './openapi'\n\n/**\n * Keywords that annotate a schema without constraining it. A single-entry `allOf` wrapper is\n * read as its `$ref` only when the wrapper carries nothing else, plus any `x-` extension.\n */\nconst ANNOTATIONS = new Set([\n 'title',\n 'description',\n 'example',\n 'examples',\n 'default',\n 'deprecated',\n 'readOnly',\n 'writeOnly',\n '$comment',\n])\n\nconst unwrapped = new WeakMap<OpenApiDocument, OpenApiDocument>()\n\n/**\n * The document with every `{ allOf: [{ $ref }], ...annotations }` node rewritten as\n * `{ $ref, ...annotations }`. From generator contract 9 the projector wraps a `$ref` that\n * carries an `example`, `examples` or `default` this way, because OAS 3.0 tooling ignores a\n * `$ref`'s siblings. Reading the wrapper as its `$ref` keeps every lookup that follows a `$ref`\n * working, and keeps the annotations for the TSDoc. The input is not modified.\n */\nexport function unwrapRefs(doc: OpenApiDocument): OpenApiDocument {\n let out = unwrapped.get(doc)\n if (out === undefined) {\n out = unwrapNode(doc) as OpenApiDocument\n unwrapped.set(doc, out)\n unwrapped.set(out, out)\n }\n return out\n}\n\nfunction unwrapNode(node: unknown): unknown {\n if (Array.isArray(node)) {\n return node.map(unwrapNode)\n }\n if (typeof node !== 'object' || node === null) {\n return node\n }\n const out: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(node)) {\n out[key] = unwrapNode(value)\n }\n const ref = wrappedRef(out)\n if (ref === undefined) {\n return out\n }\n const { allOf: _allOf, ...annotations } = out\n return { $ref: ref, ...annotations }\n}\n\n/** The `$ref` a node wraps in a single-entry `allOf`, when that is all the node constrains. */\nfunction wrappedRef(node: Record<string, unknown>): string | undefined {\n const allOf = node['allOf']\n if (!Array.isArray(allOf) || allOf.length !== 1 || '$ref' in node) {\n return undefined\n }\n const entry: unknown = allOf[0]\n if (typeof entry !== 'object' || entry === null) {\n return undefined\n }\n const keys = Object.keys(entry)\n const ref = (entry as Record<string, unknown>)['$ref']\n if (keys.length !== 1 || typeof ref !== 'string') {\n return undefined\n }\n const annotationsOnly = Object.keys(node).every(\n (key) => key === 'allOf' || ANNOTATIONS.has(key) || key.startsWith('x-'),\n )\n return annotationsOnly ? ref : undefined\n}\n","import type {\n ActionDescriptor,\n ApiDescriptor,\n AtomicDescriptor,\n Cardinality,\n ClientIdPolicy,\n CountableDescriptor,\n MenuDescriptor,\n PaginatorDescriptor,\n PaginatorKind,\n PaginatorRole,\n PaginatorStrategy,\n PivotDescriptor,\n RelationDescriptor,\n RelationMutations,\n ResourceDescriptor,\n} from '@haddowg/json-api-client'\nimport { ATOMIC_EXT, CANONICAL_PAGE_KEYS } from '@haddowg/json-api-client'\nimport type {\n HttpMethod,\n OpenApiDocument,\n OperationObject,\n PathItemObject,\n SchemaObject,\n SchemaOrBool,\n} from './openapi'\nimport { unwrapRefs } from './unwrap-refs'\n\nconst REF_PREFIX = '#/components/schemas/'\nconst JSON_API_MEDIA_TYPE = 'application/vnd.api+json'\n\n/** Sort a record's keys for deterministic, snapshot-stable output. */\nfunction sortRecord<V>(record: Record<string, V>): Record<string, V> {\n const out: Record<string, V> = {}\n // oxlint-disable-next-line no-array-sort -- sorting a freshly-created key array\n for (const key of Object.keys(record).sort()) {\n out[key] = record[key]!\n }\n return out\n}\n\n/** Resolve a local schema name from a `#/components/schemas/X` ref. */\nfunction refName(ref: string): string | undefined {\n return ref.startsWith(REF_PREFIX) ? ref.slice(REF_PREFIX.length) : undefined\n}\n\nfunction isSchema(value: SchemaOrBool | undefined): value is SchemaObject {\n return typeof value === 'object' && value !== null\n}\n\n/** The operationId prefixes of a relation's related read and its relationship endpoint. */\nconst RELATED_OPERATION = 'fetchRelated'\nconst RELATIONSHIP_OPERATIONS = [\n 'fetchRelationship',\n 'updateRelationship',\n 'addRelationship',\n 'removeRelationship',\n] as const\n\n/** Where a relation's endpoints live, read from their operationIds. */\ninterface RelationEndpoints {\n related?: string\n relationship?: string\n /** The `$ref` of a relationship mutation's request body (its request pivot shape). */\n requestRef?: string\n}\n\n/** The set of `type` keys a JSON type node declares, with `\"null\"` removed. */\nfunction typeKeys(type: string | readonly string[] | undefined): string[] {\n if (type === undefined) {\n return []\n }\n return (Array.isArray(type) ? type : [type]).filter((t) => t !== 'null')\n}\n\nexport class DescriptorBuilder {\n private readonly schemas: Record<string, SchemaObject>\n private readonly paths: Record<string, PathItemObject>\n /** Lazily-built wire-type -> collection-level paginator kind (for per-relation divergence, D6a). */\n private typePaginators?: Map<string, PaginatorDescriptor>\n\n constructor(source: OpenApiDocument) {\n const doc = unwrapRefs(source)\n this.schemas = doc.components?.schemas ?? {}\n this.paths = doc.paths ?? {}\n }\n\n /**\n * The collection-level paginator kind for a WIRE type (`tracks`), memoised. Resolves each\n * resource schema's wire type (its `type.const`) to the paginator of its collection GET — the\n * baseline a per-relation related-endpoint paginator is compared against (D6a).\n */\n private typePaginator(wireType: string): PaginatorDescriptor {\n if (this.typePaginators === undefined) {\n this.typePaginators = new Map()\n for (const [name, schema] of Object.entries(this.schemas)) {\n const type = this.resourceType(name, schema)\n if (type !== undefined) {\n this.typePaginators.set(type, this.paginator(name.slice(0, -'Resource'.length)))\n }\n }\n }\n return this.typePaginators.get(wireType) ?? 'none'\n }\n\n build(): ApiDescriptor {\n const out: Record<string, ResourceDescriptor> = {}\n for (const [name, schema] of Object.entries(this.schemas)) {\n const wireType = this.resourceType(name, schema)\n if (wireType === undefined) {\n continue\n }\n const base = name.slice(0, -'Resource'.length)\n const collection = this.collectionPath(base)\n const actions = collection ? this.actions(collection) : {}\n const descriptor: ResourceDescriptor = {\n attributes: this.attributes(base),\n relations: this.relations(wireType, base, schema, collection),\n paths: this.operationPaths(base),\n paginator: this.paginator(base),\n clientId: this.clientId(base),\n }\n const countable = this.countable(collection)\n if (countable !== undefined) {\n descriptor.countable = countable\n }\n const includable = this.includable(collection)\n if (includable !== undefined) {\n descriptor.includable = includable\n }\n const sortable = this.sortable(collection)\n if (sortable !== undefined) {\n descriptor.sortable = sortable\n }\n const filterable = this.filterable(collection)\n if (filterable !== undefined) {\n descriptor.filterable = filterable\n }\n if (Object.keys(actions).length > 0) {\n descriptor.actions = actions\n }\n // A synthetic stub for an unregistered related type — core's `permissiveResourceObject`\n // emits a `<Rel>Resource` carrying ONLY a `type` const (no `id`/`attributes`) so linkage\n // refs resolve — is reachable only through a parent's `.related()` (which works via the\n // parent's own paths). Admitting it would surface a fully-typed top-level `client.<stub>`\n // whose every method throws, so drop it (D27). A REAL registered resource carries the full\n // `type/id/attributes/…` object shape and stays, even with no attributes/collection of its\n // own; only the type-const-only stub (with no operation paths) is dropped.\n const isTypeOnlyStub = Object.keys(schema.properties ?? {}).every((prop) => prop === 'type')\n if (isTypeOnlyStub && Object.keys(descriptor.paths).length === 0) {\n continue\n }\n out[wireType] = descriptor\n }\n return sortRecord(out)\n }\n\n /**\n * The server-level Atomic Operations capability: the path whose `POST` requestBody\n * declares the atomic ext media type ({@link ATOMIC_EXT}). `null` when no such endpoint\n * exists. Server-level, so it rides {@link buildAtomic}, not the per-type descriptor.\n */\n buildAtomic(): AtomicDescriptor | null {\n for (const [path, item] of Object.entries(this.paths)) {\n const content = item.post?.requestBody?.content ?? {}\n if (Object.keys(content).some(isAtomicMediaType)) {\n return { path }\n }\n }\n return null\n }\n\n /**\n * A resource schema is one whose name ends in `Resource` (but not\n * `ResourceIdentifier`) and carries `properties.type.const` (a string) — that const\n * is the descriptor key (the wire type). Never inferred from the schema name.\n */\n private resourceType(name: string, schema: SchemaObject): string | undefined {\n if (!name.endsWith('Resource') || name.endsWith('ResourceIdentifier')) {\n return undefined\n }\n const constValue = schema.properties?.['type']\n if (isSchema(constValue) && typeof constValue.const === 'string') {\n return constValue.const\n }\n return undefined\n }\n\n /** Follow a `$ref` to its identifier/resource schema and read `properties.type.const`. */\n private resolveConst(ref: string): string | undefined {\n const target = refName(ref)\n if (target === undefined) {\n return undefined\n }\n const typeProp = this.schemas[target]?.properties?.['type']\n return isSchema(typeProp) && typeof typeProp.const === 'string' ? typeProp.const : undefined\n }\n\n private attributes(base: string): Record<string, string> {\n const attrs = this.schemas[`${base}Attributes`]\n const props = attrs?.properties\n if (props === undefined) {\n return {}\n }\n const out: Record<string, string> = {}\n for (const [name, prop] of Object.entries(props)) {\n if (isSchema(prop)) {\n out[name] = formatHint(prop)\n }\n }\n return sortRecord(out)\n }\n\n /**\n * The relations of a type: every relation its resource renders, plus each write-only relation\n * the create and update bodies accept. A write-only relation is one whose body property carries\n * `writeOnly: true` (generator contract 8) or, in an older document, one the resource doesn't\n * render. A pivot relation reads its response pivot off the rendered relationship and its\n * request pivot off the write bodies.\n */\n private relations(\n wireType: string,\n base: string,\n resource: SchemaObject,\n collection: string | undefined,\n ): Record<string, RelationDescriptor> {\n const relProps = isSchema(resource.properties?.['relationships'])\n ? (resource.properties['relationships'].properties ?? {})\n : {}\n const writes = this.writeRelationships(base)\n const endpoints = this.relationEndpoints(wireType)\n const out: Record<string, RelationDescriptor> = {}\n const add = (name: string, component: SchemaObject | undefined, writeOnly: boolean): void => {\n const parsed = component ? this.relationFromComponent(component) : undefined\n if (parsed === undefined) {\n // A relationship component the codegen can't parse (an unknown linkage shape) is\n // dropped silently otherwise — a drift class (the grammar has grown pivot/polymorphic/\n // nested forms), so warn rather than emit a client missing the relation (D28).\n // eslint-disable-next-line no-console\n console.warn(\n `json-api codegen: relationship \"${name}\" has an unrecognized linkage shape; dropping it from the descriptor.`,\n )\n return\n }\n const descriptor: RelationDescriptor = { ...parsed }\n if (writeOnly) {\n delete descriptor.readPivot\n descriptor.writeOnly = true\n }\n if (descriptor.pivot === true) {\n const writePivot = this.writePivot(\n writes.get(name)?.ref ?? endpoints.get(name)?.requestRef,\n component!,\n )\n if (writePivot !== undefined) {\n descriptor.writePivot = writePivot\n }\n }\n out[name] =\n collection === undefined\n ? descriptor\n : this.withRelationExposure(descriptor, collection, name, endpoints.get(name))\n }\n\n for (const [name, prop] of Object.entries(relProps)) {\n if (!isSchema(prop) || typeof prop.$ref !== 'string' || writes.get(name)?.writeOnly) {\n continue\n }\n add(name, this.schemas[refName(prop.$ref) ?? ''], false)\n }\n for (const [name, write] of writes) {\n if (write.writeOnly || !(name in relProps)) {\n add(name, this.schemas[refName(write.ref) ?? ''], true)\n }\n }\n return sortRecord(out)\n }\n\n /**\n * The relationships the create and update bodies accept: each one's component `$ref` and\n * whether the body marks it `writeOnly`.\n */\n private writeRelationships(base: string): Map<string, { ref: string; writeOnly: boolean }> {\n const out = new Map<string, { ref: string; writeOnly: boolean }>()\n for (const request of [`${base}CreateRequest`, `${base}UpdateRequest`]) {\n const data = this.schemas[request]?.properties?.['data']\n const relationships = isSchema(data) ? data.properties?.['relationships'] : undefined\n const props = isSchema(relationships) ? (relationships.properties ?? {}) : {}\n for (const [name, prop] of Object.entries(props)) {\n if (!isSchema(prop) || typeof prop.$ref !== 'string') {\n continue\n }\n const writeOnly = prop['writeOnly'] === true || out.get(name)?.writeOnly === true\n out.set(name, { ref: out.get(name)?.ref ?? prop.$ref, writeOnly })\n }\n }\n return out\n }\n\n /**\n * Each relation's related and relationship paths, keyed by relation name, from the\n * operationIds the projector stamps (`fetchRelated.<type>.<relation>`, …). A relation's path\n * segment is its URI field name, which may differ from its name, so the paths are never\n * derived from the name when an operationId names them.\n */\n private relationEndpoints(wireType: string): Map<string, RelationEndpoints> {\n const out = new Map<string, RelationEndpoints>()\n const entry = (rel: string): RelationEndpoints => {\n let found = out.get(rel)\n if (found === undefined) {\n found = {}\n out.set(rel, found)\n }\n return found\n }\n for (const [path, item] of Object.entries(this.paths)) {\n for (const [method, op] of Object.entries(item) as [HttpMethod, OperationObject][]) {\n const id = op?.operationId\n if (typeof id !== 'string') {\n continue\n }\n const dot = id.indexOf('.')\n const prefix = id.slice(0, dot)\n const rest = id.slice(dot + 1)\n if (dot < 0 || !rest.startsWith(`${wireType}.`)) {\n continue\n }\n const rel = rest.slice(wireType.length + 1)\n if (prefix === RELATED_OPERATION) {\n entry(rel).related = path\n } else if ((RELATIONSHIP_OPERATIONS as readonly string[]).includes(prefix)) {\n const found = entry(rel)\n found.relationship = path\n const ref = method === 'get' ? undefined : this.requestBodyRef(op)\n if (ref !== undefined) {\n found.requestRef = ref\n }\n }\n }\n }\n return out\n }\n\n /**\n * The per-relation mutation capability, derived from the HTTP methods the relationship\n * endpoint (`{collection}/{id}/relationships/{rel}`) advertises. For a to-many:\n * `add` <- POST, `remove` <- DELETE, `replace` <- PATCH. For a to-one: `set` <- PATCH.\n * Only `true` verbs are emitted (a missing verb is simply absent). Returns `undefined`\n * when the relation exposes no relationship endpoint at all.\n */\n private relationMutations(\n path: string,\n cardinality: RelationDescriptor['cardinality'],\n ): RelationMutations | undefined {\n const item = this.paths[path]\n if (item === undefined) {\n return undefined\n }\n const mutations: RelationMutations = {}\n if (cardinality === 'many') {\n if (item.post) {\n mutations.add = true\n }\n if (item.delete) {\n mutations.remove = true\n }\n if (item.patch) {\n mutations.replace = true\n }\n } else if (item.patch) {\n mutations.set = true\n }\n return mutations\n }\n\n /**\n * Attach the per-relation endpoint-exposure signal to a relation descriptor (D24). The bundle\n * can suppress a relation's related or relationship endpoint (`withoutRelatedEndpoint()` /\n * `withoutRelationshipEndpoint()`, ADR 0027), which the OpenAPI reflects by simply omitting that\n * relation's path — but codegen synthesizes generic `{rel}` templates, erasing the per-relation\n * distinction. So mark `related: false` / `relationship: false` when this relation's specific\n * path is absent, and ALWAYS emit an explicit `mutations` object (the verb flags when the\n * relationship endpoint exists, else `{}`) so the client gates a suppressed relation OFF rather\n * than failing open (offering `.get()`/`.related()`/mutations that 404).\n */\n private withRelationExposure(\n descriptor: RelationDescriptor,\n collection: string,\n name: string,\n endpoints: RelationEndpoints | undefined,\n ): RelationDescriptor {\n const out: RelationDescriptor = { ...descriptor }\n const relatedPath = endpoints?.related ?? `${collection}/{id}/${name}`\n const relationshipPath = endpoints?.relationship ?? `${collection}/{id}/relationships/${name}`\n // The client fills `{rel}` with this segment, so a relation served under its URI field name\n // (`/articles/{id}/published-by` for `publisher`) is reached at its real path.\n const segment = (endpoints?.related ?? endpoints?.relationship)?.split('/').pop()\n if (segment !== undefined && segment !== name) {\n out.uriField = segment\n }\n const relatedGet = this.operation(relatedPath, 'get')\n if (relatedGet === undefined) {\n out.related = false\n }\n const mutations = this.relationMutations(relationshipPath, descriptor.cardinality)\n if (mutations === undefined) {\n out.relationship = false\n out.mutations = {}\n } else {\n out.mutations = mutations\n }\n // The related/relationship reads may advertise their own `withCount` (`_self_` + the relation's\n // countable relations) with a negotiation profile — capture it so a typed `.related()`/`.get()`\n // can send `withCount` and negotiate the profile the endpoint requires (D3).\n const countable =\n withCountParam(relatedGet) ?? withCountParam(this.operation(relationshipPath, 'get'))\n if (countable !== undefined) {\n out.countable = countable\n }\n // A to-many related endpoint can advertise a DIFFERENT paginator than the related type's\n // top-level collection (D6a). Read the related-endpoint kind (preferring the related over the\n // relationship endpoint) and carry it ONLY when it diverges from the related type's collection\n // paginator — the client falls back to that type's paginator otherwise, so parity stays silent.\n if (descriptor.cardinality === 'many') {\n const relatedPaginator =\n this.paginatorOf(relatedGet) === 'none'\n ? this.paginatorOf(this.operation(relationshipPath, 'get'))\n : this.paginatorOf(relatedGet)\n const relatedType = descriptor.types[0]\n const typePaginator = relatedType !== undefined ? this.typePaginator(relatedType) : 'none'\n if (\n relatedPaginator !== 'none' &&\n JSON.stringify(relatedPaginator) !== JSON.stringify(typePaginator)\n ) {\n out.paginator = relatedPaginator\n }\n }\n return out\n }\n\n /**\n * Collect the custom actions for a type from its `{collection}/-actions/{name}` and\n * `{collection}/{id}/-actions/{name}` paths. The action name is the last segment; scope\n * is `resource` when the path carries `/{id}/`, else `collection`. `input` is `document`\n * (a JSON:API requestBody), `none` (no requestBody) or `raw` (a non-JSON:API body);\n * `output` is `document` (a 2xx returns a JSON:API document) or `none` (only `204`).\n */\n private actions(collection: string): Record<string, ActionDescriptor> {\n const out: Record<string, ActionDescriptor> = {}\n const collectionPrefix = `${collection}/-actions/`\n const resourcePrefix = `${collection}/{id}/-actions/`\n for (const [path, item] of Object.entries(this.paths)) {\n let scope: ActionDescriptor['scope']\n let name: string\n if (path.startsWith(resourcePrefix)) {\n scope = 'resource'\n name = path.slice(resourcePrefix.length)\n } else if (path.startsWith(collectionPrefix)) {\n scope = 'collection'\n name = path.slice(collectionPrefix.length)\n } else {\n continue\n }\n // The action name is a single trailing segment.\n if (name.length === 0 || name.includes('/')) {\n continue\n }\n // An action is invoked over one HTTP method; the bundle lets an author declare a\n // non-POST method, so read the advertised operation (POST-preferred) rather than only\n // `post` — else a GET/PATCH/DELETE-only action would silently vanish from the client.\n const picked = pickOperation(item)\n if (picked === undefined) {\n // eslint-disable-next-line no-console\n console.warn(\n `json-api codegen: custom action path \"${path}\" advertises no usable operation; skipping.`,\n )\n continue\n }\n const { method, op } = picked\n const input = actionInput(op)\n const output = actionOutput(op)\n const action: ActionDescriptor = { scope, path, input, output }\n // Only carried when non-POST (POST is the runtime default), keeping the common descriptor tiny.\n if (method !== 'post') {\n action.method = method.toUpperCase()\n }\n // A document input names its resource type so the client can accept FLAT input and build the\n // envelope (+ remap 422 pointers), matching `create`/`update` ergonomics.\n if (input === 'document') {\n const inputType = this.documentPrimary(actionRequestRef(op))?.type\n if (inputType !== undefined) {\n action.inputType = inputType\n }\n }\n // A document output names its primary resource type + cardinality so the client materialises\n // the response into that resource view (matching reads), not the raw wire envelope.\n if (output === 'document') {\n const primary = this.documentPrimary(this.firstOkJsonApiRef(op))\n if (primary !== undefined) {\n action.outputType = primary.type\n action.outputCardinality = primary.cardinality\n }\n }\n // A raw-input action carries its declared (non-JSON:API) media type so the client sends\n // the right `Content-Type` rather than a wildcard the server may reject.\n if (input === 'raw') {\n const contentType = rawContentType(op)\n if (contentType !== undefined) {\n action.contentType = contentType\n }\n }\n out[name] = action\n }\n return sortRecord(out)\n }\n\n /**\n * The wire type (and cardinality) of a document component's primary `data` — a `$ref` to a\n * resource, an inline object carrying `properties.type.const` (a create-request body), or an\n * array of resource/identifier refs (a collection). `undefined` when the type can't be resolved.\n */\n private documentPrimary(\n ref: string | undefined,\n ): { type: string; cardinality: Cardinality } | undefined {\n if (typeof ref !== 'string') {\n return undefined\n }\n const component = refName(ref)\n const data = component === undefined ? undefined : this.schemas[component]?.properties?.['data']\n if (!isSchema(data)) {\n return undefined\n }\n if (isSchema(data.items)) {\n const itemRef = data.items.$ref\n const many = typeof itemRef === 'string' ? this.resolveConst(itemRef) : undefined\n return many === undefined ? undefined : { type: many, cardinality: 'many' }\n }\n const one = this.dataConst(data)\n return one === undefined ? undefined : { type: one, cardinality: 'one' }\n }\n\n /** The wire type of a single `data` schema — a `$ref` to a resource, or an inline `type.const`. */\n private dataConst(data: SchemaObject): string | undefined {\n if (typeof data.$ref === 'string') {\n return this.resolveConst(data.$ref)\n }\n const typeProp = data.properties?.['type']\n return isSchema(typeProp) && typeof typeProp.const === 'string' ? typeProp.const : undefined\n }\n\n /** The `$ref` of the first 2xx JSON:API response body on an operation (the output document). */\n private firstOkJsonApiRef(op: OperationObject): string | undefined {\n for (const [code, response] of Object.entries(op.responses ?? {})) {\n if (!code.startsWith('2')) {\n continue\n }\n const ref = response.content?.[JSON_API_MEDIA_TYPE]?.schema?.$ref\n if (typeof ref === 'string') {\n return ref\n }\n }\n return undefined\n }\n\n /** Resolve a relationship component's `data` into a {@link RelationDescriptor}. */\n private relationFromComponent(component: SchemaObject): RelationDescriptor | undefined {\n const data = component.properties?.['data']\n if (!isSchema(data)) {\n return undefined\n }\n\n // to-many: data.type === 'array'\n if (data.type === 'array') {\n const items = data.items\n if (items === undefined) {\n return undefined\n }\n if (typeof items.$ref === 'string') {\n // monomorphic to-many\n const type = this.resolveConst(items.$ref)\n return type === undefined ? undefined : { cardinality: 'many', types: [type], pivot: false }\n }\n if (Array.isArray(items.allOf)) {\n // pivot to-many: the $ref is the allOf entry that carries it\n const type = this.constFromAllOf(items.allOf)\n if (type === undefined) {\n return undefined\n }\n const relation: RelationDescriptor = { cardinality: 'many', types: [type], pivot: true }\n const readPivot = this.pivotDescriptor(pivotNodeFromAllOf(items.allOf), 'read')\n if (readPivot !== undefined) {\n relation.readPivot = readPivot\n }\n return relation\n }\n if (Array.isArray(items.anyOf)) {\n // polymorphic to-many\n return { cardinality: 'many', types: this.constsFromRefs(items.anyOf), pivot: false }\n }\n return undefined\n }\n\n // to-one: data.anyOf with the non-null entries being $refs (or pivot allOfs);\n // a polymorphic to-one nests its $refs one level deeper in another anyOf.\n if (Array.isArray(data.anyOf)) {\n const types: string[] = []\n let pivot = false\n let readPivot: PivotDescriptor | undefined\n for (const entry of data.anyOf) {\n if (typeof entry.$ref === 'string') {\n const type = this.resolveConst(entry.$ref)\n if (type !== undefined) {\n types.push(type)\n }\n } else if (Array.isArray(entry.allOf)) {\n const type = this.constFromAllOf(entry.allOf)\n if (type !== undefined) {\n types.push(type)\n pivot = true\n readPivot = this.pivotDescriptor(pivotNodeFromAllOf(entry.allOf), 'read')\n }\n } else if (Array.isArray(entry.anyOf)) {\n // polymorphic to-one: the non-null entry is itself an anyOf of $refs\n types.push(...this.constsFromRefs(entry.anyOf))\n }\n }\n if (types.length === 0) {\n return undefined\n }\n const relation: RelationDescriptor = { cardinality: 'one', types, pivot }\n if (readPivot !== undefined) {\n relation.readPivot = readPivot\n }\n return relation\n }\n\n return undefined\n }\n\n /**\n * The request pivot of a pivot relation: read off the component a write body (or a\n * relationship mutation) refs, falling back to the rendered relationship's pivot minus its\n * `readOnly` fields when no request shape is published (before generator contract 8).\n */\n private writePivot(ref: string | undefined, fallback: SchemaObject): PivotDescriptor | undefined {\n const component = ref === undefined ? undefined : this.schemas[refName(ref) ?? '']\n return this.pivotDescriptor(\n pivotNodeOf(component ?? fallback) ?? pivotNodeOf(fallback),\n 'write',\n )\n }\n\n /**\n * A {@link PivotDescriptor} from a member's `meta.pivot` schema: field hints, the required\n * fields and the nullable ones. Generator contract 8 refs a `<Type><Rel>Pivot` (response) or\n * `<Type><Rel>WritePivot` (request) component, each with its own `required`. An older document\n * inlines one shared schema in the write context, so a read takes every field as rendered and a\n * write drops the `readOnly` ones. `undefined` when the schema has no fields.\n */\n private pivotDescriptor(\n node: SchemaObject | undefined,\n side: 'read' | 'write',\n ): PivotDescriptor | undefined {\n if (node === undefined) {\n return undefined\n }\n const shared = typeof node.$ref !== 'string'\n const schema = shared ? node : this.schemas[refName(node.$ref as string) ?? '']\n const fields: Record<string, string> = {}\n const nullable: string[] = []\n for (const [name, prop] of Object.entries(schema?.properties ?? {})) {\n if (!isSchema(prop) || prop[side === 'read' ? 'writeOnly' : 'readOnly'] === true) {\n continue\n }\n fields[name] = formatHint(prop)\n if (isNullable(prop)) {\n nullable.push(name)\n }\n }\n const names = Object.keys(fields)\n if (names.length === 0) {\n return undefined\n }\n const required =\n shared && side === 'read' ? names : names.filter((name) => schema?.required?.includes(name))\n const out: PivotDescriptor = { fields: sortRecord(fields) }\n if (required.length < names.length) {\n // oxlint-disable-next-line no-array-sort -- sorting a freshly-created array\n out.required = required.sort()\n }\n if (nullable.length > 0) {\n // oxlint-disable-next-line no-array-sort -- sorting a freshly-created array\n out.nullable = nullable.sort()\n }\n return out\n }\n\n /** Pull the related type from the `$ref` entry of an `allOf` (the pivot shape). */\n private constFromAllOf(allOf: readonly SchemaObject[]): string | undefined {\n for (const entry of allOf) {\n if (typeof entry.$ref === 'string') {\n const type = this.resolveConst(entry.$ref)\n if (type !== undefined) {\n return type\n }\n }\n }\n return undefined\n }\n\n /** Resolve every `$ref` entry in a list to its wire type. */\n private constsFromRefs(entries: readonly SchemaObject[]): string[] {\n const types: string[] = []\n for (const entry of entries) {\n if (typeof entry.$ref === 'string') {\n const type = this.resolveConst(entry.$ref)\n if (type !== undefined) {\n types.push(type)\n }\n }\n }\n return types\n }\n\n private clientId(base: string): ClientIdPolicy {\n const create = this.schemas[`${base}CreateRequest`]\n const data = isSchema(create?.properties?.['data']) ? create.properties['data'] : undefined\n if (data === undefined) {\n return 'forbidden'\n }\n if (data.properties?.['id'] === false) {\n return 'forbidden'\n }\n return data.required?.includes('id') ? 'required' : 'optional'\n }\n\n /**\n * Find the collection path for a type, then derive each per-operation path that\n * actually exists. The collection path P is the one whose POST requestBody refs\n * `<Base>CreateRequest`, else the GET whose 200 response refs `<Base>Collection`.\n */\n private operationPaths(base: string): Record<string, string> {\n const collection = this.collectionPath(base)\n const out: Record<string, string> = {}\n if (collection === undefined) {\n return out\n }\n\n if (this.operation(collection, 'get')) {\n out['fetchMany'] = collection\n }\n if (this.operation(collection, 'post')) {\n out['create'] = collection\n }\n\n const item = `${collection}/{id}`\n if (this.operation(item, 'get')) {\n out['fetchOne'] = item\n }\n if (this.operation(item, 'patch')) {\n out['update'] = item\n }\n if (this.operation(item, 'delete')) {\n out['delete'] = item\n }\n\n if (this.hasRelatedPath(collection)) {\n out['fetchRelated'] = `${collection}/{id}/{rel}`\n }\n if (this.hasRelationshipPath(collection)) {\n out['fetchRelationship'] = `${collection}/{id}/relationships/{rel}`\n }\n\n return sortRecord(out)\n }\n\n private collectionPath(base: string): string | undefined {\n let byCollection: string | undefined\n for (const [path, item] of Object.entries(this.paths)) {\n const post = item.post\n if (post && refEndsWith(this.requestBodyRef(post), `${base}CreateRequest`)) {\n return path\n }\n // Only a genuine top-level collection qualifies for the response-ref fallback —\n // a parent-scoped *related* collection (e.g. `/users/{id}/playlists`) also refs\n // `<Base>Collection` but is not a fetchMany endpoint for that type.\n if (\n byCollection === undefined &&\n !path.includes('/{id}/') &&\n refEndsWith(this.okResponseRef(item.get), `${base}Collection`)\n ) {\n byCollection = path\n }\n }\n return byCollection\n }\n\n /** Any `P/{id}/<rel>` related path (excludes relationships/ and custom `-actions`). */\n private hasRelatedPath(collection: string): boolean {\n const prefix = `${collection}/{id}/`\n return Object.keys(this.paths).some((path) => {\n if (!path.startsWith(prefix)) {\n return false\n }\n const rest = path.slice(prefix.length)\n return rest.length > 0 && !rest.includes('/') && !rest.startsWith('-')\n })\n }\n\n private hasRelationshipPath(collection: string): boolean {\n const prefix = `${collection}/{id}/relationships/`\n return Object.keys(this.paths).some(\n (path) => path.startsWith(prefix) && !path.slice(prefix.length).includes('/'),\n )\n }\n\n /** Detect the paginator from the fetchMany operation's page parameters. */\n private paginator(base: string): PaginatorDescriptor {\n const collection = this.collectionPath(base)\n return this.paginatorOf(this.operation(collection ?? '', 'get'), collection)\n }\n\n /**\n * Detect the paginator an operation advertises. A page schema stamped with `x-paginator`\n * (contract 3) names its strategy and the wire key for each role, so it decides both. Without\n * the stamp, the strategy is inferred from canonical member names (see {@link kindOfMembers}).\n * Anything unrecognised warns and generates as unpaginated. `label` (a path) names the endpoint\n * in the warning; without it nothing is logged.\n */\n private paginatorOf(op: OperationObject | undefined, label?: string): PaginatorDescriptor {\n const warn = (problem: string): 'none' => {\n if (label !== undefined) {\n // eslint-disable-next-line no-console\n console.warn(\n `json-api codegen: endpoint \"${label}\" ${problem}; treating it as unpaginated.`,\n )\n }\n return 'none'\n }\n\n const schema = op?.parameters?.find((param) => param.name === 'page')?.schema\n if (schema?.['x-paginator'] !== undefined) {\n return stampedPaginator(schema, warn)\n }\n\n const { members, menu } = this.pageMembers(op)\n if (menu === undefined) {\n const kind = kindOfMembers(members)\n if (kind !== undefined) {\n return kind\n }\n }\n // A page parameter matching no single known kind is a drift the client would silently treat\n // as unpaginated; warn rather than swallow it (D28).\n if (menu !== undefined) {\n return warn(\n `advertises a selectable page strategy menu (${menu\n .map((arm) => kindOfMembers(arm) ?? sortedList(arm))\n .join(' | ')}) without an x-paginator stamp naming its default`,\n )\n }\n return members.size > 0\n ? warn(\n `advertises page parameters matching no known paginator kind (members ${sortedList(members)})`,\n )\n : 'none'\n }\n\n /**\n * The `page` members an operation accepts, from either wire form: one `page` parameter\n * (`style: deepObject`) whose schema `properties` name the members, as `haddowg/json-api` v1\n * projects it, or the older flattened `page[number]`/`page[size]` parameters. A `oneOf` page\n * schema (a MultiPaginator menu) yields each arm's members in `menu` instead, minus the\n * `kind` discriminator.\n */\n private pageMembers(op: OperationObject | undefined): {\n members: Set<string>\n menu?: Set<string>[]\n } {\n const members = new Set<string>()\n let menu: Set<string>[] | undefined\n for (const param of op?.parameters ?? []) {\n const name = param.name\n if (name === 'page') {\n const arms = param.schema?.oneOf\n if (arms !== undefined) {\n menu = arms.map(\n (arm) => new Set(Object.keys(arm.properties ?? {}).filter((m) => m !== 'kind')),\n )\n }\n for (const member of Object.keys(param.schema?.properties ?? {})) {\n members.add(member)\n }\n } else if (name?.startsWith('page[') === true && name.endsWith(']')) {\n members.add(name.slice('page['.length, -1))\n }\n }\n return menu === undefined ? { members } : { members, menu }\n }\n\n /**\n * The `withCount` capability (Countable profile) for a type's COLLECTION read (`list`): the\n * count tokens (`schema.items.enum`) + the negotiation profile (`x-profile`) carried by the\n * collection GET's `withCount` query parameter. Returns `undefined` when the collection\n * doesn't exist or advertises no `withCount`. The profile URI is never hardcoded — it is read\n * from the parameter's `x-profile`.\n *\n * Deliberately scoped to the collection GET only. The per-endpoint token sets differ\n * (a collection counts e.g. `tracks`; a related/relationship endpoint counts `_self_` and its\n * own relations), so a single per-type `countable` can only honestly describe one endpoint.\n * The fluent surface exposes `withCount` on `list` (the collection), so `countable` mirrors\n * that endpoint — a related-GET fallback would advertise tokens `list` cannot legally send.\n */\n private countable(collection: string | undefined): CountableDescriptor | undefined {\n if (collection === undefined) {\n return undefined\n }\n return withCountParam(this.operation(collection, 'get'))\n }\n\n /**\n * The relation paths the read endpoints accept in `include` — the `include` query\n * parameter's `schema.items.enum` (already including nested dotted paths) on the collection\n * GET. Returns `undefined` when the collection advertises no `include` (nothing includable).\n *\n * Read from the collection GET to mirror {@see sortable}/{@see filterable}: the whole builder\n * is collection-centric (a type with no collection path gets no `paths` at all), and the bundle\n * advertises the same `include` enum on the collection and single-resource GETs.\n */\n private includable(collection: string | undefined): readonly string[] | undefined {\n if (collection === undefined) {\n return undefined\n }\n const tokens = paramItemsEnum(this.operation(collection, 'get'), 'include')\n return tokens !== undefined && tokens.length > 0 ? tokens : undefined\n }\n\n /**\n * The sort tokens the COLLECTION read accepts — the `sort` query parameter's\n * `schema.items.enum` (signed field names) on the collection GET. Returns `undefined` when\n * the collection advertises no `sort` parameter (sorting unsupported).\n */\n private sortable(collection: string | undefined): readonly string[] | undefined {\n if (collection === undefined) {\n return undefined\n }\n const tokens = paramItemsEnum(this.operation(collection, 'get'), 'sort')\n return tokens !== undefined && tokens.length > 0 ? tokens : undefined\n }\n\n /**\n * The filter keys the COLLECTION read accepts in `filter[...]` (the `filter[<key>]` parameter\n * names, `<key>` extracted), sorted for deterministic output. Returns `undefined` when the\n * collection advertises no `filter[...]` parameters (filtering unsupported). Value shapes are\n * deliberately not captured — `filter` values stay `unknown` (out of scope for v0.1).\n */\n private filterable(collection: string | undefined): readonly string[] | undefined {\n if (collection === undefined) {\n return undefined\n }\n const keys: string[] = []\n for (const param of this.operation(collection, 'get')?.parameters ?? []) {\n const name = param.name\n if (typeof name === 'string' && name.startsWith('filter[') && name.endsWith(']')) {\n keys.push(name.slice('filter['.length, -1))\n }\n }\n // oxlint-disable-next-line no-array-sort -- sorting a freshly-created key array\n return keys.length > 0 ? keys.sort() : undefined\n }\n\n private operation(path: string, method: HttpMethod): OperationObject | undefined {\n return this.paths[path]?.[method]\n }\n\n private requestBodyRef(op: OperationObject | undefined): string | undefined {\n return op?.requestBody?.content?.['application/vnd.api+json']?.schema?.$ref\n }\n\n private okResponseRef(op: OperationObject | undefined): string | undefined {\n return op?.responses?.['200']?.content?.['application/vnd.api+json']?.schema?.$ref\n }\n}\n\n/** The `meta.pivot` schema node of a pivot `allOf` entry list, if any. */\nfunction pivotNodeFromAllOf(allOf: readonly SchemaObject[]): SchemaObject | undefined {\n for (const entry of allOf) {\n const meta = entry.properties?.['meta']\n const pivot = isSchema(meta) ? meta.properties?.['pivot'] : undefined\n if (isSchema(pivot)) {\n return pivot\n }\n }\n return undefined\n}\n\n/**\n * The `meta.pivot` schema node of a relationship component or document: its to-many `items`\n * `allOf`, or a to-one `anyOf` entry's `allOf`.\n */\nfunction pivotNodeOf(component: SchemaObject): SchemaObject | undefined {\n const data = component.properties?.['data']\n if (!isSchema(data)) {\n return undefined\n }\n if (Array.isArray(data.items?.allOf)) {\n return pivotNodeFromAllOf(data.items.allOf)\n }\n for (const entry of data.anyOf ?? []) {\n if (Array.isArray(entry.allOf)) {\n return pivotNodeFromAllOf(entry.allOf)\n }\n }\n return undefined\n}\n\n/** Whether a schema admits `null`: a `null` type, or a `null` branch in `anyOf`/`oneOf`. */\nfunction isNullable(schema: SchemaObject): boolean {\n const type = schema.type\n if (type === 'null' || (Array.isArray(type) && type.includes('null'))) {\n return true\n }\n return [...(schema.anyOf ?? []), ...(schema.oneOf ?? [])].some((branch) => branch.type === 'null')\n}\n\n/** A schema's wire format hint: explicit `format`, else the JSON type, else a ref-enum is `string`. */\nfunction formatHint(schema: SchemaObject): string {\n if (typeof schema.format === 'string') {\n return schema.format\n }\n const types = typeKeys(schema.type)\n if (types.length > 0) {\n return types[0]!\n }\n // A $ref (typically an enum component) renders as a string union.\n if (typeof schema.$ref === 'string') {\n return 'string'\n }\n // A nullable `$ref` is `anyOf: [{ $ref }, { type: 'null' }]`: hint the value branch.\n const isNullOnly = (branch: SchemaObject): boolean =>\n branch.type !== undefined && typeKeys(branch.type).length === 0\n const branches = (schema.anyOf ?? schema.oneOf ?? []).filter((branch) => !isNullOnly(branch))\n if (branches.length === 1) {\n return formatHint(branches[0]!)\n }\n return 'unknown'\n}\n\nfunction refEndsWith(ref: string | undefined, suffix: string): boolean {\n return ref !== undefined && refName(ref) === suffix\n}\n\n/**\n * Read the {@link CountableDescriptor} off an operation's `withCount` query parameter: the\n * count tokens from its `schema.items.enum` and the negotiation profile from `x-profile`.\n * Returns `undefined` when the operation has no `withCount` parameter, or when one is present\n * but carries no `x-profile` (a `withCount` we can't tell a client how to negotiate). An empty\n * or absent token enum yields `[]` tokens (the profile alone is still actionable).\n */\nfunction withCountParam(op: OperationObject | undefined): CountableDescriptor | undefined {\n for (const param of op?.parameters ?? []) {\n if (param.name !== 'withCount') {\n continue\n }\n const profile = param['x-profile']\n if (typeof profile !== 'string') {\n return undefined\n }\n const enumValues = param.schema?.items?.enum\n const tokens = Array.isArray(enumValues)\n ? enumValues.filter((v): v is string => typeof v === 'string')\n : []\n return { tokens, profile }\n }\n return undefined\n}\n\n/**\n * The string members of an array-valued query parameter's `schema.items.enum` (the shape the\n * `include` and `sort` parameters use). Returns `undefined` when the operation carries no\n * parameter of that name, or one whose schema declares no enum.\n */\nfunction paramItemsEnum(\n op: OperationObject | undefined,\n paramName: string,\n): readonly string[] | undefined {\n for (const param of op?.parameters ?? []) {\n if (param.name !== paramName) {\n continue\n }\n const enumValues = param.schema?.items?.enum\n return Array.isArray(enumValues)\n ? enumValues.filter((v): v is string => typeof v === 'string')\n : undefined\n }\n return undefined\n}\n\n/**\n * True for the Atomic Operations ext media type — `application/vnd.api+json` carrying the\n * atomic `ext` parameter ({@link ATOMIC_EXT}). Tolerant of quoting/whitespace so any of\n * `ext=\"…\"` / `ext=…` matches.\n */\nfunction isAtomicMediaType(mediaType: string): boolean {\n return mediaType.startsWith(JSON_API_MEDIA_TYPE) && mediaType.includes(ATOMIC_EXT)\n}\n\n/** The HTTP methods an action operation may be advertised under, in resolution preference order. */\nconst ACTION_METHODS: readonly HttpMethod[] = ['post', 'get', 'put', 'patch', 'delete']\n\n/**\n * The single operation an action is invoked over: POST when advertised (the common default), else\n * the first advertised method. `undefined` when the path item carries no operation at all.\n */\nfunction pickOperation(\n item: PathItemObject,\n): { method: HttpMethod; op: OperationObject } | undefined {\n const available = ACTION_METHODS.filter((method) => item[method] !== undefined)\n const method = available.includes('post') ? 'post' : available[0]\n if (method === undefined) {\n return undefined\n }\n const op = item[method]\n return op === undefined ? undefined : { method, op }\n}\n\n/** The body shape a custom action accepts: a JSON:API document, none, or a raw payload. */\nfunction actionInput(op: OperationObject): ActionDescriptor['input'] {\n const content = op.requestBody?.content\n if (content === undefined || Object.keys(content).length === 0) {\n return 'none'\n }\n return JSON_API_MEDIA_TYPE in content ? 'document' : 'raw'\n}\n\n/** The `$ref` of an action's JSON:API request body (a `document` input), or `undefined`. */\nfunction actionRequestRef(op: OperationObject): string | undefined {\n const ref = op.requestBody?.content?.[JSON_API_MEDIA_TYPE]?.schema?.$ref\n return typeof ref === 'string' ? ref : undefined\n}\n\n/** The declared media type of a `raw`-input action — the first non-JSON:API content type. */\nfunction rawContentType(op: OperationObject): string | undefined {\n const content = op.requestBody?.content\n if (content === undefined) {\n return undefined\n }\n return Object.keys(content).find((mediaType) => mediaType !== JSON_API_MEDIA_TYPE)\n}\n\n/**\n * What a custom action returns from its first 2xx response: a `meta`-only document (a `$ref` to the\n * shared `MetaDocument` — no `data`), a resource `document` (any other JSON:API body), or `none`\n * (only a `204`).\n */\nfunction actionOutput(op: OperationObject): ActionDescriptor['output'] {\n for (const [code, response] of Object.entries(op.responses ?? {})) {\n if (!code.startsWith('2')) {\n continue\n }\n const schema = response.content?.[JSON_API_MEDIA_TYPE]?.schema\n if (schema === undefined) {\n continue\n }\n return typeof schema.$ref === 'string' && refName(schema.$ref) === 'MetaDocument'\n ? 'meta'\n : 'document'\n }\n return 'none'\n}\n\n/** Build the {@link ApiDescriptor} from a parsed OpenAPI document. */\nexport function buildDescriptor(doc: OpenApiDocument): ApiDescriptor {\n return new DescriptorBuilder(doc).build()\n}\n\n/** Detect the server-level Atomic Operations capability (`null` when none). */\nexport function buildAtomic(doc: OpenApiDocument): AtomicDescriptor | null {\n return new DescriptorBuilder(doc).buildAtomic()\n}\n\n/**\n * Classify a page member set: `number`+`size` = `page`; `offset`+`limit` = `offset`; either\n * cursor bound (`after`/`before`) = `cursor` (link-driven, D44); `number` alone = `fixed` (the\n * server fixes the size); no members = `none`; anything else = `undefined` (unrecognised).\n */\nfunction kindOfMembers(members: ReadonlySet<string>): PaginatorKind | undefined {\n if (members.has('number') && members.has('size')) {\n return 'page'\n }\n if (members.has('offset') && members.has('limit')) {\n return 'offset'\n }\n if (members.has('after') || members.has('before')) {\n return 'cursor'\n }\n if (members.size === 1 && members.has('number')) {\n return 'fixed'\n }\n return members.size === 0 ? 'none' : undefined\n}\n\n// oxlint-disable-next-line no-array-sort -- sorting a freshly-created array\nconst sortedList = (members: ReadonlySet<string>): string => [...members].sort().join(', ')\n\nconst STRATEGIES: readonly PaginatorStrategy[] = ['page', 'offset', 'cursor', 'fixed']\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\n/**\n * Read a page schema's `x-paginator` stamp. A strategy keeps the wire key the stamp names for\n * each of its roles (a missing role keeps its canonical name) and collapses to the bare kind when\n * every key is canonical. A `multi` stamp reads each `oneOf` arm by its `kind` const: an arm's own\n * stamp decides it, an unstamped arm falls back to name inference, and an arm neither recognises\n * is left out of the menu.\n */\nfunction stampedPaginator(\n schema: SchemaObject,\n warn: (problem: string) => 'none',\n): PaginatorDescriptor {\n const stamp = schema['x-paginator']\n const strategy = isRecord(stamp) ? stamp['strategy'] : undefined\n if (!isRecord(stamp) || typeof strategy !== 'string') {\n return warn('stamps a malformed x-paginator')\n }\n if (strategy === 'multi') {\n return stampedMenu(schema, stamp, warn)\n }\n if (!(STRATEGIES as readonly string[]).includes(strategy)) {\n return warn(`stamps an x-paginator strategy \"${strategy}\" this codegen does not know`)\n }\n const kind = strategy as PaginatorStrategy\n const canonical: Partial<Record<PaginatorRole, string>> = CANONICAL_PAGE_KEYS[kind]\n const stamped = isRecord(stamp['keys']) ? stamp['keys'] : {}\n const keys: Partial<Record<PaginatorRole, string>> = {}\n let renamed = false\n for (const [role, fallback] of Object.entries(canonical) as [PaginatorRole, string][]) {\n const key = typeof stamped[role] === 'string' ? stamped[role] : fallback\n keys[role] = key\n renamed ||= key !== fallback\n }\n return renamed ? { strategy: kind, keys } : kind\n}\n\nfunction stampedMenu(\n schema: SchemaObject,\n stamp: Record<string, unknown>,\n warn: (problem: string) => 'none',\n): PaginatorDescriptor {\n const arms: Record<string, MenuDescriptor['arms'][string]> = {}\n for (const arm of schema.oneOf ?? []) {\n const discriminator = arm.properties?.['kind']\n const kind = isRecord(discriminator) ? discriminator['const'] : undefined\n if (typeof kind !== 'string') {\n warn('offers a page strategy menu arm without a kind const, which is left out')\n continue\n }\n const paginator =\n arm['x-paginator'] !== undefined\n ? stampedPaginator(arm, (problem) =>\n warn(`offers a menu arm \"${kind}\" that ${problem}, which is left out`),\n )\n : (kindOfMembers(new Set(Object.keys(arm.properties ?? {}).filter((m) => m !== 'kind'))) ??\n warn(`offers a menu arm \"${kind}\" matching no known paginator kind, which is left out`))\n if (typeof paginator === 'object' && paginator.strategy === 'multi') {\n warn(`nests a page strategy menu in arm \"${kind}\", which is left out`)\n continue\n }\n if (paginator !== 'none') {\n arms[kind] = paginator\n }\n }\n const fallback = stamp['default']\n if (typeof fallback !== 'string' || arms[fallback] === undefined) {\n return warn(\n `stamps a page strategy menu whose default ${typeof fallback === 'string' ? `\"${fallback}\"` : '(missing)'} is not one of its generated arms`,\n )\n }\n return { strategy: 'multi', default: fallback, arms }\n}\n","import type { OpenApiDocument } from './openapi'\n\n/** Below this the document predates the structures this codegen reads. */\nexport const MINIMUM_CONTRACT = 1\n\n/** Above this the document carries structures this codegen does not read. */\nexport const MAXIMUM_CONTRACT = 9\n\n/**\n * Check the document's `info.x-generator.contract` against the range this codegen reads. A\n * document older than the range throws; a newer one returns a warning, because its new\n * structures would go unread and the client would silently miss what the server offers. A\n * document with no contract (json-api before 1.1.0) passes.\n */\nexport function checkContract(doc: OpenApiDocument): string | undefined {\n const contract = doc.info?.['x-generator']?.contract\n if (typeof contract !== 'number') {\n return undefined\n }\n if (contract < MINIMUM_CONTRACT) {\n throw new Error(\n `the document declares contract ${contract}, which predates what this codegen reads (it supports ${MINIMUM_CONTRACT} to ${MAXIMUM_CONTRACT}). Use an older codegen release, or regenerate the document from a newer server.`,\n )\n }\n if (contract > MAXIMUM_CONTRACT) {\n return `the document declares contract ${contract} and this codegen reads up to ${MAXIMUM_CONTRACT}. It describes capabilities that were not generated; upgrade the codegen to pick them up.`\n }\n return undefined\n}\n","import type { OpenApiDocument, SchemaObject, SchemaOrBool } from './openapi'\n\nconst REF_PREFIX = '#/components/schemas/'\nconst ERROR_DOCUMENT = /^ErrorDocument(\\d{3})?$/\n\n/** One documented error code, with whatever the document says about it. */\nexport interface DocumentedErrorCode {\n code: string\n /** The `<Code>Error` component's `description`, when the document has one (contract 4). */\n description?: string\n /** Example `detail` values, from the component's `detail` property (`example` / `examples`). */\n examples: unknown[]\n}\n\n/** The server's error catalogue as the codegen reads it. */\nexport interface ErrorCatalogue {\n /** Every code any error document offers, sorted by code. */\n codes: DocumentedErrorCode[]\n /**\n * Per status, the codes its `ErrorDocument<NNN>` offers, sorted by code. A status whose\n * document offers only the generic `Error` maps to an empty list.\n */\n byStatus: Map<number, string[]>\n}\n\nfunction isSchema(value: SchemaOrBool | undefined): value is SchemaObject {\n return typeof value === 'object' && value !== null\n}\n\n/** A schema node and its `allOf` members, where a code variant keeps its narrowing. */\nfunction layers(schema: SchemaObject): SchemaObject[] {\n return [schema, ...(schema.allOf ?? []).filter((member) => member.$ref === undefined)]\n}\n\nfunction property(schema: SchemaObject, name: string): SchemaObject | undefined {\n for (const layer of layers(schema)) {\n const prop = layer.properties?.[name]\n if (isSchema(prop)) {\n return prop\n }\n }\n return undefined\n}\n\nfunction examplesOf(detail: SchemaObject | undefined): unknown[] {\n if (detail === undefined) {\n return []\n }\n const examples = Array.isArray(detail['examples']) ? [...(detail['examples'] as unknown[])] : []\n if ('example' in detail && !examples.includes(detail['example'])) {\n examples.unshift(detail['example'])\n }\n return examples\n}\n\n/**\n * Read the documented error codes off a document's error documents. `ErrorDocument` and each\n * `ErrorDocument<NNN>` offer their codes as `errors.items.anyOf` branches that `$ref` a\n * `<Code>Error` component; a branch with a `code` const names a code, and the generic `Error`\n * branch (no const) names none.\n */\nexport function readErrorCatalogue(doc: OpenApiDocument): ErrorCatalogue {\n const schemas = doc.components?.schemas ?? {}\n const codes = new Map<string, DocumentedErrorCode>()\n const byStatus = new Map<number, string[]>()\n\n for (const [name, schema] of Object.entries(schemas)) {\n const match = ERROR_DOCUMENT.exec(name)\n if (match === null) {\n continue\n }\n const items = property(schema, 'errors')?.items\n const branches = items === undefined ? [] : [...(items.anyOf ?? []), ...(items.oneOf ?? [])]\n const documentCodes = new Set<string>()\n for (const branch of branches) {\n const component =\n typeof branch.$ref === 'string' && branch.$ref.startsWith(REF_PREFIX)\n ? schemas[branch.$ref.slice(REF_PREFIX.length)]\n : branch\n const code = component === undefined ? undefined : property(component, 'code')?.const\n if (component === undefined || typeof code !== 'string') {\n continue\n }\n documentCodes.add(code)\n if (!codes.has(code)) {\n const description = layers(component)\n .map((layer) => layer.description?.trim())\n .find((text) => text !== undefined && text !== '')\n codes.set(code, {\n code,\n ...(description ? { description } : {}),\n examples: examplesOf(property(component, 'detail')),\n })\n }\n }\n if (match[1] !== undefined) {\n // oxlint-disable-next-line no-array-sort -- sorting a freshly-created array\n byStatus.set(Number(match[1]), [...documentCodes].sort())\n }\n }\n\n return {\n // oxlint-disable-next-line no-array-sort -- sorting a freshly-created array\n codes: [...codes.values()].sort((a, b) => (a.code < b.code ? -1 : a.code > b.code ? 1 : 0)),\n // oxlint-disable-next-line no-array-sort -- sorting a freshly-created array\n byStatus: new Map([...byStatus].sort(([a], [b]) => a - b)),\n }\n}\n\n/** A TSDoc block for one code: its description, then each example detail as an `@example`. */\nfunction codeDoc(entry: DocumentedErrorCode, indent: string): string | undefined {\n const lines: string[] = []\n if (entry.description !== undefined) {\n lines.push(...entry.description.split('\\n'))\n }\n for (const example of entry.examples) {\n if (lines.length > 0) {\n lines.push('')\n }\n const text = typeof example === 'string' ? example : JSON.stringify(example)\n lines.push(...`@example ${text}`.split('\\n'))\n }\n if (lines.length === 0) {\n return undefined\n }\n if (lines.length === 1) {\n return `${indent}/** ${lines[0]!.replace(/\\*\\//g, '* /')} */`\n }\n return [\n `${indent}/**`,\n ...lines.map((line) => `${indent} * ${line.replace(/\\*\\//g, '* /')}`.trimEnd()),\n `${indent} */`,\n ].join('\\n')\n}\n\n/** A bare object key when the code is a valid identifier, else a quoted one. */\nfunction codeKey(code: string): string {\n return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(code) ? code : JSON.stringify(code)\n}\n\n/**\n * Emit `ErrorCodes`, a const object keyed by every documented code with its TSDoc on the key\n * (editors show TSDoc on an object key, not on a string-literal union member), the `ErrorCode`\n * union derived from it, and `ErrorCodeByStatus`, the codes each status's error document offers.\n * A document with no code catalogue gets an empty `ErrorCodes` and `ErrorCode = string`, so the\n * bound guard still takes any code.\n */\nexport function emitErrorCodes(catalogue: ErrorCatalogue): string {\n const codeTypes =\n catalogue.codes.length === 0\n ? [\n '/** The documented error codes. This document catalogues none. */',\n 'export const ErrorCodes = {} as const',\n '',\n '/** The documented error codes. This document catalogues none, so any code is accepted. */',\n 'export type ErrorCode = string',\n ].join('\\n')\n : [\n '/**',\n ' * Every error code this server documents, keyed by itself. Hover a key for what the code',\n ' * means: `hasErrorCode(error, ErrorCodes.RESOURCE_NOT_FOUND)`.',\n ' */',\n 'export const ErrorCodes = {',\n ...catalogue.codes.flatMap((entry) => {\n const doc = codeDoc(entry, ' ')\n const member = ` ${codeKey(entry.code)}: ${JSON.stringify(entry.code)},`\n return doc === undefined ? [member] : [doc, member]\n }),\n '} as const',\n '',\n '/**',\n ' * Every error code this server documents. An error may still carry a code that is not',\n ' * listed: the catalogue is open.',\n ' */',\n 'export type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes]',\n ].join('\\n')\n\n const statusLines = [...catalogue.byStatus].map(([status, codes]) => {\n const members = codes.map((c) => JSON.stringify(c))\n const line = ` ${status}: ${members.length === 0 ? 'never' : members.join(' | ')}`\n return line.length <= 100\n ? line\n : ` ${status}:\\n${members.map((m) => ` | ${m}`).join('\\n')}`\n })\n const byStatus = [\n '/**',\n ' * The documented error codes per HTTP status. `never` marks a status whose error document',\n ' * documents no specific code.',\n ' */',\n statusLines.length === 0\n ? 'export interface ErrorCodeByStatus {}'\n : `export interface ErrorCodeByStatus {\\n${statusLines.join('\\n')}\\n}`,\n ].join('\\n')\n\n const guard = [\n '/**',\n ' * True when `err` is a `JsonApiError` and any of its error objects carries `code`. Only takes a',\n ' * documented code; match an undocumented one with `hasErrorCode` from',\n \" * '@haddowg/json-api-client'.\",\n ' */',\n 'export const hasErrorCode = hasErrorCodeRuntime as ErrorCodeGuard<ErrorCode>',\n ].join('\\n')\n\n return [codeTypes, byStatus, guard].join('\\n\\n')\n}\n","import { createHash } from 'node:crypto'\nimport type { OpenApiDocument } from './openapi'\n\n/**\n * A deterministic provenance record identifying the spec a client was generated from.\n * Stamped into every generated artifact's header so a reader (and the `--check` drift\n * gate) can tell which spec produced the committed output. Deliberately timestamp-free\n * — the same spec must always produce byte-identical output so `--check` can compare.\n */\nexport interface Provenance {\n /** `<title> <version>` from the document's `info` (falls back to `unknown` parts). */\n readonly source: string\n /** The first declared server URL, or `undefined` when none is declared. */\n readonly server: string | undefined\n /** A SHA-256 (first 16 hex chars) of the canonicalised source document. */\n readonly hash: string\n}\n\n/**\n * Canonicalise a JSON value with object keys sorted recursively, so the content hash is\n * insensitive to key ordering in the served document (two byte-different-but-equivalent\n * specs hash the same). Arrays keep their order (it is significant in OpenAPI).\n */\nfunction canonicalise(value: unknown): unknown {\n if (Array.isArray(value)) {\n return value.map(canonicalise)\n }\n if (value !== null && typeof value === 'object') {\n const out: Record<string, unknown> = {}\n // oxlint-disable-next-line no-array-sort -- sorting a freshly-created key array\n for (const key of Object.keys(value).sort()) {\n out[key] = canonicalise((value as Record<string, unknown>)[key])\n }\n return out\n }\n return value\n}\n\n/** A SHA-256 over an arbitrary JSON value (canonicalised), truncated to 16 hex chars (64 bits). */\nexport function hashJson(value: unknown): string {\n return createHash('sha256')\n .update(JSON.stringify(canonicalise(value)))\n .digest('hex')\n .slice(0, 16)\n}\n\n/**\n * Derive the provenance record for a source OpenAPI document. The `source` identifier is\n * `<info.title> <info.version>` (each part `unknown` when absent); the `hash` is a stable\n * content hash of the whole document.\n */\nexport function deriveProvenance(doc: OpenApiDocument): Provenance {\n const title = doc.info?.title ?? 'unknown'\n const version = doc.info?.version ?? 'unknown'\n return {\n source: `${title} ${version}`,\n server: doc.servers?.[0]?.url,\n hash: hashJson(doc),\n }\n}\n\n/**\n * Render the provenance record as the JSDoc header lines stamped into a generated artifact\n * (each already prefixed with ` * `). Deterministic: no timestamp, so re-generating from the\n * same spec yields byte-identical output.\n */\nexport function provenanceLines(provenance: Provenance): string[] {\n const lines = [` * Source spec: ${provenance.source}`, ` * Spec hash: ${provenance.hash}`]\n if (provenance.server !== undefined) {\n lines.splice(1, 0, ` * Server: ${provenance.server}`)\n }\n return lines\n}\n","import {\n type ActionDescriptor,\n type ApiDescriptor,\n type AtomicDescriptor,\n HANDLE_RESERVED,\n type ResourceDescriptor,\n} from '@haddowg/json-api-client'\nimport { buildAtomic } from './build-descriptor'\nimport { emitErrorCodes, readErrorCatalogue } from './error-codes'\nimport type { OpenApiDocument, SchemaObject, SchemaOrBool } from './openapi'\nimport { deriveProvenance, provenanceLines, type Provenance } from './provenance'\nimport { unwrapRefs } from './unwrap-refs'\n\nconst REF_PREFIX = '#/components/schemas/'\nconst JSON_API_MEDIA_TYPE = 'application/vnd.api+json'\n\n/** A loose JSON:API document shape — the fallback an action body/result types as when its component can't be resolved. */\nconst LOOSE_DOCUMENT = 'Record<string, unknown>'\n\n/** A relation name that will later collide with a fluent-surface verb. */\nexport interface VerbCollision {\n type: string\n relation: string\n}\n\n/**\n * The reserved relation names: the members the read handle actually shadows (kept in sync\n * via the runtime's {@link HANDLE_RESERVED}) plus the future Phase-3 write verbs. A relation\n * named like any of these must route through `.rel(name)`, so the codegen warns at build time.\n * (`type`/`id` from {@link HANDLE_RESERVED} can never be JSON:API relation names.)\n */\nconst RESERVED_VERBS = new Set<string>([\n ...HANDLE_RESERVED,\n 'update',\n 'delete',\n 'create',\n 'list',\n 'actions',\n])\n\n/**\n * Find relations whose name shadows a reserved fluent-surface member (a handle accessor or a\n * future write verb). Such relations are routed via `.rel(name)`; the codegen warns at build time.\n */\nexport function detectVerbCollisions(descriptor: ApiDescriptor): VerbCollision[] {\n const collisions: VerbCollision[] = []\n for (const type of Object.keys(descriptor)) {\n for (const relation of Object.keys(descriptor[type]!.relations)) {\n if (RESERVED_VERBS.has(relation)) {\n collisions.push({ type, relation })\n }\n }\n }\n return collisions\n}\n\nfunction refName(ref: string): string | undefined {\n return ref.startsWith(REF_PREFIX) ? ref.slice(REF_PREFIX.length) : undefined\n}\n\nfunction isSchema(value: SchemaOrBool | undefined): value is SchemaObject {\n return typeof value === 'object' && value !== null\n}\n\n/** PascalCase a JSON:API wire type for use in a TS identifier (e.g. `public-profiles` -> `PublicProfiles`). */\nfunction pascalCase(value: string): string {\n return value\n .split(/[^a-zA-Z0-9]+/)\n .filter((part) => part.length > 0)\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join('')\n}\n\n/** Emit a JSON-string literal (used for keys that aren't bare identifiers and enum members). */\nfunction quote(value: string): string {\n return JSON.stringify(value)\n}\n\n/** True when a string is a safe bare object-key identifier. */\nfunction isIdentifier(value: string): boolean {\n return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(value)\n}\n\nfunction objectKey(value: string): string {\n return isIdentifier(value) ? value : quote(value)\n}\n\n/**\n * Render a description as a JSDoc comment at the given indent — single-line when it fits,\n * a block otherwise. Returns `undefined` for empty text. Neutralises any `*\\/` so a\n * description can never terminate the comment early.\n */\nfunction jsDoc(text: string | undefined, indent: string): string | undefined {\n const trimmed = text?.trim()\n if (!trimmed) {\n return undefined\n }\n const lines = trimmed.replace(/\\*\\//g, '* /').split('\\n')\n if (lines.length === 1) {\n return `${indent}/** ${lines[0]} */`\n }\n return [\n `${indent}/**`,\n ...lines.map((line) => `${indent} * ${line}`.trimEnd()),\n `${indent} */`,\n ].join('\\n')\n}\n\n/** The validation keywords a member's TSDoc states, each as a tag of the same name. */\nconst CONSTRAINT_KEYWORDS = [\n 'format',\n 'pattern',\n 'minLength',\n 'maxLength',\n 'minimum',\n 'exclusiveMinimum',\n 'maximum',\n 'exclusiveMaximum',\n 'multipleOf',\n 'minItems',\n 'maxItems',\n 'uniqueItems',\n 'minProperties',\n 'maxProperties',\n] as const\n\n/** A tag value as TSDoc text: strings bare, a pattern or anything structured as code. */\nfunction tagValue(keyword: string, value: unknown): string {\n if (keyword === 'pattern' || (typeof value !== 'string' && typeof value !== 'number')) {\n return `\\`${typeof value === 'string' ? value : JSON.stringify(value)}\\``\n }\n return String(value)\n}\n\n/**\n * The TSDoc for an attribute: its description, then a tag per constraint the schema declares\n * (`@minLength 1`, `@pattern …`), its `@defaultValue`, any `@example` and `@deprecated`. Each\n * schema states the constraints of the context it describes, so a read member and its create\n * and update counterparts can document different bounds. The keywords are read off the member\n * and any inline `anyOf`/`oneOf` branch; a `$ref`'d component documents itself.\n */\nfunction memberDoc(schema: SchemaObject): string | undefined {\n const layers = [\n schema,\n ...[...(schema.anyOf ?? []), ...(schema.oneOf ?? [])].filter(\n (branch) => branch.$ref === undefined,\n ),\n ]\n const tags: string[] = []\n for (const keyword of CONSTRAINT_KEYWORDS) {\n for (const layer of layers) {\n const value = layer[keyword]\n if (value === undefined || value === false) {\n continue\n }\n tags.push(value === true ? `@${keyword}` : `@${keyword} ${tagValue(keyword, value)}`)\n break\n }\n }\n if ('default' in schema) {\n tags.push(`@defaultValue \\`${JSON.stringify(schema['default'])}\\``)\n }\n const examples = Array.isArray(schema['examples']) ? [...(schema['examples'] as unknown[])] : []\n if ('example' in schema && !examples.includes(schema['example'])) {\n examples.unshift(schema['example'])\n }\n for (const example of examples) {\n tags.push(`@example ${typeof example === 'string' ? example : JSON.stringify(example)}`)\n }\n if (schema['deprecated'] === true) {\n tags.push('@deprecated')\n }\n const description = schema.description?.trim()\n if (tags.length === 0) {\n return description\n }\n return description ? `${description}\\n\\n${tags.join('\\n')}` : tags.join('\\n')\n}\n\nexport class Emitter {\n private readonly schemas: Record<string, SchemaObject>\n /** Wire type -> the schema `Base` (the `<Base>Resource` name minus `Resource`). */\n private readonly baseByType: Map<string, string>\n /** Enum component names referenced by an attribute, in first-seen order. */\n private readonly usedEnums = new Map<string, SchemaObject>()\n /**\n * Component-schema names whose dedicated interface is emitted (e.g. `AlbumsAttributes`,\n * `AlbumsCreateAttributes`). A `$ref` to one of these resolves to the interface name\n * rather than being re-expanded structurally — so an action envelope nests the precise,\n * already-named attribute type. Populated as interfaces are emitted.\n */\n private readonly emittedInterfaces = new Set<string>()\n /** Component names mid-expansion in {@link tsType} — a cycle guard for self/mutually-referential `$ref`s. */\n private readonly expanding = new Set<string>()\n /**\n * The per-action alias names actually emitted, keyed `type -> actionName -> { input?; output? }`.\n * Populated by {@link actionTypeAliases}; consumed by {@link actionTypesMap} so the action\n * type-map only references aliases that exist (a `none` input/output contributes neither).\n */\n private readonly actionAliasNames = new Map<\n string,\n Map<string, { input?: string; output?: string }>\n >()\n\n /** Provenance of the source document, stamped into the generated header for drift tracking. */\n private readonly provenance: Provenance\n\n private readonly doc: OpenApiDocument\n\n constructor(\n source: OpenApiDocument,\n private readonly descriptor: ApiDescriptor,\n private readonly atomic: AtomicDescriptor | null,\n ) {\n this.doc = unwrapRefs(source)\n this.schemas = this.doc.components?.schemas ?? {}\n this.baseByType = this.indexBases()\n this.provenance = deriveProvenance(source)\n }\n\n /** Map each declared wire type back to the `Base` of its resource schema. */\n private indexBases(): Map<string, string> {\n const out = new Map<string, string>()\n for (const [name, schema] of Object.entries(this.schemas)) {\n if (!name.endsWith('Resource') || name.endsWith('ResourceIdentifier')) {\n continue\n }\n const typeProp = schema.properties?.['type']\n if (isSchema(typeProp) && typeof typeProp.const === 'string') {\n out.set(typeProp.const, name.slice(0, -'Resource'.length))\n }\n }\n return out\n }\n\n emit(): string {\n // Resolve enums first so the alias block (which depends on `usedEnums`) is populated.\n const interfaces = Object.keys(this.descriptor).map((type) => this.attributeInterface(type))\n const writeInterfaces = Object.keys(this.descriptor).flatMap((type) =>\n this.writeAttributeInterfaces(type),\n )\n // Action input/output aliases reference component schemas; resolve them (this also\n // records any enums they reach) before the enum block is emitted.\n const actionAliases = this.actionTypeAliases()\n const enums = this.enumAliases()\n\n const parts = [\n this.header(),\n this.imports(),\n ...(enums ? [enums] : []),\n ...interfaces,\n ...writeInterfaces,\n ...actionAliases,\n this.attributesMap(),\n this.writeAttributesMap(),\n this.actionTypesMap(),\n this.resourceMap(),\n 'export type ResourceMap = typeof resourceMap',\n this.atomicConst(),\n this.pageLimitsConst(),\n emitErrorCodes(readErrorCatalogue(this.doc)),\n this.boundFactory(),\n ]\n return `${parts.join('\\n\\n')}\\n`\n }\n\n private header(): string {\n return [\n '/**',\n ' * AUTO-GENERATED by @haddowg/json-api-codegen — do not edit by hand.',\n ' * Regenerate from the source OpenAPI document instead.',\n ' *',\n ...provenanceLines(this.provenance),\n ' */',\n ].join('\\n')\n }\n\n private imports(): string {\n return [\n 'import {',\n ' type ApiDescriptor,',\n ' type ClientOptions,',\n ' createClient as createClientRuntime,',\n ' type ErrorCodeGuard,',\n ' hasErrorCode as hasErrorCodeRuntime,',\n \"} from '@haddowg/json-api-client'\",\n ].join('\\n')\n }\n\n /** Per-type attribute interface, e.g. `export interface AlbumsAttributes { ... }`. */\n private attributeInterface(type: string): string {\n const base = this.baseByType.get(type)\n const props = base ? this.schemas[`${base}Attributes`]?.properties : undefined\n // Drive field order off the (sorted) descriptor so output stays deterministic; read\n // attributes are always present (every member required, no optional marker).\n const fields = Object.keys(this.descriptor[type]!.attributes)\n return this.renderInterface(`${pascalCase(type)}Attributes`, props, fields, () => true)\n }\n\n /**\n * The per-type WRITE attribute interfaces — `<Pascal>CreateAttributes` and\n * `<Pascal>UpdateAttributes` — from the `<Base>CreateAttributes`/`<Base>UpdateAttributes`\n * components (readOnly fields are already excluded vs the read attributes by the bundle).\n * Create marks a field required iff it sits in the component's `required`; Update makes\n * every field optional. A read-only type (no create/update component) contributes nothing.\n */\n private writeAttributeInterfaces(type: string): string[] {\n const base = this.baseByType.get(type)\n if (base === undefined) {\n return []\n }\n const pascal = pascalCase(type)\n const out: string[] = []\n\n const create = this.schemas[`${base}CreateAttributes`]\n if (create !== undefined) {\n const required = new Set(create.required ?? [])\n // Sort the schema's own property keys (no descriptor to order write fields).\n // oxlint-disable-next-line no-array-sort -- sorting a freshly-created key array\n const fields = Object.keys(create.properties ?? {}).sort()\n out.push(\n this.renderInterface(`${pascal}CreateAttributes`, create.properties, fields, (field) =>\n required.has(field),\n ),\n )\n }\n\n const update = this.schemas[`${base}UpdateAttributes`]\n if (update !== undefined) {\n // oxlint-disable-next-line no-array-sort -- sorting a freshly-created key array\n const fields = Object.keys(update.properties ?? {}).sort()\n out.push(\n this.renderInterface(`${pascal}UpdateAttributes`, update.properties, fields, () => false),\n )\n }\n\n return out\n }\n\n /**\n * Per-action input/output type aliases for every type that declares custom actions. An\n * action whose `input`/`output` resolves to a component schema gets a named alias\n * (`<Pascal><Action>Input` / `<Pascal><Action>Output`) expanding that component via the\n * shared {@link tsType} machinery — a `none` input/output (no body / a `204`) contributes\n * no alias. Deterministic order: types, then action names (the descriptor is sorted).\n */\n private actionTypeAliases(): string[] {\n const out: string[] = []\n for (const type of Object.keys(this.descriptor)) {\n const actions = this.descriptor[type]?.actions\n if (actions === undefined) {\n continue\n }\n const pascal = pascalCase(type)\n for (const [actionName, action] of Object.entries(actions)) {\n const member = `${pascal}${pascalCase(actionName)}`\n const names: { input?: string; output?: string } = {}\n const inputType = this.actionBodyType(action, 'input')\n if (inputType !== undefined) {\n out.push(`export type ${member}Input = ${inputType}`)\n names.input = `${member}Input`\n }\n const outputType = this.actionBodyType(action, 'output')\n if (outputType !== undefined) {\n out.push(`export type ${member}Output = ${outputType}`)\n names.output = `${member}Output`\n }\n if (names.input !== undefined || names.output !== undefined) {\n let byAction = this.actionAliasNames.get(type)\n if (byAction === undefined) {\n byAction = new Map()\n this.actionAliasNames.set(type, byAction)\n }\n byAction.set(actionName, names)\n }\n }\n }\n return out\n }\n\n /**\n * Emit the `ActionTypes` interface wiring the emitted per-action aliases onto the typed\n * action surface — `type -> actionName -> { input?; output? }`, the client's fourth type\n * argument. So `client.albums.id(id).actions.reissue(body)` takes `AlbumsReissueInput` and\n * resolves `AlbumsReissueOutput` rather than a loose `Record<string,unknown>` / `unknown`.\n * Only actions whose alias was emitted appear (a `none`-input/output action contributes the\n * absent side, which the runtime types fall back to loosely). Emits `{}` when none exist.\n */\n private actionTypesMap(): string {\n const typeLines: string[] = []\n for (const type of Object.keys(this.descriptor)) {\n const byAction = this.actionAliasNames.get(type)\n if (byAction === undefined || byAction.size === 0) {\n continue\n }\n const actionLines: string[] = []\n for (const [actionName, names] of byAction) {\n const members: string[] = []\n if (names.input !== undefined) {\n members.push(`input: ${names.input}`)\n }\n if (names.output !== undefined) {\n members.push(`output: ${names.output}`)\n }\n actionLines.push(` ${objectKey(actionName)}: { ${members.join('; ')} }`)\n }\n typeLines.push(` ${objectKey(type)}: {\\n${actionLines.join('\\n')}\\n }`)\n }\n if (typeLines.length === 0) {\n return 'export interface ActionTypes {}'\n }\n return `export interface ActionTypes {\\n${typeLines.join('\\n')}\\n}`\n }\n\n /**\n * The TS type alias (if any) for an action's request body.\n *\n * An action's RESULT and its FLAT input are derived at the type level from the descriptor\n * (`outputType`/`outputCardinality` → the materialised resource view; `inputType` → the\n * `CreateInput` of that type), so no `output` alias is emitted and a `document` input whose\n * resource type resolves emits no `input` alias either. Only a bespoke command document (a\n * `document` input with no resolvable `inputType`) keeps a raw-envelope alias as its typed body,\n * expanded via {@link tsType} (falling back to a loose JSON:API document shape).\n */\n private actionBodyType(action: ActionDescriptor, side: 'input' | 'output'): string | undefined {\n if (side === 'output' || action.input !== 'document' || action.inputType !== undefined) {\n return undefined\n }\n const op = this.doc.paths?.[action.path]?.post\n const ref = op?.requestBody?.content?.[JSON_API_MEDIA_TYPE]?.schema?.$ref\n if (typeof ref !== 'string') {\n return LOOSE_DOCUMENT\n }\n const target = refName(ref)\n const resolved = target ? this.schemas[target] : undefined\n return resolved ? this.tsType(resolved) : LOOSE_DOCUMENT\n }\n\n /** Emit the server-level atomic capability constant (`{ path }` or `null`). */\n private atomicConst(): string {\n const doc = [\n '/**',\n ' * The server-level Atomic Operations endpoint (the atomic ext media type), or `null`',\n ' * when this server exposes none. The runtime `client.atomic` builder posts the batch here.',\n ' */',\n ].join('\\n')\n const value = this.atomic === null ? 'null' : `${this.literal(this.atomic, 0)} as const`\n return `${doc}\\nexport const atomic = ${value}`\n }\n\n /**\n * The `pageLimits` const: per collection, the `default`, `minimum` and `maximum` each `page`\n * member declares (generator contract 5 adds the paginator's default and page-size cap). A\n * menu nests them under each arm's `kind`. Members declaring none, and collections with no\n * such member, are left out. The client never clamps a `page` argument to these.\n */\n private pageLimitsConst(): string {\n const typeLines: string[] = []\n for (const type of Object.keys(this.descriptor)) {\n const path = this.descriptor[type]!.paths['fetchMany']\n const page = path === undefined ? undefined : this.doc.paths?.[path]?.get?.parameters\n const schema = page?.find((param) => param.name === 'page')?.schema\n if (schema === undefined) {\n continue\n }\n let body: string[] = []\n if (schema.oneOf !== undefined) {\n for (const arm of schema.oneOf) {\n const kind = isSchema(arm.properties?.['kind']) ? arm.properties['kind'].const : undefined\n const members = this.pageMemberLimits(arm, ' ')\n if (typeof kind === 'string' && members.length > 0) {\n body.push(` ${objectKey(kind)}: {\\n${members.join('\\n')}\\n },`)\n }\n }\n } else {\n body = this.pageMemberLimits(schema, ' ')\n }\n if (body.length > 0) {\n typeLines.push(` ${objectKey(type)}: {\\n${body.join('\\n')}\\n },`)\n }\n }\n const doc = [\n '/**',\n \" * The bounds each collection's `page` parameter declares, keyed by type, then by strategy for a\",\n ' * collection offering several, then by wire key. `default` is what the server uses when the key',\n ' * is absent and `maximum` is the largest value it serves. The client sends the `page` you pass',\n ' * unchanged, so read these to bound a page-size picker.',\n ' */',\n ].join('\\n')\n const body = typeLines.length === 0 ? '{}' : `{\\n${typeLines.join('\\n')}\\n}`\n return `${doc}\\nexport const pageLimits = ${body} as const`\n }\n\n /** One page schema's members that declare a `default`, `minimum` or `maximum`, as literal lines. */\n private pageMemberLimits(schema: SchemaObject, indent: string): string[] {\n const lines: string[] = []\n for (const [name, prop] of Object.entries(schema.properties ?? {})) {\n if (!isSchema(prop) || name === 'kind') {\n continue\n }\n const limits: string[] = []\n for (const keyword of ['default', 'minimum', 'maximum'] as const) {\n if (typeof prop[keyword] === 'number') {\n limits.push(`${keyword}: ${String(prop[keyword])}`)\n }\n }\n if (limits.length === 0) {\n continue\n }\n const doc = jsDoc(memberDoc(prop), indent)\n if (doc !== undefined) {\n lines.push(doc)\n }\n lines.push(`${indent}${objectKey(name)}: { ${limits.join(', ')} },`)\n }\n return lines\n }\n\n /**\n * Render an attribute interface from a property map, a field order, and a `required`\n * predicate (true => no `?`). Shared by the read and write attribute interfaces so the\n * tsType/JSDoc logic stays in one place.\n */\n private renderInterface(\n name: string,\n props: Record<string, SchemaOrBool> | undefined,\n fields: readonly string[],\n required: (field: string) => boolean,\n ): string {\n const lines: string[] = []\n for (const field of fields) {\n const schema = props?.[field]\n const tsType = isSchema(schema) ? this.tsType(schema) : 'unknown'\n const doc = isSchema(schema) ? jsDoc(memberDoc(schema), ' ') : undefined\n if (doc) {\n lines.push(doc)\n }\n const optional = required(field) ? '' : '?'\n lines.push(` ${objectKey(field)}${optional}: ${tsType}`)\n }\n\n this.emittedInterfaces.add(name)\n if (lines.length === 0) {\n return `export interface ${name} {}`\n }\n return `export interface ${name} {\\n${lines.join('\\n')}\\n}`\n }\n\n /** Map a JSON Schema attribute node to a precise TypeScript type. */\n private tsType(schema: SchemaObject): string {\n // A reference: an enum -> its emitted union alias; an emitted attribute interface ->\n // its interface name (so an action envelope nests precise attribute types); else\n // structural expansion of the referenced component, falling back to unknown. A\n // `expanding` guard breaks any cyclic/self-referential component chain.\n if (typeof schema.$ref === 'string') {\n const target = refName(schema.$ref)\n const resolved = target ? this.schemas[target] : undefined\n if (target && resolved && Array.isArray(resolved.enum)) {\n this.usedEnums.set(target, resolved)\n return target\n }\n if (target && this.emittedInterfaces.has(target)) {\n return target\n }\n if (resolved === undefined || target === undefined || this.expanding.has(target)) {\n return 'unknown'\n }\n this.expanding.add(target)\n const expanded = this.tsType(resolved)\n this.expanding.delete(target)\n return expanded\n }\n\n // A union of branches, as `anyOf: [{ $ref: Enum }, { type: 'null' }]` for a nullable enum.\n const branches = schema.anyOf ?? schema.oneOf\n if (schema.type === undefined && branches !== undefined && branches.length > 0) {\n const members = branches.map((branch) => this.tsType(branch))\n const nullable = members.includes('null')\n const rest = [...new Set(members.filter((member) => member !== 'null'))]\n if (rest.length === 0) {\n return 'null'\n }\n return nullable ? `${rest.join(' | ')} | null` : rest.join(' | ')\n }\n\n const types = Array.isArray(schema.type) ? schema.type : schema.type ? [schema.type] : []\n if (types.length === 1 && types[0] === 'null') {\n return 'null'\n }\n const nullable = types.includes('null')\n const base = this.baseTsType(\n schema,\n types.filter((t) => t !== 'null'),\n )\n return nullable ? `${base} | null` : base\n }\n\n /** The non-nullable TS type for the declared JSON type(s). */\n private baseTsType(schema: SchemaObject, types: readonly string[]): string {\n // An inline enum (string literals without a $ref).\n if (Array.isArray(schema.enum) && schema.enum.length > 0) {\n return schema.enum.map((value) => quote(String(value))).join(' | ')\n }\n if (types.length === 0) {\n return 'unknown'\n }\n const mapped = types.map((t) => this.scalarOrComposite(schema, t))\n // De-dupe while preserving order.\n return [...new Set(mapped)].join(' | ')\n }\n\n private scalarOrComposite(schema: SchemaObject, type: string): string {\n switch (type) {\n case 'string': {\n return 'string'\n }\n case 'number':\n case 'integer': {\n return 'number'\n }\n case 'boolean': {\n return 'boolean'\n }\n case 'object': {\n return this.objectType(schema)\n }\n case 'array': {\n return this.arrayType(schema)\n }\n default: {\n return 'unknown'\n }\n }\n }\n\n /** A nested object type from its `properties` (falls back to an index signature). */\n private objectType(schema: SchemaObject): string {\n const props = schema.properties\n if (props === undefined) {\n return 'Record<string, unknown>'\n }\n const required = new Set(schema.required ?? [])\n const members: string[] = []\n for (const [name, prop] of Object.entries(props)) {\n if (!isSchema(prop)) {\n continue\n }\n const optional = required.has(name) ? '' : '?'\n members.push(`${objectKey(name)}${optional}: ${this.tsType(prop)}`)\n }\n if (members.length === 0) {\n return 'Record<string, unknown>'\n }\n return `{ ${members.join('; ')} }`\n }\n\n private arrayType(schema: SchemaObject): string {\n const items = schema.items\n const element = isSchema(items) ? this.tsType(items) : 'unknown'\n // Wrap unions so `(A | B)[]` reads correctly.\n const list = /[|&]/.test(element) ? `(${element})[]` : `${element}[]`\n // `minItems` of 1 or more: the server never sends, or accepts, an empty list.\n const minItems = schema['minItems']\n return typeof minItems === 'number' && minItems >= 1 ? `[${element}, ...${list}]` : list\n }\n\n /** Union aliases for every enum component an attribute referenced, sorted by name. */\n private enumAliases(): string | undefined {\n if (this.usedEnums.size === 0) {\n return undefined\n }\n // oxlint-disable-next-line no-array-sort -- sorting a freshly-created key array\n const names = [...this.usedEnums.keys()].sort()\n return names\n .map((name) => {\n const schema = this.usedEnums.get(name)!\n const values = schema.enum ?? []\n const union = values.map((value) => quote(String(value))).join(' | ')\n const alias = `export type ${name} = ${union}`\n const doc = jsDoc(this.enumDoc(schema), '')\n return doc ? `${doc}\\n${alias}` : alias\n })\n .join('\\n\\n')\n }\n\n /**\n * Documentation for an enum alias: a per-value list built from `x-enum-descriptions`\n * (the richest hover DX, since a union alias can't carry per-member JSDoc), falling\n * back to the component's own `description`.\n */\n private enumDoc(schema: SchemaObject): string | undefined {\n const values = schema.enum ?? []\n const descriptions = schema['x-enum-descriptions']\n if (Array.isArray(descriptions) && descriptions.length === values.length && values.length > 0) {\n return values\n .map((value, i) => `- \\`${String(value)}\\` — ${String(descriptions[i])}`)\n .join('\\n')\n }\n return schema.description\n }\n\n /**\n * Emit the `Attributes` interface mapping each wire type to its per-type attribute\n * interface. The runtime descriptor only carries coarse format hints; this is how the\n * precise per-type attribute types reach the bound client (passed as the second type\n * argument to the runtime factory).\n */\n private attributesMap(): string {\n const lines = Object.keys(this.descriptor).map(\n (type) => ` ${objectKey(type)}: ${pascalCase(type)}Attributes`,\n )\n return `export interface Attributes {\\n${lines.join('\\n')}\\n}`\n }\n\n /**\n * Emit the `WriteAttributes` interface mapping each writable wire type to its\n * `{ create; update }` attribute pair. A read-only type (no create/update component)\n * contributes no entry, so the bound client only exposes writes where the API allows\n * them. Passed as the third type argument to the runtime factory.\n */\n private writeAttributesMap(): string {\n const lines: string[] = []\n for (const type of Object.keys(this.descriptor)) {\n const base = this.baseByType.get(type)\n const hasCreate = base !== undefined && this.schemas[`${base}CreateAttributes`] !== undefined\n const hasUpdate = base !== undefined && this.schemas[`${base}UpdateAttributes`] !== undefined\n if (!hasCreate && !hasUpdate) {\n continue\n }\n const pascal = pascalCase(type)\n const members: string[] = []\n if (hasCreate) {\n members.push(`create: ${pascal}CreateAttributes`)\n }\n if (hasUpdate) {\n members.push(`update: ${pascal}UpdateAttributes`)\n }\n lines.push(` ${objectKey(type)}: { ${members.join('; ')} }`)\n }\n if (lines.length === 0) {\n return 'export interface WriteAttributes {}'\n }\n return `export interface WriteAttributes {\\n${lines.join('\\n')}\\n}`\n }\n\n /** Emit the descriptor as a literal `as const satisfies ApiDescriptor`. */\n private resourceMap(): string {\n const body = this.literal(this.descriptor as Record<string, unknown>, 0)\n return `export const resourceMap = ${body} as const satisfies ApiDescriptor`\n }\n\n /** Render a JSON-serialisable descriptor value as deterministic TS object-literal source. */\n private literal(value: unknown, depth: number): string {\n const indent = ' '.repeat(depth)\n const inner = ' '.repeat(depth + 1)\n\n if (Array.isArray(value)) {\n if (value.length === 0) {\n return '[]'\n }\n const items = value.map((item) => `${inner}${this.literal(item, depth + 1)}`)\n return `[\\n${items.join(',\\n')}\\n${indent}]`\n }\n\n if (value !== null && typeof value === 'object') {\n const entries = Object.entries(value as Record<string, unknown>)\n if (entries.length === 0) {\n return '{}'\n }\n const lines = entries.map(\n ([key, v]) => `${inner}${objectKey(key)}: ${this.literal(v, depth + 1)}`,\n )\n return `{\\n${lines.join(',\\n')}\\n${indent}}`\n }\n\n return JSON.stringify(value)\n }\n\n private boundFactory(): string {\n return [\n '/**',\n ' * Descriptor-bound client factory; wraps the generic runtime with this API’s `resourceMap`.',\n ' * The server-level `atomic` capability is threaded in by default so `client.atomic` is wired',\n ' * (a caller may still override it via `options.atomic`). The client type carries `ErrorCode`,',\n ' * so bindings that only see the client (the Angular refs) type its errors.',\n ' */',\n 'export const createClient = (options: ClientOptions) =>',\n ' createClientRuntime<typeof resourceMap, Attributes, WriteAttributes, ActionTypes, ErrorCode>(',\n ' resourceMap,',\n ' {',\n ' atomic,',\n ' ...options,',\n ' },',\n ' )',\n ].join('\\n')\n }\n}\n\n/**\n * Generate the full source of the client module for a document + its built descriptor.\n * The server-level atomic capability is derived from the document (override via `atomic`).\n */\nexport function emit(\n doc: OpenApiDocument,\n descriptor: ApiDescriptor,\n atomic: AtomicDescriptor | null = buildAtomic(doc),\n): string {\n return new Emitter(doc, descriptor, atomic).emit()\n}\n\n/** Re-export so callers can reference the resource descriptor shape if needed. */\nexport type { ResourceDescriptor }\n","import { hashJson } from './provenance'\nimport type { SchemaBundle } from './reader'\n\n/**\n * Emit the per-type JSON Schema map as a standalone generated artifact:\n *\n * ```ts\n * export const schemas = { <type>: { …json schema… }, … } as const\n * ```\n *\n * The values are the raw, self-contained resource-object JSON Schema documents the bundle\n * serves at `GET /schemas.json` — suitable to hand straight to a validation engine via the\n * opt-in `validate?` seam (ADR 0004). This is a separate file from the client so the main\n * descriptor/client output is unaffected when `--schemas` is absent.\n *\n * The schemas are emitted as JSON (deterministic, key order preserved) so the artifact is\n * stable to diff; `as const` keeps the literal shapes narrow.\n */\nexport function emitSchemas(bundle: SchemaBundle): string {\n return `${[header(bundle), body(bundle)].join('\\n\\n')}\\n`\n}\n\nfunction header(bundle: SchemaBundle): string {\n return [\n '/**',\n ' * AUTO-GENERATED by @haddowg/json-api-codegen — do not edit by hand.',\n ' * Per-type JSON Schemas for the opt-in validation seam; regenerate from the source bundle.',\n ' *',\n ` * Schema hash: ${hashJson(bundle)}`,\n ' */',\n ].join('\\n')\n}\n\nfunction body(bundle: SchemaBundle): string {\n // `JSON.stringify` with two-space indent gives deterministic, diff-friendly output while\n // preserving the bundle's key order. The raw schema objects are valid TS object literals.\n const json = JSON.stringify(bundle, null, 2)\n return `export const schemas = ${json} as const`\n}\n","import { readFile } from 'node:fs/promises'\nimport { parse as parseYaml } from 'yaml'\nimport type { OpenApiDocument } from './openapi'\nimport type { SchemaObject } from './openapi'\n\n/** A self-contained JSON Schema document, keyed by JSON:API type, as served at `GET /schemas.json`. */\nexport type SchemaBundle = Record<string, SchemaObject>\n\n/** True when the input looks like an http(s) URL rather than a local path. */\nfunction isHttpUrl(input: string): boolean {\n return /^https?:\\/\\//i.test(input)\n}\n\n/** Decide YAML vs JSON by extension first, then by a cheap content sniff. */\nfunction looksLikeYaml(source: string, text: string): boolean {\n if (/\\.ya?ml$/i.test(source)) {\n return true\n }\n if (/\\.json$/i.test(source)) {\n return false\n }\n // No decisive extension: JSON documents start with `{`/`[` once trimmed.\n return !/^\\s*[{[]/.test(text)\n}\n\nfunction parse<T>(source: string, text: string, label: string): T {\n const doc = looksLikeYaml(source, text) ? parseYaml(text) : JSON.parse(text)\n if (doc === null || typeof doc !== 'object') {\n throw new Error(`${label} at ${source} did not parse to an object`)\n }\n return doc as T\n}\n\n/**\n * Fetch (URL) or read (file) `input`, then parse it as JSON or YAML (decided by extension,\n * falling back to a content sniff). Shared by the OpenAPI and JSON Schema readers.\n */\nasync function readSource<T>(input: string, label: string): Promise<T> {\n if (isHttpUrl(input)) {\n const res = await fetch(input)\n if (!res.ok) {\n throw new Error(`Failed to fetch ${label} from ${input}: ${res.status}`)\n }\n return parse<T>(input, await res.text(), label)\n }\n\n return parse<T>(input, await readFile(input, 'utf8'), label)\n}\n\n/**\n * Read an OpenAPI document from an http(s) URL or a local file path. Supports both JSON\n * and YAML (decided by extension, falling back to a content sniff).\n */\nexport async function readDocument(input: string): Promise<OpenApiDocument> {\n return readSource<OpenApiDocument>(input, 'OpenAPI document')\n}\n\n/**\n * Read the bundle's JSON Schema bundle (`GET /schemas.json`) from an http(s) URL or a\n * local file path — a map keyed by JSON:API type, each value a self-contained JSON Schema\n * 2020-12 resource-object document. Supports both JSON and YAML, like {@link readDocument}.\n */\nexport async function readSchemas(input: string): Promise<SchemaBundle> {\n return readSource<SchemaBundle>(input, 'JSON Schema bundle')\n}\n","/**\n * @haddowg/json-api-codegen — reads the bundle's OpenAPI 3.1 document (from a URL or\n * a local file) and emits the runtime descriptor + derived types + a bound\n * `createClient` (ADR 0001). Optionally reads the bundle's JSON Schemas to wire the\n * opt-in validation seam.\n *\n * The spec is fully self-describing for our needs (see CONTEXT.md): type identity is\n * `properties.type.const`; relationships, cardinality and related types come from the\n * relationship components' `data`; allowed `?include` paths are a bounded, pre-expanded\n * enum per endpoint; the create client-id policy is encoded in the create request\n * schema (`id: false` / required / optional).\n */\n\nimport { mkdir, readFile, writeFile } from 'node:fs/promises'\nimport { dirname } from 'node:path'\nimport { buildDescriptor } from './build-descriptor'\nimport { checkContract } from './contract'\nimport { detectVerbCollisions, emit } from './emit'\nimport { emitSchemas } from './emit-schemas'\nimport { readDocument, readSchemas } from './reader'\n\nexport { buildAtomic, buildDescriptor, DescriptorBuilder } from './build-descriptor'\nexport { checkContract, MAXIMUM_CONTRACT, MINIMUM_CONTRACT } from './contract'\nexport { detectVerbCollisions, emit, Emitter } from './emit'\nexport { emitErrorCodes, readErrorCatalogue } from './error-codes'\nexport type { DocumentedErrorCode, ErrorCatalogue } from './error-codes'\nexport type { VerbCollision } from './emit'\nexport { emitSchemas } from './emit-schemas'\nexport type * from './openapi'\nexport { deriveProvenance, hashJson, provenanceLines } from './provenance'\nexport type { Provenance } from './provenance'\nexport { readDocument, readSchemas } from './reader'\nexport type { SchemaBundle } from './reader'\n\nexport interface CodegenConfig {\n /** OpenAPI document source: an http(s) URL or a local file path. */\n input: string\n /** Output file (or directory) for the generated client. */\n output: string\n /** Server name to target (the spec is per-server). Defaults to the default server. */\n server?: string\n /** JSON Schema source for the validation seam (URL or path). Off when omitted. */\n schemas?: string\n /**\n * Drift-check mode: regenerate in-memory and compare against the committed `output`\n * (and its schema artifact when `schemas` is set) instead of writing. Nothing is\n * written; {@link check} reports whether the committed artifacts are up to date.\n */\n check?: boolean\n}\n\n/** One artifact's drift status: the file it stands for, and whether it is up to date. */\nexport interface ArtifactDrift {\n /** The committed artifact path (the client output, or its schema sibling). */\n path: string\n /** True when the committed file matches the freshly generated content. */\n upToDate: boolean\n}\n\n/** The outcome of a {@link check} run: `ok` iff every checked artifact is up to date. */\nexport interface CheckResult {\n ok: boolean\n artifacts: ArtifactDrift[]\n}\n\n/**\n * The schema-artifact path beside a client output path: `client.gen.ts` -> `client.schemas.gen.ts`\n * (any `.gen.ts`/`.ts` suffix is preserved; a suffix-less path just gains `.schemas`).\n */\nexport function schemasOutputPath(output: string): string {\n if (output.endsWith('.gen.ts')) {\n return `${output.slice(0, -'.gen.ts'.length)}.schemas.gen.ts`\n }\n if (output.endsWith('.ts')) {\n return `${output.slice(0, -'.ts'.length)}.schemas.ts`\n }\n return `${output}.schemas`\n}\n\n/** One rendered artifact: its target path and the freshly generated content. */\ninterface RenderedArtifact {\n path: string\n content: string\n}\n\n/**\n * Read the source spec(s), build the descriptor and render every generated artifact in\n * memory (the client source first, then the schema artifact when `config.schemas` is set)\n * — the shared core of {@link generate} (which writes them) and {@link check} (which\n * compares them). Verb-collision warnings are emitted here so both paths surface them.\n */\nasync function render(config: CodegenConfig): Promise<RenderedArtifact[]> {\n const doc = await readDocument(config.input)\n const contractWarning = checkContract(doc)\n if (contractWarning !== undefined) {\n console.warn(`[json-api-codegen] ${contractWarning}`)\n }\n const descriptor = buildDescriptor(doc)\n\n for (const { type, relation } of detectVerbCollisions(descriptor)) {\n console.warn(\n `[json-api-codegen] \"${type}\" has a relation named \"${relation}\" which collides with a ` +\n 'reserved verb on the resource handle; it will be reachable via .rel(\"' +\n `${relation}\") in the fluent client.`,\n )\n }\n\n if (Object.keys(descriptor).length === 0) {\n console.warn(\n `[json-api-codegen] found no JSON:API resource types in ${config.input}; the generated client is empty.`,\n )\n }\n\n const artifacts: RenderedArtifact[] = [{ path: config.output, content: emit(doc, descriptor) }]\n\n if (config.schemas !== undefined) {\n const bundle = await readSchemas(config.schemas)\n artifacts.push({ path: schemasOutputPath(config.output), content: emitSchemas(bundle) })\n }\n\n return artifacts\n}\n\n/**\n * Read the OpenAPI document, build the runtime descriptor, emit the generated client\n * module and write it to `config.output` (creating parent directories as needed).\n *\n * When `config.schemas` is set, also read the bundle's JSON Schema bundle and write a\n * separate per-type schema artifact (`<output>.schemas.gen.ts`) beside the client, wiring\n * the opt-in validation seam (ADR 0004). The main client output is unchanged either way.\n *\n * `config.server` is metadata-only for now: the served document is already per-server,\n * so the caller selects the server by pointing `input` at the right document.\n *\n * Returns the generated client source. When `config.check` is set nothing is written;\n * call {@link check} instead for the drift-gate result.\n */\nexport async function generate(config: CodegenConfig): Promise<string> {\n const artifacts = await render(config)\n await mkdir(dirname(config.output), { recursive: true })\n for (const { path, content } of artifacts) {\n await writeFile(path, content, 'utf8')\n }\n // The first artifact is always the client source.\n return artifacts[0]!.content\n}\n\n/**\n * Drift gate: regenerate every artifact in memory and compare it byte-for-byte against the\n * committed file on disk, WITHOUT writing anything. A missing committed file counts as drift\n * (not up to date). Returns per-artifact status plus an aggregate `ok` (true iff all match) —\n * the CI drift check reads `ok` and exits non-zero when it is false.\n */\nexport async function check(config: CodegenConfig): Promise<CheckResult> {\n const artifacts = await render(config)\n const results: ArtifactDrift[] = []\n for (const { path, content } of artifacts) {\n let committed: string | undefined\n try {\n committed = await readFile(path, 'utf8')\n } catch {\n committed = undefined\n }\n results.push({ path, upToDate: committed === content })\n }\n return { ok: results.every((r) => r.upToDate), artifacts: results }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@haddowg/json-api-codegen",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "description": "CLI that reads the json-api-symfony OpenAPI spec (+ JSON Schemas) and emits a typed client descriptor.",
5
5
  "license": "MIT",
6
6
  "author": "Gregory Haddow (https://github.com/haddowg)",
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-B0BIVXUz.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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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"src-G1x-BbMp.mjs","names":["REF_PREFIX","JSON_API_MEDIA_TYPE","refName","isSchema","REF_PREFIX","isSchema","parse","parseYaml"],"sources":["../src/build-descriptor.ts","../src/contract.ts","../src/error-codes.ts","../src/provenance.ts","../src/emit.ts","../src/emit-schemas.ts","../src/reader.ts","../src/index.ts"],"sourcesContent":["import type {\n ActionDescriptor,\n ApiDescriptor,\n AtomicDescriptor,\n Cardinality,\n ClientIdPolicy,\n CountableDescriptor,\n MenuDescriptor,\n PaginatorDescriptor,\n PaginatorKind,\n PaginatorRole,\n PaginatorStrategy,\n PivotDescriptor,\n RelationDescriptor,\n RelationMutations,\n ResourceDescriptor,\n} from '@haddowg/json-api-client'\nimport { ATOMIC_EXT, CANONICAL_PAGE_KEYS } from '@haddowg/json-api-client'\nimport type {\n HttpMethod,\n OpenApiDocument,\n OperationObject,\n PathItemObject,\n SchemaObject,\n SchemaOrBool,\n} from './openapi'\n\nconst REF_PREFIX = '#/components/schemas/'\nconst JSON_API_MEDIA_TYPE = 'application/vnd.api+json'\n\n/** Sort a record's keys for deterministic, snapshot-stable output. */\nfunction sortRecord<V>(record: Record<string, V>): Record<string, V> {\n const out: Record<string, V> = {}\n // oxlint-disable-next-line no-array-sort -- sorting a freshly-created key array\n for (const key of Object.keys(record).sort()) {\n out[key] = record[key]!\n }\n return out\n}\n\n/** Resolve a local schema name from a `#/components/schemas/X` ref. */\nfunction refName(ref: string): string | undefined {\n return ref.startsWith(REF_PREFIX) ? ref.slice(REF_PREFIX.length) : undefined\n}\n\nfunction isSchema(value: SchemaOrBool | undefined): value is SchemaObject {\n return typeof value === 'object' && value !== null\n}\n\n/** The operationId prefixes of a relation's related read and its relationship endpoint. */\nconst RELATED_OPERATION = 'fetchRelated'\nconst RELATIONSHIP_OPERATIONS = [\n 'fetchRelationship',\n 'updateRelationship',\n 'addRelationship',\n 'removeRelationship',\n] as const\n\n/** Where a relation's endpoints live, read from their operationIds. */\ninterface RelationEndpoints {\n related?: string\n relationship?: string\n /** The `$ref` of a relationship mutation's request body (its request pivot shape). */\n requestRef?: string\n}\n\n/** The set of `type` keys a JSON type node declares, with `\"null\"` removed. */\nfunction typeKeys(type: string | readonly string[] | undefined): string[] {\n if (type === undefined) {\n return []\n }\n return (Array.isArray(type) ? type : [type]).filter((t) => t !== 'null')\n}\n\nexport class DescriptorBuilder {\n private readonly schemas: Record<string, SchemaObject>\n private readonly paths: Record<string, PathItemObject>\n /** Lazily-built wire-type -> collection-level paginator kind (for per-relation divergence, D6a). */\n private typePaginators?: Map<string, PaginatorDescriptor>\n\n constructor(private readonly doc: OpenApiDocument) {\n this.schemas = doc.components?.schemas ?? {}\n this.paths = doc.paths ?? {}\n }\n\n /**\n * The collection-level paginator kind for a WIRE type (`tracks`), memoised. Resolves each\n * resource schema's wire type (its `type.const`) to the paginator of its collection GET — the\n * baseline a per-relation related-endpoint paginator is compared against (D6a).\n */\n private typePaginator(wireType: string): PaginatorDescriptor {\n if (this.typePaginators === undefined) {\n this.typePaginators = new Map()\n for (const [name, schema] of Object.entries(this.schemas)) {\n const type = this.resourceType(name, schema)\n if (type !== undefined) {\n this.typePaginators.set(type, this.paginator(name.slice(0, -'Resource'.length)))\n }\n }\n }\n return this.typePaginators.get(wireType) ?? 'none'\n }\n\n build(): ApiDescriptor {\n const out: Record<string, ResourceDescriptor> = {}\n for (const [name, schema] of Object.entries(this.schemas)) {\n const wireType = this.resourceType(name, schema)\n if (wireType === undefined) {\n continue\n }\n const base = name.slice(0, -'Resource'.length)\n const collection = this.collectionPath(base)\n const actions = collection ? this.actions(collection) : {}\n const descriptor: ResourceDescriptor = {\n attributes: this.attributes(base),\n relations: this.relations(wireType, base, schema, collection),\n paths: this.operationPaths(base),\n paginator: this.paginator(base),\n clientId: this.clientId(base),\n }\n const countable = this.countable(collection)\n if (countable !== undefined) {\n descriptor.countable = countable\n }\n const includable = this.includable(collection)\n if (includable !== undefined) {\n descriptor.includable = includable\n }\n const sortable = this.sortable(collection)\n if (sortable !== undefined) {\n descriptor.sortable = sortable\n }\n const filterable = this.filterable(collection)\n if (filterable !== undefined) {\n descriptor.filterable = filterable\n }\n if (Object.keys(actions).length > 0) {\n descriptor.actions = actions\n }\n // A synthetic stub for an unregistered related type — core's `permissiveResourceObject`\n // emits a `<Rel>Resource` carrying ONLY a `type` const (no `id`/`attributes`) so linkage\n // refs resolve — is reachable only through a parent's `.related()` (which works via the\n // parent's own paths). Admitting it would surface a fully-typed top-level `client.<stub>`\n // whose every method throws, so drop it (D27). A REAL registered resource carries the full\n // `type/id/attributes/…` object shape and stays, even with no attributes/collection of its\n // own; only the type-const-only stub (with no operation paths) is dropped.\n const isTypeOnlyStub = Object.keys(schema.properties ?? {}).every((prop) => prop === 'type')\n if (isTypeOnlyStub && Object.keys(descriptor.paths).length === 0) {\n continue\n }\n out[wireType] = descriptor\n }\n return sortRecord(out)\n }\n\n /**\n * The server-level Atomic Operations capability: the path whose `POST` requestBody\n * declares the atomic ext media type ({@link ATOMIC_EXT}). `null` when no such endpoint\n * exists. Server-level, so it rides {@link buildAtomic}, not the per-type descriptor.\n */\n buildAtomic(): AtomicDescriptor | null {\n for (const [path, item] of Object.entries(this.paths)) {\n const content = item.post?.requestBody?.content ?? {}\n if (Object.keys(content).some(isAtomicMediaType)) {\n return { path }\n }\n }\n return null\n }\n\n /**\n * A resource schema is one whose name ends in `Resource` (but not\n * `ResourceIdentifier`) and carries `properties.type.const` (a string) — that const\n * is the descriptor key (the wire type). Never inferred from the schema name.\n */\n private resourceType(name: string, schema: SchemaObject): string | undefined {\n if (!name.endsWith('Resource') || name.endsWith('ResourceIdentifier')) {\n return undefined\n }\n const constValue = schema.properties?.['type']\n if (isSchema(constValue) && typeof constValue.const === 'string') {\n return constValue.const\n }\n return undefined\n }\n\n /** Follow a `$ref` to its identifier/resource schema and read `properties.type.const`. */\n private resolveConst(ref: string): string | undefined {\n const target = refName(ref)\n if (target === undefined) {\n return undefined\n }\n const typeProp = this.schemas[target]?.properties?.['type']\n return isSchema(typeProp) && typeof typeProp.const === 'string' ? typeProp.const : undefined\n }\n\n private attributes(base: string): Record<string, string> {\n const attrs = this.schemas[`${base}Attributes`]\n const props = attrs?.properties\n if (props === undefined) {\n return {}\n }\n const out: Record<string, string> = {}\n for (const [name, prop] of Object.entries(props)) {\n if (isSchema(prop)) {\n out[name] = formatHint(prop)\n }\n }\n return sortRecord(out)\n }\n\n /**\n * The relations of a type: every relation its resource renders, plus each write-only relation\n * the create and update bodies accept. A write-only relation is one whose body property carries\n * `writeOnly: true` (generator contract 8) or, in an older document, one the resource doesn't\n * render. A pivot relation reads its response pivot off the rendered relationship and its\n * request pivot off the write bodies.\n */\n private relations(\n wireType: string,\n base: string,\n resource: SchemaObject,\n collection: string | undefined,\n ): Record<string, RelationDescriptor> {\n const relProps = isSchema(resource.properties?.['relationships'])\n ? (resource.properties['relationships'].properties ?? {})\n : {}\n const writes = this.writeRelationships(base)\n const endpoints = this.relationEndpoints(wireType)\n const out: Record<string, RelationDescriptor> = {}\n const add = (name: string, component: SchemaObject | undefined, writeOnly: boolean): void => {\n const parsed = component ? this.relationFromComponent(component) : undefined\n if (parsed === undefined) {\n // A relationship component the codegen can't parse (an unknown linkage shape) is\n // dropped silently otherwise — a drift class (the grammar has grown pivot/polymorphic/\n // nested forms), so warn rather than emit a client missing the relation (D28).\n // eslint-disable-next-line no-console\n console.warn(\n `json-api codegen: relationship \"${name}\" has an unrecognized linkage shape; dropping it from the descriptor.`,\n )\n return\n }\n const descriptor: RelationDescriptor = { ...parsed }\n if (writeOnly) {\n delete descriptor.readPivot\n descriptor.writeOnly = true\n }\n if (descriptor.pivot === true) {\n const writePivot = this.writePivot(\n writes.get(name)?.ref ?? endpoints.get(name)?.requestRef,\n component!,\n )\n if (writePivot !== undefined) {\n descriptor.writePivot = writePivot\n }\n }\n out[name] =\n collection === undefined\n ? descriptor\n : this.withRelationExposure(descriptor, collection, name, endpoints.get(name))\n }\n\n for (const [name, prop] of Object.entries(relProps)) {\n if (!isSchema(prop) || typeof prop.$ref !== 'string' || writes.get(name)?.writeOnly) {\n continue\n }\n add(name, this.schemas[refName(prop.$ref) ?? ''], false)\n }\n for (const [name, write] of writes) {\n if (write.writeOnly || !(name in relProps)) {\n add(name, this.schemas[refName(write.ref) ?? ''], true)\n }\n }\n return sortRecord(out)\n }\n\n /**\n * The relationships the create and update bodies accept: each one's component `$ref` and\n * whether the body marks it `writeOnly`.\n */\n private writeRelationships(base: string): Map<string, { ref: string; writeOnly: boolean }> {\n const out = new Map<string, { ref: string; writeOnly: boolean }>()\n for (const request of [`${base}CreateRequest`, `${base}UpdateRequest`]) {\n const data = this.schemas[request]?.properties?.['data']\n const relationships = isSchema(data) ? data.properties?.['relationships'] : undefined\n const props = isSchema(relationships) ? (relationships.properties ?? {}) : {}\n for (const [name, prop] of Object.entries(props)) {\n if (!isSchema(prop) || typeof prop.$ref !== 'string') {\n continue\n }\n const writeOnly = prop['writeOnly'] === true || out.get(name)?.writeOnly === true\n out.set(name, { ref: out.get(name)?.ref ?? prop.$ref, writeOnly })\n }\n }\n return out\n }\n\n /**\n * Each relation's related and relationship paths, keyed by relation name, from the\n * operationIds the projector stamps (`fetchRelated.<type>.<relation>`, …). A relation's path\n * segment is its URI field name, which may differ from its name, so the paths are never\n * derived from the name when an operationId names them.\n */\n private relationEndpoints(wireType: string): Map<string, RelationEndpoints> {\n const out = new Map<string, RelationEndpoints>()\n const entry = (rel: string): RelationEndpoints => {\n let found = out.get(rel)\n if (found === undefined) {\n found = {}\n out.set(rel, found)\n }\n return found\n }\n for (const [path, item] of Object.entries(this.paths)) {\n for (const [method, op] of Object.entries(item) as [HttpMethod, OperationObject][]) {\n const id = op?.operationId\n if (typeof id !== 'string') {\n continue\n }\n const dot = id.indexOf('.')\n const prefix = id.slice(0, dot)\n const rest = id.slice(dot + 1)\n if (dot < 0 || !rest.startsWith(`${wireType}.`)) {\n continue\n }\n const rel = rest.slice(wireType.length + 1)\n if (prefix === RELATED_OPERATION) {\n entry(rel).related = path\n } else if ((RELATIONSHIP_OPERATIONS as readonly string[]).includes(prefix)) {\n const found = entry(rel)\n found.relationship = path\n const ref = method === 'get' ? undefined : this.requestBodyRef(op)\n if (ref !== undefined) {\n found.requestRef = ref\n }\n }\n }\n }\n return out\n }\n\n /**\n * The per-relation mutation capability, derived from the HTTP methods the relationship\n * endpoint (`{collection}/{id}/relationships/{rel}`) advertises. For a to-many:\n * `add` <- POST, `remove` <- DELETE, `replace` <- PATCH. For a to-one: `set` <- PATCH.\n * Only `true` verbs are emitted (a missing verb is simply absent). Returns `undefined`\n * when the relation exposes no relationship endpoint at all.\n */\n private relationMutations(\n path: string,\n cardinality: RelationDescriptor['cardinality'],\n ): RelationMutations | undefined {\n const item = this.paths[path]\n if (item === undefined) {\n return undefined\n }\n const mutations: RelationMutations = {}\n if (cardinality === 'many') {\n if (item.post) {\n mutations.add = true\n }\n if (item.delete) {\n mutations.remove = true\n }\n if (item.patch) {\n mutations.replace = true\n }\n } else if (item.patch) {\n mutations.set = true\n }\n return mutations\n }\n\n /**\n * Attach the per-relation endpoint-exposure signal to a relation descriptor (D24). The bundle\n * can suppress a relation's related or relationship endpoint (`withoutRelatedEndpoint()` /\n * `withoutRelationshipEndpoint()`, ADR 0027), which the OpenAPI reflects by simply omitting that\n * relation's path — but codegen synthesizes generic `{rel}` templates, erasing the per-relation\n * distinction. So mark `related: false` / `relationship: false` when this relation's specific\n * path is absent, and ALWAYS emit an explicit `mutations` object (the verb flags when the\n * relationship endpoint exists, else `{}`) so the client gates a suppressed relation OFF rather\n * than failing open (offering `.get()`/`.related()`/mutations that 404).\n */\n private withRelationExposure(\n descriptor: RelationDescriptor,\n collection: string,\n name: string,\n endpoints: RelationEndpoints | undefined,\n ): RelationDescriptor {\n const out: RelationDescriptor = { ...descriptor }\n const relatedPath = endpoints?.related ?? `${collection}/{id}/${name}`\n const relationshipPath = endpoints?.relationship ?? `${collection}/{id}/relationships/${name}`\n // The client fills `{rel}` with this segment, so a relation served under its URI field name\n // (`/articles/{id}/published-by` for `publisher`) is reached at its real path.\n const segment = (endpoints?.related ?? endpoints?.relationship)?.split('/').pop()\n if (segment !== undefined && segment !== name) {\n out.uriField = segment\n }\n const relatedGet = this.operation(relatedPath, 'get')\n if (relatedGet === undefined) {\n out.related = false\n }\n const mutations = this.relationMutations(relationshipPath, descriptor.cardinality)\n if (mutations === undefined) {\n out.relationship = false\n out.mutations = {}\n } else {\n out.mutations = mutations\n }\n // The related/relationship reads may advertise their own `withCount` (`_self_` + the relation's\n // countable relations) with a negotiation profile — capture it so a typed `.related()`/`.get()`\n // can send `withCount` and negotiate the profile the endpoint requires (D3).\n const countable =\n withCountParam(relatedGet) ?? withCountParam(this.operation(relationshipPath, 'get'))\n if (countable !== undefined) {\n out.countable = countable\n }\n // A to-many related endpoint can advertise a DIFFERENT paginator than the related type's\n // top-level collection (D6a). Read the related-endpoint kind (preferring the related over the\n // relationship endpoint) and carry it ONLY when it diverges from the related type's collection\n // paginator — the client falls back to that type's paginator otherwise, so parity stays silent.\n if (descriptor.cardinality === 'many') {\n const relatedPaginator =\n this.paginatorOf(relatedGet) === 'none'\n ? this.paginatorOf(this.operation(relationshipPath, 'get'))\n : this.paginatorOf(relatedGet)\n const relatedType = descriptor.types[0]\n const typePaginator = relatedType !== undefined ? this.typePaginator(relatedType) : 'none'\n if (\n relatedPaginator !== 'none' &&\n JSON.stringify(relatedPaginator) !== JSON.stringify(typePaginator)\n ) {\n out.paginator = relatedPaginator\n }\n }\n return out\n }\n\n /**\n * Collect the custom actions for a type from its `{collection}/-actions/{name}` and\n * `{collection}/{id}/-actions/{name}` paths. The action name is the last segment; scope\n * is `resource` when the path carries `/{id}/`, else `collection`. `input` is `document`\n * (a JSON:API requestBody), `none` (no requestBody) or `raw` (a non-JSON:API body);\n * `output` is `document` (a 2xx returns a JSON:API document) or `none` (only `204`).\n */\n private actions(collection: string): Record<string, ActionDescriptor> {\n const out: Record<string, ActionDescriptor> = {}\n const collectionPrefix = `${collection}/-actions/`\n const resourcePrefix = `${collection}/{id}/-actions/`\n for (const [path, item] of Object.entries(this.paths)) {\n let scope: ActionDescriptor['scope']\n let name: string\n if (path.startsWith(resourcePrefix)) {\n scope = 'resource'\n name = path.slice(resourcePrefix.length)\n } else if (path.startsWith(collectionPrefix)) {\n scope = 'collection'\n name = path.slice(collectionPrefix.length)\n } else {\n continue\n }\n // The action name is a single trailing segment.\n if (name.length === 0 || name.includes('/')) {\n continue\n }\n // An action is invoked over one HTTP method; the bundle lets an author declare a\n // non-POST method, so read the advertised operation (POST-preferred) rather than only\n // `post` — else a GET/PATCH/DELETE-only action would silently vanish from the client.\n const picked = pickOperation(item)\n if (picked === undefined) {\n // eslint-disable-next-line no-console\n console.warn(\n `json-api codegen: custom action path \"${path}\" advertises no usable operation; skipping.`,\n )\n continue\n }\n const { method, op } = picked\n const input = actionInput(op)\n const output = actionOutput(op)\n const action: ActionDescriptor = { scope, path, input, output }\n // Only carried when non-POST (POST is the runtime default), keeping the common descriptor tiny.\n if (method !== 'post') {\n action.method = method.toUpperCase()\n }\n // A document input names its resource type so the client can accept FLAT input and build the\n // envelope (+ remap 422 pointers), matching `create`/`update` ergonomics.\n if (input === 'document') {\n const inputType = this.documentPrimary(actionRequestRef(op))?.type\n if (inputType !== undefined) {\n action.inputType = inputType\n }\n }\n // A document output names its primary resource type + cardinality so the client materialises\n // the response into that resource view (matching reads), not the raw wire envelope.\n if (output === 'document') {\n const primary = this.documentPrimary(this.firstOkJsonApiRef(op))\n if (primary !== undefined) {\n action.outputType = primary.type\n action.outputCardinality = primary.cardinality\n }\n }\n // A raw-input action carries its declared (non-JSON:API) media type so the client sends\n // the right `Content-Type` rather than a wildcard the server may reject.\n if (input === 'raw') {\n const contentType = rawContentType(op)\n if (contentType !== undefined) {\n action.contentType = contentType\n }\n }\n out[name] = action\n }\n return sortRecord(out)\n }\n\n /**\n * The wire type (and cardinality) of a document component's primary `data` — a `$ref` to a\n * resource, an inline object carrying `properties.type.const` (a create-request body), or an\n * array of resource/identifier refs (a collection). `undefined` when the type can't be resolved.\n */\n private documentPrimary(\n ref: string | undefined,\n ): { type: string; cardinality: Cardinality } | undefined {\n if (typeof ref !== 'string') {\n return undefined\n }\n const component = refName(ref)\n const data = component === undefined ? undefined : this.schemas[component]?.properties?.['data']\n if (!isSchema(data)) {\n return undefined\n }\n if (isSchema(data.items)) {\n const itemRef = data.items.$ref\n const many = typeof itemRef === 'string' ? this.resolveConst(itemRef) : undefined\n return many === undefined ? undefined : { type: many, cardinality: 'many' }\n }\n const one = this.dataConst(data)\n return one === undefined ? undefined : { type: one, cardinality: 'one' }\n }\n\n /** The wire type of a single `data` schema — a `$ref` to a resource, or an inline `type.const`. */\n private dataConst(data: SchemaObject): string | undefined {\n if (typeof data.$ref === 'string') {\n return this.resolveConst(data.$ref)\n }\n const typeProp = data.properties?.['type']\n return isSchema(typeProp) && typeof typeProp.const === 'string' ? typeProp.const : undefined\n }\n\n /** The `$ref` of the first 2xx JSON:API response body on an operation (the output document). */\n private firstOkJsonApiRef(op: OperationObject): string | undefined {\n for (const [code, response] of Object.entries(op.responses ?? {})) {\n if (!code.startsWith('2')) {\n continue\n }\n const ref = response.content?.[JSON_API_MEDIA_TYPE]?.schema?.$ref\n if (typeof ref === 'string') {\n return ref\n }\n }\n return undefined\n }\n\n /** Resolve a relationship component's `data` into a {@link RelationDescriptor}. */\n private relationFromComponent(component: SchemaObject): RelationDescriptor | undefined {\n const data = component.properties?.['data']\n if (!isSchema(data)) {\n return undefined\n }\n\n // to-many: data.type === 'array'\n if (data.type === 'array') {\n const items = data.items\n if (items === undefined) {\n return undefined\n }\n if (typeof items.$ref === 'string') {\n // monomorphic to-many\n const type = this.resolveConst(items.$ref)\n return type === undefined ? undefined : { cardinality: 'many', types: [type], pivot: false }\n }\n if (Array.isArray(items.allOf)) {\n // pivot to-many: the $ref is the allOf entry that carries it\n const type = this.constFromAllOf(items.allOf)\n if (type === undefined) {\n return undefined\n }\n const relation: RelationDescriptor = { cardinality: 'many', types: [type], pivot: true }\n const readPivot = this.pivotDescriptor(pivotNodeFromAllOf(items.allOf), 'read')\n if (readPivot !== undefined) {\n relation.readPivot = readPivot\n }\n return relation\n }\n if (Array.isArray(items.anyOf)) {\n // polymorphic to-many\n return { cardinality: 'many', types: this.constsFromRefs(items.anyOf), pivot: false }\n }\n return undefined\n }\n\n // to-one: data.anyOf with the non-null entries being $refs (or pivot allOfs);\n // a polymorphic to-one nests its $refs one level deeper in another anyOf.\n if (Array.isArray(data.anyOf)) {\n const types: string[] = []\n let pivot = false\n let readPivot: PivotDescriptor | undefined\n for (const entry of data.anyOf) {\n if (typeof entry.$ref === 'string') {\n const type = this.resolveConst(entry.$ref)\n if (type !== undefined) {\n types.push(type)\n }\n } else if (Array.isArray(entry.allOf)) {\n const type = this.constFromAllOf(entry.allOf)\n if (type !== undefined) {\n types.push(type)\n pivot = true\n readPivot = this.pivotDescriptor(pivotNodeFromAllOf(entry.allOf), 'read')\n }\n } else if (Array.isArray(entry.anyOf)) {\n // polymorphic to-one: the non-null entry is itself an anyOf of $refs\n types.push(...this.constsFromRefs(entry.anyOf))\n }\n }\n if (types.length === 0) {\n return undefined\n }\n const relation: RelationDescriptor = { cardinality: 'one', types, pivot }\n if (readPivot !== undefined) {\n relation.readPivot = readPivot\n }\n return relation\n }\n\n return undefined\n }\n\n /**\n * The request pivot of a pivot relation: read off the component a write body (or a\n * relationship mutation) refs, falling back to the rendered relationship's pivot minus its\n * `readOnly` fields when no request shape is published (before generator contract 8).\n */\n private writePivot(ref: string | undefined, fallback: SchemaObject): PivotDescriptor | undefined {\n const component = ref === undefined ? undefined : this.schemas[refName(ref) ?? '']\n return this.pivotDescriptor(\n pivotNodeOf(component ?? fallback) ?? pivotNodeOf(fallback),\n 'write',\n )\n }\n\n /**\n * A {@link PivotDescriptor} from a member's `meta.pivot` schema: field hints, the required\n * fields and the nullable ones. Generator contract 8 refs a `<Type><Rel>Pivot` (response) or\n * `<Type><Rel>WritePivot` (request) component, each with its own `required`. An older document\n * inlines one shared schema in the write context, so a read takes every field as rendered and a\n * write drops the `readOnly` ones. `undefined` when the schema has no fields.\n */\n private pivotDescriptor(\n node: SchemaObject | undefined,\n side: 'read' | 'write',\n ): PivotDescriptor | undefined {\n if (node === undefined) {\n return undefined\n }\n const shared = typeof node.$ref !== 'string'\n const schema = shared ? node : this.schemas[refName(node.$ref as string) ?? '']\n const fields: Record<string, string> = {}\n const nullable: string[] = []\n for (const [name, prop] of Object.entries(schema?.properties ?? {})) {\n if (!isSchema(prop) || prop[side === 'read' ? 'writeOnly' : 'readOnly'] === true) {\n continue\n }\n fields[name] = formatHint(prop)\n if (isNullable(prop)) {\n nullable.push(name)\n }\n }\n const names = Object.keys(fields)\n if (names.length === 0) {\n return undefined\n }\n const required =\n shared && side === 'read' ? names : names.filter((name) => schema?.required?.includes(name))\n const out: PivotDescriptor = { fields: sortRecord(fields) }\n if (required.length < names.length) {\n // oxlint-disable-next-line no-array-sort -- sorting a freshly-created array\n out.required = required.sort()\n }\n if (nullable.length > 0) {\n // oxlint-disable-next-line no-array-sort -- sorting a freshly-created array\n out.nullable = nullable.sort()\n }\n return out\n }\n\n /** Pull the related type from the `$ref` entry of an `allOf` (the pivot shape). */\n private constFromAllOf(allOf: readonly SchemaObject[]): string | undefined {\n for (const entry of allOf) {\n if (typeof entry.$ref === 'string') {\n const type = this.resolveConst(entry.$ref)\n if (type !== undefined) {\n return type\n }\n }\n }\n return undefined\n }\n\n /** Resolve every `$ref` entry in a list to its wire type. */\n private constsFromRefs(entries: readonly SchemaObject[]): string[] {\n const types: string[] = []\n for (const entry of entries) {\n if (typeof entry.$ref === 'string') {\n const type = this.resolveConst(entry.$ref)\n if (type !== undefined) {\n types.push(type)\n }\n }\n }\n return types\n }\n\n private clientId(base: string): ClientIdPolicy {\n const create = this.schemas[`${base}CreateRequest`]\n const data = isSchema(create?.properties?.['data']) ? create.properties['data'] : undefined\n if (data === undefined) {\n return 'forbidden'\n }\n if (data.properties?.['id'] === false) {\n return 'forbidden'\n }\n return data.required?.includes('id') ? 'required' : 'optional'\n }\n\n /**\n * Find the collection path for a type, then derive each per-operation path that\n * actually exists. The collection path P is the one whose POST requestBody refs\n * `<Base>CreateRequest`, else the GET whose 200 response refs `<Base>Collection`.\n */\n private operationPaths(base: string): Record<string, string> {\n const collection = this.collectionPath(base)\n const out: Record<string, string> = {}\n if (collection === undefined) {\n return out\n }\n\n if (this.operation(collection, 'get')) {\n out['fetchMany'] = collection\n }\n if (this.operation(collection, 'post')) {\n out['create'] = collection\n }\n\n const item = `${collection}/{id}`\n if (this.operation(item, 'get')) {\n out['fetchOne'] = item\n }\n if (this.operation(item, 'patch')) {\n out['update'] = item\n }\n if (this.operation(item, 'delete')) {\n out['delete'] = item\n }\n\n if (this.hasRelatedPath(collection)) {\n out['fetchRelated'] = `${collection}/{id}/{rel}`\n }\n if (this.hasRelationshipPath(collection)) {\n out['fetchRelationship'] = `${collection}/{id}/relationships/{rel}`\n }\n\n return sortRecord(out)\n }\n\n private collectionPath(base: string): string | undefined {\n let byCollection: string | undefined\n for (const [path, item] of Object.entries(this.paths)) {\n const post = item.post\n if (post && refEndsWith(this.requestBodyRef(post), `${base}CreateRequest`)) {\n return path\n }\n // Only a genuine top-level collection qualifies for the response-ref fallback —\n // a parent-scoped *related* collection (e.g. `/users/{id}/playlists`) also refs\n // `<Base>Collection` but is not a fetchMany endpoint for that type.\n if (\n byCollection === undefined &&\n !path.includes('/{id}/') &&\n refEndsWith(this.okResponseRef(item.get), `${base}Collection`)\n ) {\n byCollection = path\n }\n }\n return byCollection\n }\n\n /** Any `P/{id}/<rel>` related path (excludes relationships/ and custom `-actions`). */\n private hasRelatedPath(collection: string): boolean {\n const prefix = `${collection}/{id}/`\n return Object.keys(this.paths).some((path) => {\n if (!path.startsWith(prefix)) {\n return false\n }\n const rest = path.slice(prefix.length)\n return rest.length > 0 && !rest.includes('/') && !rest.startsWith('-')\n })\n }\n\n private hasRelationshipPath(collection: string): boolean {\n const prefix = `${collection}/{id}/relationships/`\n return Object.keys(this.paths).some(\n (path) => path.startsWith(prefix) && !path.slice(prefix.length).includes('/'),\n )\n }\n\n /** Detect the paginator from the fetchMany operation's page parameters. */\n private paginator(base: string): PaginatorDescriptor {\n const collection = this.collectionPath(base)\n return this.paginatorOf(this.operation(collection ?? '', 'get'), collection)\n }\n\n /**\n * Detect the paginator an operation advertises. A page schema stamped with `x-paginator`\n * (contract 3) names its strategy and the wire key for each role, so it decides both. Without\n * the stamp, the strategy is inferred from canonical member names (see {@link kindOfMembers}).\n * Anything unrecognised warns and generates as unpaginated. `label` (a path) names the endpoint\n * in the warning; without it nothing is logged.\n */\n private paginatorOf(op: OperationObject | undefined, label?: string): PaginatorDescriptor {\n const warn = (problem: string): 'none' => {\n if (label !== undefined) {\n // eslint-disable-next-line no-console\n console.warn(\n `json-api codegen: endpoint \"${label}\" ${problem}; treating it as unpaginated.`,\n )\n }\n return 'none'\n }\n\n const schema = op?.parameters?.find((param) => param.name === 'page')?.schema\n if (schema?.['x-paginator'] !== undefined) {\n return stampedPaginator(schema, warn)\n }\n\n const { members, menu } = this.pageMembers(op)\n if (menu === undefined) {\n const kind = kindOfMembers(members)\n if (kind !== undefined) {\n return kind\n }\n }\n // A page parameter matching no single known kind is a drift the client would silently treat\n // as unpaginated; warn rather than swallow it (D28).\n if (menu !== undefined) {\n return warn(\n `advertises a selectable page strategy menu (${menu\n .map((arm) => kindOfMembers(arm) ?? sortedList(arm))\n .join(' | ')}) without an x-paginator stamp naming its default`,\n )\n }\n return members.size > 0\n ? warn(\n `advertises page parameters matching no known paginator kind (members ${sortedList(members)})`,\n )\n : 'none'\n }\n\n /**\n * The `page` members an operation accepts, from either wire form: one `page` parameter\n * (`style: deepObject`) whose schema `properties` name the members, as `haddowg/json-api` v1\n * projects it, or the older flattened `page[number]`/`page[size]` parameters. A `oneOf` page\n * schema (a MultiPaginator menu) yields each arm's members in `menu` instead, minus the\n * `kind` discriminator.\n */\n private pageMembers(op: OperationObject | undefined): {\n members: Set<string>\n menu?: Set<string>[]\n } {\n const members = new Set<string>()\n let menu: Set<string>[] | undefined\n for (const param of op?.parameters ?? []) {\n const name = param.name\n if (name === 'page') {\n const arms = param.schema?.oneOf\n if (arms !== undefined) {\n menu = arms.map(\n (arm) => new Set(Object.keys(arm.properties ?? {}).filter((m) => m !== 'kind')),\n )\n }\n for (const member of Object.keys(param.schema?.properties ?? {})) {\n members.add(member)\n }\n } else if (name?.startsWith('page[') === true && name.endsWith(']')) {\n members.add(name.slice('page['.length, -1))\n }\n }\n return menu === undefined ? { members } : { members, menu }\n }\n\n /**\n * The `withCount` capability (Countable profile) for a type's COLLECTION read (`list`): the\n * count tokens (`schema.items.enum`) + the negotiation profile (`x-profile`) carried by the\n * collection GET's `withCount` query parameter. Returns `undefined` when the collection\n * doesn't exist or advertises no `withCount`. The profile URI is never hardcoded — it is read\n * from the parameter's `x-profile`.\n *\n * Deliberately scoped to the collection GET only. The per-endpoint token sets differ\n * (a collection counts e.g. `tracks`; a related/relationship endpoint counts `_self_` and its\n * own relations), so a single per-type `countable` can only honestly describe one endpoint.\n * The fluent surface exposes `withCount` on `list` (the collection), so `countable` mirrors\n * that endpoint — a related-GET fallback would advertise tokens `list` cannot legally send.\n */\n private countable(collection: string | undefined): CountableDescriptor | undefined {\n if (collection === undefined) {\n return undefined\n }\n return withCountParam(this.operation(collection, 'get'))\n }\n\n /**\n * The relation paths the read endpoints accept in `include` — the `include` query\n * parameter's `schema.items.enum` (already including nested dotted paths) on the collection\n * GET. Returns `undefined` when the collection advertises no `include` (nothing includable).\n *\n * Read from the collection GET to mirror {@see sortable}/{@see filterable}: the whole builder\n * is collection-centric (a type with no collection path gets no `paths` at all), and the bundle\n * advertises the same `include` enum on the collection and single-resource GETs.\n */\n private includable(collection: string | undefined): readonly string[] | undefined {\n if (collection === undefined) {\n return undefined\n }\n const tokens = paramItemsEnum(this.operation(collection, 'get'), 'include')\n return tokens !== undefined && tokens.length > 0 ? tokens : undefined\n }\n\n /**\n * The sort tokens the COLLECTION read accepts — the `sort` query parameter's\n * `schema.items.enum` (signed field names) on the collection GET. Returns `undefined` when\n * the collection advertises no `sort` parameter (sorting unsupported).\n */\n private sortable(collection: string | undefined): readonly string[] | undefined {\n if (collection === undefined) {\n return undefined\n }\n const tokens = paramItemsEnum(this.operation(collection, 'get'), 'sort')\n return tokens !== undefined && tokens.length > 0 ? tokens : undefined\n }\n\n /**\n * The filter keys the COLLECTION read accepts in `filter[...]` (the `filter[<key>]` parameter\n * names, `<key>` extracted), sorted for deterministic output. Returns `undefined` when the\n * collection advertises no `filter[...]` parameters (filtering unsupported). Value shapes are\n * deliberately not captured — `filter` values stay `unknown` (out of scope for v0.1).\n */\n private filterable(collection: string | undefined): readonly string[] | undefined {\n if (collection === undefined) {\n return undefined\n }\n const keys: string[] = []\n for (const param of this.operation(collection, 'get')?.parameters ?? []) {\n const name = param.name\n if (typeof name === 'string' && name.startsWith('filter[') && name.endsWith(']')) {\n keys.push(name.slice('filter['.length, -1))\n }\n }\n // oxlint-disable-next-line no-array-sort -- sorting a freshly-created key array\n return keys.length > 0 ? keys.sort() : undefined\n }\n\n private operation(path: string, method: HttpMethod): OperationObject | undefined {\n return this.paths[path]?.[method]\n }\n\n private requestBodyRef(op: OperationObject | undefined): string | undefined {\n return op?.requestBody?.content?.['application/vnd.api+json']?.schema?.$ref\n }\n\n private okResponseRef(op: OperationObject | undefined): string | undefined {\n return op?.responses?.['200']?.content?.['application/vnd.api+json']?.schema?.$ref\n }\n}\n\n/** The `meta.pivot` schema node of a pivot `allOf` entry list, if any. */\nfunction pivotNodeFromAllOf(allOf: readonly SchemaObject[]): SchemaObject | undefined {\n for (const entry of allOf) {\n const meta = entry.properties?.['meta']\n const pivot = isSchema(meta) ? meta.properties?.['pivot'] : undefined\n if (isSchema(pivot)) {\n return pivot\n }\n }\n return undefined\n}\n\n/**\n * The `meta.pivot` schema node of a relationship component or document: its to-many `items`\n * `allOf`, or a to-one `anyOf` entry's `allOf`.\n */\nfunction pivotNodeOf(component: SchemaObject): SchemaObject | undefined {\n const data = component.properties?.['data']\n if (!isSchema(data)) {\n return undefined\n }\n if (Array.isArray(data.items?.allOf)) {\n return pivotNodeFromAllOf(data.items.allOf)\n }\n for (const entry of data.anyOf ?? []) {\n if (Array.isArray(entry.allOf)) {\n return pivotNodeFromAllOf(entry.allOf)\n }\n }\n return undefined\n}\n\n/** Whether a schema admits `null`: a `null` type, or a `null` branch in `anyOf`/`oneOf`. */\nfunction isNullable(schema: SchemaObject): boolean {\n const type = schema.type\n if (type === 'null' || (Array.isArray(type) && type.includes('null'))) {\n return true\n }\n return [...(schema.anyOf ?? []), ...(schema.oneOf ?? [])].some((branch) => branch.type === 'null')\n}\n\n/** A schema's wire format hint: explicit `format`, else the JSON type, else a ref-enum is `string`. */\nfunction formatHint(schema: SchemaObject): string {\n if (typeof schema.format === 'string') {\n return schema.format\n }\n const types = typeKeys(schema.type)\n if (types.length > 0) {\n return types[0]!\n }\n // A $ref (typically an enum component) renders as a string union.\n if (typeof schema.$ref === 'string') {\n return 'string'\n }\n // A nullable `$ref` is `anyOf: [{ $ref }, { type: 'null' }]`: hint the value branch.\n const isNullOnly = (branch: SchemaObject): boolean =>\n branch.type !== undefined && typeKeys(branch.type).length === 0\n const branches = (schema.anyOf ?? schema.oneOf ?? []).filter((branch) => !isNullOnly(branch))\n if (branches.length === 1) {\n return formatHint(branches[0]!)\n }\n return 'unknown'\n}\n\nfunction refEndsWith(ref: string | undefined, suffix: string): boolean {\n return ref !== undefined && refName(ref) === suffix\n}\n\n/**\n * Read the {@link CountableDescriptor} off an operation's `withCount` query parameter: the\n * count tokens from its `schema.items.enum` and the negotiation profile from `x-profile`.\n * Returns `undefined` when the operation has no `withCount` parameter, or when one is present\n * but carries no `x-profile` (a `withCount` we can't tell a client how to negotiate). An empty\n * or absent token enum yields `[]` tokens (the profile alone is still actionable).\n */\nfunction withCountParam(op: OperationObject | undefined): CountableDescriptor | undefined {\n for (const param of op?.parameters ?? []) {\n if (param.name !== 'withCount') {\n continue\n }\n const profile = param['x-profile']\n if (typeof profile !== 'string') {\n return undefined\n }\n const enumValues = param.schema?.items?.enum\n const tokens = Array.isArray(enumValues)\n ? enumValues.filter((v): v is string => typeof v === 'string')\n : []\n return { tokens, profile }\n }\n return undefined\n}\n\n/**\n * The string members of an array-valued query parameter's `schema.items.enum` (the shape the\n * `include` and `sort` parameters use). Returns `undefined` when the operation carries no\n * parameter of that name, or one whose schema declares no enum.\n */\nfunction paramItemsEnum(\n op: OperationObject | undefined,\n paramName: string,\n): readonly string[] | undefined {\n for (const param of op?.parameters ?? []) {\n if (param.name !== paramName) {\n continue\n }\n const enumValues = param.schema?.items?.enum\n return Array.isArray(enumValues)\n ? enumValues.filter((v): v is string => typeof v === 'string')\n : undefined\n }\n return undefined\n}\n\n/**\n * True for the Atomic Operations ext media type — `application/vnd.api+json` carrying the\n * atomic `ext` parameter ({@link ATOMIC_EXT}). Tolerant of quoting/whitespace so any of\n * `ext=\"…\"` / `ext=…` matches.\n */\nfunction isAtomicMediaType(mediaType: string): boolean {\n return mediaType.startsWith(JSON_API_MEDIA_TYPE) && mediaType.includes(ATOMIC_EXT)\n}\n\n/** The HTTP methods an action operation may be advertised under, in resolution preference order. */\nconst ACTION_METHODS: readonly HttpMethod[] = ['post', 'get', 'put', 'patch', 'delete']\n\n/**\n * The single operation an action is invoked over: POST when advertised (the common default), else\n * the first advertised method. `undefined` when the path item carries no operation at all.\n */\nfunction pickOperation(\n item: PathItemObject,\n): { method: HttpMethod; op: OperationObject } | undefined {\n const available = ACTION_METHODS.filter((method) => item[method] !== undefined)\n const method = available.includes('post') ? 'post' : available[0]\n if (method === undefined) {\n return undefined\n }\n const op = item[method]\n return op === undefined ? undefined : { method, op }\n}\n\n/** The body shape a custom action accepts: a JSON:API document, none, or a raw payload. */\nfunction actionInput(op: OperationObject): ActionDescriptor['input'] {\n const content = op.requestBody?.content\n if (content === undefined || Object.keys(content).length === 0) {\n return 'none'\n }\n return JSON_API_MEDIA_TYPE in content ? 'document' : 'raw'\n}\n\n/** The `$ref` of an action's JSON:API request body (a `document` input), or `undefined`. */\nfunction actionRequestRef(op: OperationObject): string | undefined {\n const ref = op.requestBody?.content?.[JSON_API_MEDIA_TYPE]?.schema?.$ref\n return typeof ref === 'string' ? ref : undefined\n}\n\n/** The declared media type of a `raw`-input action — the first non-JSON:API content type. */\nfunction rawContentType(op: OperationObject): string | undefined {\n const content = op.requestBody?.content\n if (content === undefined) {\n return undefined\n }\n return Object.keys(content).find((mediaType) => mediaType !== JSON_API_MEDIA_TYPE)\n}\n\n/**\n * What a custom action returns from its first 2xx response: a `meta`-only document (a `$ref` to the\n * shared `MetaDocument` — no `data`), a resource `document` (any other JSON:API body), or `none`\n * (only a `204`).\n */\nfunction actionOutput(op: OperationObject): ActionDescriptor['output'] {\n for (const [code, response] of Object.entries(op.responses ?? {})) {\n if (!code.startsWith('2')) {\n continue\n }\n const schema = response.content?.[JSON_API_MEDIA_TYPE]?.schema\n if (schema === undefined) {\n continue\n }\n return typeof schema.$ref === 'string' && refName(schema.$ref) === 'MetaDocument'\n ? 'meta'\n : 'document'\n }\n return 'none'\n}\n\n/** Build the {@link ApiDescriptor} from a parsed OpenAPI document. */\nexport function buildDescriptor(doc: OpenApiDocument): ApiDescriptor {\n return new DescriptorBuilder(doc).build()\n}\n\n/** Detect the server-level Atomic Operations capability (`null` when none). */\nexport function buildAtomic(doc: OpenApiDocument): AtomicDescriptor | null {\n return new DescriptorBuilder(doc).buildAtomic()\n}\n\n/**\n * Classify a page member set: `number`+`size` = `page`; `offset`+`limit` = `offset`; either\n * cursor bound (`after`/`before`) = `cursor` (link-driven, D44); `number` alone = `fixed` (the\n * server fixes the size); no members = `none`; anything else = `undefined` (unrecognised).\n */\nfunction kindOfMembers(members: ReadonlySet<string>): PaginatorKind | undefined {\n if (members.has('number') && members.has('size')) {\n return 'page'\n }\n if (members.has('offset') && members.has('limit')) {\n return 'offset'\n }\n if (members.has('after') || members.has('before')) {\n return 'cursor'\n }\n if (members.size === 1 && members.has('number')) {\n return 'fixed'\n }\n return members.size === 0 ? 'none' : undefined\n}\n\n// oxlint-disable-next-line no-array-sort -- sorting a freshly-created array\nconst sortedList = (members: ReadonlySet<string>): string => [...members].sort().join(', ')\n\nconst STRATEGIES: readonly PaginatorStrategy[] = ['page', 'offset', 'cursor', 'fixed']\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\n/**\n * Read a page schema's `x-paginator` stamp. A strategy keeps the wire key the stamp names for\n * each of its roles (a missing role keeps its canonical name) and collapses to the bare kind when\n * every key is canonical. A `multi` stamp reads each `oneOf` arm by its `kind` const: an arm's own\n * stamp decides it, an unstamped arm falls back to name inference, and an arm neither recognises\n * is left out of the menu.\n */\nfunction stampedPaginator(\n schema: SchemaObject,\n warn: (problem: string) => 'none',\n): PaginatorDescriptor {\n const stamp = schema['x-paginator']\n const strategy = isRecord(stamp) ? stamp['strategy'] : undefined\n if (!isRecord(stamp) || typeof strategy !== 'string') {\n return warn('stamps a malformed x-paginator')\n }\n if (strategy === 'multi') {\n return stampedMenu(schema, stamp, warn)\n }\n if (!(STRATEGIES as readonly string[]).includes(strategy)) {\n return warn(`stamps an x-paginator strategy \"${strategy}\" this codegen does not know`)\n }\n const kind = strategy as PaginatorStrategy\n const canonical: Partial<Record<PaginatorRole, string>> = CANONICAL_PAGE_KEYS[kind]\n const stamped = isRecord(stamp['keys']) ? stamp['keys'] : {}\n const keys: Partial<Record<PaginatorRole, string>> = {}\n let renamed = false\n for (const [role, fallback] of Object.entries(canonical) as [PaginatorRole, string][]) {\n const key = typeof stamped[role] === 'string' ? stamped[role] : fallback\n keys[role] = key\n renamed ||= key !== fallback\n }\n return renamed ? { strategy: kind, keys } : kind\n}\n\nfunction stampedMenu(\n schema: SchemaObject,\n stamp: Record<string, unknown>,\n warn: (problem: string) => 'none',\n): PaginatorDescriptor {\n const arms: Record<string, MenuDescriptor['arms'][string]> = {}\n for (const arm of schema.oneOf ?? []) {\n const discriminator = arm.properties?.['kind']\n const kind = isRecord(discriminator) ? discriminator['const'] : undefined\n if (typeof kind !== 'string') {\n warn('offers a page strategy menu arm without a kind const, which is left out')\n continue\n }\n const paginator =\n arm['x-paginator'] !== undefined\n ? stampedPaginator(arm, (problem) =>\n warn(`offers a menu arm \"${kind}\" that ${problem}, which is left out`),\n )\n : (kindOfMembers(new Set(Object.keys(arm.properties ?? {}).filter((m) => m !== 'kind'))) ??\n warn(`offers a menu arm \"${kind}\" matching no known paginator kind, which is left out`))\n if (typeof paginator === 'object' && paginator.strategy === 'multi') {\n warn(`nests a page strategy menu in arm \"${kind}\", which is left out`)\n continue\n }\n if (paginator !== 'none') {\n arms[kind] = paginator\n }\n }\n const fallback = stamp['default']\n if (typeof fallback !== 'string' || arms[fallback] === undefined) {\n return warn(\n `stamps a page strategy menu whose default ${typeof fallback === 'string' ? `\"${fallback}\"` : '(missing)'} is not one of its generated arms`,\n )\n }\n return { strategy: 'multi', default: fallback, arms }\n}\n","import type { OpenApiDocument } from './openapi'\n\n/** Below this the document predates the structures this codegen reads. */\nexport const MINIMUM_CONTRACT = 1\n\n/** Above this the document carries structures this codegen does not read. */\nexport const MAXIMUM_CONTRACT = 8\n\n/**\n * Check the document's `info.x-generator.contract` against the range this codegen reads. A\n * document older than the range throws; a newer one returns a warning, because its new\n * structures would go unread and the client would silently miss what the server offers. A\n * document with no contract (json-api before 1.1.0) passes.\n */\nexport function checkContract(doc: OpenApiDocument): string | undefined {\n const contract = doc.info?.['x-generator']?.contract\n if (typeof contract !== 'number') {\n return undefined\n }\n if (contract < MINIMUM_CONTRACT) {\n throw new Error(\n `the document declares contract ${contract}, which predates what this codegen reads (it supports ${MINIMUM_CONTRACT} to ${MAXIMUM_CONTRACT}). Use an older codegen release, or regenerate the document from a newer server.`,\n )\n }\n if (contract > MAXIMUM_CONTRACT) {\n return `the document declares contract ${contract} and this codegen reads up to ${MAXIMUM_CONTRACT}. It describes capabilities that were not generated; upgrade the codegen to pick them up.`\n }\n return undefined\n}\n","import type { OpenApiDocument, SchemaObject, SchemaOrBool } from './openapi'\n\nconst REF_PREFIX = '#/components/schemas/'\nconst ERROR_DOCUMENT = /^ErrorDocument(\\d{3})?$/\n\n/** One documented error code, with whatever the document says about it. */\nexport interface DocumentedErrorCode {\n code: string\n /** The `<Code>Error` component's `description`, when the document has one (contract 4). */\n description?: string\n /** Example `detail` values, from the component's `detail` property (`example` / `examples`). */\n examples: unknown[]\n}\n\n/** The server's error catalogue as the codegen reads it. */\nexport interface ErrorCatalogue {\n /** Every code any error document offers, sorted by code. */\n codes: DocumentedErrorCode[]\n /**\n * Per status, the codes its `ErrorDocument<NNN>` offers, sorted by code. A status whose\n * document offers only the generic `Error` maps to an empty list.\n */\n byStatus: Map<number, string[]>\n}\n\nfunction isSchema(value: SchemaOrBool | undefined): value is SchemaObject {\n return typeof value === 'object' && value !== null\n}\n\n/** A schema node and its `allOf` members, where a code variant keeps its narrowing. */\nfunction layers(schema: SchemaObject): SchemaObject[] {\n return [schema, ...(schema.allOf ?? []).filter((member) => member.$ref === undefined)]\n}\n\nfunction property(schema: SchemaObject, name: string): SchemaObject | undefined {\n for (const layer of layers(schema)) {\n const prop = layer.properties?.[name]\n if (isSchema(prop)) {\n return prop\n }\n }\n return undefined\n}\n\nfunction examplesOf(detail: SchemaObject | undefined): unknown[] {\n if (detail === undefined) {\n return []\n }\n const examples = Array.isArray(detail['examples']) ? [...(detail['examples'] as unknown[])] : []\n if ('example' in detail && !examples.includes(detail['example'])) {\n examples.unshift(detail['example'])\n }\n return examples\n}\n\n/**\n * Read the documented error codes off a document's error documents. `ErrorDocument` and each\n * `ErrorDocument<NNN>` offer their codes as `errors.items.anyOf` branches that `$ref` a\n * `<Code>Error` component; a branch with a `code` const names a code, and the generic `Error`\n * branch (no const) names none.\n */\nexport function readErrorCatalogue(doc: OpenApiDocument): ErrorCatalogue {\n const schemas = doc.components?.schemas ?? {}\n const codes = new Map<string, DocumentedErrorCode>()\n const byStatus = new Map<number, string[]>()\n\n for (const [name, schema] of Object.entries(schemas)) {\n const match = ERROR_DOCUMENT.exec(name)\n if (match === null) {\n continue\n }\n const items = property(schema, 'errors')?.items\n const branches = items === undefined ? [] : [...(items.anyOf ?? []), ...(items.oneOf ?? [])]\n const documentCodes = new Set<string>()\n for (const branch of branches) {\n const component =\n typeof branch.$ref === 'string' && branch.$ref.startsWith(REF_PREFIX)\n ? schemas[branch.$ref.slice(REF_PREFIX.length)]\n : branch\n const code = component === undefined ? undefined : property(component, 'code')?.const\n if (component === undefined || typeof code !== 'string') {\n continue\n }\n documentCodes.add(code)\n if (!codes.has(code)) {\n const description = layers(component)\n .map((layer) => layer.description?.trim())\n .find((text) => text !== undefined && text !== '')\n codes.set(code, {\n code,\n ...(description ? { description } : {}),\n examples: examplesOf(property(component, 'detail')),\n })\n }\n }\n if (match[1] !== undefined) {\n // oxlint-disable-next-line no-array-sort -- sorting a freshly-created array\n byStatus.set(Number(match[1]), [...documentCodes].sort())\n }\n }\n\n return {\n // oxlint-disable-next-line no-array-sort -- sorting a freshly-created array\n codes: [...codes.values()].sort((a, b) => (a.code < b.code ? -1 : a.code > b.code ? 1 : 0)),\n // oxlint-disable-next-line no-array-sort -- sorting a freshly-created array\n byStatus: new Map([...byStatus].sort(([a], [b]) => a - b)),\n }\n}\n\n/** A TSDoc block for one code: its description, then each example detail as an `@example`. */\nfunction codeDoc(entry: DocumentedErrorCode, indent: string): string | undefined {\n const lines: string[] = []\n if (entry.description !== undefined) {\n lines.push(...entry.description.split('\\n'))\n }\n for (const example of entry.examples) {\n if (lines.length > 0) {\n lines.push('')\n }\n const text = typeof example === 'string' ? example : JSON.stringify(example)\n lines.push(...`@example ${text}`.split('\\n'))\n }\n if (lines.length === 0) {\n return undefined\n }\n if (lines.length === 1) {\n return `${indent}/** ${lines[0]!.replace(/\\*\\//g, '* /')} */`\n }\n return [\n `${indent}/**`,\n ...lines.map((line) => `${indent} * ${line.replace(/\\*\\//g, '* /')}`.trimEnd()),\n `${indent} */`,\n ].join('\\n')\n}\n\n/** A bare object key when the code is a valid identifier, else a quoted one. */\nfunction codeKey(code: string): string {\n return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(code) ? code : JSON.stringify(code)\n}\n\n/**\n * Emit `ErrorCodes`, a const object keyed by every documented code with its TSDoc on the key\n * (editors show TSDoc on an object key, not on a string-literal union member), the `ErrorCode`\n * union derived from it, and `ErrorCodeByStatus`, the codes each status's error document offers.\n * A document with no code catalogue gets an empty `ErrorCodes` and `ErrorCode = string`, so the\n * bound guard still takes any code.\n */\nexport function emitErrorCodes(catalogue: ErrorCatalogue): string {\n const codeTypes =\n catalogue.codes.length === 0\n ? [\n '/** The documented error codes. This document catalogues none. */',\n 'export const ErrorCodes = {} as const',\n '',\n '/** The documented error codes. This document catalogues none, so any code is accepted. */',\n 'export type ErrorCode = string',\n ].join('\\n')\n : [\n '/**',\n ' * Every error code this server documents, keyed by itself. Hover a key for what the code',\n ' * means: `hasErrorCode(error, ErrorCodes.RESOURCE_NOT_FOUND)`.',\n ' */',\n 'export const ErrorCodes = {',\n ...catalogue.codes.flatMap((entry) => {\n const doc = codeDoc(entry, ' ')\n const member = ` ${codeKey(entry.code)}: ${JSON.stringify(entry.code)},`\n return doc === undefined ? [member] : [doc, member]\n }),\n '} as const',\n '',\n '/**',\n ' * Every error code this server documents. An error may still carry a code that is not',\n ' * listed: the catalogue is open.',\n ' */',\n 'export type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes]',\n ].join('\\n')\n\n const statusLines = [...catalogue.byStatus].map(([status, codes]) => {\n const members = codes.map((c) => JSON.stringify(c))\n const line = ` ${status}: ${members.length === 0 ? 'never' : members.join(' | ')}`\n return line.length <= 100\n ? line\n : ` ${status}:\\n${members.map((m) => ` | ${m}`).join('\\n')}`\n })\n const byStatus = [\n '/**',\n ' * The documented error codes per HTTP status. `never` marks a status whose error document',\n ' * documents no specific code.',\n ' */',\n statusLines.length === 0\n ? 'export interface ErrorCodeByStatus {}'\n : `export interface ErrorCodeByStatus {\\n${statusLines.join('\\n')}\\n}`,\n ].join('\\n')\n\n const guard = [\n '/**',\n ' * True when `err` is a `JsonApiError` and any of its error objects carries `code`. Only takes a',\n ' * documented code; match an undocumented one with `hasErrorCode` from',\n \" * '@haddowg/json-api-client'.\",\n ' */',\n 'export const hasErrorCode = hasErrorCodeRuntime as ErrorCodeGuard<ErrorCode>',\n ].join('\\n')\n\n return [codeTypes, byStatus, guard].join('\\n\\n')\n}\n","import { createHash } from 'node:crypto'\nimport type { OpenApiDocument } from './openapi'\n\n/**\n * A deterministic provenance record identifying the spec a client was generated from.\n * Stamped into every generated artifact's header so a reader (and the `--check` drift\n * gate) can tell which spec produced the committed output. Deliberately timestamp-free\n * — the same spec must always produce byte-identical output so `--check` can compare.\n */\nexport interface Provenance {\n /** `<title> <version>` from the document's `info` (falls back to `unknown` parts). */\n readonly source: string\n /** The first declared server URL, or `undefined` when none is declared. */\n readonly server: string | undefined\n /** A SHA-256 (first 16 hex chars) of the canonicalised source document. */\n readonly hash: string\n}\n\n/**\n * Canonicalise a JSON value with object keys sorted recursively, so the content hash is\n * insensitive to key ordering in the served document (two byte-different-but-equivalent\n * specs hash the same). Arrays keep their order (it is significant in OpenAPI).\n */\nfunction canonicalise(value: unknown): unknown {\n if (Array.isArray(value)) {\n return value.map(canonicalise)\n }\n if (value !== null && typeof value === 'object') {\n const out: Record<string, unknown> = {}\n // oxlint-disable-next-line no-array-sort -- sorting a freshly-created key array\n for (const key of Object.keys(value).sort()) {\n out[key] = canonicalise((value as Record<string, unknown>)[key])\n }\n return out\n }\n return value\n}\n\n/** A SHA-256 over an arbitrary JSON value (canonicalised), truncated to 16 hex chars (64 bits). */\nexport function hashJson(value: unknown): string {\n return createHash('sha256')\n .update(JSON.stringify(canonicalise(value)))\n .digest('hex')\n .slice(0, 16)\n}\n\n/**\n * Derive the provenance record for a source OpenAPI document. The `source` identifier is\n * `<info.title> <info.version>` (each part `unknown` when absent); the `hash` is a stable\n * content hash of the whole document.\n */\nexport function deriveProvenance(doc: OpenApiDocument): Provenance {\n const title = doc.info?.title ?? 'unknown'\n const version = doc.info?.version ?? 'unknown'\n return {\n source: `${title} ${version}`,\n server: doc.servers?.[0]?.url,\n hash: hashJson(doc),\n }\n}\n\n/**\n * Render the provenance record as the JSDoc header lines stamped into a generated artifact\n * (each already prefixed with ` * `). Deterministic: no timestamp, so re-generating from the\n * same spec yields byte-identical output.\n */\nexport function provenanceLines(provenance: Provenance): string[] {\n const lines = [` * Source spec: ${provenance.source}`, ` * Spec hash: ${provenance.hash}`]\n if (provenance.server !== undefined) {\n lines.splice(1, 0, ` * Server: ${provenance.server}`)\n }\n return lines\n}\n","import {\n type ActionDescriptor,\n type ApiDescriptor,\n type AtomicDescriptor,\n HANDLE_RESERVED,\n type ResourceDescriptor,\n} from '@haddowg/json-api-client'\nimport { buildAtomic } from './build-descriptor'\nimport { emitErrorCodes, readErrorCatalogue } from './error-codes'\nimport type { OpenApiDocument, SchemaObject, SchemaOrBool } from './openapi'\nimport { deriveProvenance, provenanceLines, type Provenance } from './provenance'\n\nconst REF_PREFIX = '#/components/schemas/'\nconst JSON_API_MEDIA_TYPE = 'application/vnd.api+json'\n\n/** A loose JSON:API document shape — the fallback an action body/result types as when its component can't be resolved. */\nconst LOOSE_DOCUMENT = 'Record<string, unknown>'\n\n/** A relation name that will later collide with a fluent-surface verb. */\nexport interface VerbCollision {\n type: string\n relation: string\n}\n\n/**\n * The reserved relation names: the members the read handle actually shadows (kept in sync\n * via the runtime's {@link HANDLE_RESERVED}) plus the future Phase-3 write verbs. A relation\n * named like any of these must route through `.rel(name)`, so the codegen warns at build time.\n * (`type`/`id` from {@link HANDLE_RESERVED} can never be JSON:API relation names.)\n */\nconst RESERVED_VERBS = new Set<string>([\n ...HANDLE_RESERVED,\n 'update',\n 'delete',\n 'create',\n 'list',\n 'actions',\n])\n\n/**\n * Find relations whose name shadows a reserved fluent-surface member (a handle accessor or a\n * future write verb). Such relations are routed via `.rel(name)`; the codegen warns at build time.\n */\nexport function detectVerbCollisions(descriptor: ApiDescriptor): VerbCollision[] {\n const collisions: VerbCollision[] = []\n for (const type of Object.keys(descriptor)) {\n for (const relation of Object.keys(descriptor[type]!.relations)) {\n if (RESERVED_VERBS.has(relation)) {\n collisions.push({ type, relation })\n }\n }\n }\n return collisions\n}\n\nfunction refName(ref: string): string | undefined {\n return ref.startsWith(REF_PREFIX) ? ref.slice(REF_PREFIX.length) : undefined\n}\n\nfunction isSchema(value: SchemaOrBool | undefined): value is SchemaObject {\n return typeof value === 'object' && value !== null\n}\n\n/** PascalCase a JSON:API wire type for use in a TS identifier (e.g. `public-profiles` -> `PublicProfiles`). */\nfunction pascalCase(value: string): string {\n return value\n .split(/[^a-zA-Z0-9]+/)\n .filter((part) => part.length > 0)\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join('')\n}\n\n/** Emit a JSON-string literal (used for keys that aren't bare identifiers and enum members). */\nfunction quote(value: string): string {\n return JSON.stringify(value)\n}\n\n/** True when a string is a safe bare object-key identifier. */\nfunction isIdentifier(value: string): boolean {\n return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(value)\n}\n\nfunction objectKey(value: string): string {\n return isIdentifier(value) ? value : quote(value)\n}\n\n/**\n * Render a description as a JSDoc comment at the given indent — single-line when it fits,\n * a block otherwise. Returns `undefined` for empty text. Neutralises any `*\\/` so a\n * description can never terminate the comment early.\n */\nfunction jsDoc(text: string | undefined, indent: string): string | undefined {\n const trimmed = text?.trim()\n if (!trimmed) {\n return undefined\n }\n const lines = trimmed.replace(/\\*\\//g, '* /').split('\\n')\n if (lines.length === 1) {\n return `${indent}/** ${lines[0]} */`\n }\n return [\n `${indent}/**`,\n ...lines.map((line) => `${indent} * ${line}`.trimEnd()),\n `${indent} */`,\n ].join('\\n')\n}\n\n/** The validation keywords a member's TSDoc states, each as a tag of the same name. */\nconst CONSTRAINT_KEYWORDS = [\n 'format',\n 'pattern',\n 'minLength',\n 'maxLength',\n 'minimum',\n 'exclusiveMinimum',\n 'maximum',\n 'exclusiveMaximum',\n 'multipleOf',\n 'minItems',\n 'maxItems',\n 'uniqueItems',\n 'minProperties',\n 'maxProperties',\n] as const\n\n/** A tag value as TSDoc text: strings bare, a pattern or anything structured as code. */\nfunction tagValue(keyword: string, value: unknown): string {\n if (keyword === 'pattern' || (typeof value !== 'string' && typeof value !== 'number')) {\n return `\\`${typeof value === 'string' ? value : JSON.stringify(value)}\\``\n }\n return String(value)\n}\n\n/**\n * The TSDoc for an attribute: its description, then a tag per constraint the schema declares\n * (`@minLength 1`, `@pattern …`), its `@defaultValue`, any `@example` and `@deprecated`. Each\n * schema states the constraints of the context it describes, so a read member and its create\n * and update counterparts can document different bounds. The keywords are read off the member\n * and any inline `anyOf`/`oneOf` branch; a `$ref`'d component documents itself.\n */\nfunction memberDoc(schema: SchemaObject): string | undefined {\n const layers = [\n schema,\n ...[...(schema.anyOf ?? []), ...(schema.oneOf ?? [])].filter(\n (branch) => branch.$ref === undefined,\n ),\n ]\n const tags: string[] = []\n for (const keyword of CONSTRAINT_KEYWORDS) {\n for (const layer of layers) {\n const value = layer[keyword]\n if (value === undefined || value === false) {\n continue\n }\n tags.push(value === true ? `@${keyword}` : `@${keyword} ${tagValue(keyword, value)}`)\n break\n }\n }\n if ('default' in schema) {\n tags.push(`@defaultValue \\`${JSON.stringify(schema['default'])}\\``)\n }\n const examples = Array.isArray(schema['examples']) ? [...(schema['examples'] as unknown[])] : []\n if ('example' in schema && !examples.includes(schema['example'])) {\n examples.unshift(schema['example'])\n }\n for (const example of examples) {\n tags.push(`@example ${typeof example === 'string' ? example : JSON.stringify(example)}`)\n }\n if (schema['deprecated'] === true) {\n tags.push('@deprecated')\n }\n const description = schema.description?.trim()\n if (tags.length === 0) {\n return description\n }\n return description ? `${description}\\n\\n${tags.join('\\n')}` : tags.join('\\n')\n}\n\nexport class Emitter {\n private readonly schemas: Record<string, SchemaObject>\n /** Wire type -> the schema `Base` (the `<Base>Resource` name minus `Resource`). */\n private readonly baseByType: Map<string, string>\n /** Enum component names referenced by an attribute, in first-seen order. */\n private readonly usedEnums = new Map<string, SchemaObject>()\n /**\n * Component-schema names whose dedicated interface is emitted (e.g. `AlbumsAttributes`,\n * `AlbumsCreateAttributes`). A `$ref` to one of these resolves to the interface name\n * rather than being re-expanded structurally — so an action envelope nests the precise,\n * already-named attribute type. Populated as interfaces are emitted.\n */\n private readonly emittedInterfaces = new Set<string>()\n /** Component names mid-expansion in {@link tsType} — a cycle guard for self/mutually-referential `$ref`s. */\n private readonly expanding = new Set<string>()\n /**\n * The per-action alias names actually emitted, keyed `type -> actionName -> { input?; output? }`.\n * Populated by {@link actionTypeAliases}; consumed by {@link actionTypesMap} so the action\n * type-map only references aliases that exist (a `none` input/output contributes neither).\n */\n private readonly actionAliasNames = new Map<\n string,\n Map<string, { input?: string; output?: string }>\n >()\n\n /** Provenance of the source document, stamped into the generated header for drift tracking. */\n private readonly provenance: Provenance\n\n constructor(\n private readonly doc: OpenApiDocument,\n private readonly descriptor: ApiDescriptor,\n private readonly atomic: AtomicDescriptor | null,\n ) {\n this.schemas = doc.components?.schemas ?? {}\n this.baseByType = this.indexBases()\n this.provenance = deriveProvenance(doc)\n }\n\n /** Map each declared wire type back to the `Base` of its resource schema. */\n private indexBases(): Map<string, string> {\n const out = new Map<string, string>()\n for (const [name, schema] of Object.entries(this.schemas)) {\n if (!name.endsWith('Resource') || name.endsWith('ResourceIdentifier')) {\n continue\n }\n const typeProp = schema.properties?.['type']\n if (isSchema(typeProp) && typeof typeProp.const === 'string') {\n out.set(typeProp.const, name.slice(0, -'Resource'.length))\n }\n }\n return out\n }\n\n emit(): string {\n // Resolve enums first so the alias block (which depends on `usedEnums`) is populated.\n const interfaces = Object.keys(this.descriptor).map((type) => this.attributeInterface(type))\n const writeInterfaces = Object.keys(this.descriptor).flatMap((type) =>\n this.writeAttributeInterfaces(type),\n )\n // Action input/output aliases reference component schemas; resolve them (this also\n // records any enums they reach) before the enum block is emitted.\n const actionAliases = this.actionTypeAliases()\n const enums = this.enumAliases()\n\n const parts = [\n this.header(),\n this.imports(),\n ...(enums ? [enums] : []),\n ...interfaces,\n ...writeInterfaces,\n ...actionAliases,\n this.attributesMap(),\n this.writeAttributesMap(),\n this.actionTypesMap(),\n this.resourceMap(),\n 'export type ResourceMap = typeof resourceMap',\n this.atomicConst(),\n this.pageLimitsConst(),\n emitErrorCodes(readErrorCatalogue(this.doc)),\n this.boundFactory(),\n ]\n return `${parts.join('\\n\\n')}\\n`\n }\n\n private header(): string {\n return [\n '/**',\n ' * AUTO-GENERATED by @haddowg/json-api-codegen — do not edit by hand.',\n ' * Regenerate from the source OpenAPI document instead.',\n ' *',\n ...provenanceLines(this.provenance),\n ' */',\n ].join('\\n')\n }\n\n private imports(): string {\n return [\n 'import {',\n ' type ApiDescriptor,',\n ' type ClientOptions,',\n ' createClient as createClientRuntime,',\n ' type ErrorCodeGuard,',\n ' hasErrorCode as hasErrorCodeRuntime,',\n \"} from '@haddowg/json-api-client'\",\n ].join('\\n')\n }\n\n /** Per-type attribute interface, e.g. `export interface AlbumsAttributes { ... }`. */\n private attributeInterface(type: string): string {\n const base = this.baseByType.get(type)\n const props = base ? this.schemas[`${base}Attributes`]?.properties : undefined\n // Drive field order off the (sorted) descriptor so output stays deterministic; read\n // attributes are always present (every member required, no optional marker).\n const fields = Object.keys(this.descriptor[type]!.attributes)\n return this.renderInterface(`${pascalCase(type)}Attributes`, props, fields, () => true)\n }\n\n /**\n * The per-type WRITE attribute interfaces — `<Pascal>CreateAttributes` and\n * `<Pascal>UpdateAttributes` — from the `<Base>CreateAttributes`/`<Base>UpdateAttributes`\n * components (readOnly fields are already excluded vs the read attributes by the bundle).\n * Create marks a field required iff it sits in the component's `required`; Update makes\n * every field optional. A read-only type (no create/update component) contributes nothing.\n */\n private writeAttributeInterfaces(type: string): string[] {\n const base = this.baseByType.get(type)\n if (base === undefined) {\n return []\n }\n const pascal = pascalCase(type)\n const out: string[] = []\n\n const create = this.schemas[`${base}CreateAttributes`]\n if (create !== undefined) {\n const required = new Set(create.required ?? [])\n // Sort the schema's own property keys (no descriptor to order write fields).\n // oxlint-disable-next-line no-array-sort -- sorting a freshly-created key array\n const fields = Object.keys(create.properties ?? {}).sort()\n out.push(\n this.renderInterface(`${pascal}CreateAttributes`, create.properties, fields, (field) =>\n required.has(field),\n ),\n )\n }\n\n const update = this.schemas[`${base}UpdateAttributes`]\n if (update !== undefined) {\n // oxlint-disable-next-line no-array-sort -- sorting a freshly-created key array\n const fields = Object.keys(update.properties ?? {}).sort()\n out.push(\n this.renderInterface(`${pascal}UpdateAttributes`, update.properties, fields, () => false),\n )\n }\n\n return out\n }\n\n /**\n * Per-action input/output type aliases for every type that declares custom actions. An\n * action whose `input`/`output` resolves to a component schema gets a named alias\n * (`<Pascal><Action>Input` / `<Pascal><Action>Output`) expanding that component via the\n * shared {@link tsType} machinery — a `none` input/output (no body / a `204`) contributes\n * no alias. Deterministic order: types, then action names (the descriptor is sorted).\n */\n private actionTypeAliases(): string[] {\n const out: string[] = []\n for (const type of Object.keys(this.descriptor)) {\n const actions = this.descriptor[type]?.actions\n if (actions === undefined) {\n continue\n }\n const pascal = pascalCase(type)\n for (const [actionName, action] of Object.entries(actions)) {\n const member = `${pascal}${pascalCase(actionName)}`\n const names: { input?: string; output?: string } = {}\n const inputType = this.actionBodyType(action, 'input')\n if (inputType !== undefined) {\n out.push(`export type ${member}Input = ${inputType}`)\n names.input = `${member}Input`\n }\n const outputType = this.actionBodyType(action, 'output')\n if (outputType !== undefined) {\n out.push(`export type ${member}Output = ${outputType}`)\n names.output = `${member}Output`\n }\n if (names.input !== undefined || names.output !== undefined) {\n let byAction = this.actionAliasNames.get(type)\n if (byAction === undefined) {\n byAction = new Map()\n this.actionAliasNames.set(type, byAction)\n }\n byAction.set(actionName, names)\n }\n }\n }\n return out\n }\n\n /**\n * Emit the `ActionTypes` interface wiring the emitted per-action aliases onto the typed\n * action surface — `type -> actionName -> { input?; output? }`, the client's fourth type\n * argument. So `client.albums.id(id).actions.reissue(body)` takes `AlbumsReissueInput` and\n * resolves `AlbumsReissueOutput` rather than a loose `Record<string,unknown>` / `unknown`.\n * Only actions whose alias was emitted appear (a `none`-input/output action contributes the\n * absent side, which the runtime types fall back to loosely). Emits `{}` when none exist.\n */\n private actionTypesMap(): string {\n const typeLines: string[] = []\n for (const type of Object.keys(this.descriptor)) {\n const byAction = this.actionAliasNames.get(type)\n if (byAction === undefined || byAction.size === 0) {\n continue\n }\n const actionLines: string[] = []\n for (const [actionName, names] of byAction) {\n const members: string[] = []\n if (names.input !== undefined) {\n members.push(`input: ${names.input}`)\n }\n if (names.output !== undefined) {\n members.push(`output: ${names.output}`)\n }\n actionLines.push(` ${objectKey(actionName)}: { ${members.join('; ')} }`)\n }\n typeLines.push(` ${objectKey(type)}: {\\n${actionLines.join('\\n')}\\n }`)\n }\n if (typeLines.length === 0) {\n return 'export interface ActionTypes {}'\n }\n return `export interface ActionTypes {\\n${typeLines.join('\\n')}\\n}`\n }\n\n /**\n * The TS type alias (if any) for an action's request body.\n *\n * An action's RESULT and its FLAT input are derived at the type level from the descriptor\n * (`outputType`/`outputCardinality` → the materialised resource view; `inputType` → the\n * `CreateInput` of that type), so no `output` alias is emitted and a `document` input whose\n * resource type resolves emits no `input` alias either. Only a bespoke command document (a\n * `document` input with no resolvable `inputType`) keeps a raw-envelope alias as its typed body,\n * expanded via {@link tsType} (falling back to a loose JSON:API document shape).\n */\n private actionBodyType(action: ActionDescriptor, side: 'input' | 'output'): string | undefined {\n if (side === 'output' || action.input !== 'document' || action.inputType !== undefined) {\n return undefined\n }\n const op = this.doc.paths?.[action.path]?.post\n const ref = op?.requestBody?.content?.[JSON_API_MEDIA_TYPE]?.schema?.$ref\n if (typeof ref !== 'string') {\n return LOOSE_DOCUMENT\n }\n const target = refName(ref)\n const resolved = target ? this.schemas[target] : undefined\n return resolved ? this.tsType(resolved) : LOOSE_DOCUMENT\n }\n\n /** Emit the server-level atomic capability constant (`{ path }` or `null`). */\n private atomicConst(): string {\n const doc = [\n '/**',\n ' * The server-level Atomic Operations endpoint (the atomic ext media type), or `null`',\n ' * when this server exposes none. The runtime `client.atomic` builder posts the batch here.',\n ' */',\n ].join('\\n')\n const value = this.atomic === null ? 'null' : `${this.literal(this.atomic, 0)} as const`\n return `${doc}\\nexport const atomic = ${value}`\n }\n\n /**\n * The `pageLimits` const: per collection, the `default`, `minimum` and `maximum` each `page`\n * member declares (generator contract 5 adds the paginator's default and page-size cap). A\n * menu nests them under each arm's `kind`. Members declaring none, and collections with no\n * such member, are left out. The client never clamps a `page` argument to these.\n */\n private pageLimitsConst(): string {\n const typeLines: string[] = []\n for (const type of Object.keys(this.descriptor)) {\n const path = this.descriptor[type]!.paths['fetchMany']\n const page = path === undefined ? undefined : this.doc.paths?.[path]?.get?.parameters\n const schema = page?.find((param) => param.name === 'page')?.schema\n if (schema === undefined) {\n continue\n }\n let body: string[] = []\n if (schema.oneOf !== undefined) {\n for (const arm of schema.oneOf) {\n const kind = isSchema(arm.properties?.['kind']) ? arm.properties['kind'].const : undefined\n const members = this.pageMemberLimits(arm, ' ')\n if (typeof kind === 'string' && members.length > 0) {\n body.push(` ${objectKey(kind)}: {\\n${members.join('\\n')}\\n },`)\n }\n }\n } else {\n body = this.pageMemberLimits(schema, ' ')\n }\n if (body.length > 0) {\n typeLines.push(` ${objectKey(type)}: {\\n${body.join('\\n')}\\n },`)\n }\n }\n const doc = [\n '/**',\n \" * The bounds each collection's `page` parameter declares, keyed by type, then by strategy for a\",\n ' * collection offering several, then by wire key. `default` is what the server uses when the key',\n ' * is absent and `maximum` is the largest value it serves. The client sends the `page` you pass',\n ' * unchanged, so read these to bound a page-size picker.',\n ' */',\n ].join('\\n')\n const body = typeLines.length === 0 ? '{}' : `{\\n${typeLines.join('\\n')}\\n}`\n return `${doc}\\nexport const pageLimits = ${body} as const`\n }\n\n /** One page schema's members that declare a `default`, `minimum` or `maximum`, as literal lines. */\n private pageMemberLimits(schema: SchemaObject, indent: string): string[] {\n const lines: string[] = []\n for (const [name, prop] of Object.entries(schema.properties ?? {})) {\n if (!isSchema(prop) || name === 'kind') {\n continue\n }\n const limits: string[] = []\n for (const keyword of ['default', 'minimum', 'maximum'] as const) {\n if (typeof prop[keyword] === 'number') {\n limits.push(`${keyword}: ${String(prop[keyword])}`)\n }\n }\n if (limits.length === 0) {\n continue\n }\n const doc = jsDoc(memberDoc(prop), indent)\n if (doc !== undefined) {\n lines.push(doc)\n }\n lines.push(`${indent}${objectKey(name)}: { ${limits.join(', ')} },`)\n }\n return lines\n }\n\n /**\n * Render an attribute interface from a property map, a field order, and a `required`\n * predicate (true => no `?`). Shared by the read and write attribute interfaces so the\n * tsType/JSDoc logic stays in one place.\n */\n private renderInterface(\n name: string,\n props: Record<string, SchemaOrBool> | undefined,\n fields: readonly string[],\n required: (field: string) => boolean,\n ): string {\n const lines: string[] = []\n for (const field of fields) {\n const schema = props?.[field]\n const tsType = isSchema(schema) ? this.tsType(schema) : 'unknown'\n const doc = isSchema(schema) ? jsDoc(memberDoc(schema), ' ') : undefined\n if (doc) {\n lines.push(doc)\n }\n const optional = required(field) ? '' : '?'\n lines.push(` ${objectKey(field)}${optional}: ${tsType}`)\n }\n\n this.emittedInterfaces.add(name)\n if (lines.length === 0) {\n return `export interface ${name} {}`\n }\n return `export interface ${name} {\\n${lines.join('\\n')}\\n}`\n }\n\n /** Map a JSON Schema attribute node to a precise TypeScript type. */\n private tsType(schema: SchemaObject): string {\n // A reference: an enum -> its emitted union alias; an emitted attribute interface ->\n // its interface name (so an action envelope nests precise attribute types); else\n // structural expansion of the referenced component, falling back to unknown. A\n // `expanding` guard breaks any cyclic/self-referential component chain.\n if (typeof schema.$ref === 'string') {\n const target = refName(schema.$ref)\n const resolved = target ? this.schemas[target] : undefined\n if (target && resolved && Array.isArray(resolved.enum)) {\n this.usedEnums.set(target, resolved)\n return target\n }\n if (target && this.emittedInterfaces.has(target)) {\n return target\n }\n if (resolved === undefined || target === undefined || this.expanding.has(target)) {\n return 'unknown'\n }\n this.expanding.add(target)\n const expanded = this.tsType(resolved)\n this.expanding.delete(target)\n return expanded\n }\n\n // A union of branches, as `anyOf: [{ $ref: Enum }, { type: 'null' }]` for a nullable enum.\n const branches = schema.anyOf ?? schema.oneOf\n if (schema.type === undefined && branches !== undefined && branches.length > 0) {\n const members = branches.map((branch) => this.tsType(branch))\n const nullable = members.includes('null')\n const rest = [...new Set(members.filter((member) => member !== 'null'))]\n if (rest.length === 0) {\n return 'null'\n }\n return nullable ? `${rest.join(' | ')} | null` : rest.join(' | ')\n }\n\n const types = Array.isArray(schema.type) ? schema.type : schema.type ? [schema.type] : []\n if (types.length === 1 && types[0] === 'null') {\n return 'null'\n }\n const nullable = types.includes('null')\n const base = this.baseTsType(\n schema,\n types.filter((t) => t !== 'null'),\n )\n return nullable ? `${base} | null` : base\n }\n\n /** The non-nullable TS type for the declared JSON type(s). */\n private baseTsType(schema: SchemaObject, types: readonly string[]): string {\n // An inline enum (string literals without a $ref).\n if (Array.isArray(schema.enum) && schema.enum.length > 0) {\n return schema.enum.map((value) => quote(String(value))).join(' | ')\n }\n if (types.length === 0) {\n return 'unknown'\n }\n const mapped = types.map((t) => this.scalarOrComposite(schema, t))\n // De-dupe while preserving order.\n return [...new Set(mapped)].join(' | ')\n }\n\n private scalarOrComposite(schema: SchemaObject, type: string): string {\n switch (type) {\n case 'string': {\n return 'string'\n }\n case 'number':\n case 'integer': {\n return 'number'\n }\n case 'boolean': {\n return 'boolean'\n }\n case 'object': {\n return this.objectType(schema)\n }\n case 'array': {\n return this.arrayType(schema)\n }\n default: {\n return 'unknown'\n }\n }\n }\n\n /** A nested object type from its `properties` (falls back to an index signature). */\n private objectType(schema: SchemaObject): string {\n const props = schema.properties\n if (props === undefined) {\n return 'Record<string, unknown>'\n }\n const required = new Set(schema.required ?? [])\n const members: string[] = []\n for (const [name, prop] of Object.entries(props)) {\n if (!isSchema(prop)) {\n continue\n }\n const optional = required.has(name) ? '' : '?'\n members.push(`${objectKey(name)}${optional}: ${this.tsType(prop)}`)\n }\n if (members.length === 0) {\n return 'Record<string, unknown>'\n }\n return `{ ${members.join('; ')} }`\n }\n\n private arrayType(schema: SchemaObject): string {\n const items = schema.items\n const element = isSchema(items) ? this.tsType(items) : 'unknown'\n // Wrap unions so `(A | B)[]` reads correctly.\n const list = /[|&]/.test(element) ? `(${element})[]` : `${element}[]`\n // `minItems` of 1 or more: the server never sends, or accepts, an empty list.\n const minItems = schema['minItems']\n return typeof minItems === 'number' && minItems >= 1 ? `[${element}, ...${list}]` : list\n }\n\n /** Union aliases for every enum component an attribute referenced, sorted by name. */\n private enumAliases(): string | undefined {\n if (this.usedEnums.size === 0) {\n return undefined\n }\n // oxlint-disable-next-line no-array-sort -- sorting a freshly-created key array\n const names = [...this.usedEnums.keys()].sort()\n return names\n .map((name) => {\n const schema = this.usedEnums.get(name)!\n const values = schema.enum ?? []\n const union = values.map((value) => quote(String(value))).join(' | ')\n const alias = `export type ${name} = ${union}`\n const doc = jsDoc(this.enumDoc(schema), '')\n return doc ? `${doc}\\n${alias}` : alias\n })\n .join('\\n\\n')\n }\n\n /**\n * Documentation for an enum alias: a per-value list built from `x-enum-descriptions`\n * (the richest hover DX, since a union alias can't carry per-member JSDoc), falling\n * back to the component's own `description`.\n */\n private enumDoc(schema: SchemaObject): string | undefined {\n const values = schema.enum ?? []\n const descriptions = schema['x-enum-descriptions']\n if (Array.isArray(descriptions) && descriptions.length === values.length && values.length > 0) {\n return values\n .map((value, i) => `- \\`${String(value)}\\` — ${String(descriptions[i])}`)\n .join('\\n')\n }\n return schema.description\n }\n\n /**\n * Emit the `Attributes` interface mapping each wire type to its per-type attribute\n * interface. The runtime descriptor only carries coarse format hints; this is how the\n * precise per-type attribute types reach the bound client (passed as the second type\n * argument to the runtime factory).\n */\n private attributesMap(): string {\n const lines = Object.keys(this.descriptor).map(\n (type) => ` ${objectKey(type)}: ${pascalCase(type)}Attributes`,\n )\n return `export interface Attributes {\\n${lines.join('\\n')}\\n}`\n }\n\n /**\n * Emit the `WriteAttributes` interface mapping each writable wire type to its\n * `{ create; update }` attribute pair. A read-only type (no create/update component)\n * contributes no entry, so the bound client only exposes writes where the API allows\n * them. Passed as the third type argument to the runtime factory.\n */\n private writeAttributesMap(): string {\n const lines: string[] = []\n for (const type of Object.keys(this.descriptor)) {\n const base = this.baseByType.get(type)\n const hasCreate = base !== undefined && this.schemas[`${base}CreateAttributes`] !== undefined\n const hasUpdate = base !== undefined && this.schemas[`${base}UpdateAttributes`] !== undefined\n if (!hasCreate && !hasUpdate) {\n continue\n }\n const pascal = pascalCase(type)\n const members: string[] = []\n if (hasCreate) {\n members.push(`create: ${pascal}CreateAttributes`)\n }\n if (hasUpdate) {\n members.push(`update: ${pascal}UpdateAttributes`)\n }\n lines.push(` ${objectKey(type)}: { ${members.join('; ')} }`)\n }\n if (lines.length === 0) {\n return 'export interface WriteAttributes {}'\n }\n return `export interface WriteAttributes {\\n${lines.join('\\n')}\\n}`\n }\n\n /** Emit the descriptor as a literal `as const satisfies ApiDescriptor`. */\n private resourceMap(): string {\n const body = this.literal(this.descriptor as Record<string, unknown>, 0)\n return `export const resourceMap = ${body} as const satisfies ApiDescriptor`\n }\n\n /** Render a JSON-serialisable descriptor value as deterministic TS object-literal source. */\n private literal(value: unknown, depth: number): string {\n const indent = ' '.repeat(depth)\n const inner = ' '.repeat(depth + 1)\n\n if (Array.isArray(value)) {\n if (value.length === 0) {\n return '[]'\n }\n const items = value.map((item) => `${inner}${this.literal(item, depth + 1)}`)\n return `[\\n${items.join(',\\n')}\\n${indent}]`\n }\n\n if (value !== null && typeof value === 'object') {\n const entries = Object.entries(value as Record<string, unknown>)\n if (entries.length === 0) {\n return '{}'\n }\n const lines = entries.map(\n ([key, v]) => `${inner}${objectKey(key)}: ${this.literal(v, depth + 1)}`,\n )\n return `{\\n${lines.join(',\\n')}\\n${indent}}`\n }\n\n return JSON.stringify(value)\n }\n\n private boundFactory(): string {\n return [\n '/**',\n ' * Descriptor-bound client factory; wraps the generic runtime with this API’s `resourceMap`.',\n ' * The server-level `atomic` capability is threaded in by default so `client.atomic` is wired',\n ' * (a caller may still override it via `options.atomic`). The client type carries `ErrorCode`,',\n ' * so bindings that only see the client (the Angular refs) type its errors.',\n ' */',\n 'export const createClient = (options: ClientOptions) =>',\n ' createClientRuntime<typeof resourceMap, Attributes, WriteAttributes, ActionTypes, ErrorCode>(',\n ' resourceMap,',\n ' {',\n ' atomic,',\n ' ...options,',\n ' },',\n ' )',\n ].join('\\n')\n }\n}\n\n/**\n * Generate the full source of the client module for a document + its built descriptor.\n * The server-level atomic capability is derived from the document (override via `atomic`).\n */\nexport function emit(\n doc: OpenApiDocument,\n descriptor: ApiDescriptor,\n atomic: AtomicDescriptor | null = buildAtomic(doc),\n): string {\n return new Emitter(doc, descriptor, atomic).emit()\n}\n\n/** Re-export so callers can reference the resource descriptor shape if needed. */\nexport type { ResourceDescriptor }\n","import { hashJson } from './provenance'\nimport type { SchemaBundle } from './reader'\n\n/**\n * Emit the per-type JSON Schema map as a standalone generated artifact:\n *\n * ```ts\n * export const schemas = { <type>: { …json schema… }, … } as const\n * ```\n *\n * The values are the raw, self-contained resource-object JSON Schema documents the bundle\n * serves at `GET /schemas.json` — suitable to hand straight to a validation engine via the\n * opt-in `validate?` seam (ADR 0004). This is a separate file from the client so the main\n * descriptor/client output is unaffected when `--schemas` is absent.\n *\n * The schemas are emitted as JSON (deterministic, key order preserved) so the artifact is\n * stable to diff; `as const` keeps the literal shapes narrow.\n */\nexport function emitSchemas(bundle: SchemaBundle): string {\n return `${[header(bundle), body(bundle)].join('\\n\\n')}\\n`\n}\n\nfunction header(bundle: SchemaBundle): string {\n return [\n '/**',\n ' * AUTO-GENERATED by @haddowg/json-api-codegen — do not edit by hand.',\n ' * Per-type JSON Schemas for the opt-in validation seam; regenerate from the source bundle.',\n ' *',\n ` * Schema hash: ${hashJson(bundle)}`,\n ' */',\n ].join('\\n')\n}\n\nfunction body(bundle: SchemaBundle): string {\n // `JSON.stringify` with two-space indent gives deterministic, diff-friendly output while\n // preserving the bundle's key order. The raw schema objects are valid TS object literals.\n const json = JSON.stringify(bundle, null, 2)\n return `export const schemas = ${json} as const`\n}\n","import { readFile } from 'node:fs/promises'\nimport { parse as parseYaml } from 'yaml'\nimport type { OpenApiDocument } from './openapi'\nimport type { SchemaObject } from './openapi'\n\n/** A self-contained JSON Schema document, keyed by JSON:API type, as served at `GET /schemas.json`. */\nexport type SchemaBundle = Record<string, SchemaObject>\n\n/** True when the input looks like an http(s) URL rather than a local path. */\nfunction isHttpUrl(input: string): boolean {\n return /^https?:\\/\\//i.test(input)\n}\n\n/** Decide YAML vs JSON by extension first, then by a cheap content sniff. */\nfunction looksLikeYaml(source: string, text: string): boolean {\n if (/\\.ya?ml$/i.test(source)) {\n return true\n }\n if (/\\.json$/i.test(source)) {\n return false\n }\n // No decisive extension: JSON documents start with `{`/`[` once trimmed.\n return !/^\\s*[{[]/.test(text)\n}\n\nfunction parse<T>(source: string, text: string, label: string): T {\n const doc = looksLikeYaml(source, text) ? parseYaml(text) : JSON.parse(text)\n if (doc === null || typeof doc !== 'object') {\n throw new Error(`${label} at ${source} did not parse to an object`)\n }\n return doc as T\n}\n\n/**\n * Fetch (URL) or read (file) `input`, then parse it as JSON or YAML (decided by extension,\n * falling back to a content sniff). Shared by the OpenAPI and JSON Schema readers.\n */\nasync function readSource<T>(input: string, label: string): Promise<T> {\n if (isHttpUrl(input)) {\n const res = await fetch(input)\n if (!res.ok) {\n throw new Error(`Failed to fetch ${label} from ${input}: ${res.status}`)\n }\n return parse<T>(input, await res.text(), label)\n }\n\n return parse<T>(input, await readFile(input, 'utf8'), label)\n}\n\n/**\n * Read an OpenAPI document from an http(s) URL or a local file path. Supports both JSON\n * and YAML (decided by extension, falling back to a content sniff).\n */\nexport async function readDocument(input: string): Promise<OpenApiDocument> {\n return readSource<OpenApiDocument>(input, 'OpenAPI document')\n}\n\n/**\n * Read the bundle's JSON Schema bundle (`GET /schemas.json`) from an http(s) URL or a\n * local file path — a map keyed by JSON:API type, each value a self-contained JSON Schema\n * 2020-12 resource-object document. Supports both JSON and YAML, like {@link readDocument}.\n */\nexport async function readSchemas(input: string): Promise<SchemaBundle> {\n return readSource<SchemaBundle>(input, 'JSON Schema bundle')\n}\n","/**\n * @haddowg/json-api-codegen — reads the bundle's OpenAPI 3.1 document (from a URL or\n * a local file) and emits the runtime descriptor + derived types + a bound\n * `createClient` (ADR 0001). Optionally reads the bundle's JSON Schemas to wire the\n * opt-in validation seam.\n *\n * The spec is fully self-describing for our needs (see CONTEXT.md): type identity is\n * `properties.type.const`; relationships, cardinality and related types come from the\n * relationship components' `data`; allowed `?include` paths are a bounded, pre-expanded\n * enum per endpoint; the create client-id policy is encoded in the create request\n * schema (`id: false` / required / optional).\n */\n\nimport { mkdir, readFile, writeFile } from 'node:fs/promises'\nimport { dirname } from 'node:path'\nimport { buildDescriptor } from './build-descriptor'\nimport { checkContract } from './contract'\nimport { detectVerbCollisions, emit } from './emit'\nimport { emitSchemas } from './emit-schemas'\nimport { readDocument, readSchemas } from './reader'\n\nexport { buildAtomic, buildDescriptor, DescriptorBuilder } from './build-descriptor'\nexport { checkContract, MAXIMUM_CONTRACT, MINIMUM_CONTRACT } from './contract'\nexport { detectVerbCollisions, emit, Emitter } from './emit'\nexport { emitErrorCodes, readErrorCatalogue } from './error-codes'\nexport type { DocumentedErrorCode, ErrorCatalogue } from './error-codes'\nexport type { VerbCollision } from './emit'\nexport { emitSchemas } from './emit-schemas'\nexport type * from './openapi'\nexport { deriveProvenance, hashJson, provenanceLines } from './provenance'\nexport type { Provenance } from './provenance'\nexport { readDocument, readSchemas } from './reader'\nexport type { SchemaBundle } from './reader'\n\nexport interface CodegenConfig {\n /** OpenAPI document source: an http(s) URL or a local file path. */\n input: string\n /** Output file (or directory) for the generated client. */\n output: string\n /** Server name to target (the spec is per-server). Defaults to the default server. */\n server?: string\n /** JSON Schema source for the validation seam (URL or path). Off when omitted. */\n schemas?: string\n /**\n * Drift-check mode: regenerate in-memory and compare against the committed `output`\n * (and its schema artifact when `schemas` is set) instead of writing. Nothing is\n * written; {@link check} reports whether the committed artifacts are up to date.\n */\n check?: boolean\n}\n\n/** One artifact's drift status: the file it stands for, and whether it is up to date. */\nexport interface ArtifactDrift {\n /** The committed artifact path (the client output, or its schema sibling). */\n path: string\n /** True when the committed file matches the freshly generated content. */\n upToDate: boolean\n}\n\n/** The outcome of a {@link check} run: `ok` iff every checked artifact is up to date. */\nexport interface CheckResult {\n ok: boolean\n artifacts: ArtifactDrift[]\n}\n\n/**\n * The schema-artifact path beside a client output path: `client.gen.ts` -> `client.schemas.gen.ts`\n * (any `.gen.ts`/`.ts` suffix is preserved; a suffix-less path just gains `.schemas`).\n */\nexport function schemasOutputPath(output: string): string {\n if (output.endsWith('.gen.ts')) {\n return `${output.slice(0, -'.gen.ts'.length)}.schemas.gen.ts`\n }\n if (output.endsWith('.ts')) {\n return `${output.slice(0, -'.ts'.length)}.schemas.ts`\n }\n return `${output}.schemas`\n}\n\n/** One rendered artifact: its target path and the freshly generated content. */\ninterface RenderedArtifact {\n path: string\n content: string\n}\n\n/**\n * Read the source spec(s), build the descriptor and render every generated artifact in\n * memory (the client source first, then the schema artifact when `config.schemas` is set)\n * — the shared core of {@link generate} (which writes them) and {@link check} (which\n * compares them). Verb-collision warnings are emitted here so both paths surface them.\n */\nasync function render(config: CodegenConfig): Promise<RenderedArtifact[]> {\n const doc = await readDocument(config.input)\n const contractWarning = checkContract(doc)\n if (contractWarning !== undefined) {\n console.warn(`[json-api-codegen] ${contractWarning}`)\n }\n const descriptor = buildDescriptor(doc)\n\n for (const { type, relation } of detectVerbCollisions(descriptor)) {\n console.warn(\n `[json-api-codegen] \"${type}\" has a relation named \"${relation}\" which collides with a ` +\n 'reserved verb on the resource handle; it will be reachable via .rel(\"' +\n `${relation}\") in the fluent client.`,\n )\n }\n\n if (Object.keys(descriptor).length === 0) {\n console.warn(\n `[json-api-codegen] found no JSON:API resource types in ${config.input}; the generated client is empty.`,\n )\n }\n\n const artifacts: RenderedArtifact[] = [{ path: config.output, content: emit(doc, descriptor) }]\n\n if (config.schemas !== undefined) {\n const bundle = await readSchemas(config.schemas)\n artifacts.push({ path: schemasOutputPath(config.output), content: emitSchemas(bundle) })\n }\n\n return artifacts\n}\n\n/**\n * Read the OpenAPI document, build the runtime descriptor, emit the generated client\n * module and write it to `config.output` (creating parent directories as needed).\n *\n * When `config.schemas` is set, also read the bundle's JSON Schema bundle and write a\n * separate per-type schema artifact (`<output>.schemas.gen.ts`) beside the client, wiring\n * the opt-in validation seam (ADR 0004). The main client output is unchanged either way.\n *\n * `config.server` is metadata-only for now: the served document is already per-server,\n * so the caller selects the server by pointing `input` at the right document.\n *\n * Returns the generated client source. When `config.check` is set nothing is written;\n * call {@link check} instead for the drift-gate result.\n */\nexport async function generate(config: CodegenConfig): Promise<string> {\n const artifacts = await render(config)\n await mkdir(dirname(config.output), { recursive: true })\n for (const { path, content } of artifacts) {\n await writeFile(path, content, 'utf8')\n }\n // The first artifact is always the client source.\n return artifacts[0]!.content\n}\n\n/**\n * Drift gate: regenerate every artifact in memory and compare it byte-for-byte against the\n * committed file on disk, WITHOUT writing anything. A missing committed file counts as drift\n * (not up to date). Returns per-artifact status plus an aggregate `ok` (true iff all match) —\n * the CI drift check reads `ok` and exits non-zero when it is false.\n */\nexport async function check(config: CodegenConfig): Promise<CheckResult> {\n const artifacts = await render(config)\n const results: ArtifactDrift[] = []\n for (const { path, content } of artifacts) {\n let committed: string | undefined\n try {\n committed = await readFile(path, 'utf8')\n } catch {\n committed = undefined\n }\n results.push({ path, upToDate: committed === content })\n }\n return { ok: results.every((r) => r.upToDate), artifacts: results }\n}\n"],"mappings":"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"}