@haddowg/json-api-codegen 1.10.0 → 1.12.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-DqeWPRAD.mjs";
1
+ import { r as CodegenConfig } from "./index-Ch2PJH9Y.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>] [--examples] [--check]";
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { i as generateFiles, t as check } from "./src-C3noZURK.mjs";
2
+ import { i as generateFiles, t as check } from "./src-D4apiVHe.mjs";
3
3
  import { realpathSync } from "node:fs";
4
4
  import { fileURLToPath } from "node:url";
5
5
  //#region src/cli.ts
@@ -62,6 +62,14 @@ interface OperationObject {
62
62
  destructive?: unknown;
63
63
  idempotent?: unknown;
64
64
  };
65
+ /** The credentials the operation takes: scheme name to the scopes it needs, per alternative. */
66
+ security?: readonly SecurityRequirement[];
67
+ }
68
+ /** One security alternative: each scheme it names, with the scopes it needs under that scheme. */
69
+ type SecurityRequirement = Readonly<Record<string, readonly string[]>>;
70
+ /** A security scheme; the codegen reads only its `type`, to find the `oauth2` ones. */
71
+ interface SecuritySchemeObject {
72
+ type?: string;
65
73
  }
66
74
  type HttpMethod = 'get' | 'post' | 'patch' | 'put' | 'delete';
67
75
  type PathItemObject = Partial<Record<HttpMethod, OperationObject>>;
@@ -80,8 +88,11 @@ interface OpenApiDocument {
80
88
  url?: string;
81
89
  }[];
82
90
  paths?: Record<string, PathItemObject>;
91
+ /** The default security of every operation that declares none of its own. */
92
+ security?: readonly SecurityRequirement[];
83
93
  components?: {
84
94
  schemas?: Record<string, SchemaObject>;
95
+ securitySchemes?: Record<string, SecuritySchemeObject>;
85
96
  };
86
97
  }
87
98
  //#endregion
