@haddowg/json-api-codegen 1.5.0 → 1.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.d.mts +1 -1
- package/dist/cli.mjs +1 -1
- package/dist/{index-B0BIVXUz.d.mts → index-CjNGhJJH.d.mts} +15 -7
- package/dist/index-CjNGhJJH.d.mts.map +1 -0
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{src-G1x-BbMp.mjs → src-CKsM7dXw.mjs} +254 -55
- package/dist/src-CKsM7dXw.mjs.map +1 -0
- package/package.json +2 -2
- package/dist/index-B0BIVXUz.d.mts.map +0 -1
- package/dist/src-G1x-BbMp.mjs.map +0 -1
package/dist/cli.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as CodegenConfig } from "./index-
|
|
1
|
+
import { r as CodegenConfig } from "./index-CjNGhJJH.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/cli.d.ts
|
|
4
4
|
declare const USAGE = "Usage: json-api-codegen --input <url|file> --output <file> [--server <name>] [--schemas <url|file>] [--check]";
|
package/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { n as generate, r as schemasOutputPath, t as check } from "./src-
|
|
2
|
+
import { n as generate, r as schemasOutputPath, t as check } from "./src-CKsM7dXw.mjs";
|
|
3
3
|
import { realpathSync } from "node:fs";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
//#region src/cli.ts
|
|
@@ -77,12 +77,11 @@ interface OpenApiDocument {
|
|
|
77
77
|
//#endregion
|
|
78
78
|
//#region src/build-descriptor.d.ts
|
|
79
79
|
declare class DescriptorBuilder {
|
|
80
|
-
private readonly doc;
|
|
81
80
|
private readonly schemas;
|
|
82
81
|
private readonly paths;
|
|
83
82
|
/** Lazily-built wire-type -> collection-level paginator kind (for per-relation divergence, D6a). */
|
|
84
83
|
private typePaginators?;
|
|
85
|
-
constructor(
|
|
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 =
|
|
263
|
+
declare const MAXIMUM_CONTRACT = 9;
|
|
265
264
|
/**
|
|
266
265
|
* Check the document's `info.x-generator.contract` against the range this codegen reads. A
|
|
267
266
|
* document older than the range throws; a newer one returns a warning, because its new
|
|
@@ -282,7 +281,6 @@ interface VerbCollision {
|
|
|
282
281
|
*/
|
|
283
282
|
declare function detectVerbCollisions(descriptor: ApiDescriptor): VerbCollision[];
|
|
284
283
|
declare class Emitter {
|
|
285
|
-
private readonly doc;
|
|
286
284
|
private readonly descriptor;
|
|
287
285
|
private readonly atomic;
|
|
288
286
|
private readonly schemas;
|
|
@@ -297,6 +295,10 @@ declare class Emitter {
|
|
|
297
295
|
* already-named attribute type. Populated as interfaces are emitted.
|
|
298
296
|
*/
|
|
299
297
|
private readonly emittedInterfaces;
|
|
298
|
+
/** Enum component name -> the alias name it's emitted under. */
|
|
299
|
+
private readonly enumNames;
|
|
300
|
+
/** Type names already spoken for: the module's own, the per-type interfaces and enum aliases. */
|
|
301
|
+
private readonly takenNames;
|
|
300
302
|
/** Component names mid-expansion in {@link tsType} — a cycle guard for self/mutually-referential `$ref`s. */
|
|
301
303
|
private readonly expanding;
|
|
302
304
|
/**
|
|
@@ -307,7 +309,13 @@ declare class Emitter {
|
|
|
307
309
|
private readonly actionAliasNames;
|
|
308
310
|
/** Provenance of the source document, stamped into the generated header for drift tracking. */
|
|
309
311
|
private readonly provenance;
|
|
310
|
-
|
|
312
|
+
private readonly doc;
|
|
313
|
+
constructor(source: OpenApiDocument, descriptor: ApiDescriptor, atomic: AtomicDescriptor | null);
|
|
314
|
+
/**
|
|
315
|
+
* The alias an enum component is emitted under: its own name when that's a usable type name,
|
|
316
|
+
* else one derived from it (with a warning), kept clear of every other name in the module.
|
|
317
|
+
*/
|
|
318
|
+
private enumName;
|
|
311
319
|
/** Map each declared wire type back to the `Base` of its resource schema. */
|
|
312
320
|
private indexBases;
|
|
313
321
|
emit(): string;
|
|
@@ -503,7 +511,7 @@ declare function hashJson(value: unknown): string;
|
|
|
503
511
|
declare function deriveProvenance(doc: OpenApiDocument): Provenance;
|
|
504
512
|
/**
|
|
505
513
|
* Render the provenance record as the JSDoc header lines stamped into a generated artifact
|
|
506
|
-
* (each already prefixed with ` * `). Deterministic: no timestamp, so re-generating from the
|
|
514
|
+
* (each already prefixed with ` * `), with the document's text kept to one comment line. Deterministic: no timestamp, so re-generating from the
|
|
507
515
|
* same spec yields byte-identical output.
|
|
508
516
|
*/
|
|
509
517
|
declare function provenanceLines(provenance: Provenance): string[];
|
|
@@ -566,4 +574,4 @@ declare function generate(config: CodegenConfig): Promise<string>;
|
|
|
566
574
|
declare function check(config: CodegenConfig): Promise<CheckResult>;
|
|
567
575
|
//#endregion
|
|
568
576
|
export { InfoObject as A, MAXIMUM_CONTRACT as C, buildAtomic as D, DescriptorBuilder as E, PathItemObject as F, RequestBodyObject as I, ResponseObject as L, OpenApiDocument as M, OperationObject as N, buildDescriptor as O, ParameterObject as P, SchemaObject as R, emit as S, checkContract as T, emitErrorCodes as _, generate as a, VerbCollision as b, deriveProvenance as c, emitSchemas as d, SchemaBundle as f, ErrorCatalogue as g, DocumentedErrorCode as h, check as i, MediaTypeObject as j, HttpMethod as k, hashJson as l, readSchemas as m, CheckResult as n, schemasOutputPath as o, readDocument as p, CodegenConfig as r, Provenance as s, ArtifactDrift as t, provenanceLines as u, readErrorCatalogue as v, MINIMUM_CONTRACT as w, detectVerbCollisions as x, Emitter as y, SchemaOrBool as z };
|
|
569
|
-
//# sourceMappingURL=index-
|
|
577
|
+
//# sourceMappingURL=index-CjNGhJJH.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-CjNGhJJH.d.mts","names":[],"sources":["../src/openapi.ts","../src/build-descriptor.ts","../src/contract.ts","../src/emit.ts","../src/error-codes.ts","../src/reader.ts","../src/emit-schemas.ts","../src/provenance.ts","../src/index.ts"],"mappings":";;;;;;AAQA;;;;UAAiB,YAAA;EACf,IAAA;EACA,IAAA;EACA,KAAA;EACA,MAAA;EACA,WAAA;EACA,IAAA;EACA,UAAA,GAAa,MAAA,SAAe,YAAA;EAC5B,KAAA,GAAQ,YAAA;EACR,QAAA;EACA,KAAA,YAAiB,YAAA;EACjB,KAAA,YAAiB,YAAA;EACjB,KAAA,YAAiB,YAAA;EACjB,iBAAA;EACA,qBAAA;EAAA,CACC,GAAA;AAAA;;KAIS,YAAA,GAAe,YAAY;AAAA,UAEtB,eAAA;EACf,MAAA,GAAS,YAAY;AAAA;AAAA,UAGN,iBAAA;EACf,OAAA,GAAU,MAAM,SAAS,eAAA;EACzB,QAAA;AAAA;AAAA,UAGe,cAAA;EACf,OAAA,GAAU,MAAM,SAAS,eAAA;AAAA;AAAA,UAGV,eAAA;EACf,IAAA;EACA,EAAA;EACA,IAAA;EACA,MAAA,GAAS,YAAY;EACrB,KAAA;EACA,OAAA;EAnB8B;EAqB9B,WAAA;AAAA;AAAA,UAGe,eAAA;EACf,WAAA;EACA,UAAA,YAAsB,eAAA;EACtB,WAAA,GAAc,iBAAA;EACd,SAAA,GAAY,MAAA,SAAe,cAAA;AAAA;AAAA,KAGjB,UAAA;AAAA,KAEA,cAAA,GAAiB,OAAA,CAAQ,MAAA,CAAO,UAAA,EAAY,eAAA;AAAA,UAEvC,UAAA;EACf,KAAA;EACA,OAAA;EA5Be;EA8Bf,aAAA;IAAkB,QAAA;EAAA;AAAA;AAAA,UAGH,eAAA;EACf,OAAA;EACA,IAAA,GAAO,UAAA;EACP,OAAA;IAAqB,GAAA;EAAA;EACrB,KAAA,GAAQ,MAAA,SAAe,cAAA;EACvB,UAAA;IACE,OAAA,GAAU,MAAA,SAAe,YAAA;EAAA;AAAA;;;cCFhB,iBAAA;EAAA,iBACM,OAAA;EAAA,iBACA,KAAA;;UAET,cAAA;cAEI,MAAA,EAAQ,eAAA;EDjEZ;;;;;EAAA,QC4EA,aAAA;EAaR,KAAA,IAAS,aAAA;ED/FT;;;;;ECwJA,WAAA,IAAe,gBAAA;EDnJF;;;;;EAAA,QCkKL,YAAA;ED/JS;EAAA,QC2KT,YAAA;EAAA,QASA,UAAA;EDlLR;;;;;;AAGY;EAHZ,QCwMQ,SAAA;EDjMc;;;AAAe;EAAf,QC+Pd,kBAAA;ED7PsB;;;AACT;AAGvB;;EAJgC,QCoRtB,iBAAA;ED/QQ;;;;;;AACR;EADQ,QC4TR,iBAAA;EDxTqB;;;;;;;AACW;AAG1C;;EAJ+B,QC2VrB,oBAAA;EDnVa;;;;;;;EAAA,QCiZb,OAAA;ED7YR;;AAAW;AAGb;;EAHE,QCudQ,eAAA;EDldc;EAAA,QCued,SAAA;EDremB;EAAA,QC8enB,iBAAA;ED9eU;EAAA,QC4fV,qBAAA;ED/fR;;;;;EAAA,QC8kBQ,UAAA;ED3kBI;;;AAA6B;AAG3C;;;EAHc,QC0lBJ,eAAA;EDvlBY;EAAA,QC8nBZ,cAAA;ED5nBgB;EAAA,QCyoBhB,cAAA;EAAA,QAaA,QAAA;EDtpB8C;;;;;EAAA,QCuqB9C,cAAA;EAAA,QAmCA,cAAA;ED1sBkC;EAAA,QCguBlC,cAAA;EAAA,QAWA,mBAAA;ED3uB6D;EAAA,QCmvB7D,SAAA;EDjvBiB;;;;;;;EAAA,QC6vBjB,WAAA;EDzvBkB;AAG5B;;;;;;EAH4B,QCuyBlB,WAAA;ED9xBI;;;;;;;;;;;;;EAAA,QCo0BJ,SAAA;EDp0BmB;;AAAY;;;;ACFzC;;;EDE6B,QCo1BnB,UAAA;EAxzBC;;;;;EAAA,QAq0BD,QAAA;EA/1BA;;;;;;EAAA,QA62BA,UAAA;EAAA,QAeA,SAAA;EAAA,QAIA,cAAA;EAAA,QAIA,aAAA;AAAA;;iBAiMM,eAAA,CAAgB,GAAA,EAAK,eAAA,GAAkB,aAAa;;iBAKpD,WAAA,CAAY,GAAA,EAAK,eAAA,GAAkB,gBAAgB;;;;cCtpCtD,gBAAA;AFKb;AAAA,cEFa,gBAAA;;;;;;;iBAQG,aAAA,CAAc,GAAoB,EAAf,eAAe;;;;UCOjC,aAAA;EACf,IAAA;EACA,QAAQ;AAAA;;;;;iBAsBM,oBAAA,CAAqB,UAAA,EAAY,aAAA,GAAgB,aAAa;AAAA,cA8IjE,OAAA;EAAA,iBAoCQ,UAAA;EAAA,iBACA,MAAA;EAAA,iBApCF,OAAA;EHjLjB;EAAA,iBGmLiB,UAAA;EHjLjB;EAAA,iBGmLiB,SAAA;EHjLjB;;;;;;EAAA,iBGwLiB,iBAAA;EHrLA;EAAA,iBGuLA,SAAA;EHtLA;EAAA,iBGwLA,UAAA;EHvLA;EAAA,iBGyLA,SAAA;EHvLjB;;;AACY;AAId;EALE,iBG6LiB,gBAAA;;mBAMA,UAAA;EAAA,iBAEA,GAAA;cAGf,MAAA,EAAQ,eAAA,EACS,UAAA,EAAY,aAAA,EACZ,MAAA,EAAQ,gBAAA;EHnMG;;;AACT;EADS,QG0NtB,QAAA;EHtNwB;EAAA,QGgPxB,UAAA;EAcR,IAAA;EAAA,QA+BQ,MAAA;EAAA,QAWA,OAAA;EHvSiB;EAAA,QGoTjB,kBAAA;EHnTA;AAAA;AAGV;;;;;EAHU,QGmUA,wBAAA;EH/TiB;;AAAe;AAG1C;;;;EAH2B,QGuWjB,iBAAA;EHlWR;;;;;;;;EAAA,QG4YQ,cAAA;EHnYO;;;;;;;;;;EAAA,QGuaP,cAAA;EHrac;EAAA,QGobd,WAAA;EHnbM;;;;;AAC2B;EAD3B,QGocN,eAAA;EHhcY;EAAA,QGseZ,gBAAA;EHteY;AAAA;AAEtB;;;EAFsB,QGmgBZ,eAAA;EHjgB8C;EAAA,QG2hB9C,MAAA;EH3hBmB;EAAA,QG4kBnB,UAAA;EAAA,QAaA,iBAAA;EHzlBmB;EAAA,QGknBnB,UAAA;EAAA,QAoBA,SAAA;EHtoB8C;EAAA,QGipB9C,WAAA;EHjpB6D;AAEvE;;;;EAFuE,QGwqB7D,OAAA;EHpqBR;;;;AAE0B;AAG5B;EALE,QGqrBQ,aAAA;;;;;;;UAaA,kBAAA;EHvrBU;EAAA,QGitBV,WAAA;EHrtBR;EAAA,QG2tBQ,OAAA;EAAA,QA0BA,YAAA;AAAA;;;;;iBAwBM,IAAA,CACd,GAAA,EAAK,eAAA,EACL,UAAA,EAAY,aAAA,EACZ,MAAA,GAAQ,gBAAA;;;;UCl1BO,mBAAA;EACf,IAAA;EJA2B;EIE3B,WAAA;EJK4B;EIH5B,QAAA;AAAA;;UAIe,cAAA;EJIE;EIFjB,KAAA,EAAO,mBAAA;EJEsB;;;;EIG7B,QAAA,EAAU,GAAG;AAAA;;;;;;;iBAuCC,kBAAA,CAAmB,GAAA,EAAK,eAAA,GAAkB,cAAc;;;;;;;;iBAiFxD,cAAA,CAAe,SAAyB,EAAd,cAAc;;;;KCzI5C,YAAA,GAAe,MAAM,SAAS,YAAA;;;;;iBA+CpB,YAAA,CAAa,KAAA,WAAgB,OAAO,CAAC,eAAA;;;;;;iBASrC,WAAA,CAAY,KAAA,WAAgB,OAAO,CAAC,YAAA;;;;;ALtD1D;;;;;;;;;;;;;iBMUgB,WAAA,CAAY,MAAoB,EAAZ,YAAY;;;;;ANVhD;;;;UOEiB,UAAA;EPMP;EAAA,SOJC,MAAA;EPOQ;EAAA,SOLR,MAAA;EPMoB;EAAA,SOJpB,IAAA;AAAA;;iBAwBK,QAAA,CAAS,KAAc;;;;;;iBAYvB,gBAAA,CAAiB,GAAA,EAAK,eAAA,GAAkB,UAAU;;;;;;iBAelD,eAAA,CAAgB,UAAsB,EAAV,UAAU;;;UCjCrC,aAAA;ERjBf;EQmBA,KAAA;ERlBiB;EQoBjB,MAAA;ERnBiB;EQqBjB,MAAA;ERpBiB;EQsBjB,OAAA;ERpBA;;;AACY;AAId;EQqBE,KAAA;AAAA;;UAIe,aAAA;ERvBA;EQyBf,IAAA;;EAEA,QAAQ;AAAA;ARvBV;AAAA,UQ2BiB,WAAA;EACf,EAAA;EACA,SAAA,EAAW,aAAa;AAAA;;;;;iBAOV,iBAAA,CAAkB,MAAc;AR/BhD;;;;;;;;AAC0C;AAG1C;;;;;AAJA,iBQmGsB,QAAA,CAAS,MAAA,EAAQ,aAAA,GAAgB,OAAO;;;;;;;iBAgBxC,KAAA,CAAM,MAAA,EAAQ,aAAA,GAAgB,OAAA,CAAQ,WAAA"}
|
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-
|
|
1
|
+
import { A as InfoObject, C as MAXIMUM_CONTRACT, D as buildAtomic, E as DescriptorBuilder, F as PathItemObject, I as RequestBodyObject, L as ResponseObject, M as OpenApiDocument, N as OperationObject, O as buildDescriptor, P as ParameterObject, R as SchemaObject, S as emit, T as checkContract, _ as emitErrorCodes, a as generate, b as VerbCollision, c as deriveProvenance, d as emitSchemas, f as SchemaBundle, g as ErrorCatalogue, h as DocumentedErrorCode, i as check, j as MediaTypeObject, k as HttpMethod, l as hashJson, m as readSchemas, n as CheckResult, o as schemasOutputPath, p as readDocument, r as CodegenConfig, s as Provenance, t as ArtifactDrift, u as provenanceLines, v as readErrorCatalogue, w as MINIMUM_CONTRACT, x as detectVerbCollisions, y as Emitter, z as SchemaOrBool } from "./index-CjNGhJJH.mjs";
|
|
2
2
|
export { ArtifactDrift, CheckResult, CodegenConfig, DescriptorBuilder, type DocumentedErrorCode, Emitter, type ErrorCatalogue, type HttpMethod, type InfoObject, MAXIMUM_CONTRACT, MINIMUM_CONTRACT, type MediaTypeObject, type OpenApiDocument, type OperationObject, type ParameterObject, type PathItemObject, type Provenance, type RequestBodyObject, type ResponseObject, type SchemaBundle, type SchemaObject, type SchemaOrBool, type VerbCollision, buildAtomic, buildDescriptor, check, checkContract, deriveProvenance, detectVerbCollisions, emit, emitErrorCodes, emitSchemas, generate, hashJson, provenanceLines, readDocument, readErrorCatalogue, readSchemas, schemasOutputPath };
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { _ as checkContract, a as readSchemas, b as buildDescriptor, c as detectVerbCollisions, d as hashJson, f as provenanceLines, g as MINIMUM_CONTRACT, h as MAXIMUM_CONTRACT, i as readDocument, l as emit, m as readErrorCatalogue, n as generate, o as emitSchemas, p as emitErrorCodes, r as schemasOutputPath, s as Emitter, t as check, u as deriveProvenance, v as DescriptorBuilder, y as buildAtomic } from "./src-
|
|
1
|
+
import { _ as checkContract, a as readSchemas, b as buildDescriptor, c as detectVerbCollisions, d as hashJson, f as provenanceLines, g as MINIMUM_CONTRACT, h as MAXIMUM_CONTRACT, i as readDocument, l as emit, m as readErrorCatalogue, n as generate, o as emitSchemas, p as emitErrorCodes, r as schemasOutputPath, s as Emitter, t as check, u as deriveProvenance, v as DescriptorBuilder, y as buildAtomic } from "./src-CKsM7dXw.mjs";
|
|
2
2
|
export { DescriptorBuilder, Emitter, MAXIMUM_CONTRACT, MINIMUM_CONTRACT, buildAtomic, buildDescriptor, check, checkContract, deriveProvenance, detectVerbCollisions, emit, emitErrorCodes, emitSchemas, generate, hashJson, provenanceLines, readDocument, readErrorCatalogue, readSchemas, schemasOutputPath };
|
|
@@ -3,6 +3,64 @@ import { dirname } from "node:path";
|
|
|
3
3
|
import { ATOMIC_EXT, CANONICAL_PAGE_KEYS, HANDLE_RESERVED } from "@haddowg/json-api-client";
|
|
4
4
|
import { createHash } from "node:crypto";
|
|
5
5
|
import { parse } from "yaml";
|
|
6
|
+
//#region src/unwrap-refs.ts
|
|
7
|
+
/**
|
|
8
|
+
* Keywords that annotate a schema without constraining it. A single-entry `allOf` wrapper is
|
|
9
|
+
* read as its `$ref` only when the wrapper carries nothing else, plus any `x-` extension.
|
|
10
|
+
*/
|
|
11
|
+
const ANNOTATIONS = /* @__PURE__ */ new Set([
|
|
12
|
+
"title",
|
|
13
|
+
"description",
|
|
14
|
+
"example",
|
|
15
|
+
"examples",
|
|
16
|
+
"default",
|
|
17
|
+
"deprecated",
|
|
18
|
+
"readOnly",
|
|
19
|
+
"writeOnly",
|
|
20
|
+
"$comment"
|
|
21
|
+
]);
|
|
22
|
+
const unwrapped = /* @__PURE__ */ new WeakMap();
|
|
23
|
+
/**
|
|
24
|
+
* The document with every `{ allOf: [{ $ref }], ...annotations }` node rewritten as
|
|
25
|
+
* `{ $ref, ...annotations }`. From generator contract 9 the projector wraps a `$ref` that
|
|
26
|
+
* carries an `example`, `examples` or `default` this way, because OAS 3.0 tooling ignores a
|
|
27
|
+
* `$ref`'s siblings. Reading the wrapper as its `$ref` keeps every lookup that follows a `$ref`
|
|
28
|
+
* working, and keeps the annotations for the TSDoc. The input is not modified.
|
|
29
|
+
*/
|
|
30
|
+
function unwrapRefs(doc) {
|
|
31
|
+
let out = unwrapped.get(doc);
|
|
32
|
+
if (out === void 0) {
|
|
33
|
+
out = unwrapNode(doc);
|
|
34
|
+
unwrapped.set(doc, out);
|
|
35
|
+
unwrapped.set(out, out);
|
|
36
|
+
}
|
|
37
|
+
return out;
|
|
38
|
+
}
|
|
39
|
+
function unwrapNode(node) {
|
|
40
|
+
if (Array.isArray(node)) return node.map(unwrapNode);
|
|
41
|
+
if (typeof node !== "object" || node === null) return node;
|
|
42
|
+
const out = {};
|
|
43
|
+
for (const [key, value] of Object.entries(node)) out[key] = unwrapNode(value);
|
|
44
|
+
const ref = wrappedRef(out);
|
|
45
|
+
if (ref === void 0) return out;
|
|
46
|
+
const { allOf: _allOf, ...annotations } = out;
|
|
47
|
+
return {
|
|
48
|
+
$ref: ref,
|
|
49
|
+
...annotations
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/** The `$ref` a node wraps in a single-entry `allOf`, when that is all the node constrains. */
|
|
53
|
+
function wrappedRef(node) {
|
|
54
|
+
const allOf = node["allOf"];
|
|
55
|
+
if (!Array.isArray(allOf) || allOf.length !== 1 || "$ref" in node) return;
|
|
56
|
+
const entry = allOf[0];
|
|
57
|
+
if (typeof entry !== "object" || entry === null) return;
|
|
58
|
+
const keys = Object.keys(entry);
|
|
59
|
+
const ref = entry["$ref"];
|
|
60
|
+
if (keys.length !== 1 || typeof ref !== "string") return;
|
|
61
|
+
return Object.keys(node).every((key) => key === "allOf" || ANNOTATIONS.has(key) || key.startsWith("x-")) ? ref : void 0;
|
|
62
|
+
}
|
|
63
|
+
//#endregion
|
|
6
64
|
//#region src/build-descriptor.ts
|
|
7
65
|
const REF_PREFIX$2 = "#/components/schemas/";
|
|
8
66
|
const JSON_API_MEDIA_TYPE$1 = "application/vnd.api+json";
|
|
@@ -33,13 +91,12 @@ function typeKeys(type) {
|
|
|
33
91
|
return (Array.isArray(type) ? type : [type]).filter((t) => t !== "null");
|
|
34
92
|
}
|
|
35
93
|
var DescriptorBuilder = class {
|
|
36
|
-
doc;
|
|
37
94
|
schemas;
|
|
38
95
|
paths;
|
|
39
96
|
/** Lazily-built wire-type -> collection-level paginator kind (for per-relation divergence, D6a). */
|
|
40
97
|
typePaginators;
|
|
41
|
-
constructor(
|
|
42
|
-
|
|
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 =
|
|
908
|
+
const MAXIMUM_CONTRACT = 9;
|
|
852
909
|
/**
|
|
853
910
|
* Check the document's `info.x-generator.contract` against the range this codegen reads. A
|
|
854
911
|
* document older than the range throws; a newer one returns a warning, because its new
|
|
@@ -858,8 +915,108 @@ const MAXIMUM_CONTRACT = 8;
|
|
|
858
915
|
function checkContract(doc) {
|
|
859
916
|
const contract = doc.info?.["x-generator"]?.contract;
|
|
860
917
|
if (typeof contract !== "number") return;
|
|
861
|
-
if (contract < 1) throw new Error(`the document declares contract ${contract}, which predates what this codegen reads (it supports 1 to
|
|
862
|
-
if (contract >
|
|
918
|
+
if (contract < 1) throw new Error(`the document declares contract ${contract}, which predates what this codegen reads (it supports 1 to 9). Use an older codegen release, or regenerate the document from a newer server.`);
|
|
919
|
+
if (contract > 9) return `the document declares contract ${contract} and this codegen reads up to 9. It describes capabilities that were not generated; upgrade the codegen to pick them up.`;
|
|
920
|
+
}
|
|
921
|
+
//#endregion
|
|
922
|
+
//#region src/source.ts
|
|
923
|
+
/**
|
|
924
|
+
* Helpers for writing strings read from the OpenAPI document into generated TypeScript. Every
|
|
925
|
+
* name, literal and comment the emitters take from the document goes through one of these.
|
|
926
|
+
*/
|
|
927
|
+
const IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
928
|
+
/** Line terminators as JavaScript counts them. */
|
|
929
|
+
const LINE_BREAK = /\r\n|[\n\r\u2028\u2029]/;
|
|
930
|
+
/** A string as a TS string literal. U+2028/U+2029 are escaped too, which JSON leaves raw. */
|
|
931
|
+
function stringLiteral(value) {
|
|
932
|
+
return JSON.stringify(value).replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
933
|
+
}
|
|
934
|
+
/** True when a string is a bare identifier. */
|
|
935
|
+
function isIdentifier(value) {
|
|
936
|
+
return IDENTIFIER.test(value);
|
|
937
|
+
}
|
|
938
|
+
/**
|
|
939
|
+
* A property key for an object literal or an interface: bare when it's an identifier, quoted
|
|
940
|
+
* otherwise. `__proto__` is written as a computed key, which a runtime literal keeps as an own
|
|
941
|
+
* property instead of setting the prototype.
|
|
942
|
+
*/
|
|
943
|
+
function propertyKey(name) {
|
|
944
|
+
if (name === "__proto__") return `[${stringLiteral(name)}]`;
|
|
945
|
+
return isIdentifier(name) ? name : stringLiteral(name);
|
|
946
|
+
}
|
|
947
|
+
/** Text that can sit inside a block comment: any `*\/` is broken up so it can't close it. */
|
|
948
|
+
function commentText(text) {
|
|
949
|
+
return text.replace(/\*\//g, "* /");
|
|
950
|
+
}
|
|
951
|
+
/** {@link commentText} split into lines, for a multi-line block comment. */
|
|
952
|
+
function commentLines(text) {
|
|
953
|
+
return commentText(text).split(LINE_BREAK);
|
|
954
|
+
}
|
|
955
|
+
/** {@link commentText} on one line, for a single comment line such as the provenance header. */
|
|
956
|
+
function commentLine(text) {
|
|
957
|
+
return commentText(text).split(LINE_BREAK).join(" ");
|
|
958
|
+
}
|
|
959
|
+
/** Words a type alias can't be named: reserved words and the built-in type names. */
|
|
960
|
+
const RESERVED_TYPE_NAMES = /* @__PURE__ */ new Set([
|
|
961
|
+
"any",
|
|
962
|
+
"bigint",
|
|
963
|
+
"boolean",
|
|
964
|
+
"break",
|
|
965
|
+
"case",
|
|
966
|
+
"catch",
|
|
967
|
+
"class",
|
|
968
|
+
"const",
|
|
969
|
+
"continue",
|
|
970
|
+
"debugger",
|
|
971
|
+
"default",
|
|
972
|
+
"delete",
|
|
973
|
+
"do",
|
|
974
|
+
"else",
|
|
975
|
+
"enum",
|
|
976
|
+
"export",
|
|
977
|
+
"extends",
|
|
978
|
+
"false",
|
|
979
|
+
"finally",
|
|
980
|
+
"for",
|
|
981
|
+
"function",
|
|
982
|
+
"if",
|
|
983
|
+
"implements",
|
|
984
|
+
"import",
|
|
985
|
+
"in",
|
|
986
|
+
"instanceof",
|
|
987
|
+
"interface",
|
|
988
|
+
"let",
|
|
989
|
+
"never",
|
|
990
|
+
"new",
|
|
991
|
+
"null",
|
|
992
|
+
"number",
|
|
993
|
+
"object",
|
|
994
|
+
"package",
|
|
995
|
+
"private",
|
|
996
|
+
"protected",
|
|
997
|
+
"public",
|
|
998
|
+
"return",
|
|
999
|
+
"static",
|
|
1000
|
+
"string",
|
|
1001
|
+
"super",
|
|
1002
|
+
"switch",
|
|
1003
|
+
"symbol",
|
|
1004
|
+
"this",
|
|
1005
|
+
"throw",
|
|
1006
|
+
"true",
|
|
1007
|
+
"try",
|
|
1008
|
+
"typeof",
|
|
1009
|
+
"undefined",
|
|
1010
|
+
"unknown",
|
|
1011
|
+
"var",
|
|
1012
|
+
"void",
|
|
1013
|
+
"while",
|
|
1014
|
+
"with",
|
|
1015
|
+
"yield"
|
|
1016
|
+
]);
|
|
1017
|
+
/** True when `name` can be used as is for an exported type. */
|
|
1018
|
+
function isTypeName(name) {
|
|
1019
|
+
return isIdentifier(name) && !RESERVED_TYPE_NAMES.has(name);
|
|
863
1020
|
}
|
|
864
1021
|
//#endregion
|
|
865
1022
|
//#region src/error-codes.ts
|
|
@@ -924,24 +1081,20 @@ function readErrorCatalogue(doc) {
|
|
|
924
1081
|
/** A TSDoc block for one code: its description, then each example detail as an `@example`. */
|
|
925
1082
|
function codeDoc(entry, indent) {
|
|
926
1083
|
const lines = [];
|
|
927
|
-
if (entry.description !== void 0) lines.push(...entry.description
|
|
1084
|
+
if (entry.description !== void 0) lines.push(...commentLines(entry.description));
|
|
928
1085
|
for (const example of entry.examples) {
|
|
929
1086
|
if (lines.length > 0) lines.push("");
|
|
930
1087
|
const text = typeof example === "string" ? example : JSON.stringify(example);
|
|
931
|
-
lines.push(
|
|
1088
|
+
lines.push(...commentLines(`@example ${text}`));
|
|
932
1089
|
}
|
|
933
1090
|
if (lines.length === 0) return;
|
|
934
|
-
if (lines.length === 1) return `${indent}/** ${lines[0]
|
|
1091
|
+
if (lines.length === 1) return `${indent}/** ${lines[0]} */`;
|
|
935
1092
|
return [
|
|
936
1093
|
`${indent}/**`,
|
|
937
|
-
...lines.map((line) => `${indent} * ${line
|
|
1094
|
+
...lines.map((line) => `${indent} * ${line}`.trimEnd()),
|
|
938
1095
|
`${indent} */`
|
|
939
1096
|
].join("\n");
|
|
940
1097
|
}
|
|
941
|
-
/** A bare object key when the code is a valid identifier, else a quoted one. */
|
|
942
|
-
function codeKey(code) {
|
|
943
|
-
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(code) ? code : JSON.stringify(code);
|
|
944
|
-
}
|
|
945
1098
|
/**
|
|
946
1099
|
* Emit `ErrorCodes`, a const object keyed by every documented code with its TSDoc on the key
|
|
947
1100
|
* (editors show TSDoc on an object key, not on a string-literal union member), the `ErrorCode`
|
|
@@ -964,7 +1117,7 @@ function emitErrorCodes(catalogue) {
|
|
|
964
1117
|
"export const ErrorCodes = {",
|
|
965
1118
|
...catalogue.codes.flatMap((entry) => {
|
|
966
1119
|
const doc = codeDoc(entry, " ");
|
|
967
|
-
const member = ` ${
|
|
1120
|
+
const member = ` ${propertyKey(entry.code)}: ${stringLiteral(entry.code)},`;
|
|
968
1121
|
return doc === void 0 ? [member] : [doc, member];
|
|
969
1122
|
}),
|
|
970
1123
|
"} as const",
|
|
@@ -976,7 +1129,7 @@ function emitErrorCodes(catalogue) {
|
|
|
976
1129
|
"export type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes]"
|
|
977
1130
|
].join("\n");
|
|
978
1131
|
const statusLines = [...catalogue.byStatus].map(([status, codes]) => {
|
|
979
|
-
const members = codes.map((c) =>
|
|
1132
|
+
const members = codes.map((c) => stringLiteral(c));
|
|
980
1133
|
const line = ` ${status}: ${members.length === 0 ? "never" : members.join(" | ")}`;
|
|
981
1134
|
return line.length <= 100 ? line : ` ${status}:\n${members.map((m) => ` | ${m}`).join("\n")}`;
|
|
982
1135
|
});
|
|
@@ -1033,12 +1186,12 @@ function deriveProvenance(doc) {
|
|
|
1033
1186
|
}
|
|
1034
1187
|
/**
|
|
1035
1188
|
* Render the provenance record as the JSDoc header lines stamped into a generated artifact
|
|
1036
|
-
* (each already prefixed with ` * `). Deterministic: no timestamp, so re-generating from the
|
|
1189
|
+
* (each already prefixed with ` * `), with the document's text kept to one comment line. Deterministic: no timestamp, so re-generating from the
|
|
1037
1190
|
* same spec yields byte-identical output.
|
|
1038
1191
|
*/
|
|
1039
1192
|
function provenanceLines(provenance) {
|
|
1040
|
-
const lines = [` * Source spec: ${provenance.source}`, ` * Spec hash: ${provenance.hash}`];
|
|
1041
|
-
if (provenance.server !== void 0) lines.splice(1, 0, ` * Server: ${provenance.server}`);
|
|
1193
|
+
const lines = [` * Source spec: ${commentLine(provenance.source)}`, ` * Spec hash: ${provenance.hash}`];
|
|
1194
|
+
if (provenance.server !== void 0) lines.splice(1, 0, ` * Server: ${commentLine(provenance.server)}`);
|
|
1042
1195
|
return lines;
|
|
1043
1196
|
}
|
|
1044
1197
|
//#endregion
|
|
@@ -1083,17 +1236,25 @@ function isSchema(value) {
|
|
|
1083
1236
|
function pascalCase(value) {
|
|
1084
1237
|
return value.split(/[^a-zA-Z0-9]+/).filter((part) => part.length > 0).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
1085
1238
|
}
|
|
1086
|
-
/**
|
|
1087
|
-
function
|
|
1088
|
-
|
|
1089
|
-
}
|
|
1090
|
-
/** True when a string is a safe bare object-key identifier. */
|
|
1091
|
-
function isIdentifier(value) {
|
|
1092
|
-
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(value);
|
|
1093
|
-
}
|
|
1094
|
-
function objectKey(value) {
|
|
1095
|
-
return isIdentifier(value) ? value : quote(value);
|
|
1239
|
+
/** The identifier stem for a wire type's interfaces, `Type`-prefixed when it would start with a digit. */
|
|
1240
|
+
function typeStem(type) {
|
|
1241
|
+
const pascal = pascalCase(type);
|
|
1242
|
+
return /^[A-Za-z]/.test(pascal) ? pascal : `Type${pascal}`;
|
|
1096
1243
|
}
|
|
1244
|
+
/** Names the generated module declares or relies on, which an enum alias must not take. */
|
|
1245
|
+
const MODULE_NAMES = [
|
|
1246
|
+
"ActionTypes",
|
|
1247
|
+
"ApiDescriptor",
|
|
1248
|
+
"Attributes",
|
|
1249
|
+
"ClientOptions",
|
|
1250
|
+
"ErrorCode",
|
|
1251
|
+
"ErrorCodeByStatus",
|
|
1252
|
+
"ErrorCodeGuard",
|
|
1253
|
+
"ErrorCodes",
|
|
1254
|
+
"Record",
|
|
1255
|
+
"ResourceMap",
|
|
1256
|
+
"WriteAttributes"
|
|
1257
|
+
];
|
|
1097
1258
|
/**
|
|
1098
1259
|
* Render a description as a JSDoc comment at the given indent — single-line when it fits,
|
|
1099
1260
|
* a block otherwise. Returns `undefined` for empty text. Neutralises any `*\/` so a
|
|
@@ -1102,7 +1263,7 @@ function objectKey(value) {
|
|
|
1102
1263
|
function jsDoc(text, indent) {
|
|
1103
1264
|
const trimmed = text?.trim();
|
|
1104
1265
|
if (!trimmed) return;
|
|
1105
|
-
const lines = trimmed
|
|
1266
|
+
const lines = commentLines(trimmed);
|
|
1106
1267
|
if (lines.length === 1) return `${indent}/** ${lines[0]} */`;
|
|
1107
1268
|
return [
|
|
1108
1269
|
`${indent}/**`,
|
|
@@ -1158,7 +1319,6 @@ function memberDoc(schema) {
|
|
|
1158
1319
|
return description ? `${description}\n\n${tags.join("\n")}` : tags.join("\n");
|
|
1159
1320
|
}
|
|
1160
1321
|
var Emitter = class {
|
|
1161
|
-
doc;
|
|
1162
1322
|
descriptor;
|
|
1163
1323
|
atomic;
|
|
1164
1324
|
schemas;
|
|
@@ -1173,6 +1333,10 @@ var Emitter = class {
|
|
|
1173
1333
|
* already-named attribute type. Populated as interfaces are emitted.
|
|
1174
1334
|
*/
|
|
1175
1335
|
emittedInterfaces = /* @__PURE__ */ new Set();
|
|
1336
|
+
/** Enum component name -> the alias name it's emitted under. */
|
|
1337
|
+
enumNames = /* @__PURE__ */ new Map();
|
|
1338
|
+
/** Type names already spoken for: the module's own, the per-type interfaces and enum aliases. */
|
|
1339
|
+
takenNames;
|
|
1176
1340
|
/** Component names mid-expansion in {@link tsType} — a cycle guard for self/mutually-referential `$ref`s. */
|
|
1177
1341
|
expanding = /* @__PURE__ */ new Set();
|
|
1178
1342
|
/**
|
|
@@ -1183,13 +1347,47 @@ var Emitter = class {
|
|
|
1183
1347
|
actionAliasNames = /* @__PURE__ */ new Map();
|
|
1184
1348
|
/** Provenance of the source document, stamped into the generated header for drift tracking. */
|
|
1185
1349
|
provenance;
|
|
1186
|
-
|
|
1187
|
-
|
|
1350
|
+
doc;
|
|
1351
|
+
constructor(source, descriptor, atomic) {
|
|
1188
1352
|
this.descriptor = descriptor;
|
|
1189
1353
|
this.atomic = atomic;
|
|
1190
|
-
this.
|
|
1354
|
+
this.doc = unwrapRefs(source);
|
|
1355
|
+
this.schemas = this.doc.components?.schemas ?? {};
|
|
1191
1356
|
this.baseByType = this.indexBases();
|
|
1192
|
-
this.provenance = deriveProvenance(
|
|
1357
|
+
this.provenance = deriveProvenance(source);
|
|
1358
|
+
this.takenNames = new Set(MODULE_NAMES);
|
|
1359
|
+
for (const type of Object.keys(descriptor)) {
|
|
1360
|
+
const stem = typeStem(type);
|
|
1361
|
+
for (const suffix of [
|
|
1362
|
+
"Attributes",
|
|
1363
|
+
"CreateAttributes",
|
|
1364
|
+
"UpdateAttributes"
|
|
1365
|
+
]) this.takenNames.add(`${stem}${suffix}`);
|
|
1366
|
+
for (const action of Object.keys(descriptor[type]?.actions ?? {})) {
|
|
1367
|
+
this.takenNames.add(`${stem}${pascalCase(action)}Input`);
|
|
1368
|
+
this.takenNames.add(`${stem}${pascalCase(action)}Output`);
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
}
|
|
1372
|
+
/**
|
|
1373
|
+
* The alias an enum component is emitted under: its own name when that's a usable type name,
|
|
1374
|
+
* else one derived from it (with a warning), kept clear of every other name in the module.
|
|
1375
|
+
*/
|
|
1376
|
+
enumName(component) {
|
|
1377
|
+
const known = this.enumNames.get(component);
|
|
1378
|
+
if (known !== void 0) return known;
|
|
1379
|
+
let name = component;
|
|
1380
|
+
if (!isTypeName(component) || this.takenNames.has(component)) {
|
|
1381
|
+
const pascal = pascalCase(component);
|
|
1382
|
+
let stem = /^[A-Za-z]/.test(pascal) ? pascal : `Enum${pascal}`;
|
|
1383
|
+
if (!isTypeName(stem) || this.takenNames.has(stem)) stem = `${stem}Enum`;
|
|
1384
|
+
name = stem;
|
|
1385
|
+
for (let n = 2; this.takenNames.has(name); n++) name = `${stem}${n}`;
|
|
1386
|
+
console.warn(`Enum component ${stringLiteral(component)} can't be used as a TypeScript type name; emitting it as ${name}.`);
|
|
1387
|
+
}
|
|
1388
|
+
this.takenNames.add(name);
|
|
1389
|
+
this.enumNames.set(component, name);
|
|
1390
|
+
return name;
|
|
1193
1391
|
}
|
|
1194
1392
|
/** Map each declared wire type back to the `Base` of its resource schema. */
|
|
1195
1393
|
indexBases() {
|
|
@@ -1250,7 +1448,7 @@ var Emitter = class {
|
|
|
1250
1448
|
const base = this.baseByType.get(type);
|
|
1251
1449
|
const props = base ? this.schemas[`${base}Attributes`]?.properties : void 0;
|
|
1252
1450
|
const fields = Object.keys(this.descriptor[type].attributes);
|
|
1253
|
-
return this.renderInterface(`${
|
|
1451
|
+
return this.renderInterface(`${typeStem(type)}Attributes`, props, fields, () => true);
|
|
1254
1452
|
}
|
|
1255
1453
|
/**
|
|
1256
1454
|
* The per-type WRITE attribute interfaces — `<Pascal>CreateAttributes` and
|
|
@@ -1262,7 +1460,7 @@ var Emitter = class {
|
|
|
1262
1460
|
writeAttributeInterfaces(type) {
|
|
1263
1461
|
const base = this.baseByType.get(type);
|
|
1264
1462
|
if (base === void 0) return [];
|
|
1265
|
-
const pascal =
|
|
1463
|
+
const pascal = typeStem(type);
|
|
1266
1464
|
const out = [];
|
|
1267
1465
|
const create = this.schemas[`${base}CreateAttributes`];
|
|
1268
1466
|
if (create !== void 0) {
|
|
@@ -1289,7 +1487,7 @@ var Emitter = class {
|
|
|
1289
1487
|
for (const type of Object.keys(this.descriptor)) {
|
|
1290
1488
|
const actions = this.descriptor[type]?.actions;
|
|
1291
1489
|
if (actions === void 0) continue;
|
|
1292
|
-
const pascal =
|
|
1490
|
+
const pascal = typeStem(type);
|
|
1293
1491
|
for (const [actionName, action] of Object.entries(actions)) {
|
|
1294
1492
|
const member = `${pascal}${pascalCase(actionName)}`;
|
|
1295
1493
|
const names = {};
|
|
@@ -1333,9 +1531,9 @@ var Emitter = class {
|
|
|
1333
1531
|
const members = [];
|
|
1334
1532
|
if (names.input !== void 0) members.push(`input: ${names.input}`);
|
|
1335
1533
|
if (names.output !== void 0) members.push(`output: ${names.output}`);
|
|
1336
|
-
actionLines.push(` ${
|
|
1534
|
+
actionLines.push(` ${propertyKey(actionName)}: { ${members.join("; ")} }`);
|
|
1337
1535
|
}
|
|
1338
|
-
typeLines.push(` ${
|
|
1536
|
+
typeLines.push(` ${propertyKey(type)}: {\n${actionLines.join("\n")}\n }`);
|
|
1339
1537
|
}
|
|
1340
1538
|
if (typeLines.length === 0) return "export interface ActionTypes {}";
|
|
1341
1539
|
return `export interface ActionTypes {\n${typeLines.join("\n")}\n}`;
|
|
@@ -1383,10 +1581,10 @@ var Emitter = class {
|
|
|
1383
1581
|
if (schema.oneOf !== void 0) for (const arm of schema.oneOf) {
|
|
1384
1582
|
const kind = isSchema(arm.properties?.["kind"]) ? arm.properties["kind"].const : void 0;
|
|
1385
1583
|
const members = this.pageMemberLimits(arm, " ");
|
|
1386
|
-
if (typeof kind === "string" && members.length > 0) body.push(` ${
|
|
1584
|
+
if (typeof kind === "string" && members.length > 0) body.push(` ${propertyKey(kind)}: {\n${members.join("\n")}\n },`);
|
|
1387
1585
|
}
|
|
1388
1586
|
else body = this.pageMemberLimits(schema, " ");
|
|
1389
|
-
if (body.length > 0) typeLines.push(` ${
|
|
1587
|
+
if (body.length > 0) typeLines.push(` ${propertyKey(type)}: {\n${body.join("\n")}\n },`);
|
|
1390
1588
|
}
|
|
1391
1589
|
return `${[
|
|
1392
1590
|
"/**",
|
|
@@ -1411,7 +1609,7 @@ var Emitter = class {
|
|
|
1411
1609
|
if (limits.length === 0) continue;
|
|
1412
1610
|
const doc = jsDoc(memberDoc(prop), indent);
|
|
1413
1611
|
if (doc !== void 0) lines.push(doc);
|
|
1414
|
-
lines.push(`${indent}${
|
|
1612
|
+
lines.push(`${indent}${propertyKey(name)}: { ${limits.join(", ")} },`);
|
|
1415
1613
|
}
|
|
1416
1614
|
return lines;
|
|
1417
1615
|
}
|
|
@@ -1428,7 +1626,7 @@ var Emitter = class {
|
|
|
1428
1626
|
const doc = isSchema(schema) ? jsDoc(memberDoc(schema), " ") : void 0;
|
|
1429
1627
|
if (doc) lines.push(doc);
|
|
1430
1628
|
const optional = required(field) ? "" : "?";
|
|
1431
|
-
lines.push(` ${
|
|
1629
|
+
lines.push(` ${propertyKey(field)}${optional}: ${tsType}`);
|
|
1432
1630
|
}
|
|
1433
1631
|
this.emittedInterfaces.add(name);
|
|
1434
1632
|
if (lines.length === 0) return `export interface ${name} {}`;
|
|
@@ -1441,7 +1639,7 @@ var Emitter = class {
|
|
|
1441
1639
|
const resolved = target ? this.schemas[target] : void 0;
|
|
1442
1640
|
if (target && resolved && Array.isArray(resolved.enum)) {
|
|
1443
1641
|
this.usedEnums.set(target, resolved);
|
|
1444
|
-
return target;
|
|
1642
|
+
return this.enumName(target);
|
|
1445
1643
|
}
|
|
1446
1644
|
if (target && this.emittedInterfaces.has(target)) return target;
|
|
1447
1645
|
if (resolved === void 0 || target === void 0 || this.expanding.has(target)) return "unknown";
|
|
@@ -1466,7 +1664,7 @@ var Emitter = class {
|
|
|
1466
1664
|
}
|
|
1467
1665
|
/** The non-nullable TS type for the declared JSON type(s). */
|
|
1468
1666
|
baseTsType(schema, types) {
|
|
1469
|
-
if (Array.isArray(schema.enum) && schema.enum.length > 0) return schema.enum.map((value) =>
|
|
1667
|
+
if (Array.isArray(schema.enum) && schema.enum.length > 0) return schema.enum.map((value) => stringLiteral(String(value))).join(" | ");
|
|
1470
1668
|
if (types.length === 0) return "unknown";
|
|
1471
1669
|
const mapped = types.map((t) => this.scalarOrComposite(schema, t));
|
|
1472
1670
|
return [...new Set(mapped)].join(" | ");
|
|
@@ -1491,7 +1689,7 @@ var Emitter = class {
|
|
|
1491
1689
|
for (const [name, prop] of Object.entries(props)) {
|
|
1492
1690
|
if (!isSchema(prop)) continue;
|
|
1493
1691
|
const optional = required.has(name) ? "" : "?";
|
|
1494
|
-
members.push(`${
|
|
1692
|
+
members.push(`${propertyKey(name)}${optional}: ${this.tsType(prop)}`);
|
|
1495
1693
|
}
|
|
1496
1694
|
if (members.length === 0) return "Record<string, unknown>";
|
|
1497
1695
|
return `{ ${members.join("; ")} }`;
|
|
@@ -1508,7 +1706,8 @@ var Emitter = class {
|
|
|
1508
1706
|
if (this.usedEnums.size === 0) return;
|
|
1509
1707
|
return [...this.usedEnums.keys()].sort().map((name) => {
|
|
1510
1708
|
const schema = this.usedEnums.get(name);
|
|
1511
|
-
const
|
|
1709
|
+
const union = (schema.enum ?? []).map((value) => stringLiteral(String(value))).join(" | ");
|
|
1710
|
+
const alias = `export type ${this.enumName(name)} = ${union}`;
|
|
1512
1711
|
const doc = jsDoc(this.enumDoc(schema), "");
|
|
1513
1712
|
return doc ? `${doc}\n${alias}` : alias;
|
|
1514
1713
|
}).join("\n\n");
|
|
@@ -1531,7 +1730,7 @@ var Emitter = class {
|
|
|
1531
1730
|
* argument to the runtime factory).
|
|
1532
1731
|
*/
|
|
1533
1732
|
attributesMap() {
|
|
1534
|
-
return `export interface Attributes {\n${Object.keys(this.descriptor).map((type) => ` ${
|
|
1733
|
+
return `export interface Attributes {\n${Object.keys(this.descriptor).map((type) => ` ${propertyKey(type)}: ${typeStem(type)}Attributes`).join("\n")}\n}`;
|
|
1535
1734
|
}
|
|
1536
1735
|
/**
|
|
1537
1736
|
* Emit the `WriteAttributes` interface mapping each writable wire type to its
|
|
@@ -1546,11 +1745,11 @@ var Emitter = class {
|
|
|
1546
1745
|
const hasCreate = base !== void 0 && this.schemas[`${base}CreateAttributes`] !== void 0;
|
|
1547
1746
|
const hasUpdate = base !== void 0 && this.schemas[`${base}UpdateAttributes`] !== void 0;
|
|
1548
1747
|
if (!hasCreate && !hasUpdate) continue;
|
|
1549
|
-
const pascal =
|
|
1748
|
+
const pascal = typeStem(type);
|
|
1550
1749
|
const members = [];
|
|
1551
1750
|
if (hasCreate) members.push(`create: ${pascal}CreateAttributes`);
|
|
1552
1751
|
if (hasUpdate) members.push(`update: ${pascal}UpdateAttributes`);
|
|
1553
|
-
lines.push(` ${
|
|
1752
|
+
lines.push(` ${propertyKey(type)}: { ${members.join("; ")} }`);
|
|
1554
1753
|
}
|
|
1555
1754
|
if (lines.length === 0) return "export interface WriteAttributes {}";
|
|
1556
1755
|
return `export interface WriteAttributes {\n${lines.join("\n")}\n}`;
|
|
@@ -1570,9 +1769,9 @@ var Emitter = class {
|
|
|
1570
1769
|
if (value !== null && typeof value === "object") {
|
|
1571
1770
|
const entries = Object.entries(value);
|
|
1572
1771
|
if (entries.length === 0) return "{}";
|
|
1573
|
-
return `{\n${entries.map(([key, v]) => `${inner}${
|
|
1772
|
+
return `{\n${entries.map(([key, v]) => `${inner}${propertyKey(key)}: ${this.literal(v, depth + 1)}`).join(",\n")}\n${indent}}`;
|
|
1574
1773
|
}
|
|
1575
|
-
return JSON.stringify(value);
|
|
1774
|
+
return typeof value === "string" ? stringLiteral(value) : JSON.stringify(value);
|
|
1576
1775
|
}
|
|
1577
1776
|
boundFactory() {
|
|
1578
1777
|
return [
|
|
@@ -1631,7 +1830,7 @@ function header(bundle) {
|
|
|
1631
1830
|
].join("\n");
|
|
1632
1831
|
}
|
|
1633
1832
|
function body(bundle) {
|
|
1634
|
-
return `export const schemas = ${JSON.stringify(bundle, null, 2)} as const`;
|
|
1833
|
+
return `export const schemas = ${JSON.stringify(bundle, null, 2).replace(/^(\s*)"__proto__":/gm, "$1[\"__proto__\"]:").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029")} as const`;
|
|
1635
1834
|
}
|
|
1636
1835
|
//#endregion
|
|
1637
1836
|
//#region src/reader.ts
|
|
@@ -1775,4 +1974,4 @@ async function check(config) {
|
|
|
1775
1974
|
//#endregion
|
|
1776
1975
|
export { checkContract as _, readSchemas as a, buildDescriptor as b, detectVerbCollisions as c, hashJson as d, provenanceLines as f, MINIMUM_CONTRACT as g, MAXIMUM_CONTRACT as h, readDocument as i, emit as l, readErrorCatalogue as m, generate as n, emitSchemas as o, emitErrorCodes as p, schemasOutputPath as r, Emitter as s, check as t, deriveProvenance as u, DescriptorBuilder as v, buildAtomic as y };
|
|
1777
1976
|
|
|
1778
|
-
//# sourceMappingURL=src-
|
|
1977
|
+
//# sourceMappingURL=src-CKsM7dXw.mjs.map
|