@pikku/openapi-parser 0.12.8 → 0.12.10

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.
@@ -93,13 +93,17 @@ export async function parseOpenAPISpec(filePath) {
93
93
  tagDescriptions,
94
94
  };
95
95
  }
96
- /** Recursively resolve $ref pointers in-place */
97
- function resolveRefs(node, root) {
96
+ /** Recursively resolve $ref pointers in-place, with cycle detection */
97
+ function resolveRefs(node, root, visited) {
98
98
  if (node === null || typeof node !== 'object')
99
99
  return node;
100
+ const seen = visited ?? new Set();
101
+ if (seen.has(node))
102
+ return node;
103
+ seen.add(node);
100
104
  if (Array.isArray(node)) {
101
105
  for (let i = 0; i < node.length; i++) {
102
- node[i] = resolveRefs(node[i], root);
106
+ node[i] = resolveRefs(node[i], root, seen);
103
107
  }
104
108
  return node;
105
109
  }
@@ -109,13 +113,14 @@ function resolveRefs(node, root) {
109
113
  // Merge any sibling properties (like description overrides)
110
114
  const { $ref, ...siblings } = node;
111
115
  const result = { ...resolved, ...siblings };
112
- // Don't recurse infinitely — mark as resolved
116
+ // Don't recurse into the merged result — it shares structure with
117
+ // the original resolved object and may be circular
113
118
  return result;
114
119
  }
115
120
  return node;
116
121
  }
117
122
  for (const key of Object.keys(node)) {
118
- node[key] = resolveRefs(node[key], root);
123
+ node[key] = resolveRefs(node[key], root, seen);
119
124
  }
120
125
  return node;
121
126
  }
@@ -342,10 +347,18 @@ export function computeContractHash(spec) {
342
347
  securitySchemes: spec.securitySchemes,
343
348
  serverUrls: spec.serverUrls,
344
349
  };
345
- return createHash('sha256')
346
- .update(JSON.stringify(contract))
347
- .digest('hex')
348
- .slice(0, 16);
350
+ // Use a cycle-safe JSON serializer since resolved $ref schemas
351
+ // can contain circular object references
352
+ const seen = new WeakSet();
353
+ const json = JSON.stringify(contract, (_key, value) => {
354
+ if (typeof value === 'object' && value !== null) {
355
+ if (seen.has(value))
356
+ return '[Circular]';
357
+ seen.add(value);
358
+ }
359
+ return value;
360
+ });
361
+ return createHash('sha256').update(json).digest('hex').slice(0, 16);
349
362
  }
350
363
  function extractTagDescriptions(doc) {
351
364
  const result = {};
@@ -1 +1 @@
1
- export { type OpenAPISchema, type ZodCodegenContext, createContext, schemaToZod, schemaVarName, sanitizeTypeName, } from './openapi-to-zod-schema.js';
1
+ export { type OpenAPISchema, type ZodCodegenContext, createContext, schemaToZod, schemaVarName, sanitizeTypeName, snakeToCamel, } from './openapi-to-zod-schema.js';
@@ -1 +1 @@
1
- export { createContext, schemaToZod, schemaVarName, sanitizeTypeName, } from './openapi-to-zod-schema.js';
1
+ export { createContext, schemaToZod, schemaVarName, sanitizeTypeName, snakeToCamel, } from './openapi-to-zod-schema.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pikku/openapi-parser",
3
- "version": "0.12.8",
3
+ "version": "0.12.10",
4
4
  "description": "OpenAPI spec parser and code generator for Pikku",
5
5
  "author": "yasser.fadl@gmail.com",
6
6
  "license": "MIT",