@samchon/openapi
Advanced tools
Comparing version 1.1.2 to 1.2.0-dev.20241111
@@ -10,3 +10,4 @@ import { OpenApi } from "../OpenApi"; | ||
schema: OpenApi.IJsonSchema; | ||
recursive: false | number; | ||
}) => ILlmSchema | null; | ||
} |
@@ -57,4 +57,26 @@ "use strict"; | ||
.map(function (route) { | ||
if (route.method === "head") | ||
var _a, _b; | ||
if (route.method === "head") { | ||
errors.push({ | ||
method: route.method, | ||
path: route.path, | ||
messages: ["HEAD method is not supported in the LLM application."], | ||
operation: function () { return route.operation(); }, | ||
route: function () { return route; }, | ||
}); | ||
return null; | ||
} | ||
else if (((_a = route.body) === null || _a === void 0 ? void 0 : _a.type) === "multipart/form-data" || | ||
((_b = route.success) === null || _b === void 0 ? void 0 : _b.type) === "multipart/form-data") { | ||
errors.push({ | ||
method: route.method, | ||
path: route.path, | ||
messages: [ | ||
"The \"multipart/form-data\" content type is not supported in the LLM application.", | ||
], | ||
operation: function () { return route.operation(); }, | ||
route: function () { return route; }, | ||
}); | ||
return null; | ||
} | ||
var func = composeFunction(options)(migrate.document().components)(route); | ||
@@ -80,6 +102,6 @@ if (func === null) | ||
HttpLlmConverter.schema = function (props) { | ||
var resolved = escape({ | ||
var resolved = OpenApiTypeChecker_1.OpenApiTypeChecker.escape({ | ||
components: props.components, | ||
visited: new Set(), | ||
input: props.schema, | ||
schema: props.schema, | ||
recursive: props.recursive, | ||
}); | ||
@@ -109,2 +131,3 @@ if (resolved === null) | ||
schema: s, | ||
recursive: options.recursive, | ||
}); | ||
@@ -195,86 +218,1 @@ }; | ||
}; | ||
var escape = function (props) { | ||
var _a; | ||
if (OpenApiTypeChecker_1.OpenApiTypeChecker.isReference(props.input)) { | ||
// REFERENCE | ||
var name_1 = props.input.$ref.split("#/components/schemas/")[1]; | ||
var target = (_a = props.components.schemas) === null || _a === void 0 ? void 0 : _a[name_1]; | ||
if (!target) | ||
return null; | ||
else if (props.visited.has(name_1)) | ||
return null; | ||
return escape({ | ||
components: props.components, | ||
visited: new Set(__spreadArray(__spreadArray([], __read(props.visited), false), [name_1], false)), | ||
input: target, | ||
}); | ||
} | ||
else if (OpenApiTypeChecker_1.OpenApiTypeChecker.isOneOf(props.input)) { | ||
// ONE-OF | ||
var oneOf = props.input.oneOf.map(function (schema) { | ||
return escape(__assign(__assign({}, props), { input: schema })); | ||
}); | ||
if (oneOf.some(function (v) { return v === null; })) | ||
return null; | ||
return __assign(__assign({}, props.input), { oneOf: flat(oneOf) }); | ||
} | ||
else if (OpenApiTypeChecker_1.OpenApiTypeChecker.isObject(props.input)) { | ||
// OBJECT | ||
var properties = props.input.properties | ||
? Object.entries(props.input.properties).map(function (_a) { | ||
var _b = __read(_a, 2), key = _b[0], value = _b[1]; | ||
return [ | ||
key, | ||
escape(__assign(__assign({}, props), { input: value })), | ||
]; | ||
}) | ||
: undefined; | ||
var additionalProperties = props.input.additionalProperties | ||
? typeof props.input.additionalProperties === "object" && | ||
props.input.additionalProperties !== null | ||
? escape(__assign(__assign({}, props), { input: props.input.additionalProperties })) | ||
: props.input.additionalProperties | ||
: undefined; | ||
if (properties && properties.some(function (_a) { | ||
var _b = __read(_a, 2), _k = _b[0], v = _b[1]; | ||
return v === null; | ||
})) | ||
return null; | ||
else if (additionalProperties === null) | ||
return null; | ||
return __assign(__assign({}, props.input), { properties: properties | ||
? Object.fromEntries(properties.filter(function (_a) { | ||
var _b = __read(_a, 2), _k = _b[0], v = _b[1]; | ||
return !!v; | ||
})) | ||
: undefined, additionalProperties: additionalProperties }); | ||
} | ||
else if (OpenApiTypeChecker_1.OpenApiTypeChecker.isTuple(props.input)) { | ||
// TUPLE | ||
var prefixItems = props.input.prefixItems.map(function (schema) { | ||
return escape(__assign(__assign({}, props), { input: schema })); | ||
}); | ||
var additionalItems = typeof props.input.additionalItems === "object" && | ||
props.input.additionalItems !== null | ||
? escape(__assign(__assign({}, props), { input: props.input.additionalItems })) | ||
: props.input.additionalItems; | ||
if (prefixItems.some(function (v) { return v === null; })) | ||
return null; | ||
else if (additionalItems === null) | ||
return null; | ||
return __assign(__assign({}, props.input), { prefixItems: prefixItems, additionalItems: additionalItems }); | ||
} | ||
else if (OpenApiTypeChecker_1.OpenApiTypeChecker.isArray(props.input)) { | ||
// ARRAY | ||
var items = escape(__assign(__assign({}, props), { input: props.input.items })); | ||
if (items === null) | ||
return null; | ||
return __assign(__assign({}, props.input), { items: items }); | ||
} | ||
return props.input; | ||
}; | ||
var flat = function (elements) { | ||
return elements | ||
.map(function (elem) { return (OpenApiTypeChecker_1.OpenApiTypeChecker.isOneOf(elem) ? flat(elem.oneOf) : elem); }) | ||
.flat(); | ||
}; |
@@ -74,2 +74,3 @@ import { OpenApi } from "./OpenApi"; | ||
schema: OpenApi.IJsonSchema; | ||
recursive?: false | number; | ||
}) => ILlmSchema | null; | ||
@@ -76,0 +77,0 @@ /** |
@@ -61,3 +61,3 @@ "use strict"; | ||
HttpLlm.application = function (document, options) { | ||
var _a, _b; | ||
var _a, _b, _c; | ||
// MIGRATE | ||
@@ -69,2 +69,3 @@ if (document["x-samchon-emended"] === true) | ||
separate: (_b = options === null || options === void 0 ? void 0 : options.separate) !== null && _b !== void 0 ? _b : null, | ||
recursive: (_c = options === null || options === void 0 ? void 0 : options.recursive) !== null && _c !== void 0 ? _c : 3, | ||
}); | ||
@@ -85,3 +86,10 @@ }; | ||
*/ | ||
HttpLlm.schema = function (props) { return HttpLlmConverter_1.HttpLlmConverter.schema(props); }; | ||
HttpLlm.schema = function (props) { | ||
var _a; | ||
return HttpLlmConverter_1.HttpLlmConverter.schema({ | ||
components: props.components, | ||
schema: props.schema, | ||
recursive: (_a = props.recursive) !== null && _a !== void 0 ? _a : 3, | ||
}); | ||
}; | ||
/** | ||
@@ -88,0 +96,0 @@ * Execute the LLM function call. |
@@ -165,2 +165,13 @@ import { OpenApi } from "../OpenApi"; | ||
/** | ||
* Whether to allow recursive types or not. | ||
* | ||
* If allow, then how many times to repeat the recursive types. | ||
* | ||
* By the way, if the model is "chatgpt", the recursive types are always | ||
* allowed without any limitation, due to it supports the reference type. | ||
* | ||
* @default 3 | ||
*/ | ||
recursive: false | number; | ||
/** | ||
* Separator function for the parameters. | ||
@@ -167,0 +178,0 @@ * |
@@ -51,2 +51,13 @@ import { ILlmFunction } from "./ILlmFunction"; | ||
/** | ||
* Whether to allow recursive types or not. | ||
* | ||
* If allow, then how many times to repeat the recursive types. | ||
* | ||
* By the way, if the model is "chatgpt", the recursive types are always | ||
* allowed without any limitation, due to it supports the reference type. | ||
* | ||
* @default 3 | ||
*/ | ||
recursive: false | number; | ||
/** | ||
* Separator function for the parameters. | ||
@@ -53,0 +64,0 @@ * |
import { OpenApi } from "../OpenApi"; | ||
export declare namespace OpenApiTypeChecker { | ||
const visit: (closure: (schema: OpenApi.IJsonSchema) => void) => (components: OpenApi.IComponents) => (schema: OpenApi.IJsonSchema) => void; | ||
const isNull: (schema: OpenApi.IJsonSchema) => schema is OpenApi.IJsonSchema.INull; | ||
@@ -16,3 +15,9 @@ const isUnknown: (schema: OpenApi.IJsonSchema) => schema is OpenApi.IJsonSchema.IUnknown; | ||
const isOneOf: (schema: OpenApi.IJsonSchema) => schema is OpenApi.IJsonSchema.IOneOf; | ||
const visit: (closure: (schema: OpenApi.IJsonSchema) => void) => (components: OpenApi.IComponents) => (schema: OpenApi.IJsonSchema) => void; | ||
const escape: (props: { | ||
components: OpenApi.IComponents; | ||
schema: OpenApi.IJsonSchema; | ||
recursive: false | number; | ||
}) => OpenApi.IJsonSchema | null; | ||
const covers: (components: OpenApi.IComponents) => ((x: OpenApi.IJsonSchema, y: OpenApi.IJsonSchema) => boolean); | ||
} |
"use strict"; | ||
var __assign = (this && this.__assign) || function () { | ||
__assign = Object.assign || function(t) { | ||
for (var s, i = 1, n = arguments.length; i < n; i++) { | ||
s = arguments[i]; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) | ||
t[p] = s[p]; | ||
} | ||
return t; | ||
}; | ||
return __assign.apply(this, arguments); | ||
}; | ||
var __values = (this && this.__values) || function(o) { | ||
@@ -29,2 +40,11 @@ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; | ||
}; | ||
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { | ||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { | ||
if (ar || !(i in from)) { | ||
if (!ar) ar = Array.prototype.slice.call(from, 0, i); | ||
ar[i] = from[i]; | ||
} | ||
} | ||
return to.concat(ar || Array.prototype.slice.call(from)); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -35,2 +55,49 @@ exports.OpenApiTypeChecker = void 0; | ||
(function (OpenApiTypeChecker) { | ||
/* ----------------------------------------------------------- | ||
TYPE CHECKERS | ||
----------------------------------------------------------- */ | ||
OpenApiTypeChecker.isNull = function (schema) { | ||
return schema.type === "null"; | ||
}; | ||
OpenApiTypeChecker.isUnknown = function (schema) { | ||
return schema.type === undefined && | ||
!OpenApiTypeChecker.isConstant(schema) && | ||
!OpenApiTypeChecker.isOneOf(schema) && | ||
!OpenApiTypeChecker.isReference(schema); | ||
}; | ||
OpenApiTypeChecker.isConstant = function (schema) { | ||
return schema.const !== undefined; | ||
}; | ||
OpenApiTypeChecker.isBoolean = function (schema) { | ||
return schema.type === "boolean"; | ||
}; | ||
OpenApiTypeChecker.isInteger = function (schema) { | ||
return schema.type === "integer"; | ||
}; | ||
OpenApiTypeChecker.isNumber = function (schema) { | ||
return schema.type === "number"; | ||
}; | ||
OpenApiTypeChecker.isString = function (schema) { | ||
return schema.type === "string"; | ||
}; | ||
OpenApiTypeChecker.isArray = function (schema) { | ||
return schema.type === "array" && | ||
schema.items !== undefined; | ||
}; | ||
OpenApiTypeChecker.isTuple = function (schema) { | ||
return schema.type === "array" && | ||
schema.prefixItems !== undefined; | ||
}; | ||
OpenApiTypeChecker.isObject = function (schema) { | ||
return schema.type === "object"; | ||
}; | ||
OpenApiTypeChecker.isReference = function (schema) { | ||
return schema.$ref !== undefined; | ||
}; | ||
OpenApiTypeChecker.isOneOf = function (schema) { | ||
return schema.oneOf !== undefined; | ||
}; | ||
/* ----------------------------------------------------------- | ||
OPERATORS | ||
----------------------------------------------------------- */ | ||
OpenApiTypeChecker.visit = function (closure) { | ||
@@ -84,52 +151,150 @@ return function (components) { | ||
}; | ||
/* ----------------------------------------------------------- | ||
TYPE CHECKERS | ||
----------------------------------------------------------- */ | ||
OpenApiTypeChecker.isNull = function (schema) { | ||
return schema.type === "null"; | ||
OpenApiTypeChecker.escape = function (props) { | ||
return escapeSchema({ | ||
components: props.components, | ||
schema: props.schema, | ||
recursive: props.recursive, | ||
visited: new Map(), | ||
}) || null; | ||
}; | ||
OpenApiTypeChecker.isUnknown = function (schema) { | ||
return schema.type === undefined && | ||
!OpenApiTypeChecker.isConstant(schema) && | ||
!OpenApiTypeChecker.isOneOf(schema) && | ||
!OpenApiTypeChecker.isReference(schema); | ||
}; | ||
OpenApiTypeChecker.isConstant = function (schema) { | ||
return schema.const !== undefined; | ||
}; | ||
OpenApiTypeChecker.isBoolean = function (schema) { | ||
return schema.type === "boolean"; | ||
}; | ||
OpenApiTypeChecker.isInteger = function (schema) { | ||
return schema.type === "integer"; | ||
}; | ||
OpenApiTypeChecker.isNumber = function (schema) { | ||
return schema.type === "number"; | ||
}; | ||
OpenApiTypeChecker.isString = function (schema) { | ||
return schema.type === "string"; | ||
}; | ||
OpenApiTypeChecker.isArray = function (schema) { | ||
return schema.type === "array" && | ||
schema.items !== undefined; | ||
}; | ||
OpenApiTypeChecker.isTuple = function (schema) { | ||
return schema.type === "array" && | ||
schema.prefixItems !== undefined; | ||
}; | ||
OpenApiTypeChecker.isObject = function (schema) { | ||
return schema.type === "object"; | ||
}; | ||
OpenApiTypeChecker.isReference = function (schema) { | ||
return schema.$ref !== undefined; | ||
}; | ||
OpenApiTypeChecker.isOneOf = function (schema) { | ||
return schema.oneOf !== undefined; | ||
}; | ||
/* ----------------------------------------------------------- | ||
OPERATORS | ||
----------------------------------------------------------- */ | ||
OpenApiTypeChecker.covers = function (components) { | ||
return coverStation(components)(new Map()); | ||
}; | ||
var escapeSchema = function (props) { | ||
var _a, _b, _c; | ||
if (OpenApiTypeChecker.isReference(props.schema)) { | ||
// REFERENCE | ||
var name_1 = props.schema.$ref.split("#/components/schemas/")[1]; | ||
var target = (_a = props.components.schemas) === null || _a === void 0 ? void 0 : _a[name_1]; | ||
if (target === undefined) | ||
return null; | ||
else if (props.visited.has(name_1) === true) { | ||
if (props.recursive === false) | ||
return null; | ||
var depth = props.visited.get(name_1); | ||
if (depth > props.recursive) | ||
return undefined; | ||
props.visited.set(name_1, depth + 1); | ||
return escapeSchema({ | ||
components: props.components, | ||
schema: target, | ||
recursive: props.recursive, | ||
visited: props.visited, | ||
}); | ||
} | ||
return escapeSchema({ | ||
components: props.components, | ||
schema: target, | ||
recursive: props.recursive, | ||
visited: new Map(__spreadArray(__spreadArray([], __read(props.visited), false), [[name_1, 1]], false)), | ||
}); | ||
} | ||
else if (OpenApiTypeChecker.isOneOf(props.schema)) { | ||
// UNION | ||
var elements = props.schema.oneOf.map(function (schema) { | ||
return escapeSchema({ | ||
components: props.components, | ||
schema: schema, | ||
recursive: props.recursive, | ||
visited: props.visited, | ||
}); | ||
}); | ||
if (elements.some(function (v) { return v === null; })) | ||
return null; | ||
var filtered = elements.filter(function (v) { return v !== undefined; }); | ||
if (filtered.length === 0) | ||
return undefined; | ||
return __assign(__assign({}, props), { oneOf: filtered.map(flat(props.components)).flat() }); | ||
} | ||
else if (OpenApiTypeChecker.isObject(props.schema)) { | ||
// OBJECT | ||
var object_1 = props.schema; | ||
var properties_1 = Object.entries((_b = object_1.properties) !== null && _b !== void 0 ? _b : {}).map(function (_a) { | ||
var _b = __read(_a, 2), key = _b[0], value = _b[1]; | ||
return [ | ||
key, | ||
escapeSchema({ | ||
components: props.components, | ||
schema: value, | ||
recursive: props.recursive, | ||
visited: props.visited, | ||
}), | ||
]; | ||
}); | ||
var additionalProperties = object_1.additionalProperties | ||
? typeof object_1.additionalProperties === "object" && | ||
object_1.additionalProperties !== null | ||
? escapeSchema({ | ||
components: props.components, | ||
schema: object_1.additionalProperties, | ||
recursive: props.recursive, | ||
visited: props.visited, | ||
}) | ||
: object_1.additionalProperties | ||
: false; | ||
if (properties_1.some(function (_a) { | ||
var _b = __read(_a, 2), _k = _b[0], v = _b[1]; | ||
return v === null; | ||
}) || | ||
additionalProperties === null) | ||
return null; | ||
else if (properties_1.some(function (_a) { | ||
var _b; | ||
var _c = __read(_a, 2), k = _c[0], v = _c[1]; | ||
return v === undefined && ((_b = object_1.required) === null || _b === void 0 ? void 0 : _b.includes(k)) === true; | ||
}) === true) | ||
return undefined; | ||
return __assign(__assign({}, object_1), { properties: Object.fromEntries(properties_1.filter(function (_a) { | ||
var _b = __read(_a, 2), _k = _b[0], v = _b[1]; | ||
return v !== undefined; | ||
})), additionalProperties: additionalProperties !== null && additionalProperties !== void 0 ? additionalProperties : false, required: (_c = object_1.required) === null || _c === void 0 ? void 0 : _c.filter(function (k) { | ||
return properties_1.some(function (_a) { | ||
var _b = __read(_a, 2), key = _b[0], value = _b[1]; | ||
return key === k && value !== undefined; | ||
}); | ||
}) }); | ||
} | ||
else if (OpenApiTypeChecker.isTuple(props.schema)) { | ||
// TUPLE | ||
var elements = props.schema.prefixItems.map(function (schema) { | ||
return escapeSchema({ | ||
components: props.components, | ||
schema: schema, | ||
recursive: props.recursive, | ||
visited: props.visited, | ||
}); | ||
}); | ||
var additionalItems = props.schema.additionalItems | ||
? typeof props.schema.additionalItems === "object" && | ||
props.schema.additionalItems !== null | ||
? escapeSchema({ | ||
components: props.components, | ||
schema: props.schema.additionalItems, | ||
recursive: props.recursive, | ||
visited: props.visited, | ||
}) | ||
: props.schema.additionalItems | ||
: false; | ||
if (elements.some(function (v) { return v === null; }) || additionalItems === null) | ||
return null; | ||
else if (elements.some(function (v) { return v === undefined; })) | ||
return undefined; | ||
return __assign(__assign({}, props.schema), { prefixItems: elements, additionalItems: additionalItems !== null && additionalItems !== void 0 ? additionalItems : false }); | ||
} | ||
else if (OpenApiTypeChecker.isArray(props.schema)) { | ||
// ARRAY | ||
var items = escapeSchema({ | ||
components: props.components, | ||
schema: props.schema.items, | ||
recursive: props.recursive, | ||
visited: props.visited, | ||
}); | ||
if (items === null) | ||
return null; | ||
else if (items === undefined) | ||
return __assign(__assign({}, props.schema), { minItems: undefined, maxItems: 0, items: {} }); | ||
return __assign(__assign({}, props.schema), { items: items }); | ||
} | ||
return props.schema; | ||
}; | ||
var coverStation = function (components) { | ||
@@ -161,4 +326,4 @@ return function (visited) { | ||
// COMPARE WITH FLATTENING | ||
var alpha = flatSchema(components)(x); | ||
var beta = flatSchema(components)(y); | ||
var alpha = flat(components)(x); | ||
var beta = flat(components)(y); | ||
if (alpha.some(function (x) { return OpenApiTypeChecker.isUnknown(x); })) | ||
@@ -323,7 +488,7 @@ return true; | ||
}; | ||
var flatSchema = function (components) { | ||
var flat = function (components) { | ||
return function (schema) { | ||
schema = escapeReference(components)(schema); | ||
if (OpenApiTypeChecker.isOneOf(schema)) | ||
return schema.oneOf.map(flatSchema(components)).flat(); | ||
return schema.oneOf.map(flat(components)).flat(); | ||
return [schema]; | ||
@@ -330,0 +495,0 @@ }; |
{ | ||
"name": "@samchon/openapi", | ||
"version": "1.1.2", | ||
"version": "1.2.0-dev.20241111", | ||
"description": "OpenAPI definitions and converters for 'typia' and 'nestia'.", | ||
@@ -5,0 +5,0 @@ "main": "./lib/index.js", |
@@ -0,0 +0,0 @@ # `@samchon/openapi` |
@@ -27,3 +27,26 @@ import { OpenApi } from "../OpenApi"; | ||
.map((route) => { | ||
if (route.method === "head") return null; | ||
if (route.method === "head") { | ||
errors.push({ | ||
method: route.method, | ||
path: route.path, | ||
messages: ["HEAD method is not supported in the LLM application."], | ||
operation: () => route.operation(), | ||
route: () => route, | ||
}); | ||
return null; | ||
} else if ( | ||
route.body?.type === "multipart/form-data" || | ||
route.success?.type === "multipart/form-data" | ||
) { | ||
errors.push({ | ||
method: route.method, | ||
path: route.path, | ||
messages: [ | ||
`The "multipart/form-data" content type is not supported in the LLM application.`, | ||
], | ||
operation: () => route.operation(), | ||
route: () => route, | ||
}); | ||
return null; | ||
} | ||
const func: IHttpLlmFunction | null = composeFunction(options)( | ||
@@ -54,7 +77,8 @@ migrate.document().components, | ||
schema: OpenApi.IJsonSchema; | ||
recursive: false | number; | ||
}): ILlmSchema | null => { | ||
const resolved: OpenApi.IJsonSchema | null = escape({ | ||
const resolved: OpenApi.IJsonSchema | null = OpenApiTypeChecker.escape({ | ||
components: props.components, | ||
visited: new Set(), | ||
input: props.schema, | ||
schema: props.schema, | ||
recursive: props.recursive, | ||
}); | ||
@@ -86,2 +110,3 @@ if (resolved === null) return null; | ||
schema: s, | ||
recursive: options.recursive, | ||
}); | ||
@@ -179,117 +204,1 @@ const output: ILlmSchema | null | undefined = | ||
}; | ||
const escape = (props: { | ||
components: OpenApi.IComponents; | ||
visited: Set<string>; | ||
input: OpenApi.IJsonSchema; | ||
}): OpenApi.IJsonSchema | null => { | ||
if (OpenApiTypeChecker.isReference(props.input)) { | ||
// REFERENCE | ||
const name: string = props.input.$ref.split("#/components/schemas/")[1]; | ||
const target: OpenApi.IJsonSchema | undefined = | ||
props.components.schemas?.[name]; | ||
if (!target) return null; | ||
else if (props.visited.has(name)) return null; | ||
return escape({ | ||
components: props.components, | ||
visited: new Set([...props.visited, name]), | ||
input: target, | ||
}); | ||
} else if (OpenApiTypeChecker.isOneOf(props.input)) { | ||
// ONE-OF | ||
const oneOf: Array<OpenApi.IJsonSchema | null> = props.input.oneOf.map( | ||
(schema) => | ||
escape({ | ||
...props, | ||
input: schema, | ||
})!, | ||
); | ||
if (oneOf.some((v) => v === null)) return null; | ||
return { | ||
...props.input, | ||
oneOf: flat(oneOf as OpenApi.IJsonSchema[]), | ||
}; | ||
} else if (OpenApiTypeChecker.isObject(props.input)) { | ||
// OBJECT | ||
const properties: Array<[string, OpenApi.IJsonSchema | null]> | undefined = | ||
props.input.properties | ||
? Object.entries(props.input.properties).map( | ||
([key, value]) => | ||
[ | ||
key, | ||
escape({ | ||
...props, | ||
input: value, | ||
}), | ||
] as const, | ||
) | ||
: undefined; | ||
const additionalProperties: | ||
| OpenApi.IJsonSchema | ||
| null | ||
| boolean | ||
| undefined = props.input.additionalProperties | ||
? typeof props.input.additionalProperties === "object" && | ||
props.input.additionalProperties !== null | ||
? escape({ | ||
...props, | ||
input: props.input.additionalProperties, | ||
}) | ||
: props.input.additionalProperties | ||
: undefined; | ||
if (properties && properties.some(([_k, v]) => v === null)) return null; | ||
else if (additionalProperties === null) return null; | ||
return { | ||
...props.input, | ||
properties: properties | ||
? Object.fromEntries( | ||
properties.filter(([_k, v]) => !!v) as Array< | ||
[string, OpenApi.IJsonSchema] | ||
>, | ||
) | ||
: undefined, | ||
additionalProperties, | ||
}; | ||
} else if (OpenApiTypeChecker.isTuple(props.input)) { | ||
// TUPLE | ||
const prefixItems: Array<OpenApi.IJsonSchema | null> = | ||
props.input.prefixItems.map((schema) => | ||
escape({ | ||
...props, | ||
input: schema, | ||
}), | ||
); | ||
const additionalItems: OpenApi.IJsonSchema | null | boolean | undefined = | ||
typeof props.input.additionalItems === "object" && | ||
props.input.additionalItems !== null | ||
? escape({ | ||
...props, | ||
input: props.input.additionalItems, | ||
}) | ||
: props.input.additionalItems; | ||
if (prefixItems.some((v) => v === null)) return null; | ||
else if (additionalItems === null) return null; | ||
return { | ||
...props.input, | ||
prefixItems: prefixItems as OpenApi.IJsonSchema[], | ||
additionalItems, | ||
}; | ||
} else if (OpenApiTypeChecker.isArray(props.input)) { | ||
// ARRAY | ||
const items: OpenApi.IJsonSchema | null = escape({ | ||
...props, | ||
input: props.input.items, | ||
}); | ||
if (items === null) return null; | ||
return { | ||
...props.input, | ||
items, | ||
}; | ||
} | ||
return props.input; | ||
}; | ||
const flat = (elements: OpenApi.IJsonSchema[]): OpenApi.IJsonSchema[] => | ||
elements | ||
.map((elem) => (OpenApiTypeChecker.isOneOf(elem) ? flat(elem.oneOf) : elem)) | ||
.flat(); |
@@ -0,0 +0,0 @@ import { OpenApi } from "../OpenApi"; |
@@ -0,0 +0,0 @@ import { OpenApi } from "../OpenApi"; |
@@ -0,0 +0,0 @@ import { OpenApi } from "../OpenApi"; |
@@ -0,0 +0,0 @@ import { OpenApi } from "../OpenApi"; |
@@ -0,0 +0,0 @@ import { OpenApi } from "../OpenApi"; |
@@ -0,0 +0,0 @@ import { OpenApi } from "../OpenApi"; |
@@ -0,0 +0,0 @@ import { OpenApi } from "../OpenApi"; |
@@ -0,0 +0,0 @@ import { OpenApi } from "../OpenApi"; |
@@ -0,0 +0,0 @@ /** |
@@ -0,0 +0,0 @@ import type { HttpLlm } from "../HttpLlm"; |
@@ -0,0 +0,0 @@ import type { HttpMigration } from "../HttpMigration"; |
@@ -84,2 +84,3 @@ import { HttpMigration } from "./HttpMigration"; | ||
separate: options?.separate ?? null, | ||
recursive: options?.recursive ?? 3, | ||
}, | ||
@@ -105,3 +106,9 @@ ); | ||
schema: OpenApi.IJsonSchema; | ||
}): ILlmSchema | null => HttpLlmConverter.schema(props); | ||
recursive?: false | number; | ||
}): ILlmSchema | null => | ||
HttpLlmConverter.schema({ | ||
components: props.components, | ||
schema: props.schema, | ||
recursive: props.recursive ?? 3, | ||
}); | ||
@@ -108,0 +115,0 @@ /* ----------------------------------------------------------- |
@@ -0,0 +0,0 @@ import { OpenApi } from "./OpenApi"; |
@@ -0,0 +0,0 @@ // STRUCTURES |
@@ -0,0 +0,0 @@ import { OpenApiV3 } from "./OpenApiV3"; |
@@ -0,0 +0,0 @@ /** |
@@ -0,0 +0,0 @@ /** |
@@ -0,0 +0,0 @@ /// <reference lib="dom" /> |
@@ -182,2 +182,14 @@ import { OpenApi } from "../OpenApi"; | ||
/** | ||
* Whether to allow recursive types or not. | ||
* | ||
* If allow, then how many times to repeat the recursive types. | ||
* | ||
* By the way, if the model is "chatgpt", the recursive types are always | ||
* allowed without any limitation, due to it supports the reference type. | ||
* | ||
* @default 3 | ||
*/ | ||
recursive: false | number; | ||
/** | ||
* Separator function for the parameters. | ||
@@ -184,0 +196,0 @@ * |
@@ -0,0 +0,0 @@ import { OpenApi } from "../OpenApi"; |
@@ -0,0 +0,0 @@ import { OpenApi } from "../OpenApi"; |
@@ -0,0 +0,0 @@ import { OpenApi } from "../OpenApi"; |
@@ -0,0 +0,0 @@ /** |
@@ -53,2 +53,14 @@ import { ILlmFunction } from "./ILlmFunction"; | ||
/** | ||
* Whether to allow recursive types or not. | ||
* | ||
* If allow, then how many times to repeat the recursive types. | ||
* | ||
* By the way, if the model is "chatgpt", the recursive types are always | ||
* allowed without any limitation, due to it supports the reference type. | ||
* | ||
* @default 3 | ||
*/ | ||
recursive: false | number; | ||
/** | ||
* Separator function for the parameters. | ||
@@ -55,0 +67,0 @@ * |
@@ -0,0 +0,0 @@ import { ILlmSchema } from "./ILlmSchema"; |
@@ -0,0 +0,0 @@ /** |
@@ -0,0 +0,0 @@ /** |
@@ -0,0 +0,0 @@ export namespace Escaper { |
@@ -0,0 +0,0 @@ import { IHttpLlmFunction } from "../structures/IHttpLlmFunction"; |
@@ -0,0 +0,0 @@ import { IHttpLlmFunction } from "../structures/IHttpLlmFunction"; |
@@ -0,0 +0,0 @@ import { ILlmSchema } from "../structures/ILlmSchema"; |
@@ -0,0 +0,0 @@ export namespace MapUtil { |
@@ -0,0 +0,0 @@ import { StringUtil } from "./StringUtil"; |
@@ -5,38 +5,2 @@ import { OpenApi } from "../OpenApi"; | ||
export namespace OpenApiTypeChecker { | ||
export const visit = | ||
(closure: (schema: OpenApi.IJsonSchema) => void) => | ||
(components: OpenApi.IComponents) => { | ||
const already: Set<string> = new Set(); | ||
const next = (schema: OpenApi.IJsonSchema): void => { | ||
closure(schema); | ||
if (OpenApiTypeChecker.isReference(schema)) { | ||
const key: string = schema.$ref.split("#/components/schemas/").pop()!; | ||
if (already.has(key) === true) return; | ||
already.add(key); | ||
const found: OpenApi.IJsonSchema | undefined = | ||
components.schemas?.[key]; | ||
if (found !== undefined) next(found); | ||
} else if (OpenApiTypeChecker.isOneOf(schema)) | ||
schema.oneOf.forEach(next); | ||
else if (OpenApiTypeChecker.isObject(schema)) { | ||
for (const value of Object.values(schema.properties ?? {})) | ||
next(value); | ||
if ( | ||
typeof schema.additionalProperties === "object" && | ||
schema.additionalProperties !== null | ||
) | ||
next(schema.additionalProperties); | ||
} else if (OpenApiTypeChecker.isArray(schema)) next(schema.items); | ||
else if (OpenApiTypeChecker.isTuple(schema)) { | ||
(schema.prefixItems ?? []).forEach(next); | ||
if ( | ||
typeof schema.additionalItems === "object" && | ||
schema.additionalItems !== null | ||
) | ||
next(schema.additionalItems); | ||
} | ||
}; | ||
return next; | ||
}; | ||
/* ----------------------------------------------------------- | ||
@@ -104,2 +68,50 @@ TYPE CHECKERS | ||
----------------------------------------------------------- */ | ||
export const visit = | ||
(closure: (schema: OpenApi.IJsonSchema) => void) => | ||
(components: OpenApi.IComponents) => { | ||
const already: Set<string> = new Set(); | ||
const next = (schema: OpenApi.IJsonSchema): void => { | ||
closure(schema); | ||
if (OpenApiTypeChecker.isReference(schema)) { | ||
const key: string = schema.$ref.split("#/components/schemas/").pop()!; | ||
if (already.has(key) === true) return; | ||
already.add(key); | ||
const found: OpenApi.IJsonSchema | undefined = | ||
components.schemas?.[key]; | ||
if (found !== undefined) next(found); | ||
} else if (OpenApiTypeChecker.isOneOf(schema)) | ||
schema.oneOf.forEach(next); | ||
else if (OpenApiTypeChecker.isObject(schema)) { | ||
for (const value of Object.values(schema.properties ?? {})) | ||
next(value); | ||
if ( | ||
typeof schema.additionalProperties === "object" && | ||
schema.additionalProperties !== null | ||
) | ||
next(schema.additionalProperties); | ||
} else if (OpenApiTypeChecker.isArray(schema)) next(schema.items); | ||
else if (OpenApiTypeChecker.isTuple(schema)) { | ||
(schema.prefixItems ?? []).forEach(next); | ||
if ( | ||
typeof schema.additionalItems === "object" && | ||
schema.additionalItems !== null | ||
) | ||
next(schema.additionalItems); | ||
} | ||
}; | ||
return next; | ||
}; | ||
export const escape = (props: { | ||
components: OpenApi.IComponents; | ||
schema: OpenApi.IJsonSchema; | ||
recursive: false | number; | ||
}): OpenApi.IJsonSchema | null => | ||
escapeSchema({ | ||
components: props.components, | ||
schema: props.schema, | ||
recursive: props.recursive, | ||
visited: new Map(), | ||
}) || null; | ||
export const covers = ( | ||
@@ -110,2 +122,159 @@ components: OpenApi.IComponents, | ||
const escapeSchema = (props: { | ||
components: OpenApi.IComponents; | ||
schema: OpenApi.IJsonSchema; | ||
recursive: false | number; | ||
visited: Map<string, number>; | ||
}): OpenApi.IJsonSchema | null | undefined => { | ||
if (isReference(props.schema)) { | ||
// REFERENCE | ||
const name: string = props.schema.$ref.split("#/components/schemas/")[1]; | ||
const target: OpenApi.IJsonSchema | undefined = | ||
props.components.schemas?.[name]; | ||
if (target === undefined) return null; | ||
else if (props.visited.has(name) === true) { | ||
if (props.recursive === false) return null; | ||
const depth: number = props.visited.get(name)!; | ||
if (depth > props.recursive) return undefined; | ||
props.visited.set(name, depth + 1); | ||
return escapeSchema({ | ||
components: props.components, | ||
schema: target, | ||
recursive: props.recursive, | ||
visited: props.visited, | ||
}); | ||
} | ||
return escapeSchema({ | ||
components: props.components, | ||
schema: target, | ||
recursive: props.recursive, | ||
visited: new Map([...props.visited, [name, 1]]), | ||
}); | ||
} else if (isOneOf(props.schema)) { | ||
// UNION | ||
const elements: Array<OpenApi.IJsonSchema | null | undefined> = | ||
props.schema.oneOf.map((schema) => | ||
escapeSchema({ | ||
components: props.components, | ||
schema: schema, | ||
recursive: props.recursive, | ||
visited: props.visited, | ||
}), | ||
); | ||
if (elements.some((v) => v === null)) return null; | ||
const filtered: OpenApi.IJsonSchema[] = elements.filter( | ||
(v) => v !== undefined, | ||
) as OpenApi.IJsonSchema[]; | ||
if (filtered.length === 0) return undefined; | ||
return { | ||
...props, | ||
oneOf: filtered.map(flat(props.components)).flat(), | ||
}; | ||
} else if (isObject(props.schema)) { | ||
// OBJECT | ||
const object: OpenApi.IJsonSchema.IObject = props.schema; | ||
const properties: Array< | ||
[string, OpenApi.IJsonSchema | null | undefined] | ||
> = Object.entries(object.properties ?? {}).map(([key, value]) => [ | ||
key, | ||
escapeSchema({ | ||
components: props.components, | ||
schema: value, | ||
recursive: props.recursive, | ||
visited: props.visited, | ||
}), | ||
]); | ||
const additionalProperties: | ||
| OpenApi.IJsonSchema | ||
| null | ||
| boolean | ||
| undefined = object.additionalProperties | ||
? typeof object.additionalProperties === "object" && | ||
object.additionalProperties !== null | ||
? escapeSchema({ | ||
components: props.components, | ||
schema: object.additionalProperties, | ||
recursive: props.recursive, | ||
visited: props.visited, | ||
}) | ||
: object.additionalProperties | ||
: false; | ||
if ( | ||
properties.some(([_k, v]) => v === null) || | ||
additionalProperties === null | ||
) | ||
return null; | ||
else if ( | ||
properties.some( | ||
([k, v]) => v === undefined && object.required?.includes(k) === true, | ||
) === true | ||
) | ||
return undefined; | ||
return { | ||
...object, | ||
properties: Object.fromEntries( | ||
properties.filter(([_k, v]) => v !== undefined) as Array< | ||
[string, OpenApi.IJsonSchema] | ||
>, | ||
), | ||
additionalProperties: additionalProperties ?? false, | ||
required: object.required?.filter((k) => | ||
properties.some(([key, value]) => key === k && value !== undefined), | ||
), | ||
}; | ||
} else if (isTuple(props.schema)) { | ||
// TUPLE | ||
const elements: Array<OpenApi.IJsonSchema | null | undefined> = | ||
props.schema.prefixItems.map((schema) => | ||
escapeSchema({ | ||
components: props.components, | ||
schema: schema, | ||
recursive: props.recursive, | ||
visited: props.visited, | ||
}), | ||
); | ||
const additionalItems: OpenApi.IJsonSchema | null | boolean | undefined = | ||
props.schema.additionalItems | ||
? typeof props.schema.additionalItems === "object" && | ||
props.schema.additionalItems !== null | ||
? escapeSchema({ | ||
components: props.components, | ||
schema: props.schema.additionalItems, | ||
recursive: props.recursive, | ||
visited: props.visited, | ||
}) | ||
: props.schema.additionalItems | ||
: false; | ||
if (elements.some((v) => v === null) || additionalItems === null) | ||
return null; | ||
else if (elements.some((v) => v === undefined)) return undefined; | ||
return { | ||
...props.schema, | ||
prefixItems: elements as OpenApi.IJsonSchema[], | ||
additionalItems: additionalItems ?? false, | ||
}; | ||
} else if (isArray(props.schema)) { | ||
// ARRAY | ||
const items: OpenApi.IJsonSchema | null | undefined = escapeSchema({ | ||
components: props.components, | ||
schema: props.schema.items, | ||
recursive: props.recursive, | ||
visited: props.visited, | ||
}); | ||
if (items === null) return null; | ||
else if (items === undefined) | ||
return { | ||
...props.schema, | ||
minItems: undefined, | ||
maxItems: 0, | ||
items: {}, | ||
}; | ||
return { | ||
...props.schema, | ||
items: items, | ||
}; | ||
} | ||
return props.schema; | ||
}; | ||
const coverStation = | ||
@@ -140,4 +309,4 @@ (components: OpenApi.IComponents) => | ||
// COMPARE WITH FLATTENING | ||
const alpha: OpenApi.IJsonSchema[] = flatSchema(components)(x); | ||
const beta: OpenApi.IJsonSchema[] = flatSchema(components)(y); | ||
const alpha: OpenApi.IJsonSchema[] = flat(components)(x); | ||
const beta: OpenApi.IJsonSchema[] = flat(components)(y); | ||
if (alpha.some((x) => isUnknown(x))) return true; | ||
@@ -331,8 +500,7 @@ else if (beta.some((x) => isUnknown(x))) return false; | ||
const flatSchema = | ||
const flat = | ||
(components: OpenApi.IComponents) => | ||
(schema: OpenApi.IJsonSchema): OpenApi.IJsonSchema[] => { | ||
schema = escapeReference(components)(schema); | ||
if (isOneOf(schema)) | ||
return schema.oneOf.map(flatSchema(components)).flat(); | ||
if (isOneOf(schema)) return schema.oneOf.map(flat(components)).flat(); | ||
return [schema]; | ||
@@ -339,0 +507,0 @@ }; |
@@ -0,0 +0,0 @@ import { NamingConvention } from "./NamingConvention"; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
1189505
20085
1