Skip to content

Commit

Permalink
Fix OpenApi.IJsonSchema.ITuple downgrading problem.
Browse files Browse the repository at this point in the history
  • Loading branch information
samchon committed Nov 11, 2024
1 parent 101aada commit c78adbc
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 51 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@samchon/openapi",
"version": "2.0.0-dev.20241111-3",
"version": "2.0.0-dev.20241112",
"description": "OpenAPI definitions and converters for 'typia' and 'nestia'.",
"main": "./lib/index.js",
"module": "./lib/index.mjs",
Expand Down
2 changes: 1 addition & 1 deletion src/converters/HttpLlmConverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export namespace HttpLlmConverter {
errors.push({
method: route.method,
path: route.path,
messages: ["Failed to escape $ref"],
messages: ["Failed to escape $ref"], // @todo
operation: () => route.operation(),
route: () => route as any as Route,
});
Expand Down
12 changes: 2 additions & 10 deletions src/converters/LlmConverterV3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,10 @@ export namespace LlmConverterV3 {
recursive: props.recursive,
});
if (resolved === null) return null;
const downgraded: ILlmSchemaV3 = OpenApiV3Downgrader.downgradeSchema({
return OpenApiV3Downgrader.downgradeSchema({
original: {},
downgraded: {},
})(resolved) as ILlmSchemaV3;
LlmTypeCheckerV3.visit(downgraded, (schema) => {
if (
LlmTypeCheckerV3.isOneOf(schema) &&
(schema as any).discriminator !== undefined
)
delete (schema as any).discriminator;
});
return downgraded;
})(resolved);
};

