UNPKG

oas

Version:

Comprehensive tooling for working with OpenAPI definitions

135 lines (134 loc) 4.51 kB
import { query } from "../chunk-CKC36IL7.js"; // src/reducer/index.ts import jsonPointer from "jsonpointer"; function getUsedRefs(schema) { return query(["$..['$ref']"], schema); } function accumulateUsedRefs(schema, $refs, $ref) { let $refSchema; if (typeof $ref === "string") $refSchema = jsonPointer.get(schema, $ref.substring(1)); if ($refSchema === void 0) { return; } getUsedRefs($refSchema).forEach(({ value: currRef }) => { if (typeof currRef !== "string") { return; } if ($refs.has(currRef)) { return; } $refs.add(currRef); accumulateUsedRefs(schema, $refs, currRef); }); } function reducer(definition, opts = {}) { const reduceTags = "tags" in opts ? opts.tags.map((tag) => tag.toLowerCase()) : []; const reducePaths = "paths" in opts ? Object.entries(opts.paths).reduce((acc, [key, value]) => { const newKey = key.toLowerCase(); const newValue = Array.isArray(value) ? value.map((v) => v.toLowerCase()) : value.toLowerCase(); acc[newKey] = newValue; return acc; }, {}) : {}; const $refs = /* @__PURE__ */ new Set(); const usedTags = /* @__PURE__ */ new Set(); if (!definition.openapi) { throw new Error("Sorry, only OpenAPI definitions are supported."); } const reduced = JSON.parse(JSON.stringify(definition)); if ("security" in reduced) { Object.values(reduced.security).forEach((sec) => { Object.keys(sec).forEach((scheme) => { $refs.add(`#/components/securitySchemes/${scheme}`); }); }); } if ("paths" in reduced) { Object.keys(reduced.paths).forEach((path) => { const pathLC = path.toLowerCase(); if (Object.keys(reducePaths).length) { if (!(pathLC in reducePaths)) { delete reduced.paths[path]; return; } } Object.keys(reduced.paths[path]).forEach((method) => { if (method !== "parameters") { if (Object.keys(reducePaths).length) { if (reducePaths[pathLC] !== "*" && Array.isArray(reducePaths[pathLC]) && !reducePaths[pathLC].includes(method)) { delete reduced.paths[path][method]; return; } } } const operation = reduced.paths[path][method]; if (reduceTags.length) { if (!("tags" in operation)) { delete reduced.paths[path][method]; return; } else if (!operation.tags.filter((tag) => reduceTags.includes(tag.toLowerCase())).length) { delete reduced.paths[path][method]; return; } } if ("tags" in operation) { operation.tags.forEach((tag) => { usedTags.add(tag); }); } getUsedRefs(operation).forEach(({ value: ref }) => { $refs.add(ref); }); if ("security" in operation) { Object.values(operation.security).forEach((sec) => { Object.keys(sec).forEach((scheme) => { $refs.add(`#/components/securitySchemes/${scheme}`); }); }); } }); if (!Object.keys(reduced.paths[path]).length) { delete reduced.paths[path]; } }); if (!Object.keys(reduced.paths).length) { throw new Error("All paths in the API definition were removed. Did you supply the right path name to reduce by?"); } } $refs.forEach(($ref) => accumulateUsedRefs(reduced, $refs, $ref)); if ("components" in reduced) { Object.keys(reduced.components).forEach((componentType) => { Object.keys(reduced.components[componentType]).forEach((component) => { const refIsUsed = $refs.has(`#/components/${componentType}/${component}`) || Array.from($refs).some((ref) => { return ref.startsWith(`#/components/${componentType}/${component}/`); }); if (!refIsUsed) { delete reduced.components[componentType][component]; } }); if (!Object.keys(reduced.components[componentType]).length) { delete reduced.components[componentType]; } }); if (!Object.keys(reduced.components).length) { delete reduced.components; } } if ("tags" in reduced) { reduced.tags.forEach((tag, k) => { if (!usedTags.has(tag.name)) { delete reduced.tags[k]; } }); reduced.tags = reduced.tags.filter(Boolean); if (!reduced.tags.length) { delete reduced.tags; } } return reduced; } export { reducer as default }; //# sourceMappingURL=index.js.map