@@ -91,7 +102,22 @@ declare class DescriptorBuilder {
91
102
  private readonly paths;
92
103
  /** Lazily-built wire-type -> collection-level paginator kind (for per-relation divergence, D6a). */
93
104
  private typePaginators?;
105
+ /** The names of the document's `oauth2` security schemes, under which operations list scopes. */
106
+ private readonly scopeSchemes;
107
+ /** The document's default security, which an operation without its own inherits. */
108
+ private readonly defaultSecurity;
94
109
  constructor(source: OpenApiDocument);
110
+ /**
111
+ * The OAuth scopes an operation needs (generator contract 16): those its `security` lists under
112
+ * an `oauth2` scheme, in order and without repeats. `undefined` when it lists none.
113
+ */
114
+ private scopes;
115
+ /**
116
+ * The scopes each of a type's CRUD, related and relationship operations needs, keyed by the
117
+ * operationId without the type (`fetchOne`, `fetchRelated.author`). Operations needing none are
118
+ * left out; actions carry their own.
119
+ */
120
+ private operationScopes;
95
121
  /**
96
122
  * The collection-level paginator kind for a WIRE type (`tracks`), memoised. Resolves each
97
123
  * resource schema's wire type (its `type.const`) to the paginator of its collection GET — the
@@ -304,7 +330,7 @@ declare function buildExamples(doc: OpenApiDocument, descriptor: ApiDescriptor):
304
330
  /** Below this the document predates the structures this codegen reads. */
305
331
  declare const MINIMUM_CONTRACT = 1;
306
332
  /** Above this the document carries structures this codegen does not read. */
307
- declare const MAXIMUM_CONTRACT = 15;
333
+ declare const MAXIMUM_CONTRACT = 17;
308
334
  /**
309
335
  * Check the document's `info.x-generator.contract` against the range this codegen reads. A
310
336
  * document older than the range throws; a newer one returns a warning, because its new
@@ -691,5 +717,5 @@ declare function generateFiles(config: CodegenConfig): Promise<string[]>;
691
717
  */
692
718
  declare function check(config: CodegenConfig): Promise<CheckResult>;
693
719
  //#endregion
694
- export { operationExamples as A, PathItemObject as B, VerbCollision as C, MINIMUM_CONTRACT as D, MAXIMUM_CONTRACT as E, InfoObject as F, ResponseObject as H, MediaTypeObject as I, OpenApiDocument as L, buildAtomic as M, buildDescriptor as N, checkContract as O, HttpMethod as P, OperationObject as R, Emitter as S, emit as T, SchemaObject as U, RequestBodyObject as V, SchemaOrBool as W, emitExamples as _, examplesOutputPath as a, emitErrorCodes as b, schemasOutputPath as c, hashJson as d, provenanceLines as f, readSchemas as g, readDocument as h, check as i, DescriptorBuilder as j, buildExamples as k, Provenance as l, SchemaBundle as m, CheckResult as n, generate as o, emitSchemas as p, CodegenConfig as r, generateFiles as s, ArtifactDrift as t, deriveProvenance as u, DocumentedErrorCode as v, detectVerbCollisions as w, readErrorCatalogue as x, ErrorCatalogue as y, ParameterObject as z };
695
- //# sourceMappingURL=index-DqeWPRAD.d.mts.map
720
+ export { operationExamples as A, PathItemObject as B, VerbCollision as C, MINIMUM_CONTRACT as D, MAXIMUM_CONTRACT as E, InfoObject as F, SecurityRequirement as G, ResponseObject as H, MediaTypeObject as I, SecuritySchemeObject as K, OpenApiDocument as L, buildAtomic as M, buildDescriptor as N, checkContract as O, HttpMethod as P, OperationObject as R, Emitter as S, emit as T, SchemaObject as U, RequestBodyObject as V, SchemaOrBool as W, emitExamples as _, examplesOutputPath as a, emitErrorCodes as b, schemasOutputPath as c, hashJson as d, provenanceLines as f, readSchemas as g, readDocument as h, check as i, DescriptorBuilder as j, buildExamples as k, Provenance as l, SchemaBundle as m, CheckResult as n, generate as o, emitSchemas as p, CodegenConfig as r, generateFiles as s, ArtifactDrift as t, deriveProvenance as u, DocumentedErrorCode as v, detectVerbCollisions as w, readErrorCatalogue as x, ErrorCatalogue as y, ParameterObject as z };
721
+ //# sourceMappingURL=index-Ch2PJH9Y.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-Ch2PJH9Y.d.mts","names":[],"sources":["../src/openapi.ts","../src/build-descriptor.ts","../src/build-examples.ts","../src/contract.ts","../src/emit.ts","../src/error-codes.ts","../src/emit-examples.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 operationExamples, B as PathItemObject, C as VerbCollision, D as MINIMUM_CONTRACT, E as MAXIMUM_CONTRACT, F as InfoObject, H as ResponseObject, I as MediaTypeObject, L as OpenApiDocument, M as buildAtomic, N as buildDescriptor, O as checkContract, P as HttpMethod, R as OperationObject, S as Emitter, T as emit, U as SchemaObject, V as RequestBodyObject, W as SchemaOrBool, _ as emitExamples, a as examplesOutputPath, b as emitErrorCodes, c as schemasOutputPath, d as hashJson, f as provenanceLines, g as readSchemas, h as readDocument, i as check, j as DescriptorBuilder, k as buildExamples, l as Provenance, m as SchemaBundle, n as CheckResult, o as generate, p as emitSchemas, r as CodegenConfig, s as generateFiles, t as ArtifactDrift, u as deriveProvenance, v as DocumentedErrorCode, w as detectVerbCollisions, x as readErrorCatalogue, y as ErrorCatalogue, z as ParameterObject } from "./index-DqeWPRAD.mjs";
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, buildExamples, check, checkContract, deriveProvenance, detectVerbCollisions, emit, emitErrorCodes, emitExamples, emitSchemas, examplesOutputPath, generate, generateFiles, hashJson, operationExamples, provenanceLines, readDocument, readErrorCatalogue, readSchemas, schemasOutputPath };
1
+ import { A as operationExamples, B as PathItemObject, C as VerbCollision, D as MINIMUM_CONTRACT, E as MAXIMUM_CONTRACT, F as InfoObject, G as SecurityRequirement, H as ResponseObject, I as MediaTypeObject, K as SecuritySchemeObject, L as OpenApiDocument, M as buildAtomic, N as buildDescriptor, O as checkContract, P as HttpMethod, R as OperationObject, S as Emitter, T as emit, U as SchemaObject, V as RequestBodyObject, W as SchemaOrBool, _ as emitExamples, a as examplesOutputPath, b as emitErrorCodes, c as schemasOutputPath, d as hashJson, f as provenanceLines, g as readSchemas, h as readDocument, i as check, j as DescriptorBuilder, k as buildExamples, l as Provenance, m as SchemaBundle, n as CheckResult, o as generate, p as emitSchemas, r as CodegenConfig, s as generateFiles, t as ArtifactDrift, u as deriveProvenance, v as DocumentedErrorCode, w as detectVerbCollisions, x as readErrorCatalogue, y as ErrorCatalogue, z as ParameterObject } from "./index-Ch2PJH9Y.mjs";
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 SecurityRequirement, type SecuritySchemeObject, type VerbCollision, buildAtomic, buildDescriptor, buildExamples, check, checkContract, deriveProvenance, detectVerbCollisions, emit, emitErrorCodes, emitExamples, emitSchemas, examplesOutputPath, generate, generateFiles, hashJson, operationExamples, provenanceLines, readDocument, readErrorCatalogue, readSchemas, schemasOutputPath };
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { C as DescriptorBuilder, S as operationExamples, T as buildDescriptor, _ as readErrorCatalogue, a as schemasOutputPath, b as checkContract, c as emitSchemas, d as detectVerbCollisions, f as emit, g as emitErrorCodes, h as provenanceLines, i as generateFiles, l as emitExamples, m as hashJson, n as examplesOutputPath, o as readDocument, p as deriveProvenance, r as generate, s as readSchemas, t as check, u as Emitter, v as MAXIMUM_CONTRACT, w as buildAtomic, x as buildExamples, y as MINIMUM_CONTRACT } from "./src-C3noZURK.mjs";
1
+ import { C as DescriptorBuilder, S as operationExamples, T as buildDescriptor, _ as readErrorCatalogue, a as schemasOutputPath, b as checkContract, c as emitSchemas, d as detectVerbCollisions, f as emit, g as emitErrorCodes, h as provenanceLines, i as generateFiles, l as emitExamples, m as hashJson, n as examplesOutputPath, o as readDocument, p as deriveProvenance, r as generate, s as readSchemas, t as check, u as Emitter, v as MAXIMUM_CONTRACT, w as buildAtomic, x as buildExamples, y as MINIMUM_CONTRACT } from "./src-D4apiVHe.mjs";
2
2
  export { DescriptorBuilder, Emitter, MAXIMUM_CONTRACT, MINIMUM_CONTRACT, buildAtomic, buildDescriptor, buildExamples, check, checkContract, deriveProvenance, detectVerbCollisions, emit, emitErrorCodes, emitExamples, emitSchemas, examplesOutputPath, generate, generateFiles, hashJson, operationExamples, provenanceLines, readDocument, readErrorCatalogue, readSchemas, schemasOutputPath };
