diff --git a/package.json b/package.json index 9899ed3b..a2558b2a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@samchon/openapi", - "version": "6.0.0", + "version": "6.0.1", "description": "Universal OpenAPI to LLM function calling schemas. Transform any Swagger/OpenAPI document into type-safe schemas for OpenAI, Claude, Qwen, and more.", "main": "./lib/index.js", "module": "./lib/index.mjs", diff --git a/src/composers/HttpMigrateRouteComposer.ts b/src/composers/HttpMigrateRouteComposer.ts index 0c9f3592..48c9e5eb 100644 --- a/src/composers/HttpMigrateRouteComposer.ts +++ b/src/composers/HttpMigrateRouteComposer.ts @@ -316,11 +316,7 @@ export namespace HttpMigrateRouteComposer { query: IHttpMigrateRoute.IQuery | null; body: IHttpMigrateRoute.IBody | null; }): string => { - const commentTags: string[] = []; - const add = (text: string) => { - if (commentTags.every((line) => line !== text)) commentTags.push(text); - }; - + // write basic description combining with summary let description: string = props.operation.description ?? ""; if (!!props.operation.summary?.length) { const summary: string = props.operation.summary.endsWith(".") @@ -337,6 +333,15 @@ export namespace HttpMigrateRouteComposer { .map((s) => s.trim()) .join("\n"); + //---- + // compose jsdoc comment tags + //---- + const commentTags: string[] = []; + const add = (text: string) => { + if (commentTags.every((line) => line !== text)) commentTags.push(text); + }; + + // parameters add("@param connection"); for (const p of props.parameters ?? []) { const param = p.parameter(); @@ -347,12 +352,33 @@ export namespace HttpMigrateRouteComposer { } if (props.body?.description()?.length) add(`@param body ${writeIndented(props.body.description()!, 12)}`); + + // security for (const security of props.operation.security ?? []) for (const [name, scopes] of Object.entries(security)) add(`@security ${[name, ...scopes].join("")}`); + + // categorizing tags if (props.operation.tags) props.operation.tags.forEach((name) => add(`@tag ${name}`)); + + // deprecated if (props.operation.deprecated) add("@deprecated"); + + // plugin properties + for (const [key, value] of Object.entries(props.operation)) { + if (key.startsWith("x-") === false) continue; + else if ( + value !== null && + typeof value !== "boolean" && + typeof value !== "number" && + typeof value !== "string" + ) + continue; + add(`@${key} ${value}`); + } + + // finalize description description = description.length ? commentTags.length ? `${description}\n\n${commentTags.join("\n")}` diff --git a/test/src/features/migrate/test_http_migrate_route_plugin.ts b/test/src/features/migrate/test_http_migrate_route_plugin.ts new file mode 100644 index 00000000..a1bb9957 --- /dev/null +++ b/test/src/features/migrate/test_http_migrate_route_plugin.ts @@ -0,0 +1,41 @@ +import { TestValidator } from "@nestia/e2e"; +import { + HttpMigration, + IHttpMigrateApplication, + IHttpMigrateRoute, + OpenApi, +} from "@samchon/openapi"; + +export const test_http_migrate_route_plugin = async (): Promise => { + const document: OpenApi.IDocument = { + openapi: "3.1.0", + "x-samchon-emended-v4": true, + paths: { + "/items": { + get: { + description: "Retrieve a list of items.", + ...{ + "x-autobe-specification": [ + "Hello everyone!", + "", + "Nice to to meet you all.", + ].join("\n"), + }, + }, + }, + }, + components: {}, + }; + const migrate: IHttpMigrateApplication = HttpMigration.application(document); + const route: IHttpMigrateRoute = migrate.routes[0]; + TestValidator.equals("plugin")(route.comment())( + [ + "Retrieve a list of items.", + "", + "@param connection", + "@x-autobe-specification Hello everyone!", + "", + "Nice to to meet you all.", + ].join("\n"), + ); +};