From 942cc2f28b4c8e6db50f0db4cb0a2b56d3ada680 Mon Sep 17 00:00:00 2001 From: Dereck Tu Date: Tue, 16 Dec 2025 10:29:38 -0500 Subject: [PATCH] fix: pass default openapi object to any case Ticket: DX-2582 This commit passes the defaultOpenAPIObject to the any case. This allows for us to not drop the jsdoc information on t.any types. It is valid openapi to have descriptions and other metadata on any types: https://swagger.io/docs/specification/v3_0/data-models/data-types/#any-type From the following slack thread: https://bitgo.slack.com/archives/C057BHBRG4B/p1765481932730759 \# Test Tested in `entity-validation`: ``` $ > diff test.json test2.json 3123,3137c3123,3125 < "frontPhoto": { < "description": "Front photo of the identity document", < "example": "\"passport-front.jpg\"", < "format": "binary" < }, < "backPhoto": { < "description": "Back photo of the identity document", < "example": "\"drivers-license-back.png\"", < "format": "binary" < }, < "proofOfResidency": { < "description": "Proof of residency", < "example": "\"rental-lease.pdf\"", < "format": "binary" < } --- > "frontPhoto": {}, > "backPhoto": {}, > "proofOfResidency": {} 3264,3278c3252,3254 < "frontPhoto": { < "description": "Front photo of the identity document", < "example": "\"passport-front.jpg\"", < "format": "binary" < }, < "backPhoto": { < "description": "Back photo of the identity document", < "example": "\"drivers-license-back.png\"", < "format": "binary" < }, < "proofOfResidency": { < "description": "Proof of residency", < "example": "\"rental-lease.pdf\"", < "format": "binary" < } --- > "frontPhoto": {}, > "backPhoto": {}, > "proofOfResidency": {} ``` --- packages/openapi-generator/src/openapi.ts | 2 +- .../test/openapi/jsdoc.test.ts | 128 ++++++++++++++++++ 2 files changed, 129 insertions(+), 1 deletion(-) diff --git a/packages/openapi-generator/src/openapi.ts b/packages/openapi-generator/src/openapi.ts index 652a4853..b7dd89b1 100644 --- a/packages/openapi-generator/src/openapi.ts +++ b/packages/openapi-generator/src/openapi.ts @@ -234,7 +234,7 @@ export function schemaToOpenAPI( case 'undefined': return undefined; case 'any': - return {}; + return { ...defaultOpenAPIObject }; default: return {}; } diff --git a/packages/openapi-generator/test/openapi/jsdoc.test.ts b/packages/openapi-generator/test/openapi/jsdoc.test.ts index 7333578a..39efd86c 100644 --- a/packages/openapi-generator/test/openapi/jsdoc.test.ts +++ b/packages/openapi-generator/test/openapi/jsdoc.test.ts @@ -1232,3 +1232,131 @@ testCase( }, }, ); + +const ROUTE_WITH_ANY_AND_DESCRIPTION = ` +import * as t from 'io-ts'; +import * as h from '@api-ts/io-ts-http'; + +/** + * A simple route + * + * @operationId api.v1.test + * @tag Test Routes + */ +export const route = h.httpRoute({ + path: '/foo', + method: 'GET', + request: h.httpRequest({}), + response: { + 200: { + /** + * Test description + */ + test: t.any + } + }, +}); +`; + +testCase('route with example object', ROUTE_WITH_ANY_AND_DESCRIPTION, { + openapi: '3.0.3', + info: { + title: 'Test', + version: '1.0.0', + }, + paths: { + '/foo': { + get: { + summary: 'A simple route', + operationId: 'api.v1.test', + tags: ['Test Routes'], + parameters: [], + responses: { + 200: { + description: 'OK', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + test: { + description: 'Test description', + }, + }, + required: ['test'], + }, + }, + }, + }, + }, + }, + }, + }, + components: { + schemas: {}, + }, +}); + +const ROUTE_WITH_ANY_AND_FORMAT = ` +import * as t from 'io-ts'; +import * as h from '@api-ts/io-ts-http'; + +/** + * A simple route + * + * @operationId api.v1.test + * @tag Test Routes + */ +export const route = h.httpRoute({ + path: '/foo', + method: 'GET', + request: h.httpRequest({}), + response: { + 200: { + /** + * @format binary + */ + test: t.any + } + }, +}); +`; + +testCase('route with example object', ROUTE_WITH_ANY_AND_FORMAT, { + openapi: '3.0.3', + info: { + title: 'Test', + version: '1.0.0', + }, + paths: { + '/foo': { + get: { + summary: 'A simple route', + operationId: 'api.v1.test', + tags: ['Test Routes'], + parameters: [], + responses: { + 200: { + description: 'OK', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + test: { + format: 'binary', + }, + }, + required: ['test'], + }, + }, + }, + }, + }, + }, + }, + }, + components: { + schemas: {}, + }, +});