UNPKG

@samchon/openapi

Version:

OpenAPI definitions and converters for 'typia' and 'nestia'.

215 lines (214 loc) 12 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.OpenApiV3Downgrader = void 0; const OpenApiTypeChecker_1 = require("../utils/OpenApiTypeChecker"); var OpenApiV3Downgrader; (function (OpenApiV3Downgrader) { OpenApiV3Downgrader.downgrade = (input) => { const collection = OpenApiV3Downgrader.downgradeComponents(input.components); return { openapi: "3.0.0", servers: input.servers, info: input.info, components: collection.downgraded, paths: input.paths ? Object.fromEntries(Object.entries(input.paths) .filter(([_, v]) => v !== undefined) .map(([key, value]) => [key, downgradePathItem(collection)(value)])) : undefined, security: input.security, tags: input.tags, }; }; /* ----------------------------------------------------------- OPERATORS ----------------------------------------------------------- */ const downgradePathItem = (collection) => (pathItem) => (Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, pathItem), (pathItem.get ? { get: downgradeOperation(collection)(pathItem.get) } : undefined)), (pathItem.put ? { put: downgradeOperation(collection)(pathItem.put) } : undefined)), (pathItem.post ? { post: downgradeOperation(collection)(pathItem.post) } : undefined)), (pathItem.delete ? { delete: downgradeOperation(collection)(pathItem.delete) } : undefined)), (pathItem.options ? { options: downgradeOperation(collection)(pathItem.options) } : undefined)), (pathItem.head ? { head: downgradeOperation(collection)(pathItem.head) } : undefined)), (pathItem.patch ? { patch: downgradeOperation(collection)(pathItem.patch) } : undefined)), (pathItem.trace ? { trace: downgradeOperation(collection)(pathItem.trace) } : undefined))); const downgradeOperation = (collection) => (input) => (Object.assign(Object.assign({}, input), { parameters: input.parameters ? input.parameters.map(downgradeParameter(collection)) : undefined, requestBody: input.requestBody ? downgradeRequestBody(collection)(input.requestBody) : undefined, responses: input.responses ? Object.fromEntries(Object.entries(input.responses) .filter(([_, v]) => v !== undefined) .map(([key, value]) => [ key, downgradeResponse(collection)(value), ])) : undefined })); const downgradeParameter = (collection) => (input) => (Object.assign(Object.assign({}, input), { schema: OpenApiV3Downgrader.downgradeSchema(collection)(input.schema) })); const downgradeRequestBody = (collection) => (input) => (Object.assign(Object.assign({}, input), { content: input.content ? downgradeContent(collection)(input.content) : undefined })); const downgradeResponse = (collection) => (input) => (Object.assign(Object.assign({}, input), { content: input.content ? downgradeContent(collection)(input.content) : undefined, headers: input.headers ? Object.fromEntries(Object.entries(input.headers) .filter(([_, v]) => v !== undefined) .map(([key, value]) => [ key, Object.assign(Object.assign({}, value), { schema: OpenApiV3Downgrader.downgradeSchema(collection)(value.schema) }), ])) : undefined })); const downgradeContent = (collection) => (record) => Object.fromEntries(Object.entries(record) .filter(([_, v]) => v !== undefined) .map(([key, value]) => [ key, Object.assign(Object.assign({}, value), { schema: (value === null || value === void 0 ? void 0 : value.schema) ? OpenApiV3Downgrader.downgradeSchema(collection)(value.schema) : undefined }), ])); /* ----------------------------------------------------------- DEFINITIONS ----------------------------------------------------------- */ OpenApiV3Downgrader.downgradeComponents = (input) => { const collection = { original: input, downgraded: { securitySchemes: input.securitySchemes, }, }; if (input.schemas) { collection.downgraded.schemas = {}; for (const [key, value] of Object.entries(input.schemas)) if (value !== undefined) collection.downgraded.schemas[key] = OpenApiV3Downgrader.downgradeSchema(collection)(value); } return collection; }; OpenApiV3Downgrader.downgradeSchema = (collection) => (input) => { const nullable = isNullable(new Set())(collection.original)(input); const union = []; const attribute = Object.assign({ title: input.title, description: input.description, example: input.example, examples: input.examples }, Object.fromEntries(Object.entries(input).filter(([key, value]) => key.startsWith("x-") && value !== undefined))); const visit = (schema) => { if (OpenApiTypeChecker_1.OpenApiTypeChecker.isBoolean(schema)) union.push({ type: "boolean" }); else if (OpenApiTypeChecker_1.OpenApiTypeChecker.isBoolean(schema) || OpenApiTypeChecker_1.OpenApiTypeChecker.isInteger(schema) || OpenApiTypeChecker_1.OpenApiTypeChecker.isNumber(schema) || OpenApiTypeChecker_1.OpenApiTypeChecker.isString(schema) || OpenApiTypeChecker_1.OpenApiTypeChecker.isReference(schema)) union.push(Object.assign({}, schema)); else if (OpenApiTypeChecker_1.OpenApiTypeChecker.isArray(schema)) union.push(Object.assign(Object.assign({}, schema), { items: OpenApiV3Downgrader.downgradeSchema(collection)(schema.items) })); else if (OpenApiTypeChecker_1.OpenApiTypeChecker.isTuple(schema)) union.push(Object.assign(Object.assign(Object.assign({}, schema), { items: (() => { if (schema.additionalItems === true) return {}; const elements = [ ...schema.prefixItems, ...(typeof schema.additionalItems === "object" ? [OpenApiV3Downgrader.downgradeSchema(collection)(schema.additionalItems)] : []), ]; if (elements.length === 0) return {}; return { oneOf: elements.map(OpenApiV3Downgrader.downgradeSchema(collection)), }; })(), minItems: schema.prefixItems.length, maxItems: !!schema.additionalItems === true ? undefined : schema.prefixItems.length }), { prefixItems: undefined, additionalItems: undefined, })); else if (OpenApiTypeChecker_1.OpenApiTypeChecker.isObject(schema)) union.push(Object.assign(Object.assign({}, schema), { properties: schema.properties ? Object.fromEntries(Object.entries(schema.properties) .filter(([_, v]) => v !== undefined) .map(([key, value]) => [ key, OpenApiV3Downgrader.downgradeSchema(collection)(value), ])) : undefined, additionalProperties: typeof schema.additionalProperties === "object" ? OpenApiV3Downgrader.downgradeSchema(collection)(schema.additionalProperties) : schema.additionalProperties, required: schema.required })); else if (OpenApiTypeChecker_1.OpenApiTypeChecker.isOneOf(schema)) schema.oneOf.forEach(visit); }; const visitConstant = (schema) => { const insert = (value) => { var _a; const matched = union.find((u) => u.type === typeof value); if (matched !== undefined) { (_a = matched.enum) !== null && _a !== void 0 ? _a : (matched.enum = []); matched.enum.push(value); } else union.push({ type: typeof value, enum: [value] }); }; if (OpenApiTypeChecker_1.OpenApiTypeChecker.isConstant(schema)) insert(schema.const); else if (OpenApiTypeChecker_1.OpenApiTypeChecker.isOneOf(schema)) for (const u of schema.oneOf) if (OpenApiTypeChecker_1.OpenApiTypeChecker.isConstant(u)) insert(u.const); }; visit(input); visitConstant(input); if (nullable === true) for (const u of union) if (OpenApiTypeChecker_1.OpenApiTypeChecker.isReference(u)) downgradeNullableReference(new Set())(collection)(u); else u.nullable = true; if (nullable === true && union.length === 0) return Object.assign({ type: "null" }, attribute); return Object.assign(Object.assign({}, (union.length === 0 ? { type: undefined } : union.length === 1 ? Object.assign({}, union[0]) : { oneOf: union })), attribute); }; const downgradeNullableReference = (visited) => (collection) => (schema) => { var _a, _b, _c; var _d; const key = schema.$ref.split("/").pop(); if (key.endsWith(".Nullable")) return; const found = (_a = collection.original.schemas) === null || _a === void 0 ? void 0 : _a[key]; if (found === undefined) return; else if (isNullable(visited)(collection.original)(found) === true) return; else if (((_b = collection.downgraded.schemas) === null || _b === void 0 ? void 0 : _b[`${key}.Nullable`]) === undefined) { (_c = (_d = collection.downgraded).schemas) !== null && _c !== void 0 ? _c : (_d.schemas = {}); collection.downgraded.schemas[`${key}.Nullable`] = {}; collection.downgraded.schemas[`${key}.Nullable`] = OpenApiV3Downgrader.downgradeSchema(collection)(OpenApiTypeChecker_1.OpenApiTypeChecker.isOneOf(found) ? Object.assign(Object.assign({}, found), { oneOf: [...found.oneOf, { type: "null" }] }) : Object.assign({ oneOf: [found, { type: "null" }], title: found.title, description: found.description, example: found.example, examples: found.examples }, Object.fromEntries(Object.entries(found).filter(([key, value]) => key.startsWith("x-") && value !== undefined)))); } schema.$ref += ".Nullable"; }; const isNullable = (visited) => (components) => (schema) => { var _a; if (OpenApiTypeChecker_1.OpenApiTypeChecker.isNull(schema)) return true; else if (OpenApiTypeChecker_1.OpenApiTypeChecker.isReference(schema)) { if (visited.has(schema.$ref)) return false; visited.add(schema.$ref); const key = schema.$ref.split("/").pop(); const next = (_a = components.schemas) === null || _a === void 0 ? void 0 : _a[key]; return next ? isNullable(visited)(components)(next) : false; } return (OpenApiTypeChecker_1.OpenApiTypeChecker.isOneOf(schema) && schema.oneOf.some(isNullable(visited)(components))); }; })(OpenApiV3Downgrader || (exports.OpenApiV3Downgrader = OpenApiV3Downgrader = {}));