@skmtc/core 0.28.3 → 0.28.5

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.
Files changed (37) hide show
  1. package/esm/helpers/collateExamples.d.ts +11 -1
  2. package/esm/helpers/collateExamples.d.ts.map +1 -1
  3. package/esm/helpers/collateExamples.js +20 -5
  4. package/esm/oas/example/Example.d.ts +2 -2
  5. package/esm/oas/example/Example.d.ts.map +1 -1
  6. package/esm/oas/example/Example.js +4 -1
  7. package/esm/parse/v3-0/example/toExamplesV3.d.ts +10 -5
  8. package/esm/parse/v3-0/example/toExamplesV3.d.ts.map +1 -1
  9. package/esm/parse/v3-0/example/toExamplesV3.js +27 -18
  10. package/esm/parse/v3-0/header/toHeadersV3.d.ts +2 -0
  11. package/esm/parse/v3-0/header/toHeadersV3.d.ts.map +1 -1
  12. package/esm/parse/v3-0/header/toHeadersV3.js +3 -3
  13. package/esm/parse/v3-1/example/toExamplesV3.d.ts +10 -5
  14. package/esm/parse/v3-1/example/toExamplesV3.d.ts.map +1 -1
  15. package/esm/parse/v3-1/example/toExamplesV3.js +27 -18
  16. package/esm/parse/v3-1/header/toHeadersV3.d.ts +2 -0
  17. package/esm/parse/v3-1/header/toHeadersV3.d.ts.map +1 -1
  18. package/esm/parse/v3-1/header/toHeadersV3.js +3 -3
  19. package/package.json +1 -1
  20. package/script/helpers/collateExamples.d.ts +11 -1
  21. package/script/helpers/collateExamples.d.ts.map +1 -1
  22. package/script/helpers/collateExamples.js +20 -5
  23. package/script/oas/example/Example.d.ts +2 -2
  24. package/script/oas/example/Example.d.ts.map +1 -1
  25. package/script/oas/example/Example.js +4 -1
  26. package/script/parse/v3-0/example/toExamplesV3.d.ts +10 -5
  27. package/script/parse/v3-0/example/toExamplesV3.d.ts.map +1 -1
  28. package/script/parse/v3-0/example/toExamplesV3.js +27 -18
  29. package/script/parse/v3-0/header/toHeadersV3.d.ts +2 -0
  30. package/script/parse/v3-0/header/toHeadersV3.d.ts.map +1 -1
  31. package/script/parse/v3-0/header/toHeadersV3.js +3 -3
  32. package/script/parse/v3-1/example/toExamplesV3.d.ts +10 -5
  33. package/script/parse/v3-1/example/toExamplesV3.d.ts.map +1 -1
  34. package/script/parse/v3-1/example/toExamplesV3.js +27 -18
  35. package/script/parse/v3-1/header/toHeadersV3.d.ts +2 -0
  36. package/script/parse/v3-1/header/toHeadersV3.d.ts.map +1 -1
  37. package/script/parse/v3-1/header/toHeadersV3.js +3 -3
@@ -9,6 +9,16 @@ type CollatedExampleArgs = {
9
9
  objectSchema: OasSchema | OasRef<'schema'> | undefined;
10
10
  /** Current recursion depth (used to prevent infinite loops) */
11
11
  depth: number;
12
+ /**
13
+ * The `$ref` pointers already entered on THIS path, used to cut reference
14
+ * cycles. Callers start collation without it; the function threads it.
15
+ *
16
+ * Path-scoped rather than global on purpose. A global set would also stop a
17
+ * cycle, and would additionally drop the example for the SECOND of two
18
+ * sibling uses of the same schema — silently emptying samples on every
19
+ * document that reuses a type, which is most of them.
20
+ */
21
+ seen?: ReadonlySet<string>;
12
22
  };
13
23
  /**
14
24
  * Recursively collates and builds example values from OpenAPI schemas.
@@ -155,6 +165,6 @@ type CollatedExampleArgs = {
155
165
  * }
156
166
  * ```
157
167
  */
158
- export declare const collateExamples: ({ objectSchema, depth }: CollatedExampleArgs) => unknown;
168
+ export declare const collateExamples: ({ objectSchema, depth, seen }: CollatedExampleArgs) => unknown;
159
169
  export {};
160
170
  //# sourceMappingURL=collateExamples.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"collateExamples.d.ts","sourceRoot":"","sources":["../../src/helpers/collateExamples.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAGxD;;GAEG;AACH,KAAK,mBAAmB,GAAG;IACzB,+DAA+D;IAC/D,YAAY,EAAE,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,SAAS,CAAA;IACtD,+DAA+D;IAC/D,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgJG;AACH,eAAO,MAAM,eAAe,GAAI,yBAAyB,mBAAmB,KAAG,OAyF9E,CAAA"}
1
+ {"version":3,"file":"collateExamples.d.ts","sourceRoot":"","sources":["../../src/helpers/collateExamples.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAGxD;;GAEG;AACH,KAAK,mBAAmB,GAAG;IACzB,+DAA+D;IAC/D,YAAY,EAAE,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,SAAS,CAAA;IACtD,+DAA+D;IAC/D,KAAK,EAAE,MAAM,CAAA;IACb;;;;;;;;OAQG;IACH,IAAI,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;CAC3B,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgJG;AACH,eAAO,MAAM,eAAe,GAAI,+BAA+B,mBAAmB,KAAG,OAyGpF,CAAA"}
@@ -145,7 +145,7 @@ import { isEmpty } from './isEmpty.js';
145
145
  * }
