UNPKG

@samchon/openapi

Version:

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

394 lines (393 loc) 23.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.OpenApiV3_1Emender = void 0; const OpenApiExclusiveEmender_1 = require("../utils/OpenApiExclusiveEmender"); var OpenApiV3_1Emender; (function (OpenApiV3_1Emender) { OpenApiV3_1Emender.convert = (input) => { var _a; if (input["x-samchon-emended-v4"] === true) return input; return Object.assign(Object.assign({}, input), { components: convertComponents((_a = input.components) !== null && _a !== void 0 ? _a : {}), paths: input.paths ? Object.fromEntries(Object.entries(input.paths) .filter(([_, v]) => v !== undefined) .map(([key, value]) => [key, convertPathItem(input)(value)])) : undefined, webhooks: input.webhooks ? Object.fromEntries(Object.entries(input.webhooks) .filter(([_, v]) => v !== undefined) .map(([key, value]) => [key, convertWebhooks(input)(value)]) .filter(([_, value]) => value !== undefined)) : undefined, "x-samchon-emended-v4": true }); }; /* ----------------------------------------------------------- OPERATORS ----------------------------------------------------------- */ const convertWebhooks = (doc) => (webhook) => { var _a, _b, _c; if (!TypeChecker.isReference(webhook)) return convertPathItem(doc)(webhook); const found = (_b = (_a = doc.components) === null || _a === void 0 ? void 0 : _a.pathItems) === null || _b === void 0 ? void 0 : _b[(_c = webhook.$ref.split("/").pop()) !== null && _c !== void 0 ? _c : ""]; return found ? convertPathItem(doc)(found) : undefined; }; const convertPathItem = (doc) => (pathItem) => (Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, pathItem), (pathItem.get ? { get: convertOperation(doc)(pathItem)(pathItem.get) } : undefined)), (pathItem.put ? { put: convertOperation(doc)(pathItem)(pathItem.put) } : undefined)), (pathItem.post ? { post: convertOperation(doc)(pathItem)(pathItem.post) } : undefined)), (pathItem.delete ? { delete: convertOperation(doc)(pathItem)(pathItem.delete) } : undefined)), (pathItem.options ? { options: convertOperation(doc)(pathItem)(pathItem.options) } : undefined)), (pathItem.head ? { head: convertOperation(doc)(pathItem)(pathItem.head) } : undefined)), (pathItem.patch ? { patch: convertOperation(doc)(pathItem)(pathItem.patch) } : undefined)), (pathItem.trace ? { trace: convertOperation(doc)(pathItem)(pathItem.trace) } : undefined))); const convertOperation = (doc) => (pathItem) => (input) => { var _a, _b; return (Object.assign(Object.assign({}, input), { parameters: pathItem.parameters !== undefined || input.parameters !== undefined ? [...((_a = pathItem.parameters) !== null && _a !== void 0 ? _a : []), ...((_b = input.parameters) !== null && _b !== void 0 ? _b : [])] .map((p) => { var _a, _b, _c, _d, _e, _f, _g, _h; if (!TypeChecker.isReference(p)) return convertParameter((_a = doc.components) !== null && _a !== void 0 ? _a : {})(p); const found = p.$ref.startsWith("#/components/headers/") ? (_c = (_b = doc.components) === null || _b === void 0 ? void 0 : _b.headers) === null || _c === void 0 ? void 0 : _c[(_d = p.$ref.split("/").pop()) !== null && _d !== void 0 ? _d : ""] : (_f = (_e = doc.components) === null || _e === void 0 ? void 0 : _e.parameters) === null || _f === void 0 ? void 0 : _f[(_g = p.$ref.split("/").pop()) !== null && _g !== void 0 ? _g : ""]; return found !== undefined ? convertParameter((_h = doc.components) !== null && _h !== void 0 ? _h : {})(Object.assign(Object.assign({}, found), { in: "header" })) : undefined; }) .filter((_, v) => v !== undefined) : undefined, requestBody: input.requestBody ? convertRequestBody(doc)(input.requestBody) : undefined, responses: input.responses ? Object.fromEntries(Object.entries(input.responses) .filter(([_, v]) => v !== undefined) .map(([key, value]) => [key, convertResponse(doc)(value)]) .filter(([_, value]) => value !== undefined)) : undefined })); }; const convertParameter = (components) => (input) => (Object.assign(Object.assign({}, input), { schema: convertSchema(components)(input.schema), examples: input.examples ? Object.fromEntries(Object.entries(input.examples) .map(([key, value]) => { var _a, _b; return [ key, TypeChecker.isReference(value) ? (_a = components.examples) === null || _a === void 0 ? void 0 : _a[(_b = value.$ref.split("/").pop()) !== null && _b !== void 0 ? _b : ""] : value, ]; }) .filter(([_, v]) => v !== undefined)) : undefined })); const convertRequestBody = (doc) => (input) => { var _a, _b, _c, _d; if (TypeChecker.isReference(input)) { const found = (_b = (_a = doc.components) === null || _a === void 0 ? void 0 : _a.requestBodies) === null || _b === void 0 ? void 0 : _b[(_c = input.$ref.split("/").pop()) !== null && _c !== void 0 ? _c : ""]; if (found === undefined) return undefined; input = found; } return Object.assign(Object.assign({}, input), { content: input.content ? convertContent((_d = doc.components) !== null && _d !== void 0 ? _d : {})(input.content) : undefined }); }; const convertResponse = (doc) => (input) => { var _a, _b, _c, _d; if (TypeChecker.isReference(input)) { const found = (_b = (_a = doc.components) === null || _a === void 0 ? void 0 : _a.responses) === null || _b === void 0 ? void 0 : _b[(_c = input.$ref.split("/").pop()) !== null && _c !== void 0 ? _c : ""]; if (found === undefined) return undefined; input = found; } return Object.assign(Object.assign({}, input), { content: input.content ? convertContent((_d = doc.components) !== null && _d !== void 0 ? _d : {})(input.content) : undefined, headers: input.headers ? Object.fromEntries(Object.entries(input.headers) .filter(([_, v]) => v !== undefined) .map(([key, value]) => [ key, (() => { var _a, _b, _c, _d, _e; if (TypeChecker.isReference(value) === false) return convertParameter((_a = doc.components) !== null && _a !== void 0 ? _a : {})(Object.assign(Object.assign({}, value), { in: "header" })); const found = value.$ref.startsWith("#/components/headers/") ? (_c = (_b = doc.components) === null || _b === void 0 ? void 0 : _b.headers) === null || _c === void 0 ? void 0 : _c[(_d = value.$ref.split("/").pop()) !== null && _d !== void 0 ? _d : ""] : undefined; return found !== undefined ? convertParameter((_e = doc.components) !== null && _e !== void 0 ? _e : {})(Object.assign(Object.assign({}, found), { in: "header" })) : undefined; })(), ]) .filter(([_, v]) => v !== undefined)) : undefined }); }; const convertContent = (components) => (record) => Object.fromEntries(Object.entries(record) .filter(([_, v]) => v !== undefined) .map(([key, value]) => [ key, Object.assign(Object.assign({}, value), { schema: value.schema ? convertSchema(components)(value.schema) : undefined, examples: value.examples ? Object.fromEntries(Object.entries(value.examples) .map(([key, value]) => { var _a, _b; return [ key, TypeChecker.isReference(value) ? (_a = components.examples) === null || _a === void 0 ? void 0 : _a[(_b = value.$ref.split("/").pop()) !== null && _b !== void 0 ? _b : ""] : value, ]; }) .filter(([_, v]) => v !== undefined)) : undefined }), ])); /* ----------------------------------------------------------- DEFINITIONS ----------------------------------------------------------- */ const convertComponents = (input) => { var _a; return ({ schemas: Object.fromEntries(Object.entries((_a = input.schemas) !== null && _a !== void 0 ? _a : {}) .filter(([_, v]) => v !== undefined) .map(([key, value]) => [key, convertSchema(input)(value)])), securitySchemes: input.securitySchemes, }); }; const convertSchema = (components) => (input) => { const union = []; const attribute = Object.assign(Object.assign({ title: input.title, description: input.description }, Object.fromEntries(Object.entries(input).filter(([key, value]) => key.startsWith("x-") && value !== undefined))), { examples: Array.isArray(input.examples) ? Object.fromEntries(input.examples.map((v, i) => [`v${i}`, v])) : input.examples }); const nullable = { value: false, default: undefined, }; const visit = (schema) => { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l; // NULLABLE PROPERTY if (schema.nullable === true) { nullable.value || (nullable.value = true); if (schema.default === null) nullable.default = null; } if (Array.isArray(schema.enum) && ((_a = schema.enum) === null || _a === void 0 ? void 0 : _a.length) && ((_b = schema.enum) === null || _b === void 0 ? void 0 : _b.some((e) => e === null))) nullable.value || (nullable.value = true); // MIXED TYPE CASE if (TypeChecker.isMixed(schema)) { if (schema.const !== undefined) visit(Object.assign(Object.assign({}, schema), { type: undefined, oneOf: undefined, anyOf: undefined, allOf: undefined, $ref: undefined, })); if (schema.oneOf !== undefined) visit(Object.assign(Object.assign({}, schema), { type: undefined, anyOf: undefined, allOf: undefined, $ref: undefined, })); if (schema.anyOf !== undefined) visit(Object.assign(Object.assign({}, schema), { type: undefined, oneOf: undefined, allOf: undefined, $ref: undefined, })); if (schema.allOf !== undefined) visit(Object.assign(Object.assign({}, schema), { type: undefined, oneOf: undefined, anyOf: undefined, $ref: undefined, })); for (const type of schema.type) if (type === "boolean" || type === "number" || type === "string") visit(Object.assign(Object.assign(Object.assign({}, schema), { enum: ((_c = schema.enum) === null || _c === void 0 ? void 0 : _c.length) && schema.enum.filter((e) => e !== null) ? schema.enum.filter((x) => typeof x === type) : undefined, }), { type: type })); else if (type === "integer") visit(Object.assign(Object.assign(Object.assign({}, schema), { enum: ((_d = schema.enum) === null || _d === void 0 ? void 0 : _d.length) && schema.enum.filter((e) => e !== null) ? schema.enum.filter((x) => x !== null && typeof x === "number" && Number.isInteger(x)) : undefined, }), { type: type })); else visit(Object.assign(Object.assign({}, schema), { type: type })); } // UNION TYPE CASE else if (TypeChecker.isOneOf(schema)) schema.oneOf.forEach(visit); else if (TypeChecker.isAnyOf(schema)) schema.anyOf.forEach(visit); else if (TypeChecker.isAllOf(schema)) if (schema.allOf.length === 1) visit(schema.allOf[0]); else union.push(convertAllOfSchema(components)(schema)); // ATOMIC TYPE CASE (CONSIDER ENUM VALUES) else if (TypeChecker.isBoolean(schema)) if (((_e = schema.enum) === null || _e === void 0 ? void 0 : _e.length) && schema.enum.filter((e) => e !== null).length) for (const value of schema.enum.filter((e) => e !== null)) union.push(Object.assign({ const: value }, Object.assign(Object.assign({}, schema), { type: undefined, enum: undefined, default: undefined }))); else union.push(Object.assign(Object.assign(Object.assign({}, schema), { default: (_f = schema.default) !== null && _f !== void 0 ? _f : undefined }), { enum: undefined, })); else if (TypeChecker.isInteger(schema) || TypeChecker.isNumber(schema)) if (((_g = schema.enum) === null || _g === void 0 ? void 0 : _g.length) && schema.enum.filter((e) => e !== null)) for (const value of schema.enum.filter((e) => e !== null)) union.push(Object.assign({ const: value }, Object.assign(Object.assign({}, schema), { type: undefined, enum: undefined, default: undefined, minimum: undefined, maximum: undefined, exclusiveMinimum: undefined, exclusiveMaximum: undefined, multipleOf: undefined }))); else union.push(OpenApiExclusiveEmender_1.OpenApiExclusiveEmender.emend(Object.assign(Object.assign(Object.assign(Object.assign({}, schema), { default: (_h = schema.default) !== null && _h !== void 0 ? _h : undefined }), { enum: undefined, }), { exclusiveMinimum: typeof schema.exclusiveMinimum === "boolean" ? schema.exclusiveMinimum === true ? schema.minimum : undefined : schema.exclusiveMinimum, exclusiveMaximum: typeof schema.exclusiveMaximum === "boolean" ? schema.exclusiveMaximum === true ? schema.maximum : undefined : schema.exclusiveMaximum, minimum: schema.exclusiveMinimum === true ? undefined : schema.minimum, maximum: schema.exclusiveMaximum === true ? undefined : schema.maximum }))); else if (TypeChecker.isString(schema)) if (((_j = schema.enum) === null || _j === void 0 ? void 0 : _j.length) && schema.enum.filter((e) => e !== null).length) for (const value of schema.enum.filter((e) => e !== null)) union.push(Object.assign({ const: value }, Object.assign(Object.assign({}, schema), { type: undefined, enum: undefined, default: undefined }))); else union.push(Object.assign(Object.assign(Object.assign({}, schema), { default: (_k = schema.default) !== null && _k !== void 0 ? _k : undefined }), { enum: undefined, })); // ARRAY TYPE CASE (CONSIDER TUPLE) else if (TypeChecker.isArray(schema)) { if (Array.isArray(schema.items)) union.push(Object.assign(Object.assign({}, schema), { items: undefined, prefixItems: schema.items.map(convertSchema(components)), additionalItems: typeof schema.additionalItems === "object" && schema.additionalItems !== null ? convertSchema(components)(schema.additionalItems) : schema.additionalItems, })); else if (Array.isArray(schema.prefixItems)) union.push(Object.assign(Object.assign({}, schema), { items: undefined, prefixItems: schema.prefixItems.map(convertSchema(components)), additionalItems: typeof schema.additionalItems === "object" && schema.additionalItems !== null ? convertSchema(components)(schema.additionalItems) : schema.additionalItems, })); else if (schema.items === undefined) union.push(Object.assign(Object.assign({}, schema), { items: undefined, prefixItems: [], })); else union.push(Object.assign(Object.assign({}, schema), { items: convertSchema(components)(schema.items), prefixItems: undefined, additionalItems: undefined, })); } // OBJECT TYPE CASE else if (TypeChecker.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, convertSchema(components)(value)])) : {}, additionalProperties: schema.additionalProperties ? typeof schema.additionalProperties === "object" && schema.additionalProperties !== null ? convertSchema(components)(schema.additionalProperties) : schema.additionalProperties : undefined, required: (_l = schema.required) !== null && _l !== void 0 ? _l : [], })); else if (TypeChecker.isRecursiveReference(schema)) union.push(Object.assign(Object.assign({}, schema), { $ref: schema.$recursiveRef, $recursiveRef: undefined, })); // THE OTHERS else union.push(schema); }; visit(input); if (nullable.value === true && !union.some((e) => e.type === "null")) union.push({ type: "null", default: nullable.default, }); return Object.assign(Object.assign(Object.assign({}, (union.length === 0 ? { type: undefined } : union.length === 1 ? Object.assign({}, union[0]) : { oneOf: union.map((u) => (Object.assign(Object.assign({}, u), { nullable: undefined }))) })), attribute), { nullable: undefined }); }; const convertAllOfSchema = (components) => (input) => { const objects = input.allOf.map((schema) => retrieveObject(components)(schema)); if (objects.some((obj) => obj === null)) return Object.assign({ type: undefined }, { allOf: undefined, }); return Object.assign(Object.assign(Object.assign({}, input), { type: "object", properties: Object.fromEntries(objects .map((o) => { var _a; return Object.entries((_a = o === null || o === void 0 ? void 0 : o.properties) !== null && _a !== void 0 ? _a : {}); }) .flat() .map(([key, value]) => [key, convertSchema(components)(value)])) }), { allOf: undefined, required: [...new Set(objects.map((o) => { var _a; return (_a = o === null || o === void 0 ? void 0 : o.required) !== null && _a !== void 0 ? _a : []; }).flat())], }); }; const retrieveObject = (components) => (input, visited = new Set()) => { var _a, _b, _c, _d, _e, _f; if (TypeChecker.isObject(input)) return input.properties !== undefined && !input.additionalProperties ? input : null; else if (visited.has(input)) return null; else visited.add(input); if (TypeChecker.isReference(input)) return retrieveObject(components)((_c = (_a = components.schemas) === null || _a === void 0 ? void 0 : _a[(_b = input.$ref.split("/").pop()) !== null && _b !== void 0 ? _b : ""]) !== null && _c !== void 0 ? _c : {}, visited); else if (TypeChecker.isRecursiveReference(input)) return retrieveObject(components)((_f = (_d = components.schemas) === null || _d === void 0 ? void 0 : _d[(_e = input.$recursiveRef.split("/").pop()) !== null && _e !== void 0 ? _e : ""]) !== null && _f !== void 0 ? _f : {}, visited); return null; }; let TypeChecker; (function (TypeChecker) { TypeChecker.isConstant = (schema) => schema.const !== undefined; TypeChecker.isBoolean = (schema) => schema.type === "boolean"; TypeChecker.isInteger = (schema) => schema.type === "integer"; TypeChecker.isNumber = (schema) => schema.type === "number"; TypeChecker.isString = (schema) => schema.type === "string"; TypeChecker.isArray = (schema) => schema.type === "array"; TypeChecker.isObject = (schema) => schema.type === "object"; TypeChecker.isReference = (schema) => schema.$ref !== undefined; TypeChecker.isRecursiveReference = (schema) => schema.$recursiveRef !== undefined; TypeChecker.isAllOf = (schema) => schema.allOf !== undefined; TypeChecker.isAnyOf = (schema) => schema.anyOf !== undefined; TypeChecker.isOneOf = (schema) => schema.oneOf !== undefined; TypeChecker.isNullOnly = (schema) => schema.type === "null"; TypeChecker.isMixed = (schema) => Array.isArray(schema.type); })(TypeChecker || (TypeChecker = {})); })(OpenApiV3_1Emender || (exports.OpenApiV3_1Emender = OpenApiV3_1Emender = {}));