@samchon/openapi
Version:
OpenAPI definitions and converters for 'typia' and 'nestia'.
237 lines (236 loc) • 11 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LlmSchemaV3Composer = void 0;
const OpenApiV3Downgrader_1 = require("../../converters/OpenApiV3Downgrader");
const OpenApiV3Upgrader_1 = require("../../converters/OpenApiV3Upgrader");
const LlmTypeCheckerV3_1 = require("../../utils/LlmTypeCheckerV3");
const OpenApiConstraintShifter_1 = require("../../utils/OpenApiConstraintShifter");
const OpenApiTypeChecker_1 = require("../../utils/OpenApiTypeChecker");
const OpenApiValidator_1 = require("../../utils/OpenApiValidator");
const LlmDescriptionInverter_1 = require("./LlmDescriptionInverter");
const LlmParametersComposer_1 = require("./LlmParametersComposer");
var LlmSchemaV3Composer;
(function (LlmSchemaV3Composer) {
/**
* @internal
*/
LlmSchemaV3Composer.IS_DEFS = false;
/* -----------------------------------------------------------
CONVERTERS
----------------------------------------------------------- */
LlmSchemaV3Composer.parameters = (props) => {
const entity = LlmParametersComposer_1.LlmParametersFinder.parameters(Object.assign(Object.assign({}, props), { method: "LlmSchemaV3Composer.parameters" }));
if (entity.success === false)
return entity;
const result = LlmSchemaV3Composer.schema(props);
if (result.success === false)
return result;
return {
success: true,
value: Object.assign(Object.assign({}, result.value), { additionalProperties: false }),
};
};
LlmSchemaV3Composer.schema = (props) => {
// CHECK TUPLE TYPE
const reasons = [];
OpenApiTypeChecker_1.OpenApiTypeChecker.visit({
closure: (next, accessor) => {
var _a;
if (props.validate)
reasons.push(...props.validate(next, accessor));
if (OpenApiTypeChecker_1.OpenApiTypeChecker.isTuple(next))
reasons.push({
accessor: accessor,
schema: next,
message: "LLM does not allow tuple type.",
});
else if (OpenApiTypeChecker_1.OpenApiTypeChecker.isReference(next)) {
// UNABLE TO FIND MATCHED REFERENCE
const key = next.$ref.split("#/components/schemas/")[1];
if (((_a = props.components.schemas) === null || _a === void 0 ? void 0 : _a[key]) === undefined) {
reasons.push({
schema: next,
message: `${accessor}: unable to find reference type ${JSON.stringify(key)}.`,
accessor: accessor,
});
}
}
},
components: props.components,
schema: props.schema,
accessor: props.accessor,
refAccessor: props.refAccessor,
});
// if ((valid as boolean) === false) return null;
if (reasons.length > 0)
return {
success: false,
error: {
method: "LlmSchemaV3Composer.schema",
message: "Failed to compose LLM schema of v3",
reasons,
},
};
// CHECK MISMATCHES
const escaped = OpenApiTypeChecker_1.OpenApiTypeChecker.escape(Object.assign(Object.assign({}, props), { recursive: props.config.recursive }));
if (escaped.success === false)
// UNREACHABLE
return {
success: false,
error: {
method: "LlmSchemaV3Composer.schema",
message: "Failed to compose LLM schema of v3",
reasons: escaped.error.reasons,
},
};
// SPECIALIZATIONS
const downgraded = OpenApiV3Downgrader_1.OpenApiV3Downgrader.downgradeSchema({
original: {
schemas: {},
},
downgraded: {},
})(escaped.value);
LlmTypeCheckerV3_1.LlmTypeCheckerV3.visit({
closure: (next) => {
var _a, _b;
if (LlmTypeCheckerV3_1.LlmTypeCheckerV3.isOneOf(next) &&
next.discriminator !== undefined)
delete next.discriminator;
else if (LlmTypeCheckerV3_1.LlmTypeCheckerV3.isObject(next)) {
(_a = next.properties) !== null && _a !== void 0 ? _a : (next.properties = {});
(_b = next.required) !== null && _b !== void 0 ? _b : (next.required = []);
}
if (props.config.constraint === false) {
if (LlmTypeCheckerV3_1.LlmTypeCheckerV3.isInteger(next) ||
LlmTypeCheckerV3_1.LlmTypeCheckerV3.isNumber(next))
OpenApiConstraintShifter_1.OpenApiConstraintShifter.shiftNumeric(next);
else if (LlmTypeCheckerV3_1.LlmTypeCheckerV3.isString(next))
OpenApiConstraintShifter_1.OpenApiConstraintShifter.shiftString(next);
else if (LlmTypeCheckerV3_1.LlmTypeCheckerV3.isArray(next))
OpenApiConstraintShifter_1.OpenApiConstraintShifter.shiftArray(next);
}
},
schema: downgraded,
});
return {
success: true,
value: downgraded,
};
};
/* -----------------------------------------------------------
SEPARATORS
----------------------------------------------------------- */
LlmSchemaV3Composer.separateParameters = (props) => {
var _a;
const [llm, human] = separateObject({
predicate: props.predicate,
schema: props.parameters,
});
return {
llm: (_a = llm) !== null && _a !== void 0 ? _a : {
type: "object",
properties: {},
additionalProperties: false,
required: [],
},
human: human,
validate: llm
? OpenApiValidator_1.OpenApiValidator.create({
components: {},
schema: LlmSchemaV3Composer.invert({ schema: llm }),
required: true,
})
: undefined,
};
};
const separateStation = (props) => {
if (props.predicate(props.schema) === true)
return [null, props.schema];
else if (LlmTypeCheckerV3_1.LlmTypeCheckerV3.isUnknown(props.schema) ||
LlmTypeCheckerV3_1.LlmTypeCheckerV3.isOneOf(props.schema))
return [props.schema, null];
else if (LlmTypeCheckerV3_1.LlmTypeCheckerV3.isObject(props.schema))
return separateObject({
predicate: props.predicate,
schema: props.schema,
});
else if (LlmTypeCheckerV3_1.LlmTypeCheckerV3.isArray(props.schema))
return separateArray({
predicate: props.predicate,
schema: props.schema,
});
return [props.schema, null];
};
const separateArray = (props) => {
const [x, y] = separateStation({
predicate: props.predicate,
schema: props.schema.items,
});
return [
x !== null
? Object.assign(Object.assign({}, props.schema), { items: x }) : null,
y !== null
? Object.assign(Object.assign({}, props.schema), { items: y }) : null,
];
};
const separateObject = (props) => {
var _a, _b;
// EMPTY OBJECT
if (Object.keys((_a = props.schema.properties) !== null && _a !== void 0 ? _a : {}).length === 0 &&
!!props.schema.additionalProperties === false)
return [props.schema, null];
const llm = Object.assign(Object.assign({}, props.schema), { properties: {}, additionalProperties: props.schema.additionalProperties });
const human = Object.assign(Object.assign({}, props.schema), { properties: {}, additionalProperties: props.schema.additionalProperties });
for (const [key, value] of Object.entries((_b = props.schema.properties) !== null && _b !== void 0 ? _b : {})) {
const [x, y] = separateStation({
predicate: props.predicate,
schema: value,
});
if (x !== null)
llm.properties[key] = x;
if (y !== null)
human.properties[key] = y;
}
if (typeof props.schema.additionalProperties === "object" &&
props.schema.additionalProperties !== null) {
const [dx, dy] = separateStation({
predicate: props.predicate,
schema: props.schema.additionalProperties,
});
llm.additionalProperties = dx !== null && dx !== void 0 ? dx : false;
human.additionalProperties = dy !== null && dy !== void 0 ? dy : false;
}
return [
!!Object.keys(llm.properties).length || !!llm.additionalProperties
? shrinkRequired(llm)
: null,
!!Object.keys(human.properties).length || !!human.additionalProperties
? shrinkRequired(human)
: null,
];
};
const shrinkRequired = (s) => {
s.required = s.required.filter((key) => s.properties[key] !== undefined);
return s;
};
/* -----------------------------------------------------------
INVERTERS
----------------------------------------------------------- */
LlmSchemaV3Composer.invert = (props) => {
const upgraded = OpenApiV3Upgrader_1.OpenApiV3Upgrader.convertSchema({})(props.schema);
OpenApiTypeChecker_1.OpenApiTypeChecker.visit({
closure: (schema) => {
if (OpenApiTypeChecker_1.OpenApiTypeChecker.isArray(schema))
Object.assign(schema, Object.assign(Object.assign({}, schema), LlmDescriptionInverter_1.LlmDescriptionInverter.array(schema.description)));
else if (OpenApiTypeChecker_1.OpenApiTypeChecker.isInteger(schema) ||
OpenApiTypeChecker_1.OpenApiTypeChecker.isNumber(schema))
Object.assign(schema, Object.assign(Object.assign({}, schema), LlmDescriptionInverter_1.LlmDescriptionInverter.numeric(schema.description)));
else if (OpenApiTypeChecker_1.OpenApiTypeChecker.isString(schema))
Object.assign(schema, Object.assign(Object.assign({}, schema), LlmDescriptionInverter_1.LlmDescriptionInverter.string(schema.description)));
},
components: {},
schema: upgraded,
});
return upgraded;
};
})(LlmSchemaV3Composer || (exports.LlmSchemaV3Composer = LlmSchemaV3Composer = {}));