openapi-modifier
Version:
This package allows you to automate the process of modifying OpenAPI specifications by applying a set of predefined rules
102 lines (101 loc) • 4.82 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.configSchema = void 0;
const zod_1 = require("zod");
const each_schema_1 = require("../common/utils/iterators/each-schema");
const config_1 = require("../common/config");
const parse_component_descriptor_1 = require("../common/utils/config/parse-component-descriptor");
const empty_1 = require("../common/utils/empty");
const configSchema = zod_1.z
.object({
ignore: zod_1.z.array(zod_1.z.union([
config_1.simpleComponentDescriptorConfigSchema,
config_1.componentDescriptorConfigSchema,
zod_1.z.instanceof(RegExp),
])).optional(),
printDeletedComponents: zod_1.z.boolean().optional(),
})
.strict();
exports.configSchema = configSchema;
const REF_SEPARATOR = '/';
const shortenRef = (ref) => {
return ref.split(REF_SEPARATOR).slice(0, 4).join(REF_SEPARATOR);
};
const processor = {
configSchema,
defaultConfig: {},
processDocument: (openAPIFile, config, logger) => {
const { ignore, printDeletedComponents } = config;
const ignoredComponentRegExps = (ignore || []).map(item => {
if (item instanceof RegExp) {
return item;
}
return null;
}).filter(empty_1.isNonNil);
const ignoredComponentNames = (ignore || []).map(item => {
if (item instanceof RegExp) {
return null;
}
return (0, parse_component_descriptor_1.parseAnyComponentDescriptor)(item, logger);
}).map(componentDescriptor => componentDescriptor === null || componentDescriptor === void 0 ? void 0 : componentDescriptor.componentName).filter(empty_1.isNonNil);
logger.trace(`Ignore component names: ${ignoredComponentNames}`);
const ignoredComponentNamesSet = new Set(ignoredComponentNames);
const usageIgnoredComponentNames = ignoredComponentNames.reduce((acc, componentName) => {
acc[componentName] = 0;
return acc;
}, {});
const components = openAPIFile.document.components || {};
let hasUnusedComponents = true;
while (hasUnusedComponents) {
logger.trace(`New iteration of removing unused components ...`);
let usagedCount = {};
Object.keys(components).forEach((component) => {
Object.keys(components[component] || {}).forEach((key) => {
const isIgnored = (ignoredComponentNamesSet === null || ignoredComponentNamesSet === void 0 ? void 0 : ignoredComponentNamesSet.has(key)) || ignoredComponentRegExps.some((ignoredComponentRegExp) => {
return ignoredComponentRegExp.test(key);
});
if (isIgnored) {
if (!usageIgnoredComponentNames[key]) {
usageIgnoredComponentNames[key] = 0;
}
usageIgnoredComponentNames[key] += 1;
return;
}
usagedCount[`#/components/${component}/${key}`] = 0;
});
});
logger.trace('usageIgnoredComponentNames', usageIgnoredComponentNames);
(0, each_schema_1.forEachSchema)(openAPIFile, (schema) => {
logger.trace('forEachSchema the callback was called', schema);
if ('$ref' in schema) {
const shortenedRef = shortenRef(schema['$ref']);
usagedCount[shortenedRef] = (usagedCount[shortenedRef] || 0) + 1;
}
});
logger.trace('usagedCount', usagedCount);
hasUnusedComponents = false;
Object.keys(usagedCount).forEach((ref) => {
var _a;
if (!usagedCount[ref]) {
logger.trace('Removing ref ... - ', ref);
hasUnusedComponents = true;
const [, , component, key] = ref.split(REF_SEPARATOR);
const componentsObj = (_a = openAPIFile.document.components) === null || _a === void 0 ? void 0 : _a[component];
if (componentsObj) {
if (printDeletedComponents) {
logger.info(`Deleted the "${key}" component ("${component}") as not used`);
}
delete componentsObj[key];
}
}
});
}
Object.keys(usageIgnoredComponentNames).forEach((ignoredComponentName) => {
if (!usageIgnoredComponentNames[ignoredComponentName]) {
logger.warning(`Not usaged ignore component: "${ignoredComponentName}"`);
}
});
return openAPIFile;
},
};
exports.default = processor;