@skmtc/core 0.28.4 → 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.
@@ -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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skmtc/core",
3
- "version": "0.28.4",
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;