@samchon/openapi
Advanced tools
Comparing version 2.0.0-dev.20241120-3 to 2.0.0-dev.20241121-2
@@ -76,3 +76,3 @@ "use strict"; | ||
var visit = function (input) { | ||
var _a; | ||
var _a, _b; | ||
if (OpenApiTypeChecker_1.OpenApiTypeChecker.isOneOf(input)) { | ||
@@ -87,3 +87,3 @@ input.oneOf.forEach(visit); | ||
return 0; | ||
if (props.options.reference === true || | ||
if (props.options.escape === false || | ||
OpenApiTypeChecker_1.OpenApiTypeChecker.isRecursiveReference({ | ||
@@ -113,7 +113,35 @@ components: props.components, | ||
}); | ||
converted.description = OpenApiTypeChecker_1.OpenApiTypeChecker.writeReferenceDescription({ | ||
components: props.components, | ||
$ref: input.$ref, | ||
description: converted.description, | ||
escape: false, | ||
}); | ||
props.$defs[key_1] = converted; | ||
return out(); | ||
} | ||
else | ||
return visit(target); | ||
else { | ||
var length_1 = union.length; | ||
visit(target); | ||
if (length_1 === union.length - 1 && | ||
union[union.length - 1].schema !== null) | ||
union[union.length - 1] = { | ||
tags: union[union.length - 1].tags, | ||
schema: __assign(__assign({}, union[union.length - 1].schema), { description: OpenApiTypeChecker_1.OpenApiTypeChecker.writeReferenceDescription({ | ||
components: props.components, | ||
$ref: input.$ref, | ||
description: (_b = union[union.length - 1].schema) === null || _b === void 0 ? void 0 : _b.description, | ||
escape: true, | ||
}) }), | ||
}; | ||
else | ||
attribute.description = | ||
OpenApiTypeChecker_1.OpenApiTypeChecker.writeReferenceDescription({ | ||
components: props.components, | ||
$ref: input.$ref, | ||
description: attribute.description, | ||
escape: true, | ||
}); | ||
return union.length; | ||
} | ||
} | ||
@@ -250,3 +278,3 @@ else if (OpenApiTypeChecker_1.OpenApiTypeChecker.isObject(input)) { | ||
input.oneOf.forEach(visitConstant); | ||
else if (props.options.reference === false && | ||
else if (props.options.escape === true && | ||
OpenApiTypeChecker_1.OpenApiTypeChecker.isReference(input) && | ||
@@ -253,0 +281,0 @@ OpenApiTypeChecker_1.OpenApiTypeChecker.isRecursiveReference({ |
@@ -14,6 +14,2 @@ /** | ||
/** | ||
* @internal | ||
*/ | ||
private body_; | ||
/** | ||
* Initializer Constructor. | ||
@@ -20,0 +16,0 @@ * |
@@ -72,4 +72,4 @@ "use strict"; | ||
separate: (_b = (_a = props.options) === null || _a === void 0 ? void 0 : _a.separate) !== null && _b !== void 0 ? _b : null, | ||
reference: (_d = (_c = props.options) === null || _c === void 0 ? void 0 : _c.reference) !== null && _d !== void 0 ? _d : false, | ||
constraint: (_f = (_e = props.options) === null || _e === void 0 ? void 0 : _e.constraint) !== null && _f !== void 0 ? _f : true, | ||
escape: (_d = (_c = props.options) === null || _c === void 0 ? void 0 : _c.escape) !== null && _d !== void 0 ? _d : false, | ||
constraint: (_f = (_e = props.options) === null || _e === void 0 ? void 0 : _e.constraint) !== null && _f !== void 0 ? _f : false, | ||
} | ||
@@ -76,0 +76,0 @@ : { |
@@ -7,6 +7,2 @@ /** | ||
export declare namespace OpenApiV3_1 { | ||
/** | ||
* @internal | ||
*/ | ||
const is: (input: any) => input is IDocument; | ||
type Method = "get" | "post" | "put" | "delete" | "options" | "head" | "patch" | "trace"; | ||
@@ -13,0 +9,0 @@ interface IDocument { |
@@ -8,6 +8,2 @@ /** | ||
type Method = "get" | "post" | "put" | "delete" | "options" | "head" | "patch" | "trace"; | ||
/** | ||
* @internal | ||
*/ | ||
const is: (input: any) => input is IDocument; | ||
interface IDocument { | ||
@@ -14,0 +10,0 @@ openapi: "3.0" | `3.0.${number}`; |
@@ -31,9 +31,10 @@ /** | ||
* For reference, if you've composed the `IChatGptSchema` type with the | ||
* {@link ILlmApplication.IChatGptOptions.reference} `false` option, only the recursived | ||
* named types would be archived into the {@link IChatGptSchema.IParameters.$defs}, | ||
* and the others would be ecaped from the {@link IChatGptSchema.IReference} type. | ||
* {@link ILlmApplication.IChatGptOptions.escape} `true` option (default is `false`), | ||
* only the recursived named types would be archived into the | ||
* {@link IChatGptSchema.IParameters.$defs}, and the others would be ecaped from the | ||
* {@link IChatGptSchema.IReference} type. | ||
* | ||
* Also, if you've composed the `IChatGptSchema` type with the | ||
* {@link ILlmApplication.IChatGptOptions.constraint} `false` option, the | ||
* `IChatGptSchema` would not compose these properties. Instead, these | ||
* {@link ILlmApplication.IChatGptOptions.constraint} `false` option (default `false`), | ||
* the `IChatGptSchema` would not compose these properties. Instead, these | ||
* properties would be written on {@link IChatGptSchema.__IAttribute.descripotion} | ||
@@ -40,0 +41,0 @@ * field like `@format uuid` case. |
@@ -147,5 +147,5 @@ import { IChatGptSchema } from "./IChatGptSchema"; | ||
/** | ||
* Whether to allow reference type in everywhere. | ||
* Whether to escape reference type or not. | ||
* | ||
* If you configure this property to `false`, most of reference types | ||
* If you configure this property to `true`, most of reference types | ||
* represented by {@link IChatGptSchema.IReference} would be escaped to | ||
@@ -165,3 +165,3 @@ * a plain type unless recursive type case. | ||
*/ | ||
reference: boolean; | ||
escape: boolean; | ||
/** | ||
@@ -168,0 +168,0 @@ * Whether to allow contraint properties or not. |
@@ -8,6 +8,2 @@ /** | ||
type Method = "get" | "post" | "put" | "delete" | "options" | "head" | "patch" | "trace"; | ||
/** | ||
* @internal | ||
*/ | ||
const is: (input: any) => input is IDocument; | ||
interface IDocument { | ||
@@ -14,0 +10,0 @@ swagger: "2.0" | `2.0.${number}`; |
@@ -196,3 +196,3 @@ "use strict"; | ||
props.visited.set(name_1, depth + 1); | ||
return escapeSchema({ | ||
var res_1 = escapeSchema({ | ||
components: props.components, | ||
@@ -203,4 +203,11 @@ schema: target, | ||
}); | ||
return res_1 | ||
? __assign(__assign({}, res_1), { description: OpenApiTypeChecker.writeReferenceDescription({ | ||
components: props.components, | ||
$ref: props.schema.$ref, | ||
description: res_1.description, | ||
escape: true, | ||
}) }) : res_1; | ||
} | ||
return escapeSchema({ | ||
var res = escapeSchema({ | ||
components: props.components, | ||
@@ -211,2 +218,9 @@ schema: target, | ||
}); | ||
return res | ||
? __assign(__assign({}, res), { description: OpenApiTypeChecker.writeReferenceDescription({ | ||
components: props.components, | ||
$ref: props.schema.$ref, | ||
description: res.description, | ||
escape: true, | ||
}) }) : res; | ||
} | ||
@@ -228,3 +242,3 @@ else if (OpenApiTypeChecker.isOneOf(props.schema)) { | ||
return undefined; | ||
return __assign(__assign({}, props), { oneOf: filtered.map(function (v) { return flat(props.components, v); }).flat() }); | ||
return __assign(__assign({}, props), { oneOf: filtered.map(function (v) { return flatSchema(props.components, v); }).flat() }); | ||
} | ||
@@ -342,4 +356,4 @@ else if (OpenApiTypeChecker.isObject(props.schema)) { | ||
// COMPARE WITH FLATTENING | ||
var alpha = flat(p.components, p.x); | ||
var beta = flat(p.components, p.y); | ||
var alpha = flatSchema(p.components, p.x); | ||
var beta = flatSchema(p.components, p.y); | ||
if (alpha.some(function (x) { return OpenApiTypeChecker.isUnknown(x); })) | ||
@@ -535,18 +549,51 @@ return true; | ||
}; | ||
var flatSchema = function (components, schema) { | ||
schema = escapeReferenceOfFlatSchema(components, schema); | ||
if (OpenApiTypeChecker.isOneOf(schema)) | ||
return schema.oneOf.map(function (v) { return flatSchema(components, v); }).flat(); | ||
return [schema]; | ||
}; | ||
var escapeReferenceOfFlatSchema = function (components, schema) { | ||
var _a, _b; | ||
if (OpenApiTypeChecker.isReference(schema) === false) | ||
return schema; | ||
var key = schema.$ref.replace("#/components/schemas/", ""); | ||
var found = escapeReferenceOfFlatSchema(components, (_b = (_a = components.schemas) === null || _a === void 0 ? void 0 : _a[key]) !== null && _b !== void 0 ? _b : {}); | ||
if (found === undefined) | ||
throw new Error("Reference type not found: ".concat(JSON.stringify(schema.$ref))); | ||
return escapeReferenceOfFlatSchema(components, found); | ||
}; | ||
/** | ||
* @internal | ||
*/ | ||
OpenApiTypeChecker.writeReferenceDescription = function (props) { | ||
var _a; | ||
var index = props.$ref.lastIndexOf("."); | ||
if (index === -1) | ||
return props.description; | ||
var accessors = props.$ref | ||
.split("#/components/schemas/")[1] | ||
.split("."); | ||
var pReferences = accessors | ||
.slice(0, props.escape ? accessors.length : accessors.length - 1) | ||
.map(function (_, i, array) { return array.slice(0, i + 1).join("."); }) | ||
.map(function (key) { | ||
var _a, _b; | ||
return ({ | ||
key: key, | ||
description: (_b = (_a = props.components.schemas) === null || _a === void 0 ? void 0 : _a[key]) === null || _b === void 0 ? void 0 : _b.description, | ||
}); | ||
}) | ||
.filter(function (schema) { return !!(schema === null || schema === void 0 ? void 0 : schema.description); }) | ||
.reverse(); | ||
if (pReferences.length === 0) | ||
return props.description; | ||
return __spreadArray(__spreadArray([], __read((((_a = props.description) === null || _a === void 0 ? void 0 : _a.length) ? [props.description] : [])), false), __read(pReferences.map(function (pRef, i) { | ||
return "Description of the ".concat(i === 0 && props.escape ? "current" : "parent", " {@link ").concat(pRef.key, "} type:\n\n") + | ||
pRef.description | ||
.split("\n") | ||
.map(function (str) { return "> ".concat(str); }) | ||
.join("\n"); | ||
})), false).join("\n\n------------------------------\n\n"); | ||
}; | ||
})(OpenApiTypeChecker || (exports.OpenApiTypeChecker = OpenApiTypeChecker = {})); | ||
var flat = function (components, schema) { | ||
schema = escapeReference(components, schema); | ||
if (OpenApiTypeChecker.isOneOf(schema)) | ||
return schema.oneOf.map(function (v) { return flat(components, v); }).flat(); | ||
return [schema]; | ||
}; | ||
var escapeReference = function (components, schema) { | ||
var _a, _b; | ||
if (OpenApiTypeChecker.isReference(schema) === false) | ||
return schema; | ||
var key = schema.$ref.replace("#/components/schemas/", ""); | ||
var found = escapeReference(components, (_b = (_a = components.schemas) === null || _a === void 0 ? void 0 : _a[key]) !== null && _b !== void 0 ? _b : {}); | ||
if (found === undefined) | ||
throw new Error("Reference not found: ".concat(JSON.stringify(schema.$ref))); | ||
return escapeReference(components, found); | ||
}; |
{ | ||
"name": "@samchon/openapi", | ||
"version": "2.0.0-dev.20241120-3", | ||
"version": "2.0.0-dev.20241121-2", | ||
"description": "OpenAPI definitions and converters for 'typia' and 'nestia'.", | ||
@@ -5,0 +5,0 @@ "main": "./lib/index.js", |
@@ -0,1 +1,7 @@ | ||
> ## Next version is coming. | ||
> | ||
> This is the `next` version README document. | ||
> | ||
> If you wanna see the latest version, go to the [`v1.0` branch](https://github.com/samchon/openapi/tree/v1.0). | ||
# `@samchon/openapi` | ||
@@ -16,3 +22,3 @@ ```mermaid | ||
[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/samchon/openapi/blob/master/LICENSE) | ||
[![npm version](https://img.shields.io/npm/v/@samchon/openapi.svg)](https://www.npmjs.com/package/@samchon/openapi) | ||
[![npm version](https://img.shields.io/npm/v/@samchon/openapi/next.svg)](https://www.npmjs.com/package/@samchon/openapi/next.svg) | ||
[![Downloads](https://img.shields.io/npm/dm/@samchon/openapi.svg)](https://www.npmjs.com/package/@samchon/openapi) | ||
@@ -54,6 +60,6 @@ [![Build Status](https://github.com/samchon/openapi/workflows/build/badge.svg)](https://github.com/samchon/openapi/actions?query=workflow%3Abuild) | ||
```bash | ||
npm install @samchon/openapi | ||
npm install @samchon/openapi --tag next | ||
``` | ||
Just install by `npm i @samchon/openapi` command. | ||
Just install by `npm i @samchon/openapi --tag next` command. | ||
@@ -60,0 +66,0 @@ Here is an example code utilizing the `@samchon/openapi` for LLM function calling purpose. |
@@ -53,3 +53,3 @@ import { OpenApi } from "../OpenApi"; | ||
if ( | ||
props.options.reference === true || | ||
props.options.escape === false || | ||
OpenApiTypeChecker.isRecursiveReference({ | ||
@@ -83,5 +83,39 @@ components: props.components, | ||
}); | ||
converted.description = OpenApiTypeChecker.writeReferenceDescription({ | ||
components: props.components, | ||
$ref: input.$ref, | ||
description: converted.description, | ||
escape: false, | ||
}); | ||
props.$defs[key] = converted; | ||
return out(); | ||
} else return visit(target); | ||
} else { | ||
const length: number = union.length; | ||
visit(target); | ||
if ( | ||
length === union.length - 1 && | ||
union[union.length - 1].schema !== null | ||
) | ||
union[union.length - 1] = { | ||
tags: union[union.length - 1].tags, | ||
schema: { | ||
...union[union.length - 1].schema, | ||
description: OpenApiTypeChecker.writeReferenceDescription({ | ||
components: props.components, | ||
$ref: input.$ref, | ||
description: union[union.length - 1].schema?.description, | ||
escape: true, | ||
}), | ||
}, | ||
}; | ||
else | ||
attribute.description = | ||
OpenApiTypeChecker.writeReferenceDescription({ | ||
components: props.components, | ||
$ref: input.$ref, | ||
description: attribute.description, | ||
escape: true, | ||
}); | ||
return union.length; | ||
} | ||
} else if (OpenApiTypeChecker.isObject(input)) { | ||
@@ -231,3 +265,3 @@ const properties: Record<string, IChatGptSchema | null> = | ||
else if ( | ||
props.options.reference === false && | ||
props.options.escape === true && | ||
OpenApiTypeChecker.isReference(input) && | ||
@@ -234,0 +268,0 @@ OpenApiTypeChecker.isRecursiveReference({ |
@@ -102,8 +102,8 @@ import { HttpMigration } from "./HttpMigration"; | ||
null, | ||
reference: | ||
escape: | ||
(props.options as IHttpLlmApplication.IChatGptOptions | undefined) | ||
?.reference ?? false, | ||
?.escape ?? false, | ||
constraint: | ||
(props.options as IHttpLlmApplication.IChatGptOptions | undefined) | ||
?.constraint ?? true, | ||
?.constraint ?? false, | ||
} satisfies IHttpLlmApplication.IChatGptOptions) | ||
@@ -110,0 +110,0 @@ : ({ |
@@ -31,9 +31,10 @@ /** | ||
* For reference, if you've composed the `IChatGptSchema` type with the | ||
* {@link ILlmApplication.IChatGptOptions.reference} `false` option, only the recursived | ||
* named types would be archived into the {@link IChatGptSchema.IParameters.$defs}, | ||
* and the others would be ecaped from the {@link IChatGptSchema.IReference} type. | ||
* {@link ILlmApplication.IChatGptOptions.escape} `true` option (default is `false`), | ||
* only the recursived named types would be archived into the | ||
* {@link IChatGptSchema.IParameters.$defs}, and the others would be ecaped from the | ||
* {@link IChatGptSchema.IReference} type. | ||
* | ||
* Also, if you've composed the `IChatGptSchema` type with the | ||
* {@link ILlmApplication.IChatGptOptions.constraint} `false` option, the | ||
* `IChatGptSchema` would not compose these properties. Instead, these | ||
* {@link ILlmApplication.IChatGptOptions.constraint} `false` option (default `false`), | ||
* the `IChatGptSchema` would not compose these properties. Instead, these | ||
* properties would be written on {@link IChatGptSchema.__IAttribute.descripotion} | ||
@@ -40,0 +41,0 @@ * field like `@format uuid` case. |
@@ -181,5 +181,5 @@ import { IChatGptSchema } from "./IChatGptSchema"; | ||
/** | ||
* Whether to allow reference type in everywhere. | ||
* Whether to escape reference type or not. | ||
* | ||
* If you configure this property to `false`, most of reference types | ||
* If you configure this property to `true`, most of reference types | ||
* represented by {@link IChatGptSchema.IReference} would be escaped to | ||
@@ -199,3 +199,3 @@ * a plain type unless recursive type case. | ||
*/ | ||
reference: boolean; | ||
escape: boolean; | ||
@@ -202,0 +202,0 @@ /** |
@@ -173,3 +173,3 @@ import { OpenApi } from "../OpenApi"; | ||
props.visited.set(name, depth + 1); | ||
return escapeSchema({ | ||
const res: OpenApi.IJsonSchema | null | undefined = escapeSchema({ | ||
components: props.components, | ||
@@ -180,4 +180,15 @@ schema: target, | ||
}); | ||
return res | ||
? { | ||
...res, | ||
description: writeReferenceDescription({ | ||
components: props.components, | ||
$ref: props.schema.$ref, | ||
description: res.description, | ||
escape: true, | ||
}), | ||
} | ||
: res; | ||
} | ||
return escapeSchema({ | ||
const res: OpenApi.IJsonSchema | null | undefined = escapeSchema({ | ||
components: props.components, | ||
@@ -188,2 +199,13 @@ schema: target, | ||
}); | ||
return res | ||
? { | ||
...res, | ||
description: writeReferenceDescription({ | ||
components: props.components, | ||
$ref: props.schema.$ref, | ||
description: res.description, | ||
escape: true, | ||
}), | ||
} | ||
: res; | ||
} else if (isOneOf(props.schema)) { | ||
@@ -207,3 +229,3 @@ // UNION | ||
...props, | ||
oneOf: filtered.map((v) => flat(props.components, v)).flat(), | ||
oneOf: filtered.map((v) => flatSchema(props.components, v)).flat(), | ||
}; | ||
@@ -350,4 +372,4 @@ } else if (isObject(props.schema)) { | ||
// COMPARE WITH FLATTENING | ||
const alpha: OpenApi.IJsonSchema[] = flat(p.components, p.x); | ||
const beta: OpenApi.IJsonSchema[] = flat(p.components, p.y); | ||
const alpha: OpenApi.IJsonSchema[] = flatSchema(p.components, p.x); | ||
const beta: OpenApi.IJsonSchema[] = flatSchema(p.components, p.y); | ||
if (alpha.some((x) => isUnknown(x))) return true; | ||
@@ -586,27 +608,75 @@ else if (beta.some((x) => isUnknown(x))) return false; | ||
(x === "iri-reference" && y === "uri-reference"); | ||
const flatSchema = ( | ||
components: OpenApi.IComponents, | ||
schema: OpenApi.IJsonSchema, | ||
): OpenApi.IJsonSchema[] => { | ||
schema = escapeReferenceOfFlatSchema(components, schema); | ||
if (OpenApiTypeChecker.isOneOf(schema)) | ||
return schema.oneOf.map((v) => flatSchema(components, v)).flat(); | ||
return [schema]; | ||
}; | ||
const escapeReferenceOfFlatSchema = ( | ||
components: OpenApi.IComponents, | ||
schema: OpenApi.IJsonSchema, | ||
): Exclude<OpenApi.IJsonSchema, OpenApi.IJsonSchema.IReference> => { | ||
if (OpenApiTypeChecker.isReference(schema) === false) return schema; | ||
const key = schema.$ref.replace("#/components/schemas/", ""); | ||
const found: OpenApi.IJsonSchema | undefined = escapeReferenceOfFlatSchema( | ||
components, | ||
components.schemas?.[key] ?? {}, | ||
); | ||
if (found === undefined) | ||
throw new Error( | ||
`Reference type not found: ${JSON.stringify(schema.$ref)}`, | ||
); | ||
return escapeReferenceOfFlatSchema(components, found); | ||
}; | ||
/** | ||
* @internal | ||
*/ | ||
export const writeReferenceDescription = (props: { | ||
components: OpenApi.IComponents; | ||
$ref: string; | ||
description: string | undefined; | ||
escape: boolean; | ||
}): string | undefined => { | ||
const index: number = props.$ref.lastIndexOf("."); | ||
if (index === -1) return props.description; | ||
const accessors: string[] = props.$ref | ||
.split("#/components/schemas/")[1] | ||
.split("."); | ||
const pReferences: IParentReference[] = accessors | ||
.slice(0, props.escape ? accessors.length : accessors.length - 1) | ||
.map((_, i, array) => array.slice(0, i + 1).join(".")) | ||
.map((key) => ({ | ||
key, | ||
description: props.components.schemas?.[key]?.description, | ||
})) | ||
.filter((schema): schema is IParentReference => !!schema?.description) | ||
.reverse(); | ||
if (pReferences.length === 0) return props.description; | ||
return [ | ||
...(props.description?.length ? [props.description] : []), | ||
...pReferences.map( | ||
(pRef, i) => | ||
`Description of the ${i === 0 && props.escape ? "current" : "parent"} {@link ${pRef.key}} type:\n\n` + | ||
pRef.description | ||
.split("\n") | ||
.map((str) => `> ${str}`) | ||
.join("\n"), | ||
), | ||
].join("\n\n------------------------------\n\n"); | ||
}; | ||
} | ||
const flat = ( | ||
components: OpenApi.IComponents, | ||
schema: OpenApi.IJsonSchema, | ||
): OpenApi.IJsonSchema[] => { | ||
schema = escapeReference(components, schema); | ||
if (OpenApiTypeChecker.isOneOf(schema)) | ||
return schema.oneOf.map((v) => flat(components, v)).flat(); | ||
return [schema]; | ||
}; | ||
const escapeReference = ( | ||
components: OpenApi.IComponents, | ||
schema: OpenApi.IJsonSchema, | ||
): Exclude<OpenApi.IJsonSchema, OpenApi.IJsonSchema.IReference> => { | ||
if (OpenApiTypeChecker.isReference(schema) === false) return schema; | ||
const key = schema.$ref.replace("#/components/schemas/", ""); | ||
const found: OpenApi.IJsonSchema | undefined = escapeReference( | ||
components, | ||
components.schemas?.[key] ?? {}, | ||
); | ||
if (found === undefined) | ||
throw new Error(`Reference not found: ${JSON.stringify(schema.$ref)}`); | ||
return escapeReference(components, found); | ||
}; | ||
/** | ||
* @internal | ||
*/ | ||
interface IParentReference { | ||
key: string; | ||
description: string; | ||
} |
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
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1535502
26603
414