export const separate = (props: {
Expand Down
30 changes: 14 additions & 16 deletions src/converters/OpenApiV3Downgrader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,31 +208,29 @@ export namespace OpenApiV3Downgrader {
items: downgradeSchema(collection)(schema.items),
});
else if (OpenApiTypeChecker.isTuple(schema))
union.push({
visit({
...schema,
items: ((): OpenApiV3.IJsonSchema => {
if (schema.additionalItems === true) return {};
const elements = [
type: "array",
items: {
oneOf: [
...schema.prefixItems,
...(typeof schema.additionalItems === "object"
? [downgradeSchema(collection)(schema.additionalItems)]
...(typeof schema.additionalItems === "object" &&
schema.additionalItems !== null
? [schema.additionalItems]
: []),
];
if (elements.length === 0) return {};
return {
oneOf: elements.map(downgradeSchema(collection) as any),
};
})(),
minItems: schema.prefixItems.length,
],
},
minItems: schema.minItems ?? schema.prefixItems.length,
maxItems:
!!schema.additionalItems === true
schema.maxItems ??
(schema.additionalItems === true
? undefined
: schema.prefixItems.length,
: schema.prefixItems.length),
...{
prefixItems: undefined,
additionalItems: undefined,
},
});
} satisfies OpenApi.IJsonSchema.IArray);
else if (OpenApiTypeChecker.isObject(schema))
union.push({
...schema,
Expand Down
43 changes: 20 additions & 23 deletions src/converters/SwaggerV2Downgrader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,34 +228,29 @@ export namespace SwaggerV2Downgrader {
: undefined,
});
else if (OpenApiTypeChecker.isTuple(schema))
union.push({
visit({
...schema,
items: ((): SwaggerV2.IJsonSchema => {
if (schema.additionalItems === true) return {};
const elements = [
type: "array",
items: {
oneOf: [
...schema.prefixItems,
...(typeof schema.additionalItems === "object"
? [downgradeSchema(collection)(schema.additionalItems)]
...(typeof schema.additionalItems === "object" &&
schema.additionalItems !== null
? [schema.additionalItems]
: []),
];
if (elements.length === 0) return {};
return {
"x-oneOf": elements.map(downgradeSchema(collection) as any),
};
})(),
minItems: schema.prefixItems.length,
],
},
minItems: schema.minItems ?? schema.prefixItems.length,
maxItems:
!!schema.additionalItems === true
schema.maxItems ??
(schema.additionalItems === true
? undefined
: schema.prefixItems.length,
: schema.prefixItems.length),
...{
prefixItems: undefined,
additionalItems: undefined,
},
examples: schema.examples
? Object.values(schema.examples)
: undefined,
});
} satisfies OpenApi.IJsonSchema.IArray);
else if (OpenApiTypeChecker.isObject(schema))
union.push({
...schema,
Expand Down Expand Up @@ -285,16 +280,18 @@ export namespace SwaggerV2Downgrader {
const insert = (value: any): void => {
const matched: SwaggerV2.IJsonSchema.INumber | undefined = union.find(
(u) =>
(u as SwaggerV2.IJsonSchema.__ISignificant<any>).type === value,
(u as SwaggerV2.IJsonSchema.__ISignificant<any>).type ===
typeof value,
) as SwaggerV2.IJsonSchema.INumber | undefined;
if (matched !== undefined) {
matched.enum ??= [];
matched.enum.push(value);
} else union.push({ type: typeof value as "number", enum: [value] });
if (OpenApiTypeChecker.isConstant(schema)) insert(schema.const);
else if (OpenApiTypeChecker.isOneOf(schema))
schema.oneOf.forEach(insert);
};
if (OpenApiTypeChecker.isConstant(schema)) insert(schema.const);
else if (OpenApiTypeChecker.isOneOf(schema))
for (const u of schema.oneOf)
if (OpenApiTypeChecker.isConstant(u)) insert(u.const);
};

visit(input);
Expand Down
1 change: 1 addition & 0 deletions src/utils/OpenApiTypeChecker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ export namespace OpenApiTypeChecker {
return {
...props,
oneOf: filtered.map((v) => flat(props.components, v)).flat(),
discriminator: undefined,
};
} else if (isObject(props.schema)) {
// OBJECT
Expand Down
35 changes: 35 additions & 0 deletions test/features/openapi/test_json_schema_downgrade_v20_tuple.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { TestValidator } from "@nestia/e2e";
import { SwaggerV2Downgrader } from "@samchon/openapi/lib/converters/SwaggerV2Downgrader";
import typia from "typia";

export const test_json_schema_downgrade_v20_tuple = (): void => {
const collection = typia.json.application<[[false, 1, 2, "three", null]]>();
const schema = SwaggerV2Downgrader.downgradeSchema({
original: collection.components,
downgraded: {},
})(collection.schemas[0]);
TestValidator.equals("tuple")(schema)({
type: "array",
items: {
"x-oneOf": [
{
type: "boolean",
enum: [false],
"x-nullable": true,
},
{
type: "number",
enum: [1, 2],
"x-nullable": true,
},
{
type: "string",
enum: ["three"],
"x-nullable": true,
},
],
},
minItems: 5,
maxItems: 5,
});
};
35 changes: 35 additions & 0 deletions test/features/openapi/test_json_schema_downgrade_v30_tuple.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { TestValidator } from "@nestia/e2e";
import { OpenApiV3Downgrader } from "@samchon/openapi/lib/converters/OpenApiV3Downgrader";
import typia from "typia";

export const test_json_schema_downgrade_v30_tuple = (): void => {
const collection = typia.json.application<[[false, 1, 2, "three", null]]>();
const schema = OpenApiV3Downgrader.downgradeSchema({
original: collection.components,
downgraded: {},
})(collection.schemas[0]);
TestValidator.equals("tuple")(schema)({
type: "array",
items: {
oneOf: [
{
type: "boolean",
enum: [false],
nullable: true,
},
{
type: "number",
enum: [1, 2],
nullable: true,
},
{
type: "string",
enum: ["three"],
nullable: true,
},
],
},
minItems: 5,
maxItems: 5,
});
};

0 comments on commit c78adbc

Please sign in to comment.