@samchon/openapi
Version:
OpenAPI definitions and converters for 'typia' and 'nestia'.
252 lines (251 loc) • 10.3 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.LlmTypeCheckerV3 = void 0;
const OpenApiTypeCheckerBase_1 = require("./internal/OpenApiTypeCheckerBase");
/**
* Type checker for LLM type schema.
*
* `LlmSchemaTypeChecker` is a type checker of {@link ILlmSchemaV3}.
*
* @author Samchon
*/
var LlmTypeCheckerV3;
(function (LlmTypeCheckerV3) {
/* -----------------------------------------------------------
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 ILlmSchemaV3.IOneOf.oneOf}
* - {@link ILlmSchemaV3.IObject.additionalProperties}
* - {@link ILlmSchemaV3.IArray.items}
*
* @param props Properties for visiting
*/
LlmTypeCheckerV3.visit = (props) => {
var _a;
const accessor = (_a = props.accessor) !== null && _a !== void 0 ? _a : "$input.schema";
props.closure(props.schema, accessor);
if (LlmTypeCheckerV3.isOneOf(props.schema))
props.schema.oneOf.forEach((s, i) => LlmTypeCheckerV3.visit({
closure: props.closure,
schema: s,
accessor: `${accessor}.oneOf[${i}]`,
}));
else if (LlmTypeCheckerV3.isObject(props.schema)) {
for (const [k, s] of Object.entries(props.schema.properties))
LlmTypeCheckerV3.visit({
closure: props.closure,
schema: s,
accessor: `${accessor}.properties[${JSON.stringify(k)}]`,
});
if (typeof props.schema.additionalProperties === "object" &&
props.schema.additionalProperties !== null)
LlmTypeCheckerV3.visit({
closure: props.closure,
schema: props.schema.additionalProperties,
accessor: `${accessor}.additionalProperties`,
});
}
else if (LlmTypeCheckerV3.isArray(props.schema))
LlmTypeCheckerV3.visit({
closure: props.closure,
schema: props.schema.items,
accessor: `${accessor}.items`,
});
};
LlmTypeCheckerV3.covers = (x, y) => {
const alpha = flatSchema(x);
const beta = flatSchema(y);
if (alpha.some((x) => LlmTypeCheckerV3.isUnknown(x)))
return true;
else if (beta.some((x) => LlmTypeCheckerV3.isUnknown(x)))
return false;
return beta.every((b) => alpha.some((a) => {
// CHECK EQUALITY
if (a === b)
return true;
else if (LlmTypeCheckerV3.isUnknown(a))
return true;
else if (LlmTypeCheckerV3.isUnknown(b))
return false;
else if (LlmTypeCheckerV3.isNullOnly(a))
return LlmTypeCheckerV3.isNullOnly(b);
else if (LlmTypeCheckerV3.isNullOnly(b))
return LlmTypeCheckerV3.isNullable(a);
else if (LlmTypeCheckerV3.isNullable(a) && !LlmTypeCheckerV3.isNullable(b))
return false;
// ATOMIC CASE
else if (LlmTypeCheckerV3.isBoolean(a))
return LlmTypeCheckerV3.isBoolean(b) && coverBoolean(a, b);
else if (LlmTypeCheckerV3.isInteger(a))
return LlmTypeCheckerV3.isInteger(b) && coverInteger(a, b);
else if (LlmTypeCheckerV3.isNumber(a))
return (LlmTypeCheckerV3.isNumber(b) || LlmTypeCheckerV3.isInteger(b)) && coverNumber(a, b);
else if (LlmTypeCheckerV3.isString(a))
return LlmTypeCheckerV3.isString(b) && covertString(a, b);
// INSTANCE CASE
else if (LlmTypeCheckerV3.isArray(a))
return LlmTypeCheckerV3.isArray(b) && coverArray(a, b);
else if (LlmTypeCheckerV3.isObject(a))
return LlmTypeCheckerV3.isObject(b) && coverObject(a, b);
else if (LlmTypeCheckerV3.isOneOf(a))
return false;
}));
};
/**
* @internal
*/
const coverBoolean = (x, y) => x.enum === undefined ||
(y.enum !== undefined && x.enum.every((v) => y.enum.includes(v)));
/**
* @internal
*/
const coverInteger = (x, y) => {
if (x.enum !== undefined)
return y.enum !== undefined && x.enum.every((v) => y.enum.includes(v));
return x.type === y.type && OpenApiTypeCheckerBase_1.OpenApiTypeCheckerBase.coverNumericRange(x, y);
};
/**
* @internal
*/
const coverNumber = (x, y) => {
if (x.enum !== undefined)
return y.enum !== undefined && x.enum.every((v) => y.enum.includes(v));
return ((x.type === y.type || (x.type === "number" && y.type === "integer")) &&
OpenApiTypeCheckerBase_1.OpenApiTypeCheckerBase.coverNumericRange(x, y));
};
/**
* @internal
*/
const covertString = (x, y) => {
if (x.enum !== undefined)
return y.enum !== undefined && x.enum.every((v) => y.enum.includes(v));
return [
x.type === y.type,
x.format === undefined ||
(y.format !== undefined && coverFormat(x.format, y.format)),
x.pattern === undefined || x.pattern === y.pattern,
x.minLength === undefined ||
(y.minLength !== undefined && x.minLength <= y.minLength),
x.maxLength === undefined ||
(y.maxLength !== undefined && x.maxLength >= y.maxLength),
].every((v) => v);
};
const coverFormat = (x, y) => x === y ||
(x === "idn-email" && y === "email") ||
(x === "idn-hostname" && y === "hostname") ||
(["uri", "iri"].includes(x) && y === "url") ||
(x === "iri" && y === "uri") ||
(x === "iri-reference" && y === "uri-reference");
/**
* @internal
*/
const coverArray = (x, y) => LlmTypeCheckerV3.covers(x.items, y.items);
const coverObject = (x, y) => {
var _a;
if (!x.additionalProperties && !!y.additionalProperties)
return false;
else if ((!!x.additionalProperties &&
!!y.additionalProperties &&
typeof x.additionalProperties === "object" &&
y.additionalProperties === true) ||
(typeof x.additionalProperties === "object" &&
typeof y.additionalProperties === "object" &&
!LlmTypeCheckerV3.covers(x.additionalProperties, y.additionalProperties)))
return false;
return Object.entries((_a = y.properties) !== null && _a !== void 0 ? _a : {}).every(([key, b]) => {
var _a, _b, _c, _d, _e;
const a = (_a = x.properties) === null || _a === void 0 ? void 0 : _a[key];
if (a === undefined)
return false;
else if (((_c = (_b = x.required) === null || _b === void 0 ? void 0 : _b.includes(key)) !== null && _c !== void 0 ? _c : false) === true &&
((_e = (_d = y.required) === null || _d === void 0 ? void 0 : _d.includes(key)) !== null && _e !== void 0 ? _e : false) === false)
return false;
return LlmTypeCheckerV3.covers(a, b);
});
};
const flatSchema = (schema) => LlmTypeCheckerV3.isOneOf(schema) ? schema.oneOf.flatMap(flatSchema) : [schema];
/* -----------------------------------------------------------
TYPE CHECKERS
----------------------------------------------------------- */
/**
* Test whether the schema is an union type.
*
* @param schema Target schema
* @returns Whether union type or not
*/
LlmTypeCheckerV3.isOneOf = (schema) => schema.oneOf !== undefined;
/**
* Test whether the schema is an object type.
*
* @param schema Target schema
* @returns Whether object type or not
*/
LlmTypeCheckerV3.isObject = (schema) => schema.type === "object";
/**
* Test whether the schema is an array type.
*
* @param schema Target schema
* @returns Whether array type or not
*/
LlmTypeCheckerV3.isArray = (schema) => schema.type === "array";
/**
* Test whether the schema is a boolean type.
*
* @param schema Target schema
* @returns Whether boolean type or not
*/
LlmTypeCheckerV3.isBoolean = (schema) => schema.type === "boolean";
/**
* Test whether the schema is an integer type.
*
* @param schema Target schema
* @returns Whether integer type or not
*/
LlmTypeCheckerV3.isInteger = (schema) => schema.type === "integer";
/**
* Test whether the schema is a number type.
*
* @param schema Target schema
* @returns Whether number type or not
*/
LlmTypeCheckerV3.isNumber = (schema) => schema.type === "number";
/**
* Test whether the schema is a string type.
*
* @param schema Target schema
* @returns Whether string type or not
*/
LlmTypeCheckerV3.isString = (schema) => schema.type === "string";
/**
* Test whether the schema is a null type.
*
* @param schema Target schema
* @returns Whether null type or not
*/
LlmTypeCheckerV3.isNullOnly = (schema) => schema.type === "null";
/**
* Test whether the schema is a nullable type.
*
* @param schema Target schema
* @returns Whether nullable type or not
*/
LlmTypeCheckerV3.isNullable = (schema) => !LlmTypeCheckerV3.isUnknown(schema) &&
(LlmTypeCheckerV3.isNullOnly(schema) ||
(LlmTypeCheckerV3.isOneOf(schema)
? schema.oneOf.some(LlmTypeCheckerV3.isNullable)
: schema.nullable === true));
/**
* Test whether the schema is an unknown type.
*
* @param schema Target schema
* @returns Whether unknown type or not
*/
LlmTypeCheckerV3.isUnknown = (schema) => !LlmTypeCheckerV3.isOneOf(schema) && schema.type === undefined;
})(LlmTypeCheckerV3 || (exports.LlmTypeCheckerV3 = LlmTypeCheckerV3 = {}));
;