146
146
  * ```
147
147
  */
148
- export const collateExamples = ({ objectSchema, depth }) => {
148
+ export const collateExamples = ({ objectSchema, depth, seen }) => {
149
149
  if (!objectSchema) {
150
150
  return undefined;
151
151
  }
@@ -154,9 +154,21 @@ export const collateExamples = ({ objectSchema, depth }) => {
154
154
  }
155
155
  switch (objectSchema.type) {
156
156
  case 'ref': {
157
+ // A schema that reaches itself has no finite example, so the recursive
158
+ // key is omitted and collation continues around it.
159
+ //
160
+ // Without this the cycle simply pads the path until the depth limit
161
+ // throws, roughly sixteen steps in — so a self-referential schema and a
162
+ // legitimately deep one fail identically, and a caller that only wanted a
163
+ // sample body gets an exception instead. Cutting the cycle here is what
164
+ // makes the depth limit mean what it says.
165
+ if (seen?.has(objectSchema.$ref)) {
166
+ return undefined;
167
+ }
157
168
  return collateExamples({
158
169
  objectSchema: objectSchema.resolve(),
159
- depth: depth + 1
170
+ depth: depth + 1,
171
+ seen: new Set(seen ?? []).add(objectSchema.$ref)
160
172
  });
161
173
  }
162
174
  case 'object': {
@@ -170,7 +182,8 @@ export const collateExamples = ({ objectSchema, depth }) => {
170
182
  }
171
183
  const propertyExample = collateExamples({
172
184
  objectSchema: value,
173
- depth: depth + 1
185
+ depth: depth + 1,
186
+ seen
174
187
  });
175
188
  if (propertyExample) {
176
189
  output[key] = propertyExample;
@@ -184,7 +197,8 @@ export const collateExamples = ({ objectSchema, depth }) => {
184
197
  }
185
198
  const itemsExample = collateExamples({
186
199
  objectSchema: objectSchema.items,
187
- depth: depth + 1
200
+ depth: depth + 1,
201
+ seen
188
202
  });
189
203
  return itemsExample ? [itemsExample] : undefined;
190
204
  }
@@ -202,7 +216,8 @@ export const collateExamples = ({ objectSchema, depth }) => {
202
216
  for (const member of objectSchema.members) {
203
217
  const unionExample = collateExamples({
204
218
  objectSchema: member,
205
- depth: depth + 1
219
+ depth: depth + 1,
220
+ seen
206
221
  });
207
222
  if (unionExample) {
208
223
  return unionExample;
@@ -9,8 +9,8 @@ export type ExampleFields = {
9
9
  summary?: string;
10
10
  /** Longer description of the example */
11
11
  description?: string;
12
- /** The example value */
13
- value: unknown;
12
+ /** The example value — absent when the example is given as an `externalValue` */
13
+ value?: unknown;
14
14
  /** The external value of the example */
15
15
  externalValue?: string;
16
16
  /** Custom extension fields (x-* properties) */
@@ -1 +1 @@
1
- {"version":3,"file":"Example.d.ts","sourceRoot":"","sources":["../../../src/oas/example/Example.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AAC9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAE9C;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,mCAAmC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,wCAAwC;IACxC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,wBAAwB;IACxB,KAAK,EAAE,OAAO,CAAA;IACd,wCAAwC;IACxC,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,+CAA+C;IAC/C,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC1C,CAAA;AAED,qBAAa,UAAU;IACrB,gDAAgD;IAChD,OAAO,EAAE,SAAS,CAAY;IAC9B,gBAAgB;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;gBAE7B,MAAM,EAAE,aAAa;IAQjC,4CAA4C;IAC5C,KAAK,IAAI,IAAI,IAAI,MAAM,CAAC,SAAS,CAAC;IAIlC,qBAAqB;IACrB,OAAO,IAAI,UAAU;IAIrB,WAAW,IAAI,UAAU;IAIzB,YAAY,CAAC,QAAQ,EAAE,mBAAmB,GAAG,SAAS,CAAC,aAAa;CAOrE"}
1
+ {"version":3,"file":"Example.d.ts","sourceRoot":"","sources":["../../../src/oas/example/Example.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AAC9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAE9C;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,mCAAmC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,wCAAwC;IACxC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,iFAAiF;IACjF,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,wCAAwC;IACxC,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,+CAA+C;IAC/C,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC1C,CAAA;AAED,qBAAa,UAAU;IACrB,gDAAgD;IAChD,OAAO,EAAE,SAAS,CAAY;IAC9B,gBAAgB;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;gBAE7B,MAAM,EAAE,aAAa;IAQjC,4CAA4C;IAC5C,KAAK,IAAI,IAAI,IAAI,MAAM,CAAC,SAAS,CAAC;IAIlC,qBAAqB;IACrB,OAAO,IAAI,UAAU;IAIrB,WAAW,IAAI,UAAU;IAIzB,YAAY,CAAC,QAAQ,EAAE,mBAAmB,GAAG,SAAS,CAAC,aAAa;CAUrE"}
@@ -59,7 +59,10 @@ export class OasExample {
59
59
  return {
60
60
  summary: this.summary,
61
61
  description: this.description,
62
- value: this.value
62
+ value: this.value,
63
+ // Without this an `externalValue`-only example round-trips to an Example
64
+ // Object holding neither an inline value nor a pointer to one.
65
+ externalValue: this.externalValue
63
66
  };
64
67
  }
65
68
  }
@@ -4,7 +4,12 @@ import { OasExample } from '../../../oas/example/Example.js';
4
4
  import type { OasRef } from '../../../oas/ref/Ref.js';
5
5
  import type { StackTrail } from '../../../context/StackTrail.js';
6
6
  export type ToExampleSimpleV3Args = {
7
- example: OpenAPIV3.ExampleObject;
7
+ /**
8
+ * The example value itself. The singular `example` field of a media type,
9
+ * parameter or header is a LITERAL value — not an Example Object — so it
10
+ * carries no `summary`, `description` or `externalValue` to read.
11
+ */
12
+ example: unknown;
8
13
  /** The stack trail for tracing */
9
14
  stackTrail: StackTrail;
10
15
  /** Parse context for tracing and error handling */
@@ -13,8 +18,8 @@ export type ToExampleSimpleV3Args = {
13
18
  /**
14
19
  * Creates a simple OAS example from a value.
15
20
  *
16
- * Converts a raw example value into an OasExample object with basic
17
- * fields. Used for simple example scenarios where only the value matters.
21
+ * Wraps a literal example value as an {@link OasExample}. Used for the singular
22
+ * `example` field, where only the value exists.
18
23
  *
19
24
  * @param args - Arguments containing the example value
20
25
  * @returns OasExample object with the provided value
@@ -27,8 +32,8 @@ export declare const toExampleSimpleV3: ({ example }: ToExampleSimpleV3Args) =>
27
32
  * with context for tracing and error handling.
28
33
  */
29
34
  export type ToExamplesV3Args = {
30
- /** Single example object (OpenAPI v3 format) */
31
- example: OpenAPIV3.ExampleObject | undefined;
35
+ /** The singular `example` field — a literal value, not an Example Object */
36
+ example: unknown;
32
37
  /** Collection of named examples (OpenAPI v3 format) */
33
38
  examples: Record<string, OpenAPIV3.ExampleObject | OpenAPIV3.ReferenceObject> | undefined;
34
39
  /** Key name for the example context */
@@ -1 +1 @@
1
- {"version":3,"file":"toExamplesV3.d.ts","sourceRoot":"","sources":["../../../../src/parse/v3-0/example/toExamplesV3.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AACtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAG9C,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAE5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAErD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAA;AAChE,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,EAAE,SAAS,CAAC,aAAa,CAAA;IAChC,kCAAkC;IAClC,UAAU,EAAE,UAAU,CAAA;IACtB,mDAAmD;IACnD,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,GAAI,aAE/B,qBAAqB,KAAG,UAAU,GAAG,MAAM,CAAC,SAAS,CASvD,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,gDAAgD;IAChD,OAAO,EAAE,SAAS,CAAC,aAAa,GAAG,SAAS,CAAA;IAC5C,uDAAuD;IACvD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,aAAa,GAAG,SAAS,CAAC,eAAe,CAAC,GAAG,SAAS,CAAA;IACzF,uCAAuC;IACvC,UAAU,EAAE,MAAM,CAAA;IAClB,kCAAkC;IAClC,UAAU,EAAE,UAAU,CAAA;IACtB,mDAAmD;IACnD,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY,GAAI,wDAM1B,gBAAgB,KAAG,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,SAoCtE,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,SAAS,CAAC,aAAa,GAAG,SAAS,CAAC,eAAe,CAAA;IAC5D,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW,GAAI,kCAIzB,eAAe,KAAG,UAAU,GAAG,MAAM,CAAC,SAAS,CAqBjD,CAAA"}
1
+ {"version":3,"file":"toExamplesV3.d.ts","sourceRoot":"","sources":["../../../../src/parse/v3-0/example/toExamplesV3.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AACtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAG9C,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAE5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAErD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAA;AAChE,MAAM,MAAM,qBAAqB,GAAG;IAClC;;;;OAIG;IACH,OAAO,EAAE,OAAO,CAAA;IAChB,kCAAkC;IAClC,UAAU,EAAE,UAAU,CAAA;IACtB,mDAAmD;IACnD,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,GAAI,aAE/B,qBAAqB,KAAG,UAAU,GAAG,MAAM,CAAC,SAAS,CAIvD,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,4EAA4E;IAC5E,OAAO,EAAE,OAAO,CAAA;IAChB,uDAAuD;IACvD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,aAAa,GAAG,SAAS,CAAC,eAAe,CAAC,GAAG,SAAS,CAAA;IACzF,uCAAuC;IACvC,UAAU,EAAE,MAAM,CAAA;IAClB,kCAAkC;IAClC,UAAU,EAAE,UAAU,CAAA;IACtB,mDAAmD;IACnD,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY,GAAI,wDAM1B,gBAAgB,KAAG,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,SAiDtE,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,SAAS,CAAC,aAAa,GAAG,SAAS,CAAC,eAAe,CAAA;IAC5D,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW,GAAI,kCAIzB,eAAe,KAAG,UAAU,GAAG,MAAM,CAAC,SAAS,CAyBjD,CAAA"}
@@ -5,19 +5,14 @@ import { toSpecificationExtensionsV3 } from '../specificationExtensions/toSpecif
5
5
  /**
6
6
  * Creates a simple OAS example from a value.
7
7
  *
8
- * Converts a raw example value into an OasExample object with basic
9
- * fields. Used for simple example scenarios where only the value matters.
8
+ * Wraps a literal example value as an {@link OasExample}. Used for the singular
9
+ * `example` field, where only the value exists.
10
10
  *
11
11
  * @param args - Arguments containing the example value
12
12
  * @returns OasExample object with the provided value
13
13
  */
14
14
  export const toExampleSimpleV3 = ({ example }) => {
15
- const fields = {
16
- value: example.value,
17
- summary: example.summary,
18
- description: example.description,
19
- externalValue: example.externalValue
20
- };
15
+ const fields = { value: example };
21
16
  return new OasExample(fields);
22
17
  };
23
18
  /**
@@ -31,31 +26,41 @@ export const toExampleSimpleV3 = ({ example }) => {
31
26
  * @returns Record of processed examples, or undefined if no examples
32
27
  */
33
28
  export const toExamplesV3 = ({ example, examples, exampleKey, stackTrail, context }) => {
34
- if (example && examples) {
29
+ // An empty map is declared but carries nothing, so it cannot be the richer
30
+ // field — letting it win would discard the singular in favour of no examples
31
+ // at all.
32
+ const namedExamples = examples && Object.keys(examples).length > 0 ? examples : undefined;
33
+ // `example` is a literal, so test presence rather than truthiness — `false`,
34
+ // `0` and `''` are all valid example values.
35
+ if (example !== undefined && examples !== undefined) {
35
36
  context.logIssue({
36
37
  key: 'example',
37
38
  level: 'warning',
38
- message: `Both example and examples are defined for ${exampleKey}`,
39
+ message: `Both example and examples are defined for ${exampleKey}; using ${namedExamples ? 'examples' : 'example'}`,
39
40
  parent: examples,
40
41
  stackTrail,
41
42
  type: 'EXAMPLE_AND_EXAMPLES_DEFINED'
42
43
  });
43
44
  }
44
- if (example) {
45
- return {
46
- [exampleKey]: stackTrail.trace('example', st => toExampleSimpleV3({ example, stackTrail: st, context }))
47
- };
48
- }
49
- if (examples) {
45
+ // The spec makes the two mutually exclusive, so reaching here with both is
46
+ // malformed input. Prefer `examples`: it is the richer field — many entries,
47
+ // each with a summary and description — and the singular carries nothing it
48
+ // cannot express, so this discards strictly less.
49
+ if (namedExamples) {
50
50
  return stackTrail.trace('examples', st => {
51
51
  const output = {};
52
- const entries = Object.entries(examples);
52
+ const entries = Object.entries(namedExamples);
53
53
  for (const [key, value] of entries) {
54
54
  output[key] = st.trace(key, st2 => toExampleV3({ example: value, stackTrail: st2, context }));
55
55
  }
56
56
  return output;
57
57
  });
58
58
  }
59
+ if (example !== undefined) {
60
+ return {
61
+ [exampleKey]: stackTrail.trace('example', st => toExampleSimpleV3({ example, stackTrail: st, context }))
62
+ };
63
+ }
59
64
  return undefined;
60
65
  };
61
66
  /**
@@ -72,7 +77,10 @@ export const toExampleV3 = ({ example, stackTrail, context }) => {
72
77
  if (isRef(example)) {
73
78
  return toRefV31({ ref: example, refType: 'example', stackTrail, context });
74
79
  }
75
- const { summary, description, value, ...skipped } = example;
80
+ // `externalValue` is the alternative to `value` — an example too large or too
81
+ // awkward to inline. Leaving it in `skipped` both loses it and reports a
82
+ // standard field as an unexpected property.
83
+ const { summary, description, value, externalValue, ...skipped } = example;
76
84
  const extensionFields = toSpecificationExtensionsV3({
77
85
  skipped,
78
86
  parent: example,
@@ -84,6 +92,7 @@ export const toExampleV3 = ({ example, stackTrail, context }) => {
84
92
  summary,
85
93
  description,
86
94
  value,
95
+ externalValue,
87
96
  extensionFields
88
97
  });
89
98
  };
@@ -11,6 +11,8 @@ export type ToHeadersV3Args = {
11
11
  export declare const toHeadersV3: ({ headers, stackTrail, context }: ToHeadersV3Args) => Record<string, OasHeader | OasRef<"header">> | undefined;
12
12
  export type ToHeaderV3Args = {
13
13
  header: OpenAPIV3.ReferenceObject | OpenAPIV3.HeaderObject;
14
+ /** The header's name, used to key a singular `example` */
15
+ name: string;
14
16
  stackTrail: StackTrail;
15
17
  context: ParseContextType;
16
18
  };
@@ -1 +1 @@
1
- {"version":3,"file":"toHeadersV3.d.ts","sourceRoot":"","sources":["../../../../src/parse/v3-0/header/toHeadersV3.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AAEtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAE9C,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAA;AAEzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAErD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAA;AAChE,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,eAAe,GAAG,SAAS,CAAC,YAAY,CAAC,GAAG,SAAS,CAAA;IACvF,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED,eAAO,MAAM,WAAW,GAAI,kCAIzB,eAAe,KAAG,MAAM,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,SAenE,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,SAAS,CAAC,eAAe,GAAG,SAAS,CAAC,YAAY,CAAA;IAC1D,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA"}
1
+ {"version":3,"file":"toHeadersV3.d.ts","sourceRoot":"","sources":["../../../../src/parse/v3-0/header/toHeadersV3.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AAEtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAE9C,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAA;AAEzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAErD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAA;AAChE,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,eAAe,GAAG,SAAS,CAAC,YAAY,CAAC,GAAG,SAAS,CAAA;IACvF,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED,eAAO,MAAM,WAAW,GAAI,kCAIzB,eAAe,KAAG,MAAM,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,SAenE,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,SAAS,CAAC,eAAe,GAAG,SAAS,CAAC,YAAY,CAAA;IAC1D,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA"}
@@ -12,11 +12,11 @@ export const toHeadersV3 = ({ headers, stackTrail, context }) => {
12
12
  const output = {};
13
13
  const entries = Object.entries(headers);
14
14
  for (const [key, value] of entries) {
15
- output[key] = stackTrail.trace(key, st => toHeaderV3({ header: value, stackTrail: st, context }));
15
+ output[key] = stackTrail.trace(key, st => toHeaderV3({ header: value, name: key, stackTrail: st, context }));
16
16
  }
17
17
  return output;
18
18
  };
19
- const toHeaderV3 = ({ header, stackTrail, context }) => {
19
+ const toHeaderV3 = ({ header, name, stackTrail, context }) => {
20
20
  if (isRef(header)) {
21
21
  return toRefV31({ ref: header, refType: 'header', stackTrail, context });
22
22
  }
@@ -36,7 +36,7 @@ const toHeaderV3 = ({ header, stackTrail, context }) => {
36
36
  examples: toExamplesV3({
37
37
  examples,
38
38
  example,
39
- exampleKey: `TEMP`,
39
+ exampleKey: name,
40
40
  stackTrail,
41
41
  context
42
42
  }),
@@ -4,7 +4,12 @@ import { OasExample } from '../../../oas/example/Example.js';
4
4
  import type { OasRef } from '../../../oas/ref/Ref.js';
5
5
  import type { StackTrail } from '../../../context/StackTrail.js';
6
6
  export type ToExampleSimpleV3Args = {
7
- example: OpenAPIV3.ExampleObject;
7
+ /**
8
+ * The example value itself. The singular `example` field of a media type,
9
+ * parameter or header is a LITERAL value — not an Example Object — so it
10
+ * carries no `summary`, `description` or `externalValue` to read.
11
+ */
12
+ example: unknown;
8
13
  /** The stack trail for tracing */
9
14
  stackTrail: StackTrail;
10
15
  /** Parse context for tracing and error handling */
@@ -13,8 +18,8 @@ export type ToExampleSimpleV3Args = {
13
18
  /**
14
19
  * Creates a simple OAS example from a value.
15
20
  *
16
- * Converts a raw example value into an OasExample object with basic
17
- * fields. Used for simple example scenarios where only the value matters.
21
+ * Wraps a literal example value as an {@link OasExample}. Used for the singular
22
+ * `example` field, where only the value exists.
18
23
  *
19
24
  * @param args - Arguments containing the example value
20
25
  * @returns OasExample object with the provided value
@@ -27,8 +32,8 @@ export declare const toExampleSimpleV3: ({ example }: ToExampleSimpleV3Args) =>
27
32
  * with context for tracing and error handling.
28
33
  */
29
34
  export type ToExamplesV3Args = {
30
- /** Single example object (OpenAPI v3 format) */
31
- example: OpenAPIV3.ExampleObject | undefined;
35
+ /** The singular `example` field — a literal value, not an Example Object */
36
+ example: unknown;
32
37
  /** Collection of named examples (OpenAPI v3 format) */
33
38
  examples: Record<string, OpenAPIV3.ExampleObject | OpenAPIV3.ReferenceObject> | undefined;
34
39
  /** Key name for the example context */
@@ -1 +1 @@
1
- {"version":3,"file":"toExamplesV3.d.ts","sourceRoot":"","sources":["../../../../src/parse/v3-1/example/toExamplesV3.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AACtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAG9C,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAE5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAErD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAA;AAChE,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,EAAE,SAAS,CAAC,aAAa,CAAA;IAChC,kCAAkC;IAClC,UAAU,EAAE,UAAU,CAAA;IACtB,mDAAmD;IACnD,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,GAAI,aAE/B,qBAAqB,KAAG,UAAU,GAAG,MAAM,CAAC,SAAS,CASvD,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,gDAAgD;IAChD,OAAO,EAAE,SAAS,CAAC,aAAa,GAAG,SAAS,CAAA;IAC5C,uDAAuD;IACvD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,aAAa,GAAG,SAAS,CAAC,eAAe,CAAC,GAAG,SAAS,CAAA;IACzF,uCAAuC;IACvC,UAAU,EAAE,MAAM,CAAA;IAClB,kCAAkC;IAClC,UAAU,EAAE,UAAU,CAAA;IACtB,mDAAmD;IACnD,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY,GAAI,wDAM1B,gBAAgB,KAAG,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,SAoCtE,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,SAAS,CAAC,aAAa,GAAG,SAAS,CAAC,eAAe,CAAA;IAC5D,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW,GAAI,kCAIzB,eAAe,KAAG,UAAU,GAAG,MAAM,CAAC,SAAS,CAqBjD,CAAA"}
1
+ {"version":3,"file":"toExamplesV3.d.ts","sourceRoot":"","sources":["../../../../src/parse/v3-1/example/toExamplesV3.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AACtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAG9C,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAE5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAErD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAA;AAChE,MAAM,MAAM,qBAAqB,GAAG;IAClC;;;;OAIG;IACH,OAAO,EAAE,OAAO,CAAA;IAChB,kCAAkC;IAClC,UAAU,EAAE,UAAU,CAAA;IACtB,mDAAmD;IACnD,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,GAAI,aAE/B,qBAAqB,KAAG,UAAU,GAAG,MAAM,CAAC,SAAS,CAIvD,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,4EAA4E;IAC5E,OAAO,EAAE,OAAO,CAAA;IAChB,uDAAuD;IACvD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,aAAa,GAAG,SAAS,CAAC,eAAe,CAAC,GAAG,SAAS,CAAA;IACzF,uCAAuC;IACvC,UAAU,EAAE,MAAM,CAAA;IAClB,kCAAkC;IAClC,UAAU,EAAE,UAAU,CAAA;IACtB,mDAAmD;IACnD,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY,GAAI,wDAM1B,gBAAgB,KAAG,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,SAiDtE,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,SAAS,CAAC,aAAa,GAAG,SAAS,CAAC,eAAe,CAAA;IAC5D,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW,GAAI,kCAIzB,eAAe,KAAG,UAAU,GAAG,MAAM,CAAC,SAAS,CAyBjD,CAAA"}
@@ -5,19 +5,14 @@ import { toSpecificationExtensionsV3 } from '../specificationExtensions/toSpecif
5
5
  /**
6
6
  * Creates a simple OAS example from a value.
7
7
  *
8
- * Converts a raw example value into an OasExample object with basic
9
- * fields. Used for simple example scenarios where only the value matters.
8
+ * Wraps a literal example value as an {@link OasExample}. Used for the singular
9
+ * `example` field, where only the value exists.
10
10
  *
11
11
  * @param args - Arguments containing the example value
12
12
  * @returns OasExample object with the provided value
13
13
  */
14
14
  export const toExampleSimpleV3 = ({ example }) => {
15
- const fields = {
16
- value: example.value,
17
- summary: example.summary,
18
- description: example.description,
19
- externalValue: example.externalValue
20
- };
15
+ const fields = { value: example };
21
16
  return new OasExample(fields);
22
17
  };
23
18
  /**
@@ -31,31 +26,41 @@ export const toExampleSimpleV3 = ({ example }) => {
31
26
  * @returns Record of processed examples, or undefined if no examples
32
27
  */
33
28
  export const toExamplesV3 = ({ example, examples, exampleKey, stackTrail, context }) => {
34
- if (example && examples) {
29
+ // An empty map is declared but carries nothing, so it cannot be the richer
30
+ // field — letting it win would discard the singular in favour of no examples
31
+ // at all.
32
+ const namedExamples = examples && Object.keys(examples).length > 0 ? examples : undefined;
33
+ // `example` is a literal, so test presence rather than truthiness — `false`,
34
+ // `0` and `''` are all valid example values.
35
+ if (example !== undefined && examples !== undefined) {
35
36
  context.logIssue({
36
37
  key: 'example',
37
38
  level: 'warning',
38
- message: `Both example and examples are defined for ${exampleKey}`,
39
+ message: `Both example and examples are defined for ${exampleKey}; using ${namedExamples ? 'examples' : 'example'}`,
39
40
  parent: examples,
40
41
  stackTrail,
41
42
  type: 'EXAMPLE_AND_EXAMPLES_DEFINED'
42
43
  });
43
44
  }
44
- if (example) {
45
- return {
46
- [exampleKey]: stackTrail.trace('example', st => toExampleSimpleV3({ example, stackTrail: st, context }))
47
- };
48
- }
49
- if (examples) {
45
+ // The spec makes the two mutually exclusive, so reaching here with both is
46
+ // malformed input. Prefer `examples`: it is the richer field — many entries,
47
+ // each with a summary and description — and the singular carries nothing it
48
+ // cannot express, so this discards strictly less.
49
+ if (namedExamples) {
50
50
  return stackTrail.trace('examples', st => {
51
51
  const output = {};
52
- const entries = Object.entries(examples);
52
+ const entries = Object.entries(namedExamples);
53
53
  for (const [key, value] of entries) {
54
54
  output[key] = st.trace(key, st2 => toExampleV3({ example: value, stackTrail: st2, context }));
55
55
  }
56
56
  return output;
57
57
  });
58
58
  }
59
+ if (example !== undefined) {
60
+ return {
61
+ [exampleKey]: stackTrail.trace('example', st => toExampleSimpleV3({ example, stackTrail: st, context }))
62
+ };
63
+ }
59
64
  return undefined;
60
65
  };
61
66
  /**
@@ -72,7 +77,10 @@ export const toExampleV3 = ({ example, stackTrail, context }) => {
72
77
  if (isRef(example)) {
73
78
  return toRefV31({ ref: example, refType: 'example', stackTrail, context });
74
79
  }
75
- const { summary, description, value, ...skipped } = example;
80
+ // `externalValue` is the alternative to `value` — an example too large or too
81
+ // awkward to inline. Leaving it in `skipped` both loses it and reports a
82
+ // standard field as an unexpected property.
83
+ const { summary, description, value, externalValue, ...skipped } = example;
76
84
  const extensionFields = toSpecificationExtensionsV3({
77
85
  skipped,
78
86
  parent: example,
@@ -84,6 +92,7 @@ export const toExampleV3 = ({ example, stackTrail, context }) => {
84
92
  summary,
85
93
  description,
86
94
  value,
95
+ externalValue,
87
96
  extensionFields
88
97
  });
89
98
  };
@@ -11,6 +11,8 @@ export type ToHeadersV3Args = {
11
11
  export declare const toHeadersV3: ({ headers, stackTrail, context }: ToHeadersV3Args) => Record<string, OasHeader | OasRef<"header">> | undefined;
12
12
  export type ToHeaderV3Args = {
13
13
  header: OpenAPIV3.ReferenceObject | OpenAPIV3.HeaderObject;
14
+ /** The header's name, used to key a singular `example` */
15
+ name: string;
14
16
  stackTrail: StackTrail;
15
17
  context: ParseContextType;
16
18
  };
@@ -1 +1 @@
1
- {"version":3,"file":"toHeadersV3.d.ts","sourceRoot":"","sources":["../../../../src/parse/v3-1/header/toHeadersV3.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AAEtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAE9C,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAA;AAEzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAErD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAA;AAChE,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,eAAe,GAAG,SAAS,CAAC,YAAY,CAAC,GAAG,SAAS,CAAA;IACvF,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED,eAAO,MAAM,WAAW,GAAI,kCAIzB,eAAe,KAAG,MAAM,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,SAenE,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,SAAS,CAAC,eAAe,GAAG,SAAS,CAAC,YAAY,CAAA;IAC1D,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA"}
1
+ {"version":3,"file":"toHeadersV3.d.ts","sourceRoot":"","sources":["../../../../src/parse/v3-1/header/toHeadersV3.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AAEtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAE9C,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAA;AAEzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAErD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAA;AAChE,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,eAAe,GAAG,SAAS,CAAC,YAAY,CAAC,GAAG,SAAS,CAAA;IACvF,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED,eAAO,MAAM,WAAW,GAAI,kCAIzB,eAAe,KAAG,MAAM,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,SAenE,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,SAAS,CAAC,eAAe,GAAG,SAAS,CAAC,YAAY,CAAA;IAC1D,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA"}
@@ -12,11 +12,11 @@ export const toHeadersV3 = ({ headers, stackTrail, context }) => {
12
12
  const output = {};
13
13
  const entries = Object.entries(headers);
14
14
  for (const [key, value] of entries) {
15
- output[key] = stackTrail.trace(key, st => toHeaderV3({ header: value, stackTrail: st, context }));
15
+ output[key] = stackTrail.trace(key, st => toHeaderV3({ header: value, name: key, stackTrail: st, context }));
16
16
  }
17
17
  return output;
18
18
  };
19
- const toHeaderV3 = ({ header, stackTrail, context }) => {
19
+ const toHeaderV3 = ({ header, name, stackTrail, context }) => {
20
20
  if (isRef(header)) {
21
21
  return toRefV31({ ref: header, refType: 'header', stackTrail, context });
22
22
  }
@@ -36,7 +36,7 @@ const toHeaderV3 = ({ header, stackTrail, context }) => {
36
36
  examples: toExamplesV3({
37
37
  examples,
38
38
  example,
39
- exampleKey: `TEMP`,
39
+ exampleKey: name,
40
40
  stackTrail,
41
41
  context
42
42
  }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skmtc/core",
3
- "version": "0.28.3",
3
+ "version": "0.28.5",
4
4
  "description": "Skmtc is a declarative code generation framework",
5
5
  "keywords": [
6
6
  "openapi",
@@ -9,6 +9,16 @@ type CollatedExampleArgs = {
9
9
  objectSchema: OasSchema | OasRef<'schema'> | undefined;
10
10
  /** Current recursion depth (used to prevent infinite loops) */
11
11
  depth: number;
12
+ /**
13
+ * The `$ref` pointers already entered on THIS path, used to cut reference
14
+ * cycles. Callers start collation without it; the function threads it.
15
+ *
16
+ * Path-scoped rather than global on purpose. A global set would also stop a
17
+ * cycle, and would additionally drop the example for the SECOND of two
18
+ * sibling uses of the same schema — silently emptying samples on every
19
+ * document that reuses a type, which is most of them.
20
+ */
21
+ seen?: ReadonlySet<string>;
12
22
  };
13
23
  /**
14
24
  * Recursively collates and builds example values from OpenAPI schemas.
@@ -155,6 +165,6 @@ type CollatedExampleArgs = {
155
165
  * }
156
166
  * ```
