UNPKG

@samchon/openapi

Version:

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

288 lines (287 loc) 11.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ChatGptTypeChecker = void 0; const MapUtil_1 = require("./MapUtil"); var ChatGptTypeChecker; (function (ChatGptTypeChecker) { /* ----------------------------------------------------------- TYPE CHECKERS ----------------------------------------------------------- */ /** * Test whether the schema is a nul type. * * @param schema Target schema * @returns Whether null type or not */ ChatGptTypeChecker.isNull = (schema) => schema.type === "null"; /** * Test whether the schema is an unknown type. * * @param schema Target schema * @returns Whether unknown type or not */ ChatGptTypeChecker.isUnknown = (schema) => schema.type === undefined && !ChatGptTypeChecker.isAnyOf(schema) && !ChatGptTypeChecker.isReference(schema); /** * Test whether the schema is a boolean type. * * @param schema Target schema * @returns Whether boolean type or not */ ChatGptTypeChecker.isBoolean = (schema) => schema.type === "boolean"; /** * Test whether the schema is an integer type. * * @param schema Target schema * @returns Whether integer type or not */ ChatGptTypeChecker.isInteger = (schema) => schema.type === "integer"; /** * Test whether the schema is a number type. * * @param schema Target schema * @returns Whether number type or not */ ChatGptTypeChecker.isNumber = (schema) => schema.type === "number"; /** * Test whether the schema is a string type. * * @param schema Target schema * @returns Whether string type or not */ ChatGptTypeChecker.isString = (schema) => schema.type === "string"; /** * Test whether the schema is an array type. * * @param schema Target schema * @returns Whether array type or not */ ChatGptTypeChecker.isArray = (schema) => schema.type === "array" && schema.items !== undefined; /** * Test whether the schema is an object type. * * @param schema Target schema * @returns Whether object type or not */ ChatGptTypeChecker.isObject = (schema) => schema.type === "object"; /** * Test whether the schema is a reference type. * * @param schema Target schema * @returns Whether reference type or not */ ChatGptTypeChecker.isReference = (schema) => schema.$ref !== undefined; /** * Test whether the schema is an union type. * * @param schema Target schema * @returns Whether union type or not */ ChatGptTypeChecker.isAnyOf = (schema) => schema.anyOf !== undefined; /* ----------------------------------------------------------- OPERATORS ----------------------------------------------------------- */ /** * Visit every nested schemas. * * Visit every nested schemas of the target, and apply the `props.closure` function. * * Here is the list of occurring nested visitings: * * - {@link IChatGptSchema.IAnyOf.anyOf} * - {@link IChatGptSchema.IReference} * - {@link IChatGptSchema.IObject.properties} * - {@link IChatGptSchema.IArray.items} * * @param props Properties for visiting */ ChatGptTypeChecker.visit = (props) => { var _a, _b; const already = new Set(); const refAccessor = (_a = props.refAccessor) !== null && _a !== void 0 ? _a : "$input.$defs"; const next = (schema, accessor) => { var _a; props.closure(schema, accessor); if (ChatGptTypeChecker.isReference(schema)) { const key = schema.$ref.split("#/$defs/").pop(); if (already.has(key) === true) return; already.add(key); const found = (_a = props.$defs) === null || _a === void 0 ? void 0 : _a[key]; if (found !== undefined) next(found, `${refAccessor}[${key}]`); } else if (ChatGptTypeChecker.isAnyOf(schema)) schema.anyOf.forEach((s, i) => next(s, `${accessor}.anyOf[${i}]`)); else if (ChatGptTypeChecker.isObject(schema)) { for (const [key, value] of Object.entries(schema.properties)) next(value, `${accessor}.properties[${JSON.stringify(key)}]`); if (typeof schema.additionalProperties === "object" && schema.additionalProperties !== null) next(schema.additionalProperties, `${accessor}.additionalProperties`); } else if (ChatGptTypeChecker.isArray(schema)) next(schema.items, `${accessor}.items`); }; next(props.schema, (_b = props.accessor) !== null && _b !== void 0 ? _b : "$input.schemas"); }; /** * Test whether the `x` schema covers the `y` schema. * * @param props Properties for testing * @returns Whether the `x` schema covers the `y` schema */ ChatGptTypeChecker.covers = (props) => coverStation({ $defs: props.$defs, x: props.x, y: props.y, visited: new Map(), }); const coverStation = (p) => { var _a; const cache = (_a = p.visited.get(p.x)) === null || _a === void 0 ? void 0 : _a.get(p.y); if (cache !== undefined) return cache; // FOR RECURSIVE CASE const nested = MapUtil_1.MapUtil.take(p.visited)(p.x)(() => new Map()); nested.set(p.y, true); // COMPUTE IT const result = coverSchema(p); nested.set(p.y, result); return result; }; const coverSchema = (p) => { // CHECK EQUALITY if (p.x === p.y) return true; else if (ChatGptTypeChecker.isReference(p.x) && ChatGptTypeChecker.isReference(p.y) && p.x.$ref === p.y.$ref) return true; // COMPARE WITH FLATTENING const alpha = flatSchema(p.$defs, p.x); const beta = flatSchema(p.$defs, p.y); if (alpha.some((x) => ChatGptTypeChecker.isUnknown(x))) return true; else if (beta.some((x) => ChatGptTypeChecker.isUnknown(x))) return false; return beta.every((b) => alpha.some((a) => coverEscapedSchema({ $defs: p.$defs, visited: p.visited, x: a, y: b, }))); }; const coverEscapedSchema = (p) => { // CHECK EQUALITY if (p.x === p.y) return true; else if (ChatGptTypeChecker.isUnknown(p.x)) return true; else if (ChatGptTypeChecker.isUnknown(p.y)) return false; else if (ChatGptTypeChecker.isNull(p.x)) return ChatGptTypeChecker.isNull(p.y); // ATOMIC CASE else if (ChatGptTypeChecker.isBoolean(p.x)) return ChatGptTypeChecker.isBoolean(p.y) && coverBoolean(p.x, p.y); else if (ChatGptTypeChecker.isInteger(p.x)) return ChatGptTypeChecker.isInteger(p.y) && coverInteger(p.x, p.y); else if (ChatGptTypeChecker.isNumber(p.x)) return ChatGptTypeChecker.isNumber(p.y) && coverNumber(p.x, p.y); else if (ChatGptTypeChecker.isString(p.x)) return ChatGptTypeChecker.isString(p.y) && coverString(p.x, p.y); // INSTANCE CASE else if (ChatGptTypeChecker.isArray(p.x)) return (ChatGptTypeChecker.isArray(p.y) && coverArray({ $defs: p.$defs, visited: p.visited, x: p.x, y: p.y, })); else if (ChatGptTypeChecker.isObject(p.x)) return (ChatGptTypeChecker.isObject(p.y) && coverObject({ $defs: p.$defs, visited: p.visited, x: p.x, y: p.y, })); else if (ChatGptTypeChecker.isReference(p.x)) return ChatGptTypeChecker.isReference(p.y) && p.x.$ref === p.y.$ref; return false; }; const coverArray = (p) => coverStation({ $defs: p.$defs, visited: p.visited, x: p.x.items, y: p.y.items, }); const coverObject = (p) => { var _a; if (!p.x.additionalProperties && !!p.y.additionalProperties) return false; else if (!!p.x.additionalProperties && !!p.y.additionalProperties && ((typeof p.x.additionalProperties === "object" && p.y.additionalProperties === true) || (typeof p.x.additionalProperties === "object" && typeof p.y.additionalProperties === "object" && !coverStation({ $defs: p.$defs, visited: p.visited, x: p.x.additionalProperties, y: p.y.additionalProperties, })))) return false; return Object.entries((_a = p.y.properties) !== null && _a !== void 0 ? _a : {}).every(([key, b]) => { var _a, _b, _c, _d, _e; const a = (_a = p.x.properties) === null || _a === void 0 ? void 0 : _a[key]; if (a === undefined) return false; else if (((_c = (_b = p.x.required) === null || _b === void 0 ? void 0 : _b.includes(key)) !== null && _c !== void 0 ? _c : false) === true && ((_e = (_d = p.y.required) === null || _d === void 0 ? void 0 : _d.includes(key)) !== null && _e !== void 0 ? _e : false) === false) return false; return coverStation({ $defs: p.$defs, visited: p.visited, x: a, y: b, }); }); }; const coverBoolean = (x, y) => { var _a, _b; if (!!((_a = x.enum) === null || _a === void 0 ? void 0 : _a.length)) return !!((_b = y.enum) === null || _b === void 0 ? void 0 : _b.length) && y.enum.every((v) => x.enum.includes(v)); return true; }; const coverInteger = (x, y) => { var _a, _b; if (!!((_a = x.enum) === null || _a === void 0 ? void 0 : _a.length)) return !!((_b = y.enum) === null || _b === void 0 ? void 0 : _b.length) && y.enum.every((v) => x.enum.includes(v)); return x.type === y.type; }; const coverNumber = (x, y) => { var _a, _b; if (!!((_a = x.enum) === null || _a === void 0 ? void 0 : _a.length)) return !!((_b = y.enum) === null || _b === void 0 ? void 0 : _b.length) && y.enum.every((v) => x.enum.includes(v)); return x.type === y.type || (x.type === "number" && y.type === "integer"); }; const coverString = (x, y) => { var _a, _b; if (!!((_a = x.enum) === null || _a === void 0 ? void 0 : _a.length)) return !!((_b = y.enum) === null || _b === void 0 ? void 0 : _b.length) && y.enum.every((v) => x.enum.includes(v)); return x.type === y.type; }; const flatSchema = ($defs, schema) => { schema = escapeReference($defs, schema); if (ChatGptTypeChecker.isAnyOf(schema)) return schema.anyOf.map((v) => flatSchema($defs, v)).flat(); return [schema]; }; const escapeReference = ($defs, schema) => ChatGptTypeChecker.isReference(schema) ? escapeReference($defs, $defs[schema.$ref.replace("#/$defs/", "")]) : schema; })(ChatGptTypeChecker || (exports.ChatGptTypeChecker = ChatGptTypeChecker = {}));