@@ -95,10 +95,49 @@ var DescriptorBuilder = class {
95
95
  paths;
96
96
  /** Lazily-built wire-type -> collection-level paginator kind (for per-relation divergence, D6a). */
97
97
  typePaginators;
98
+ /** The names of the document's `oauth2` security schemes, under which operations list scopes. */
99
+ scopeSchemes;
100
+ /** The document's default security, which an operation without its own inherits. */
101
+ defaultSecurity;
98
102
  constructor(source) {
99
103
  const doc = unwrapRefs(source);
100
104
  this.schemas = doc.components?.schemas ?? {};
101
105
  this.paths = doc.paths ?? {};
106
+ this.scopeSchemes = new Set(Object.entries(doc.components?.securitySchemes ?? {}).filter(([, scheme]) => scheme?.type === "oauth2").map(([name]) => name));
107
+ this.defaultSecurity = doc.security ?? [];
108
+ }
109
+ /**
110
+ * The OAuth scopes an operation needs (generator contract 16): those its `security` lists under
111
+ * an `oauth2` scheme, in order and without repeats. `undefined` when it lists none.
112
+ */
113
+ scopes(op) {
114
+ if (op === void 0 || this.scopeSchemes.size === 0) return;
115
+ const out = /* @__PURE__ */ new Set();
116
+ for (const requirement of op.security ?? this.defaultSecurity) for (const [scheme, scopes] of Object.entries(requirement)) if (this.scopeSchemes.has(scheme) && Array.isArray(scopes)) for (const scope of scopes) out.add(scope);
117
+ return out.size === 0 ? void 0 : [...out];
118
+ }
119
+ /**
120
+ * The scopes each of a type's CRUD, related and relationship operations needs, keyed by the
121
+ * operationId without the type (`fetchOne`, `fetchRelated.author`). Operations needing none are
122
+ * left out; actions carry their own.
123
+ */
124
+ operationScopes(wireType) {
125
+ const out = {};
126
+ for (const item of Object.values(this.paths)) for (const op of Object.values(item)) {
127
+ const id = op?.operationId;
128
+ if (typeof id !== "string") continue;
129
+ const dot = id.indexOf(".");
130
+ const prefix = id.slice(0, dot);
131
+ const rest = id.slice(dot + 1);
132
+ if (dot < 0 || prefix === "action" || prefix === "atomic") continue;
133
+ let key;
134
+ if (rest === wireType) key = prefix;
135
+ else if (rest.startsWith(`${wireType}.`)) key = `${prefix}.${rest.slice(wireType.length + 1)}`;
136
+ else continue;
137
+ const scopes = this.scopes(op);
138
+ if (scopes !== void 0) out[key] = scopes;
139
+ }
140
+ return sortRecord(out);
102
141
  }
103
142
  /**
104
143
  * The collection-level paginator kind for a WIRE type (`tracks`), memoised. Resolves each
@@ -139,6 +178,8 @@ var DescriptorBuilder = class {
139
178
  const filterable = this.filterable(collection);
140
179
  if (filterable !== void 0) descriptor.filterable = filterable;
141
180
  if (Object.keys(actions).length > 0) descriptor.actions = actions;
181
+ const scopes = this.operationScopes(wireType);
182
+ if (Object.keys(scopes).length > 0) descriptor.scopes = scopes;
142
183
  if (Object.keys(schema.properties ?? {}).every((prop) => prop === "type") && Object.keys(descriptor.paths).length === 0) continue;
143
184
  out[wireType] = descriptor;
144
185
  }
@@ -152,7 +193,13 @@ var DescriptorBuilder = class {
152
193
  buildAtomic() {
153
194
  for (const [path, item] of Object.entries(this.paths)) {
154
195
  const content = item.post?.requestBody?.content ?? {};
155
- if (Object.keys(content).some(isAtomicMediaType)) return { path };
196
+ if (Object.keys(content).some(isAtomicMediaType)) {
197
+ const scopes = this.scopes(item.post);
198
+ return scopes === void 0 ? { path } : {
199
+ path,
200
+ scopes
201
+ };
202
+ }
156
203
  }
157
204
  return null;
158
205
  }
@@ -403,6 +450,11 @@ var DescriptorBuilder = class {
403
450
  const value = safety?.[flag];
404
451
  if (typeof value === "boolean") action[flag] = value;
405
452
  }
453
+ const scopes = this.scopes(op);
454
+ if (scopes !== void 0) action.scopes = scopes;
455
+ const okSchema = okJsonApiSchema(op);
456
+ const mediaType = okSchema === void 0 ? void 0 : locationMediaType(okSchema);
457
+ if (mediaType !== void 0) action.location = { mediaType };
406
458
  return action;
407
459
  }
408
460
  /**
@@ -484,7 +536,8 @@ var DescriptorBuilder = class {
484
536
  firstOkJsonApiRef(op) {
485
537
  for (const [code, response] of Object.entries(op.responses ?? {})) {
486
538
  if (!code.startsWith("2")) continue;
487
- const ref = response.content?.[JSON_API_MEDIA_TYPE$1]?.schema?.$ref;
539
+ const schema = response.content?.[JSON_API_MEDIA_TYPE$1]?.schema;
540
+ const ref = schema === void 0 ? void 0 : documentArms(schema)[0]?.$ref;
488
541
  if (typeof ref === "string") return ref;
489
542
  }
490
543
  }
@@ -515,16 +568,21 @@ var DescriptorBuilder = class {
515
568
  if (readPivot !== void 0) relation.readPivot = readPivot;
516
569
  return relation;
517
570
  }
518
- if (Array.isArray(items.anyOf)) return {
519
- cardinality: "many",
520
- types: this.constsFromRefs(items.anyOf),
521
- pivot: false
522
- };
571
+ if (Array.isArray(items.anyOf)) {
572
+ const types = this.constsFromRefs(items.anyOf);
573
+ return types.length === 0 ? void 0 : {
574
+ cardinality: "many",
575
+ types,
576
+ polymorphic: true,
577
+ pivot: false
578
+ };
579
+ }
523
580
  return;
524
581
  }
525
582
  if (Array.isArray(data.anyOf)) {
526
583
  const types = [];
527
584
  let pivot = false;
585
+ let polymorphic = false;
528
586
  let readPivot;
529
587
  for (const entry of data.anyOf) if (typeof entry.$ref === "string") {
530
588
  const type = this.resolveConst(entry.$ref);
@@ -536,9 +594,17 @@ var DescriptorBuilder = class {
536
594
  pivot = true;
537
595
  readPivot = this.pivotDescriptor(pivotNodeFromAllOf(entry.allOf), "read");
538
596
  }
539
- } else if (Array.isArray(entry.anyOf)) types.push(...this.constsFromRefs(entry.anyOf));
597
+ } else if (Array.isArray(entry.anyOf)) {
598
+ types.push(...this.constsFromRefs(entry.anyOf));
599
+ polymorphic = true;
600
+ }
540
601
  if (types.length === 0) return;
541
- const relation = {
602
+ const relation = polymorphic ? {
603
+ cardinality: "one",
604
+ types,
605
+ polymorphic: true,
606
+ pivot
607
+ } : {
542
608
  cardinality: "one",
543
609
  types,
544
610
  pivot
@@ -914,13 +980,47 @@ function rawContentType(op) {
914
980
  * (only a `204`).
915
981
  */
916
982
  function actionOutput(op) {
983
+ const schema = okJsonApiSchema(op);
984
+ if (schema === void 0) return "none";
985
+ const arm = documentArms(schema)[0];
986
+ if (arm === void 0) return locationMediaType(schema) === void 0 ? "document" : "location";
987
+ return typeof arm.$ref === "string" && refName$1(arm.$ref) === "MetaDocument" ? "meta" : "document";
988
+ }
989
+ /** The JSON:API schema of an operation's first success response that declares one. */
990
+ function okJsonApiSchema(op) {
917
991
  for (const [code, response] of Object.entries(op.responses ?? {})) {
918
992
  if (!code.startsWith("2")) continue;
919
993
  const schema = response.content?.[JSON_API_MEDIA_TYPE$1]?.schema;
920
- if (schema === void 0) continue;
921
- return typeof schema.$ref === "string" && refName$1(schema.$ref) === "MetaDocument" ? "meta" : "document";
994
+ if (schema !== void 0) return schema;
995
+ }
996
+ }
997
+ /** Whether a schema is a location document: a `$ref` to `LocationDocument`, or an `allOf` with one. */
998
+ function isLocationSchema(schema) {
999
+ const isRef = (entry) => typeof entry.$ref === "string" && refName$1(entry.$ref) === "LocationDocument";
1000
+ return isRef(schema) || (schema.allOf?.some(isRef) ?? false);
1001
+ }
1002
+ /**
1003
+ * The documents a success response's schema offers besides a location document (generator
1004
+ * contract 17): each `oneOf` member that isn't one, or the schema itself when it isn't one.
1005
+ */
1006
+ function documentArms(schema) {
1007
+ return (schema.oneOf ?? [schema]).filter((arm) => !isLocationSchema(arm));
1008
+ }
1009
+ /**
1010
+ * The media type a location document's `links.location.type` is fixed to (generator contract
1011
+ * 17), `application/octet-stream` when the schema fixes none, or `undefined` when the schema
1012
+ * offers no location document.
1013
+ */
1014
+ function locationMediaType(schema) {
1015
+ const location = (schema.oneOf ?? [schema]).find(isLocationSchema);
1016
+ if (location === void 0) return;
1017
+ for (const entry of location.allOf ?? []) {
1018
+ const links = entry.properties?.["links"];
1019
+ const link = isSchema$3(links) ? links.properties?.["location"] : void 0;
1020
+ const type = isSchema$3(link) ? link.properties?.["type"] : void 0;
1021
+ if (isSchema$3(type) && typeof type.const === "string") return type.const;
922
1022
  }
923
- return "none";
1023
+ return "application/octet-stream";
924
1024
  }
925
1025
  /** Build the {@link ApiDescriptor} from a parsed OpenAPI document. */
926
1026
  function buildDescriptor(doc) {
@@ -1085,7 +1185,7 @@ function buildExamples(doc, descriptor) {
1085
1185
  /** Below this the document predates the structures this codegen reads. */
1086
1186
  const MINIMUM_CONTRACT = 1;
1087
1187
  /** Above this the document carries structures this codegen does not read. */
1088
- const MAXIMUM_CONTRACT = 15;
1188
+ const MAXIMUM_CONTRACT = 17;
1089
1189
  /**
1090
1190
  * Check the document's `info.x-generator.contract` against the range this codegen reads. A
1091
1191
  * document older than the range throws; a newer one returns a warning, because its new
@@ -1095,8 +1195,8 @@ const MAXIMUM_CONTRACT = 15;
1095
1195
  function checkContract(doc) {
1096
1196
  const contract = doc.info?.["x-generator"]?.contract;
1097
1197
  if (typeof contract !== "number") return;
1098
- if (contract < 1) throw new Error(`the document declares contract ${contract}, which predates what this codegen reads (it supports 1 to 15). Use an older codegen release, or regenerate the document from a newer server.`);
1099
- if (contract > 15) return `the document declares contract ${contract} and this codegen reads up to 15. It describes capabilities that were not generated; upgrade the codegen to pick them up.`;
1198
+ if (contract < 1) throw new Error(`the document declares contract ${contract}, which predates what this codegen reads (it supports 1 to 17). Use an older codegen release, or regenerate the document from a newer server.`);
1199
+ if (contract > 17) return `the document declares contract ${contract} and this codegen reads up to 17. It describes capabilities that were not generated; upgrade the codegen to pick them up.`;
1100
1200
  }
1101
1201
  //#endregion
1102
1202
  //#region src/declared-links.ts
@@ -1575,6 +1675,53 @@ function safetyDoc(action) {
1575
1675
  if (words.length === 0) return;
1576
1676
  return `The server declares this action ${words.length === 1 ? words[0] : `${words.slice(0, -1).join(", ")} and ${words.at(-1)}`}.`;
1577
1677
  }
1678
+ /**
1679
+ * What an action that answers with a URL returns (generator contract 17), as JSDoc, or
1680
+ * `undefined` for any other action.
1681
+ */
1682
+ function locationDoc(action) {
1683
+ if (action.location === void 0) return;
1684
+ const serving = `a URL serving \`${action.location.mediaType}\``;
1685
+ return action.output === "location" ? `Returns ${serving} as an \`ActionLocation\`. The client doesn't follow it.` : `May return ${serving} instead, as an \`ActionLocation\`. The client doesn't follow it.`;
1686
+ }
1687
+ /** A list of scopes as inline code joined into prose: `a`, `b` and `c`. */
1688
+ function scopeList(scopes) {
1689
+ const quoted = scopes.map((scope) => `\`${scope}\``);
1690
+ return quoted.length === 1 ? quoted[0] : `${quoted.slice(0, -1).join(", ")} and ${quoted.at(-1)}`;
1691
+ }
1692
+ /** The sentence naming the OAuth scopes an operation needs (generator contract 16). */
1693
+ function scopeDoc(scopes) {
1694
+ if (scopes === void 0 || scopes.length === 0) return;
1695
+ return `Needs the OAuth ${scopes.length === 1 ? "scope" : "scopes"} ${scopeList(scopes)}.`;
1696
+ }
1697
+ /** The descriptor's `paths` keys, by the operation whose scopes they carry. */
1698
+ const PATH_OPERATIONS = {
1699
+ fetchMany: "fetchCollection",
1700
+ create: "create",
1701
+ fetchOne: "fetchOne",
1702
+ update: "update",
1703
+ delete: "delete"
1704
+ };
1705
+ /** A relation's operations, in the order its JSDoc lists their scopes. */
1706
+ const RELATION_OPERATIONS = [
1707
+ "fetchRelated",
1708
+ "fetchRelationship",
1709
+ "updateRelationship",
1710
+ "addRelationship",
1711
+ "removeRelationship"
1712
+ ];
1713
+ /** The OAuth scopes each of a relation's endpoints needs, one line per operation, or `undefined`. */
1714
+ function relationScopeDoc(scopes, relation) {
1715
+ const lines = RELATION_OPERATIONS.flatMap((operation) => {
1716
+ const needed = scopes?.[`${operation}.${relation}`];
1717
+ return needed === void 0 || needed.length === 0 ? [] : [`- \`${operation}\` needs ${scopeList(needed)}`];
1718
+ });
1719
+ return lines.length === 0 ? void 0 : [
1720
+ "OAuth scopes:",
1721
+ "",
1722
+ ...lines
1723
+ ].join("\n");
1724
+ }
1578
1725
  /** Whether a media type carries JSON: JSON:API, `application/json` or a `+json` suffix. */
1579
1726
  function isJsonMedia(mediaType) {
1580
1727
  const essence = mediaType.split(";")[0].trim().toLowerCase();
@@ -1686,12 +1833,23 @@ var Emitter = class {
1686
1833
  const op = actionOperation(this.doc, action);
1687
1834
  const parts = [
1688
1835
  actionDoc(action.path.slice(action.path.lastIndexOf("/") + 1), op),
1836
+ locationDoc(action),
1689
1837
  safetyDoc(action),
1838
+ scopeDoc(action.scopes),
1690
1839
  exampleDoc(op)
1691
1840
  ].filter((part) => part !== void 0);
1692
1841
  const doc = parts.length === 0 ? void 0 : parts.join("\n\n");
1693
1842
  if (doc !== void 0) this.literalDocs.set(`${type}/actions/${name}`, doc);
1694
1843
  }
1844
+ const scopes = descriptor[type]?.scopes;
1845
+ for (const [key, operation] of Object.entries(PATH_OPERATIONS)) {
1846
+ const doc = scopeDoc(scopes?.[operation]);
1847
+ if (doc !== void 0 && descriptor[type]?.paths[key] !== void 0) this.literalDocs.set(`${type}/paths/${key}`, doc);
1848
+ }
1849
+ for (const relation of Object.keys(descriptor[type]?.relations ?? {})) {
1850
+ const doc = relationScopeDoc(scopes, relation);
1851
+ if (doc !== void 0) this.literalDocs.set(`${type}/relations/${relation}`, doc);
1852
+ }
1695
1853
  }
1696
1854
  }
1697
1855
  /**
@@ -2035,10 +2193,12 @@ var Emitter = class {
2035
2193
  }
2036
2194
  /** Emit the server-level atomic capability constant (`{ path }` or `null`). */
2037
2195
  atomicConst() {
2196
+ const atomicScopes = scopeDoc(this.atomic?.scopes);
2038
2197
  return `${[
2039
2198
  "/**",
2040
2199
  " * The server-level Atomic Operations endpoint (the atomic ext media type), or `null`",
2041
2200
  " * when this server exposes none. The runtime `client.atomic` builder posts the batch here.",
2201
+ ...atomicScopes === void 0 ? [] : [" *", ` * ${atomicScopes}`],
2042
2202
  " */"
2043
2203
  ].join("\n")}\nexport const atomic = ${this.atomic === null ? "null" : `${this.literal(this.atomic, 0)} as const`}`;
2044
2204
  }
@@ -2518,4 +2678,4 @@ async function check(config) {
2518
2678
  //#endregion
2519
2679
  export { DescriptorBuilder as C, operationExamples as S, buildDescriptor as T, readErrorCatalogue as _, schemasOutputPath as a, checkContract as b, emitSchemas as c, detectVerbCollisions as d, emit as f, emitErrorCodes as g, provenanceLines as h, generateFiles as i, emitExamples as l, hashJson as m, examplesOutputPath as n, readDocument as o, deriveProvenance as p, generate as r, readSchemas as s, check as t, Emitter as u, MAXIMUM_CONTRACT as v, buildAtomic as w, buildExamples as x, MINIMUM_CONTRACT as y };
2520
2680
 
2521
- //# sourceMappingURL=src-C3noZURK.mjs.map
2681
+ //# sourceMappingURL=src-D4apiVHe.mjs.map