UNPKG

@samchon/openapi

Version:

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

294 lines (293 loc) 15.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SwaggerV2Downgrader = void 0; const OpenApiTypeChecker_1 = require("../utils/OpenApiTypeChecker"); var SwaggerV2Downgrader; (function (SwaggerV2Downgrader) { SwaggerV2Downgrader.downgrade = (input) => { var _a, _b, _c; const collection = SwaggerV2Downgrader.downgradeComponents(input.components); return { swagger: "2.0", info: input.info, host: ((_b = (_a = input.servers) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.url) ? input.servers[0].url.split("://").pop() : "", definitions: collection.downgraded, securityDefinitions: ((_c = input.components) === null || _c === void 0 ? void 0 : _c.securitySchemes) ? Object.fromEntries(Object.entries(input.components.securitySchemes) .filter(([_, v]) => v !== undefined) .map(([key, value]) => downgradeSecurityScheme(value).map((v) => [key, v])) .flat()) : undefined, 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) => { var _a; return (Object.assign(Object.assign(Object.assign({}, input), { parameters: input.parameters !== undefined || input.requestBody !== undefined ? [ ...((_a = input.parameters) !== null && _a !== void 0 ? _a : []).map(downgradeParameter(collection)), ...(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 }), { requestBody: undefined, servers: undefined, })); }; const downgradeParameter = (collection) => (input, i) => { var _a, _b; return (Object.assign(Object.assign(Object.assign(Object.assign({}, SwaggerV2Downgrader.downgradeSchema(collection)(input.schema)), input), { required: (_a = input.schema) === null || _a === void 0 ? void 0 : _a.required, schema: undefined, name: (_b = input.name) !== null && _b !== void 0 ? _b : `p${i}` }), { example: undefined, examples: undefined, })); }; const downgradeRequestBody = (collection) => (input) => { var _a, _b, _c; return ({ name: "body", in: "body", description: input.description, required: input.required, schema: SwaggerV2Downgrader.downgradeSchema(collection)((_c = (_b = Object.values((_a = input.content) !== null && _a !== void 0 ? _a : {})[0]) === null || _b === void 0 ? void 0 : _b.schema) !== null && _c !== void 0 ? _c : {}), }); }; const downgradeResponse = (collection) => (input) => { var _a, _b, _c; return ({ description: input.description, schema: SwaggerV2Downgrader.downgradeSchema(collection)((_c = (_b = Object.values((_a = input.content) !== null && _a !== void 0 ? _a : {})[0]) === null || _b === void 0 ? void 0 : _b.schema) !== null && _c !== void 0 ? _c : {}), headers: input.headers ? Object.fromEntries(Object.entries(input.headers) .filter(([_, v]) => v !== undefined) .map(([key, value]) => [ key, Object.assign(Object.assign(Object.assign({}, value), { schema: SwaggerV2Downgrader.downgradeSchema(collection)(value.schema) }), { example: undefined, examples: undefined, }), ])) : undefined, }); }; /* ----------------------------------------------------------- DEFINITIONS ----------------------------------------------------------- */ SwaggerV2Downgrader.downgradeComponents = (input) => { const collection = { original: input, downgraded: {}, }; if (input.schemas) { collection.downgraded.schemas = {}; for (const [key, value] of Object.entries(input.schemas)) if (value !== undefined) collection.downgraded[key.split("/").pop()] = SwaggerV2Downgrader.downgradeSchema(collection)(value); } return collection; }; SwaggerV2Downgrader.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.values(input.examples) : undefined }, 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)) union.push(Object.assign(Object.assign({}, schema), { examples: schema.examples ? Object.values(schema.examples) : undefined })); else if (OpenApiTypeChecker_1.OpenApiTypeChecker.isReference(schema)) union.push({ $ref: `#/definitions/${schema.$ref.split("/").pop()}` }); else if (OpenApiTypeChecker_1.OpenApiTypeChecker.isArray(schema)) union.push(Object.assign(Object.assign({}, schema), { items: SwaggerV2Downgrader.downgradeSchema(collection)(schema.items), examples: schema.examples ? Object.values(schema.examples) : undefined })); else if (OpenApiTypeChecker_1.OpenApiTypeChecker.isTuple(schema)) union.push(Object.assign(Object.assign(Object.assign(Object.assign({}, schema), { items: (() => { if (schema.additionalItems === true) return {}; const elements = [ ...schema.prefixItems, ...(typeof schema.additionalItems === "object" ? [SwaggerV2Downgrader.downgradeSchema(collection)(schema.additionalItems)] : []), ]; if (elements.length === 0) return {}; return { "x-oneOf": elements.map(SwaggerV2Downgrader.downgradeSchema(collection)), }; })(), minItems: schema.prefixItems.length, maxItems: !!schema.additionalItems === true ? undefined : schema.prefixItems.length }), { prefixItems: undefined, additionalItems: undefined, }), { examples: schema.examples ? Object.values(schema.examples) : 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, SwaggerV2Downgrader.downgradeSchema(collection)(value), ])) : undefined, additionalProperties: typeof schema.additionalProperties === "object" ? SwaggerV2Downgrader.downgradeSchema(collection)(schema.additionalProperties) : schema.additionalProperties, required: schema.required, examples: schema.examples ? Object.values(schema.examples) : undefined })); 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 === 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)) schema.oneOf.forEach(insert); }; }; visit(input); visitConstant(input); if (nullable) { for (const u of union) if (OpenApiTypeChecker_1.OpenApiTypeChecker.isReference(u)) downgradeNullableReference(new Set())(collection)(u); else u["x-nullable"] = true; } if (nullable === true && union.length === 0) return Object.assign({ type: "null" }, attribute); return Object.assign(Object.assign(Object.assign({}, (union.length === 0 ? { type: undefined } : union.length === 1 ? Object.assign({}, union[0]) : { "x-oneOf": union })), attribute), (union.length > 1 ? { discriminator: undefined } : {})); }; const downgradeNullableReference = (visited) => (collection) => (schema) => { var _a; 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 (collection.downgraded[`${key}.Nullable`] === undefined) { collection.downgraded[`${key}.Nullable`] = {}; collection.downgraded[`${key}.Nullable`] = SwaggerV2Downgrader.downgradeSchema(collection)(OpenApiTypeChecker_1.OpenApiTypeChecker.isOneOf(found) ? Object.assign(Object.assign({}, found), { oneOf: [...found.oneOf, { type: "null" }] }) : Object.assign(Object.assign({ title: found.title, description: found.description, example: found.example, examples: found.examples ? Object.values(found.examples) : undefined }, Object.fromEntries(Object.entries(found).filter(([key, value]) => key.startsWith("x-") && value !== undefined))), { oneOf: [found, { type: "null" }] })); } schema.$ref += ".Nullable"; }; const downgradeSecurityScheme = (input) => { if (input.type === "apiKey") return [input]; else if (input.type === "http") if (input.scheme === "basic") return [{ type: "basic", description: input.description }]; else return []; else if (input.type === "oauth2") { const output = []; if (input.flows.implicit) output.push({ type: "oauth2", flow: "implicit", authorizationUrl: input.flows.implicit.authorizationUrl, scopes: input.flows.implicit.scopes, }); if (input.flows.password) output.push({ type: "oauth2", flow: "password", tokenUrl: input.flows.password.tokenUrl, scopes: input.flows.password.scopes, }); if (input.flows.clientCredentials) output.push({ type: "oauth2", flow: "application", tokenUrl: input.flows.clientCredentials.tokenUrl, scopes: input.flows.clientCredentials.scopes, }); if (input.flows.authorizationCode) output.push({ type: "oauth2", flow: "accessCode", authorizationUrl: input.flows.authorizationCode.authorizationUrl, tokenUrl: input.flows.authorizationCode.tokenUrl, scopes: input.flows.authorizationCode.scopes, }); return output; } return []; }; 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))); }; })(SwaggerV2Downgrader || (exports.SwaggerV2Downgrader = SwaggerV2Downgrader = {}));