diff --git a/packages/openapi-generator/src/codec.ts b/packages/openapi-generator/src/codec.ts index a3a96354..f420c55d 100644 --- a/packages/openapi-generator/src/codec.ts +++ b/packages/openapi-generator/src/codec.ts @@ -374,8 +374,13 @@ export function parseCodecInitializer( if (E.isLeft(initE)) { return initE; } - const [newSourceFile, init] = initE.right; - return parsePlainInitializer(project, newSourceFile, init); + const [newSourceFile, init, comment] = initE.right; + const plainInitE = parsePlainInitializer(project, newSourceFile, init); + + if (E.isLeft(plainInitE)) return plainInitE; + if (comment !== undefined) plainInitE.right.comment = comment; + + return plainInitE; } } const args = init.arguments.map>(({ expression }) => { diff --git a/packages/openapi-generator/src/openapi.ts b/packages/openapi-generator/src/openapi.ts index d60493cb..f983e4b5 100644 --- a/packages/openapi-generator/src/openapi.ts +++ b/packages/openapi-generator/src/openapi.ts @@ -260,25 +260,13 @@ function routeToOpenAPI(route: Route): [string, string, OpenAPIV3.OperationObjec {}, ); - const stripTopLevelComment = (schema: Schema) => { - const copy = { ...schema }; - - if (copy.comment?.description !== undefined && copy.comment?.description !== '') { - copy.comment.description = ''; - } - - return copy; - }; - - const topLevelStripped = stripTopLevelComment(route.body!); - const requestBody = route.body === undefined ? {} : { requestBody: { content: { - 'application/json': { schema: schemaToOpenAPI(topLevelStripped) }, + 'application/json': { schema: schemaToOpenAPI(route.body) }, }, }, }; diff --git a/packages/openapi-generator/test/openapi.test.ts b/packages/openapi-generator/test/openapi.test.ts index 791c3134..0b7a0ee4 100644 --- a/packages/openapi-generator/test/openapi.test.ts +++ b/packages/openapi-generator/test/openapi.test.ts @@ -12,6 +12,7 @@ import { type Route, type Schema, } from '../src'; +import { SourceFile } from '../src/sourceFile'; async function testCase( description: string, @@ -28,8 +29,8 @@ async function testCase( if (sourceFile === undefined) { throw new Error('Failed to parse source file'); } - - const project = new Project(); + const files: Record = { './index.ts': sourceFile }; + const project = new Project(files); const routes: Route[] = []; const schemas: Record = {}; const errors: string[] = []; @@ -3454,4 +3455,114 @@ testCase('route with reduntant response schemas', SCHEMA_WITH_REDUNDANT_UNIONS, components: { schemas: {} } -}); \ No newline at end of file +}); + +const SCHEMA_WITH_TITLES_IN_REQUEST_BODIES = ` +import * as t from 'io-ts'; +import * as h from '@api-ts/io-ts-http'; + +/** + * @title Some Readable BodyFoo Title + */ +const BodyFoo = t.type({ + /** a foo description */ + foo: t.string, +}); + +/** + * @title Some Readable ParamsFoo Title + */ +const ParamsFoo = { someId: t.string }; + +export const route = h.httpRoute({ + path: '/foo', + method: 'POST', + request: h.httpRequest({ + params: {}, + body: h.httpRequest({ params: ParamsFoo, body: BodyFoo, }) + }), + response: { + 200: t.literal('OK'), + }, +}); +` + +testCase("route with titles in request bodies", SCHEMA_WITH_TITLES_IN_REQUEST_BODIES, { + openapi: '3.0.3', + info: { + title: 'Test', + version: '1.0.0' + }, + paths: { + '/foo': { + post: { + parameters: [], + requestBody: { + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + params: { + type: 'object', + title: "Some Readable ParamsFoo Title", + properties: { + someId: { type: 'string' } + }, + required: [ 'someId' ] + }, + body: { + type: 'object', + title: 'Some Readable BodyFoo Title', + properties: { + foo: { + type: 'string', + description: 'a foo description' + } + }, + required: [ 'foo' ] + } + }, + required: [ 'params', 'body' ] + } + } + } + }, + responses: { + '200': { + description: 'OK', + content: { + 'application/json': { + schema: { + type: 'string', + enum: [ 'OK' ] + } + } + } + } + } + } + } + }, + components: { + schemas: { + ParamsFoo: { + title: 'Some Readable ParamsFoo Title', + type: 'object', + properties: { someId: { type: 'string' } }, + required: [ 'someId' ] + }, + BodyFoo: { + title: 'Some Readable BodyFoo Title', + type: 'object', + properties: { + foo: { + type: 'string', + description: 'a foo description' + } + }, + required: [ 'foo' ] + } + } + } +});