oas
Version:
Comprehensive tooling for working with OpenAPI definitions
135 lines (134 loc) • 4.51 kB
JavaScript
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