openapi-modifier
Version:
This package allows you to automate the process of modifying OpenAPI specifications by applying a set of predefined rules
169 lines (168 loc) • 10.3 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.configSchema = void 0;
const zod_1 = require("zod");
const normilizers_1 = require("../common/utils/normilizers");
const config_1 = require("../common/config");
const refs_1 = require("../common/utils/refs");
const each_operation_1 = require("../common/utils/iterators/each-operation");
const each_schema_1 = require("../common/utils/iterators/each-schema");
const object_schema_1 = require("../common/utils/object-schema");
const deep_clone_1 = require("../common/utils/deep-clone");
const factory_1 = require("../../logger/messages/factory");
const parse_component_descriptor_1 = require("../common/utils/config/parse-component-descriptor");
const empty_1 = require("../common/utils/empty");
const parse_endpoint_descriptor_1 = require("../common/utils/config/parse-endpoint-descriptor");
const configSchema = zod_1.z
.object({
ignoreComponents: zod_1.z.array(config_1.anyComponentDescriptorConfigSchema).optional(),
ignoreEndpoints: zod_1.z.array(config_1.anyEndpointDescriptorConfigSchema).optional(),
ignoreEndpointParameters: zod_1.z.array(config_1.parameterDescriptorConfigSchema).optional(),
showDeprecatedDescriptions: zod_1.z.boolean().optional(),
})
.strict();
exports.configSchema = configSchema;
const processor = {
configSchema,
defaultConfig: {},
processDocument: (openAPIFile, config, logger) => {
var _a, _b;
const { ignoreComponents, ignoreEndpoints, ignoreEndpointParameters, showDeprecatedDescriptions } = config;
const sourceOpenAPIFile = (0, deep_clone_1.deepClone)(openAPIFile);
const parsedIgnoreComponents = ignoreComponents === null || ignoreComponents === void 0 ? void 0 : ignoreComponents.map((componentDescriptor) => {
return (0, parse_component_descriptor_1.parseAnyComponentDescriptor)(componentDescriptor, logger);
}).filter(empty_1.isNonNil);
const parsedIgnoreEndpoints = ignoreEndpoints === null || ignoreEndpoints === void 0 ? void 0 : ignoreEndpoints.map((endpointDescriptor) => {
return (0, parse_endpoint_descriptor_1.parseAnyEndpointDescriptor)(endpointDescriptor, logger);
}).filter(empty_1.isNonNil);
const usageIgnoreComponents = (parsedIgnoreComponents === null || parsedIgnoreComponents === void 0 ? void 0 : parsedIgnoreComponents.reduce((acc, item) => {
acc[item.componentName] = 0;
return acc;
}, {})) || {};
const componentSchemas = (_b = (_a = openAPIFile.document) === null || _a === void 0 ? void 0 : _a.components) === null || _b === void 0 ? void 0 : _b.schemas;
Object.keys(componentSchemas || {}).forEach((name) => {
if (!componentSchemas) {
return;
}
const schema = componentSchemas === null || componentSchemas === void 0 ? void 0 : componentSchemas[name];
const checkIsIgnoredComponent = ({ name }) => {
if (!parsedIgnoreComponents) {
return false;
}
const shouldIgnore = parsedIgnoreComponents.some((item) => {
return item.componentName === name;
});
if (!usageIgnoreComponents[name]) {
usageIgnoreComponents[name] = 0;
}
usageIgnoreComponents[name] += 1;
return shouldIgnore;
};
if (!(0, refs_1.checkIsRefSchema)(schema) &&
(schema === null || schema === void 0 ? void 0 : schema.deprecated) &&
!checkIsIgnoredComponent({ name })) {
logger.trace(`Deleted component - "${name}"`);
if (showDeprecatedDescriptions) {
logger.notImportantWarning(factory_1.messagesFactory.deprecated.field(name, schema === null || schema === void 0 ? void 0 : schema.description));
}
delete componentSchemas[name];
}
if ((0, refs_1.checkIsRefSchema)(schema) && !checkIsIgnoredComponent({ name })) {
const resolvedSchema = (0, refs_1.resolveRef)(sourceOpenAPIFile, schema);
if (resolvedSchema === null || resolvedSchema === void 0 ? void 0 : resolvedSchema.deprecated) {
logger.trace(`Deleted component by resolving ref - "${name}"`);
if (showDeprecatedDescriptions) {
logger.notImportantWarning(factory_1.messagesFactory.deprecated.fieldByRef(name, resolvedSchema === null || resolvedSchema === void 0 ? void 0 : resolvedSchema.description));
}
componentSchemas === null || componentSchemas === void 0 ? true : delete componentSchemas[name];
}
}
});
(0, each_operation_1.forEachOperation)(openAPIFile, ({ operationSchema, method, path }) => {
var _a, _b, _c;
const pathObjSchema = (_b = (_a = openAPIFile === null || openAPIFile === void 0 ? void 0 : openAPIFile.document) === null || _a === void 0 ? void 0 : _a.paths) === null || _b === void 0 ? void 0 : _b[path];
const checkIsIgnoredEndpoint = ({ path, method }) => {
if (!parsedIgnoreEndpoints) {
return false;
}
return parsedIgnoreEndpoints.some((item) => {
return item.path === path && (0, normilizers_1.normalizeMethod)(item.method) === (0, normilizers_1.normalizeMethod)(method);
});
};
if (operationSchema.deprecated &&
pathObjSchema &&
!checkIsIgnoredEndpoint({
path,
method,
})) {
logger.trace(`Deleted endpoint - "${JSON.stringify({ path, method })}"`);
if (showDeprecatedDescriptions) {
logger.notImportantWarning(factory_1.messagesFactory.deprecated.endpoint(method, path, (_c = pathObjSchema[method]) === null || _c === void 0 ? void 0 : _c.description));
}
delete pathObjSchema[method];
}
if (operationSchema === null || operationSchema === void 0 ? void 0 : operationSchema.parameters) {
operationSchema.parameters = operationSchema.parameters.filter((parameter) => {
const checkIsIgnoredEndpointParameter = ({ path, method, parameterName, parameterIn }) => {
if (!ignoreEndpointParameters) {
return false;
}
return ignoreEndpointParameters.some((item) => {
return (item.path === path &&
(0, normilizers_1.normalizeMethod)(item.method) === (0, normilizers_1.normalizeMethod)(method) &&
item.name === parameterName &&
item.in === parameterIn);
});
};
if (!(0, refs_1.checkIsRefSchema)(parameter) &&
(parameter === null || parameter === void 0 ? void 0 : parameter.deprecated) &&
!checkIsIgnoredEndpointParameter({
path,
method,
parameterName: parameter.name,
parameterIn: parameter.in,
})) {
logger.trace(`Deleted parameter - "${JSON.stringify(parameter)}"`);
if (showDeprecatedDescriptions) {
logger.notImportantWarning(factory_1.messagesFactory.deprecated.endpointParameter(method, path, parameter.name, parameter.in, parameter === null || parameter === void 0 ? void 0 : parameter.description));
}
return false;
}
return true;
});
}
});
(0, each_schema_1.forEachSchema)(openAPIFile, (schema) => {
if ((0, object_schema_1.checkIsObjectSchema)(schema)) {
const properties = (schema === null || schema === void 0 ? void 0 : schema.properties) || {};
Object.keys(properties).forEach((propertyKey) => {
const propertySchema = properties[propertyKey];
if (!(0, refs_1.checkIsRefSchema)(propertySchema) && (propertySchema === null || propertySchema === void 0 ? void 0 : propertySchema.deprecated)) {
logger.trace(`Deleted property - "${propertyKey}"`);
if (showDeprecatedDescriptions) {
logger.notImportantWarning(factory_1.messagesFactory.deprecated.field(propertyKey, propertySchema === null || propertySchema === void 0 ? void 0 : propertySchema.description));
}
delete properties[propertyKey];
}
if ((0, refs_1.checkIsRefSchema)(propertySchema)) {
const resolvedPropertySchema = (0, refs_1.resolveRef)(sourceOpenAPIFile, propertySchema);
if (resolvedPropertySchema === null || resolvedPropertySchema === void 0 ? void 0 : resolvedPropertySchema.deprecated) {
logger.trace(`Deleted property by resolving ref - "${propertyKey}"`);
if (showDeprecatedDescriptions) {
logger.notImportantWarning(factory_1.messagesFactory.deprecated.fieldByRef(propertyKey, resolvedPropertySchema === null || resolvedPropertySchema === void 0 ? void 0 : resolvedPropertySchema.description));
}
delete properties[propertyKey];
}
}
});
}
});
Object.keys(usageIgnoreComponents).forEach((componentName) => {
if (!usageIgnoreComponents[componentName]) {
logger.warning(`Not usaged ignore component: "${componentName}"`);
}
});
return openAPIFile;
},
};
exports.default = processor;