UNPKG

@furystack/rest

Version:
68 lines 2.39 kB
/** * Resolves an internal JSON Pointer (e.g. `#/components/schemas/User`) against a document tree. */ const resolvePointer = (root, pointer) => { const segments = pointer .replace(/^#\//, '') .split('/') .map((s) => s.replace(/~1/g, '/').replace(/~0/g, '~')); let current = root; for (const segment of segments) { if (current === null || current === undefined || typeof current !== 'object') return undefined; current = current[segment]; } return current; }; /** * Deep-walks a value and replaces all `{ $ref: "#/..." }` objects with the resolved target. * Tracks visited `$ref` strings to prevent infinite loops from circular references. */ const resolveNode = (node, root, visited) => { if (node === null || node === undefined || typeof node !== 'object') return node; if (Array.isArray(node)) { return node.map((item) => resolveNode(item, root, visited)); } const obj = node; if (typeof obj.$ref === 'string') { const ref = obj.$ref; if (!ref.startsWith('#/')) return node; if (visited.has(ref)) return {}; visited.add(ref); const resolved = resolvePointer(root, ref); if (resolved === undefined) return node; const result = resolveNode(resolved, root, new Set(visited)); visited.delete(ref); return result; } const result = {}; for (const [key, value] of Object.entries(obj)) { result[key] = resolveNode(value, root, visited); } return result; }; /** * Resolves all internal `$ref` pointers in an OpenAPI document, inlining the referenced objects. * * Only internal references (`#/...`) are supported. External file references are left as-is. * Circular references are broken by substituting an empty object `{}`. * * @param doc - The OpenAPI document with `$ref` pointers * @returns A new OpenAPI document with all internal `$ref` pointers resolved * * @example * ```typescript * import { resolveOpenApiRefs } from '@furystack/rest' * * const resolved = resolveOpenApiRefs(myOpenApiDoc) * // All $ref pointers have been replaced with the actual schemas * ``` */ export const resolveOpenApiRefs = (doc) => { return resolveNode(structuredClone(doc), doc, new Set()); }; //# sourceMappingURL=openapi-resolve-refs.js.map