157
167
  */
158
- export declare const collateExamples: ({ objectSchema, depth }: CollatedExampleArgs) => unknown;
168
+ export declare const collateExamples: ({ objectSchema, depth, seen }: CollatedExampleArgs) => unknown;
159
169
  export {};
160
170
  //# sourceMappingURL=collateExamples.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"collateExamples.d.ts","sourceRoot":"","sources":["../../src/helpers/collateExamples.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAGxD;;GAEG;AACH,KAAK,mBAAmB,GAAG;IACzB,+DAA+D;IAC/D,YAAY,EAAE,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,SAAS,CAAA;IACtD,+DAA+D;IAC/D,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgJG;AACH,eAAO,MAAM,eAAe,GAAI,yBAAyB,mBAAmB,KAAG,OAyF9E,CAAA"}
1
+ {"version":3,"file":"collateExamples.d.ts","sourceRoot":"","sources":["../../src/helpers/collateExamples.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAGxD;;GAEG;AACH,KAAK,mBAAmB,GAAG;IACzB,+DAA+D;IAC/D,YAAY,EAAE,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,SAAS,CAAA;IACtD,+DAA+D;IAC/D,KAAK,EAAE,MAAM,CAAA;IACb;;;;;;;;OAQG;IACH,IAAI,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;CAC3B,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgJG;AACH,eAAO,MAAM,eAAe,GAAI,+BAA+B,mBAAmB,KAAG,OAyGpF,CAAA"}
@@ -148,7 +148,7 @@ const isEmpty_js_1 = require("./isEmpty.js");
148
148
  * }
