@samchon/openapi
Version:
OpenAPI definitions and converters for 'typia' and 'nestia'.
394 lines (393 loc) • 23.7 kB
JavaScript
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 = {}));
;