openapi-modifier
Version:
This package allows you to automate the process of modifying OpenAPI specifications by applying a set of predefined rules
124 lines (123 loc) • 5.34 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.configSchema = void 0;
const zod_1 = require("zod");
const path_1 = __importDefault(require("path"));
const fs_1 = __importDefault(require("fs"));
const yaml_1 = __importDefault(require("yaml"));
const deepmerge_1 = __importDefault(require("deepmerge"));
const each_operation_1 = require("../common/utils/iterators/each-operation");
const each_component_1 = require("../common/utils/iterators/each-component");
const configSchema = zod_1.z
.object({
path: zod_1.z.string().optional(),
ignoreOperationCollisions: zod_1.z.boolean().optional(),
ignoreComponentCollisions: zod_1.z.boolean().optional(),
})
.strict();
exports.configSchema = configSchema;
const getComponentHash = ({ name }) => `${name}`;
const getOperationHash = ({ method, path }) => `[${method}] - ${path}`;
const processor = {
configSchema,
defaultConfig: {},
processDocument: (openAPIFile, config, logger) => {
const { path: openAPIFilePath, ignoreOperationCollisions, ignoreComponentCollisions } = config;
if (!openAPIFilePath) {
logger.warning(`Empty path: ${path_1.default}`);
return openAPIFile;
}
let contentBuffer;
try {
const absoluteInputPath = path_1.default.isAbsolute(openAPIFilePath) ? openAPIFilePath : path_1.default.resolve(process.cwd(), openAPIFilePath);
logger.trace(`Absolute input path: ${absoluteInputPath}`);
contentBuffer = fs_1.default.readFileSync(absoluteInputPath);
}
catch (error) {
if (error instanceof Error) {
logger.error(error, `Not found input file: ${openAPIFilePath}`);
}
throw error;
}
const content = contentBuffer.toString();
const inputFileExtension = path_1.default.extname(openAPIFilePath) || null;
logger.trace(`Input file extension: ${inputFileExtension}`);
let document = null;
try {
switch (inputFileExtension) {
case '.yml':
case '.yaml': {
document = yaml_1.default.parse(content);
break;
}
case '.json': {
document = JSON.parse(content);
break;
}
default: {
logger.warning(`Not processable extension! ${inputFileExtension}`);
}
}
}
catch (error) {
if (error instanceof Error) {
logger.error(error, `Parse input file: ${content}`);
}
return openAPIFile;
}
if (!ignoreOperationCollisions) {
const sourceFileOperationsHashes = [];
(0, each_operation_1.forEachOperation)(openAPIFile, ({ method, path }) => {
const operationHash = getOperationHash({
method,
path,
});
sourceFileOperationsHashes.push(operationHash);
});
let operationHashCollisions = [];
(0, each_operation_1.forEachOperation)({ document }, ({ method, path }) => {
const operationHash = getOperationHash({
method,
path,
});
if (sourceFileOperationsHashes.includes(operationHash)) {
operationHashCollisions.push(operationHash);
}
});
if (operationHashCollisions === null || operationHashCollisions === void 0 ? void 0 : operationHashCollisions.length) {
const errorMessage = `Failed to merge openapi's, operaion conflicts: \n ${operationHashCollisions.join('\n')}`;
logger.errorMessage(errorMessage);
return openAPIFile;
}
}
if (!ignoreComponentCollisions) {
const sourceFileComponentHashes = [];
(0, each_component_1.forEachComponent)(openAPIFile, ({ name }) => {
const componentHash = getComponentHash({
name,
});
sourceFileComponentHashes.push(componentHash);
});
let componentHashCollisions = [];
(0, each_component_1.forEachComponent)({ document }, ({ name }) => {
const componentHash = getComponentHash({
name,
});
if (sourceFileComponentHashes.includes(componentHash)) {
componentHashCollisions.push(componentHash);
}
});
if (componentHashCollisions === null || componentHashCollisions === void 0 ? void 0 : componentHashCollisions.length) {
const errorMessage = `Failed to merge openapi's, component conflicts: \n ${componentHashCollisions.join('\n')}`;
logger.errorMessage(errorMessage);
return openAPIFile;
}
}
openAPIFile.document = (0, deepmerge_1.default)(openAPIFile.document, document);
return openAPIFile;
},
};
exports.default = processor;