diff --git a/packages/openapi-generator/src/jsdoc.ts b/packages/openapi-generator/src/jsdoc.ts index 6bf698f5..532c7cca 100644 --- a/packages/openapi-generator/src/jsdoc.ts +++ b/packages/openapi-generator/src/jsdoc.ts @@ -43,7 +43,7 @@ export function parseCommentBlock(comment: Block): JSDoc { if (line.tokens.description === '') { continue; } - summary = line.tokens.description; + summary = line.tokens.description.trim(); } else { description = `${description ?? ''}\n${line.tokens.description}`; } diff --git a/packages/openapi-generator/src/knownImports.ts b/packages/openapi-generator/src/knownImports.ts index fab630d0..b4025247 100644 --- a/packages/openapi-generator/src/knownImports.ts +++ b/packages/openapi-generator/src/knownImports.ts @@ -49,6 +49,7 @@ export const KNOWN_IMPORTS: KnownImports = { 'io-ts': { string: () => E.right({ type: 'string', primitive: true }), number: () => E.right({ type: 'number', primitive: true }), + integer: () => E.right({ type: 'integer', primitive: true }), bigint: () => E.right({ type: 'number' }), boolean: () => E.right({ type: 'boolean', primitive: true }), null: () => E.right({ type: 'null' }), diff --git a/packages/openapi-generator/src/openapi.ts b/packages/openapi-generator/src/openapi.ts index a7fe83de..7f0d3736 100644 --- a/packages/openapi-generator/src/openapi.ts +++ b/packages/openapi-generator/src/openapi.ts @@ -20,18 +20,23 @@ export function schemaToOpenAPI( switch (schema.type) { case 'boolean': case 'string': - case 'number': return { type: schema.type, ...(schema.enum ? { enum: schema.enum } : {}), ...defaultOpenAPIObject, }; - case 'integer': + case 'number': return { type: 'number', ...(schema.enum ? { enum: schema.enum } : {}), ...defaultOpenAPIObject, }; + case 'integer': + return { + type: 'integer', + ...(schema.enum ? { enum: schema.enum } : {}), + ...defaultOpenAPIObject, + }; case 'null': // TODO: OpenAPI v3 does not have an explicit null type, is there a better way to represent this? // Or should we just conflate explicit null and undefined properties? diff --git a/packages/openapi-generator/test/openapi/base.test.ts b/packages/openapi-generator/test/openapi/base.test.ts index 6617df93..f92e3677 100644 --- a/packages/openapi-generator/test/openapi/base.test.ts +++ b/packages/openapi-generator/test/openapi/base.test.ts @@ -716,6 +716,128 @@ testCase('route with array union of null and undefined', ROUTE_WITH_ARRAY_UNION_ } }); +const ROUTE_WITH_INTEGER_QUERY_PARAM = ` +import * as t from 'io-ts'; +import * as h from '@api-ts/io-ts-http'; + +/** + * A route with integer query parameter + * + * @operationId api.v1.integerTest + * @tag Test Routes + */ +export const route = h.httpRoute({ + path: '/items', + method: 'GET', + request: h.httpRequest({ + query: { + /** + * Maximum number of items to return + * @example 100 + */ + limit: t.integer, + + /** + * Page number for pagination + * @minimum 1 + */ + page: t.integer, + + /** + * Regular number parameter for comparison + */ + ratio: t.number + }, + }), + response: { + 200: t.type({ + items: t.array(t.string), + totalCount: t.integer + }) + }, +}); +`; + +testCase('route with integer query parameters', ROUTE_WITH_INTEGER_QUERY_PARAM, { + openapi: '3.0.3', + info: { + title: 'Test', + version: '1.0.0', + }, + paths: { + '/items': { + get: { + summary: 'A route with integer query parameter', + operationId: 'api.v1.integerTest', + tags: [ + 'Test Routes' + ], + parameters: [ + { + name: 'limit', + description: 'Maximum number of items to return', + in: 'query', + required: true, + schema: { + type: 'integer', + example: 100 + } + }, + { + name: 'page', + description: 'Page number for pagination', + in: 'query', + required: true, + schema: { + type: 'integer', + minimum: 1 + } + }, + { + name: 'ratio', + description: 'Regular number parameter for comparison', + in: 'query', + required: true, + schema: { + type: 'number' + } + } + ], + responses: { + '200': { + description: 'OK', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + items: { + type: 'array', + items: { + type: 'string' + } + }, + totalCount: { + type: 'integer' + } + }, + required: [ + 'items', + 'totalCount' + ] + } + } + } + } + } + } + } + }, + components: { + schemas: {} + } +}); + const MULTIPLE_ROUTES = ` import * as t from 'io-ts'; import * as h from '@api-ts/io-ts-http';