149
149
  * ```
150
150
  */
151
- const collateExamples = ({ objectSchema, depth }) => {
151
+ const collateExamples = ({ objectSchema, depth, seen }) => {
152
152
  if (!objectSchema) {
153
153
  return undefined;
154
154
  }
@@ -157,9 +157,21 @@ const collateExamples = ({ objectSchema, depth }) => {
157
157
  }
158
158
  switch (objectSchema.type) {
159
159
  case 'ref': {
160
+ // A schema that reaches itself has no finite example, so the recursive
161
+ // key is omitted and collation continues around it.
162
+ //
163
+ // Without this the cycle simply pads the path until the depth limit
164
+ // throws, roughly sixteen steps in — so a self-referential schema and a
165
+ // legitimately deep one fail identically, and a caller that only wanted a
166
+ // sample body gets an exception instead. Cutting the cycle here is what
167
+ // makes the depth limit mean what it says.
168
+ if (seen?.has(objectSchema.$ref)) {
169
+ return undefined;
170
+ }
160
171
  return (0, exports.collateExamples)({
161
172
  objectSchema: objectSchema.resolve(),
162
- depth: depth + 1
173
+ depth: depth + 1,
174
+ seen: new Set(seen ?? []).add(objectSchema.$ref)
163
175
  });
164
176
  }
165
177
  case 'object': {
@@ -173,7 +185,8 @@ const collateExamples = ({ objectSchema, depth }) => {
173
185
  }
174
186
  const propertyExample = (0, exports.collateExamples)({
175
187
  objectSchema: value,
176
- depth: depth + 1
188
+ depth: depth + 1,
189
+ seen
177
190
  });
178
191
  if (propertyExample) {
179
192
  output[key] = propertyExample;
@@ -187,7 +200,8 @@ const collateExamples = ({ objectSchema, depth }) => {
187
200
  }
188
201
  const itemsExample = (0, exports.collateExamples)({
189
202
  objectSchema: objectSchema.items,
190
- depth: depth + 1
203
+ depth: depth + 1,
204
+ seen
191
205
  });
192
206
  return itemsExample ? [itemsExample] : undefined;
193
207
  }
@@ -205,7 +219,8 @@ const collateExamples = ({ objectSchema, depth }) => {
205
219
  for (const member of objectSchema.members) {
206
220
  const unionExample = (0, exports.collateExamples)({
207
221
  objectSchema: member,
208
- depth: depth + 1
222
+ depth: depth + 1,
223
+ seen
209
224
  });
210
225
  if (unionExample) {
211
226
  return unionExample;
@@ -9,8 +9,8 @@ export type ExampleFields = {
9
9
  summary?: string;
10
10
  /** Longer description of the example */
11
11
  description?: string;
12
- /** The example value */
13
- value: unknown;
12
+ /** The example value — absent when the example is given as an `externalValue` */
13
+ value?: unknown;
14
14
  /** The external value of the example */
15
15
  externalValue?: string;
16
16
  /** Custom extension fields (x-* properties) */
@@ -1 +1 @@
1
- {"version":3,"file":"Example.d.ts","sourceRoot":"","sources":["../../../src/oas/example/Example.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AAC9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAE9C;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,mCAAmC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,wCAAwC;IACxC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,wBAAwB;IACxB,KAAK,EAAE,OAAO,CAAA;IACd,wCAAwC;IACxC,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,+CAA+C;IAC/C,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC1C,CAAA;AAED,qBAAa,UAAU;IACrB,gDAAgD;IAChD,OAAO,EAAE,SAAS,CAAY;IAC9B,gBAAgB;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;gBAE7B,MAAM,EAAE,aAAa;IAQjC,4CAA4C;IAC5C,KAAK,IAAI,IAAI,IAAI,MAAM,CAAC,SAAS,CAAC;IAIlC,qBAAqB;IACrB,OAAO,IAAI,UAAU;IAIrB,WAAW,IAAI,UAAU;IAIzB,YAAY,CAAC,QAAQ,EAAE,mBAAmB,GAAG,SAAS,CAAC,aAAa;CAOrE"}
1
+ {"version":3,"file":"Example.d.ts","sourceRoot":"","sources":["../../../src/oas/example/Example.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AAC9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAE9C;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,mCAAmC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,wCAAwC;IACxC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,iFAAiF;IACjF,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,wCAAwC;IACxC,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,+CAA+C;IAC/C,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC1C,CAAA;AAED,qBAAa,UAAU;IACrB,gDAAgD;IAChD,OAAO,EAAE,SAAS,CAAY;IAC9B,gBAAgB;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;gBAE7B,MAAM,EAAE,aAAa;IAQjC,4CAA4C;IAC5C,KAAK,IAAI,IAAI,IAAI,MAAM,CAAC,SAAS,CAAC;IAIlC,qBAAqB;IACrB,OAAO,IAAI,UAAU;IAIrB,WAAW,IAAI,UAAU;IAIzB,YAAY,CAAC,QAAQ,EAAE,mBAAmB,GAAG,SAAS,CAAC,aAAa;CAUrE"}
@@ -62,7 +62,10 @@ class OasExample {
62
62
  return {
63
63
  summary: this.summary,
64
64
  description: this.description,
65
- value: this.value
65
+ value: this.value,
66
+ // Without this an `externalValue`-only example round-trips to an Example
67
+ // Object holding neither an inline value nor a pointer to one.
68
+ externalValue: this.externalValue
66
69
  };
67
70
  }
68
71
  }
@@ -4,7 +4,12 @@ import { OasExample } from '../../../oas/example/Example.js';
4
4
  import type { OasRef } from '../../../oas/ref/Ref.js';
5
5
  import type { StackTrail } from '../../../context/StackTrail.js';
6
6
  export type ToExampleSimpleV3Args = {
7
- example: OpenAPIV3.ExampleObject;
7
+ /**
8
+ * The example value itself. The singular `example` field of a media type,
9
+ * parameter or header is a LITERAL value — not an Example Object — so it
10
+ * carries no `summary`, `description` or `externalValue` to read.
11
+ */
12
+ example: unknown;
8
13
  /** The stack trail for tracing */
9
14
  stackTrail: StackTrail;
10
15
  /** Parse context for tracing and error handling */
@@ -13,8 +18,8 @@ export type ToExampleSimpleV3Args = {
13
18
  /**
14
19
  * Creates a simple OAS example from a value.
15
20
  *
16
- * Converts a raw example value into an OasExample object with basic
17
- * fields. Used for simple example scenarios where only the value matters.
21
+ * Wraps a literal example value as an {@link OasExample}. Used for the singular
22
+ * `example` field, where only the value exists.
18
23
  *
19
24
  * @param args - Arguments containing the example value
20
25
  * @returns OasExample object with the provided value
@@ -27,8 +32,8 @@ export declare const toExampleSimpleV3: ({ example }: ToExampleSimpleV3Args) =>
27
32
  * with context for tracing and error handling.
28
33
  */
29
34
  export type ToExamplesV3Args = {
30
- /** Single example object (OpenAPI v3 format) */
31
- example: OpenAPIV3.ExampleObject | undefined;
35
+ /** The singular `example` field — a literal value, not an Example Object */
36
+ example: unknown;
32
37
  /** Collection of named examples (OpenAPI v3 format) */
33
38
  examples: Record<string, OpenAPIV3.ExampleObject | OpenAPIV3.ReferenceObject> | undefined;
34
39
  /** Key name for the example context */
@@ -1 +1 @@
1
- {"version":3,"file":"toExamplesV3.d.ts","sourceRoot":"","sources":["../../../../src/parse/v3-0/example/toExamplesV3.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AACtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAG9C,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAE5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAErD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAA;AAChE,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,EAAE,SAAS,CAAC,aAAa,CAAA;IAChC,kCAAkC;IAClC,UAAU,EAAE,UAAU,CAAA;IACtB,mDAAmD;IACnD,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,GAAI,aAE/B,qBAAqB,KAAG,UAAU,GAAG,MAAM,CAAC,SAAS,CASvD,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,gDAAgD;IAChD,OAAO,EAAE,SAAS,CAAC,aAAa,GAAG,SAAS,CAAA;IAC5C,uDAAuD;IACvD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,aAAa,GAAG,SAAS,CAAC,eAAe,CAAC,GAAG,SAAS,CAAA;IACzF,uCAAuC;IACvC,UAAU,EAAE,MAAM,CAAA;IAClB,kCAAkC;IAClC,UAAU,EAAE,UAAU,CAAA;IACtB,mDAAmD;IACnD,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY,GAAI,wDAM1B,gBAAgB,KAAG,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,SAoCtE,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,SAAS,CAAC,aAAa,GAAG,SAAS,CAAC,eAAe,CAAA;IAC5D,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW,GAAI,kCAIzB,eAAe,KAAG,UAAU,GAAG,MAAM,CAAC,SAAS,CAqBjD,CAAA"}
1
+ {"version":3,"file":"toExamplesV3.d.ts","sourceRoot":"","sources":["../../../../src/parse/v3-0/example/toExamplesV3.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AACtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAG9C,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAE5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAErD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAA;AAChE,MAAM,MAAM,qBAAqB,GAAG;IAClC;;;;OAIG;IACH,OAAO,EAAE,OAAO,CAAA;IAChB,kCAAkC;IAClC,UAAU,EAAE,UAAU,CAAA;IACtB,mDAAmD;IACnD,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,GAAI,aAE/B,qBAAqB,KAAG,UAAU,GAAG,MAAM,CAAC,SAAS,CAIvD,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,4EAA4E;IAC5E,OAAO,EAAE,OAAO,CAAA;IAChB,uDAAuD;IACvD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,aAAa,GAAG,SAAS,CAAC,eAAe,CAAC,GAAG,SAAS,CAAA;IACzF,uCAAuC;IACvC,UAAU,EAAE,MAAM,CAAA;IAClB,kCAAkC;IAClC,UAAU,EAAE,UAAU,CAAA;IACtB,mDAAmD;IACnD,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY,GAAI,wDAM1B,gBAAgB,KAAG,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,SAiDtE,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,SAAS,CAAC,aAAa,GAAG,SAAS,CAAC,eAAe,CAAA;IAC5D,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW,GAAI,kCAIzB,eAAe,KAAG,UAAU,GAAG,MAAM,CAAC,SAAS,CAyBjD,CAAA"}
@@ -8,19 +8,14 @@ const toSpecificationExtensionsV3_js_1 = require("../specificationExtensions/toS
8
8
  /**
9
9
  * Creates a simple OAS example from a value.
10
10
  *
11
- * Converts a raw example value into an OasExample object with basic
12
- * fields. Used for simple example scenarios where only the value matters.
11
+ * Wraps a literal example value as an {@link OasExample}. Used for the singular
12
+ * `example` field, where only the value exists.
13
13
  *
14
14
  * @param args - Arguments containing the example value
15
15
  * @returns OasExample object with the provided value
16
16
  */
17
17
  const toExampleSimpleV3 = ({ example }) => {
18
- const fields = {
19
- value: example.value,
20
- summary: example.summary,
21
- description: example.description,
22
- externalValue: example.externalValue
23
- };
18
+ const fields = { value: example };
24
19
  return new Example_js_1.OasExample(fields);
25
20
  };
26
21
  exports.toExampleSimpleV3 = toExampleSimpleV3;
@@ -35,31 +30,41 @@ exports.toExampleSimpleV3 = toExampleSimpleV3;
35
30
  * @returns Record of processed examples, or undefined if no examples
36
31
  */
37
32
  const toExamplesV3 = ({ example, examples, exampleKey, stackTrail, context }) => {
38
- if (example && examples) {
33
+ // An empty map is declared but carries nothing, so it cannot be the richer
34
+ // field — letting it win would discard the singular in favour of no examples
35
+ // at all.
36
+ const namedExamples = examples && Object.keys(examples).length > 0 ? examples : undefined;
37
+ // `example` is a literal, so test presence rather than truthiness — `false`,
38
+ // `0` and `''` are all valid example values.
39
+ if (example !== undefined && examples !== undefined) {
39
40
  context.logIssue({
40
41
  key: 'example',
41
42
  level: 'warning',
42
- message: `Both example and examples are defined for ${exampleKey}`,
43
+ message: `Both example and examples are defined for ${exampleKey}; using ${namedExamples ? 'examples' : 'example'}`,
43
44
  parent: examples,
44
45
  stackTrail,
45
46
  type: 'EXAMPLE_AND_EXAMPLES_DEFINED'
46
47
  });
47
48
  }
48
- if (example) {
49
- return {
50
- [exampleKey]: stackTrail.trace('example', st => (0, exports.toExampleSimpleV3)({ example, stackTrail: st, context }))
51
- };
52
- }
53
- if (examples) {
49
+ // The spec makes the two mutually exclusive, so reaching here with both is
50
+ // malformed input. Prefer `examples`: it is the richer field — many entries,
51
+ // each with a summary and description — and the singular carries nothing it
52
+ // cannot express, so this discards strictly less.
53
+ if (namedExamples) {
54
54
  return stackTrail.trace('examples', st => {
55
55
  const output = {};
56
- const entries = Object.entries(examples);
56
+ const entries = Object.entries(namedExamples);
57
57
  for (const [key, value] of entries) {
58
58
  output[key] = st.trace(key, st2 => (0, exports.toExampleV3)({ example: value, stackTrail: st2, context }));
59
59
  }
60
60
  return output;
61
61
  });
62
62
  }
63
+ if (example !== undefined) {
64
+ return {
65
+ [exampleKey]: stackTrail.trace('example', st => (0, exports.toExampleSimpleV3)({ example, stackTrail: st, context }))
66
+ };
67
+ }
63
68
  return undefined;
64
69
  };
65
70
  exports.toExamplesV3 = toExamplesV3;
@@ -77,7 +82,10 @@ const toExampleV3 = ({ example, stackTrail, context }) => {
77
82
  if ((0, refFns_js_1.isRef)(example)) {
78
83
  return (0, toRefV31_js_1.toRefV31)({ ref: example, refType: 'example', stackTrail, context });
79
84
  }
80
- const { summary, description, value, ...skipped } = example;
85
+ // `externalValue` is the alternative to `value` — an example too large or too
86
+ // awkward to inline. Leaving it in `skipped` both loses it and reports a
87
+ // standard field as an unexpected property.
88
+ const { summary, description, value, externalValue, ...skipped } = example;
81
89
  const extensionFields = (0, toSpecificationExtensionsV3_js_1.toSpecificationExtensionsV3)({
82
90
  skipped,
83
91
  parent: example,
@@ -89,6 +97,7 @@ const toExampleV3 = ({ example, stackTrail, context }) => {
89
97
  summary,
90
98
  description,
91
99
  value,
100
+ externalValue,
92
101
  extensionFields
93
102
  });
94
103
  };
@@ -11,6 +11,8 @@ export type ToHeadersV3Args = {
11
11
  export declare const toHeadersV3: ({ headers, stackTrail, context }: ToHeadersV3Args) => Record<string, OasHeader | OasRef<"header">> | undefined;
12
12
  export type ToHeaderV3Args = {
13
13
  header: OpenAPIV3.ReferenceObject | OpenAPIV3.HeaderObject;
14
+ /** The header's name, used to key a singular `example` */
15
+ name: string;
14
16
  stackTrail: StackTrail;
15
17
  context: ParseContextType;
16
18
  };
@@ -1 +1 @@
1
- {"version":3,"file":"toHeadersV3.d.ts","sourceRoot":"","sources":["../../../../src/parse/v3-0/header/toHeadersV3.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AAEtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAE9C,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAA;AAEzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAErD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAA;AAChE,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,eAAe,GAAG,SAAS,CAAC,YAAY,CAAC,GAAG,SAAS,CAAA;IACvF,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED,eAAO,MAAM,WAAW,GAAI,kCAIzB,eAAe,KAAG,MAAM,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,SAenE,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,SAAS,CAAC,eAAe,GAAG,SAAS,CAAC,YAAY,CAAA;IAC1D,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA"}
1
+ {"version":3,"file":"toHeadersV3.d.ts","sourceRoot":"","sources":["../../../../src/parse/v3-0/header/toHeadersV3.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AAEtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAE9C,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAA;AAEzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAErD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAA;AAChE,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,eAAe,GAAG,SAAS,CAAC,YAAY,CAAC,GAAG,SAAS,CAAA;IACvF,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED,eAAO,MAAM,WAAW,GAAI,kCAIzB,eAAe,KAAG,MAAM,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,SAenE,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,SAAS,CAAC,eAAe,GAAG,SAAS,CAAC,YAAY,CAAA;IAC1D,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA"}
@@ -15,12 +15,12 @@ const toHeadersV3 = ({ headers, stackTrail, context }) => {
15
15
  const output = {};
16
16
  const entries = Object.entries(headers);
17
17
  for (const [key, value] of entries) {
18
- output[key] = stackTrail.trace(key, st => toHeaderV3({ header: value, stackTrail: st, context }));
18
+ output[key] = stackTrail.trace(key, st => toHeaderV3({ header: value, name: key, stackTrail: st, context }));
19
19
  }
20
20
  return output;
21
21
  };
22
22
  exports.toHeadersV3 = toHeadersV3;
23
- const toHeaderV3 = ({ header, stackTrail, context }) => {
23
+ const toHeaderV3 = ({ header, name, stackTrail, context }) => {
24
24
  if ((0, refFns_js_1.isRef)(header)) {
25
25
  return (0, toRefV31_js_1.toRefV31)({ ref: header, refType: 'header', stackTrail, context });
26
26
  }
@@ -40,7 +40,7 @@ const toHeaderV3 = ({ header, stackTrail, context }) => {
40
40
  examples: (0, toExamplesV3_js_1.toExamplesV3)({
41
41
  examples,
42
42
  example,
43
- exampleKey: `TEMP`,
43
+ exampleKey: name,
44
44
  stackTrail,
45
45
  context
46
46
  }),
@@ -4,7 +4,12 @@ import { OasExample } from '../../../oas/example/Example.js';
4
4
  import type { OasRef } from '../../../oas/ref/Ref.js';
5
5
  import type { StackTrail } from '../../../context/StackTrail.js';
6
6
  export type ToExampleSimpleV3Args = {
7
- example: OpenAPIV3.ExampleObject;
7
+ /**
8
+ * The example value itself. The singular `example` field of a media type,
9
+ * parameter or header is a LITERAL value — not an Example Object — so it
10
+ * carries no `summary`, `description` or `externalValue` to read.
11
+ */
12
+ example: unknown;
8
13
  /** The stack trail for tracing */
9
14
  stackTrail: StackTrail;
10
15
  /** Parse context for tracing and error handling */
@@ -13,8 +18,8 @@ export type ToExampleSimpleV3Args = {
13
18
  /**
14
19
  * Creates a simple OAS example from a value.
15
20
  *
16
- * Converts a raw example value into an OasExample object with basic
17
- * fields. Used for simple example scenarios where only the value matters.
21
+ * Wraps a literal example value as an {@link OasExample}. Used for the singular
22
+ * `example` field, where only the value exists.
18
23
  *
19
24
  * @param args - Arguments containing the example value
20
25
  * @returns OasExample object with the provided value
@@ -27,8 +32,8 @@ export declare const toExampleSimpleV3: ({ example }: ToExampleSimpleV3Args) =>
27
32
  * with context for tracing and error handling.
28
33
  */
29
34
  export type ToExamplesV3Args = {
30
- /** Single example object (OpenAPI v3 format) */
31
- example: OpenAPIV3.ExampleObject | undefined;
35
+ /** The singular `example` field — a literal value, not an Example Object */
36
+ example: unknown;
32
37
  /** Collection of named examples (OpenAPI v3 format) */
33
38
  examples: Record<string, OpenAPIV3.ExampleObject | OpenAPIV3.ReferenceObject> | undefined;
34
39
  /** Key name for the example context */
@@ -1 +1 @@
1
- {"version":3,"file":"toExamplesV3.d.ts","sourceRoot":"","sources":["../../../../src/parse/v3-1/example/toExamplesV3.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AACtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAG9C,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAE5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAErD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAA;AAChE,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,EAAE,SAAS,CAAC,aAAa,CAAA;IAChC,kCAAkC;IAClC,UAAU,EAAE,UAAU,CAAA;IACtB,mDAAmD;IACnD,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,GAAI,aAE/B,qBAAqB,KAAG,UAAU,GAAG,MAAM,CAAC,SAAS,CASvD,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,gDAAgD;IAChD,OAAO,EAAE,SAAS,CAAC,aAAa,GAAG,SAAS,CAAA;IAC5C,uDAAuD;IACvD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,aAAa,GAAG,SAAS,CAAC,eAAe,CAAC,GAAG,SAAS,CAAA;IACzF,uCAAuC;IACvC,UAAU,EAAE,MAAM,CAAA;IAClB,kCAAkC;IAClC,UAAU,EAAE,UAAU,CAAA;IACtB,mDAAmD;IACnD,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY,GAAI,wDAM1B,gBAAgB,KAAG,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,SAoCtE,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,SAAS,CAAC,aAAa,GAAG,SAAS,CAAC,eAAe,CAAA;IAC5D,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW,GAAI,kCAIzB,eAAe,KAAG,UAAU,GAAG,MAAM,CAAC,SAAS,CAqBjD,CAAA"}
1
+ {"version":3,"file":"toExamplesV3.d.ts","sourceRoot":"","sources":["../../../../src/parse/v3-1/example/toExamplesV3.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AACtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAG9C,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAE5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAErD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAA;AAChE,MAAM,MAAM,qBAAqB,GAAG;IAClC;;;;OAIG;IACH,OAAO,EAAE,OAAO,CAAA;IAChB,kCAAkC;IAClC,UAAU,EAAE,UAAU,CAAA;IACtB,mDAAmD;IACnD,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,GAAI,aAE/B,qBAAqB,KAAG,UAAU,GAAG,MAAM,CAAC,SAAS,CAIvD,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,4EAA4E;IAC5E,OAAO,EAAE,OAAO,CAAA;IAChB,uDAAuD;IACvD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,aAAa,GAAG,SAAS,CAAC,eAAe,CAAC,GAAG,SAAS,CAAA;IACzF,uCAAuC;IACvC,UAAU,EAAE,MAAM,CAAA;IAClB,kCAAkC;IAClC,UAAU,EAAE,UAAU,CAAA;IACtB,mDAAmD;IACnD,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY,GAAI,wDAM1B,gBAAgB,KAAG,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,SAiDtE,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,SAAS,CAAC,aAAa,GAAG,SAAS,CAAC,eAAe,CAAA;IAC5D,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW,GAAI,kCAIzB,eAAe,KAAG,UAAU,GAAG,MAAM,CAAC,SAAS,CAyBjD,CAAA"}
@@ -8,19 +8,14 @@ const toSpecificationExtensionsV3_js_1 = require("../specificationExtensions/toS
8
8
  /**
9
9
  * Creates a simple OAS example from a value.
10
10
  *
11
- * Converts a raw example value into an OasExample object with basic
12
- * fields. Used for simple example scenarios where only the value matters.
11
+ * Wraps a literal example value as an {@link OasExample}. Used for the singular
12
+ * `example` field, where only the value exists.
13
13
  *
14
14
  * @param args - Arguments containing the example value
15
15
  * @returns OasExample object with the provided value
16
16
  */
17
17
  const toExampleSimpleV3 = ({ example }) => {
18
- const fields = {
19
- value: example.value,
20
- summary: example.summary,
21
- description: example.description,
22
- externalValue: example.externalValue
23
- };
18
+ const fields = { value: example };
24
19
  return new Example_js_1.OasExample(fields);
25
20
  };
26
21
  exports.toExampleSimpleV3 = toExampleSimpleV3;
@@ -35,31 +30,41 @@ exports.toExampleSimpleV3 = toExampleSimpleV3;
35
30
  * @returns Record of processed examples, or undefined if no examples
36
31
  */
37
32
  const toExamplesV3 = ({ example, examples, exampleKey, stackTrail, context }) => {
38
- if (example && examples) {
33
+ // An empty map is declared but carries nothing, so it cannot be the richer
34
+ // field — letting it win would discard the singular in favour of no examples
35
+ // at all.
36
+ const namedExamples = examples && Object.keys(examples).length > 0 ? examples : undefined;
37
+ // `example` is a literal, so test presence rather than truthiness — `false`,
38
+ // `0` and `''` are all valid example values.
39
+ if (example !== undefined && examples !== undefined) {
39
40
  context.logIssue({
40
41
  key: 'example',
41
42
  level: 'warning',
42
- message: `Both example and examples are defined for ${exampleKey}`,
43
+ message: `Both example and examples are defined for ${exampleKey}; using ${namedExamples ? 'examples' : 'example'}`,
43
44
  parent: examples,
44
45
  stackTrail,
45
46
  type: 'EXAMPLE_AND_EXAMPLES_DEFINED'
46
47
  });
47
48
  }
48
- if (example) {
49
- return {
50
- [exampleKey]: stackTrail.trace('example', st => (0, exports.toExampleSimpleV3)({ example, stackTrail: st, context }))
51
- };
52
- }
53
- if (examples) {
49
+ // The spec makes the two mutually exclusive, so reaching here with both is
50
+ // malformed input. Prefer `examples`: it is the richer field — many entries,
51
+ // each with a summary and description — and the singular carries nothing it
52
+ // cannot express, so this discards strictly less.
53
+ if (namedExamples) {
54
54
  return stackTrail.trace('examples', st => {
55
55
  const output = {};
56
- const entries = Object.entries(examples);
56
+ const entries = Object.entries(namedExamples);
57
57
  for (const [key, value] of entries) {
58
58
  output[key] = st.trace(key, st2 => (0, exports.toExampleV3)({ example: value, stackTrail: st2, context }));
59
59
  }
60
60
  return output;
61
61
  });
62
62
  }
63
+ if (example !== undefined) {
64
+ return {
65
+ [exampleKey]: stackTrail.trace('example', st => (0, exports.toExampleSimpleV3)({ example, stackTrail: st, context }))
66
+ };
67
+ }
63
68
  return undefined;
64
69
  };
65
70
  exports.toExamplesV3 = toExamplesV3;
@@ -77,7 +82,10 @@ const toExampleV3 = ({ example, stackTrail, context }) => {
77
82
  if ((0, refFns_js_1.isRef)(example)) {
78
83
  return (0, toRefV31_js_1.toRefV31)({ ref: example, refType: 'example', stackTrail, context });
79
84
  }
80
- const { summary, description, value, ...skipped } = example;
85
+ // `externalValue` is the alternative to `value` — an example too large or too
86
+ // awkward to inline. Leaving it in `skipped` both loses it and reports a
87
+ // standard field as an unexpected property.
88
+ const { summary, description, value, externalValue, ...skipped } = example;
81
89
  const extensionFields = (0, toSpecificationExtensionsV3_js_1.toSpecificationExtensionsV3)({
82
90
  skipped,
83
91
  parent: example,
@@ -89,6 +97,7 @@ const toExampleV3 = ({ example, stackTrail, context }) => {
89
97
  summary,
90
98
  description,
91
99
  value,
100
+ externalValue,
92
101
  extensionFields
93
102
  });
94
103
  };
@@ -11,6 +11,8 @@ export type ToHeadersV3Args = {
11
11
  export declare const toHeadersV3: ({ headers, stackTrail, context }: ToHeadersV3Args) => Record<string, OasHeader | OasRef<"header">> | undefined;
12
12
  export type ToHeaderV3Args = {
13
13
  header: OpenAPIV3.ReferenceObject | OpenAPIV3.HeaderObject;
14
+ /** The header's name, used to key a singular `example` */
15
+ name: string;
14
16
  stackTrail: StackTrail;
15
17
  context: ParseContextType;
16
18
  };
@@ -1 +1 @@
1
- {"version":3,"file":"toHeadersV3.d.ts","sourceRoot":"","sources":["../../../../src/parse/v3-1/header/toHeadersV3.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AAEtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAE9C,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAA;AAEzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAErD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAA;AAChE,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,eAAe,GAAG,SAAS,CAAC,YAAY,CAAC,GAAG,SAAS,CAAA;IACvF,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED,eAAO,MAAM,WAAW,GAAI,kCAIzB,eAAe,KAAG,MAAM,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,SAenE,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,SAAS,CAAC,eAAe,GAAG,SAAS,CAAC,YAAY,CAAA;IAC1D,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA"}
1
+ {"version":3,"file":"toHeadersV3.d.ts","sourceRoot":"","sources":["../../../../src/parse/v3-1/header/toHeadersV3.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AAEtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAE9C,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAA;AAEzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAErD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAA;AAChE,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,eAAe,GAAG,SAAS,CAAC,YAAY,CAAC,GAAG,SAAS,CAAA;IACvF,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED,eAAO,MAAM,WAAW,GAAI,kCAIzB,eAAe,KAAG,MAAM,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,SAenE,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,SAAS,CAAC,eAAe,GAAG,SAAS,CAAC,YAAY,CAAA;IAC1D,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA"}
@@ -15,12 +15,12 @@ const toHeadersV3 = ({ headers, stackTrail, context }) => {
15
15
  const output = {};
16
16
  const entries = Object.entries(headers);
17
17
  for (const [key, value] of entries) {
18
- output[key] = stackTrail.trace(key, st => toHeaderV3({ header: value, stackTrail: st, context }));
18
+ output[key] = stackTrail.trace(key, st => toHeaderV3({ header: value, name: key, stackTrail: st, context }));
19
19
  }
20
20
  return output;
21
21
  };
22
22
  exports.toHeadersV3 = toHeadersV3;
23
- const toHeaderV3 = ({ header, stackTrail, context }) => {
23
+ const toHeaderV3 = ({ header, name, stackTrail, context }) => {
24
24
  if ((0, refFns_js_1.isRef)(header)) {
25
25
  return (0, toRefV31_js_1.toRefV31)({ ref: header, refType: 'header', stackTrail, context });
26
26
  }
@@ -40,7 +40,7 @@ const toHeaderV3 = ({ header, stackTrail, context }) => {
40
40
  examples: (0, toExamplesV3_js_1.toExamplesV3)({
41
41
  examples,
42
42
  example,
43
- exampleKey: `TEMP`,
43
+ exampleKey: name,
44
44
  stackTrail,
45
45
  context
46
46
  }),