From 9879e1d0e729832e8bcba43b8232cb4fed9ec427 Mon Sep 17 00:00:00 2001 From: Aleksandr Batalov Date: Sat, 21 Jun 2025 03:43:19 +0400 Subject: [PATCH 1/3] chore(test-fixtures): add `$ref` example for the `responses` --- .../no-extra-options.ts.snapshot.ts | 32 +++++++---------- ...icit-component-enum-exports.ts.snapshot.ts | 22 ++++++------ ...-explicit-component-exports.ts.snapshot.ts | 22 ++++++------ .../with-extra-options.ts.snapshot.ts | 22 ++++++------ .../__snapshots__/getServices.spec.ts.snap | 36 +++++-------------- .../services/FilesService.ts.snapshot.ts | 2 +- .../services/FilesService.ts.snapshot.ts | 2 +- packages/test-fixtures/openapi.json | 24 ++++++------- 8 files changed, 72 insertions(+), 90 deletions(-) diff --git a/packages/openapi-typescript-plugin/src/__snapshots__/no-extra-options.ts.snapshot.ts b/packages/openapi-typescript-plugin/src/__snapshots__/no-extra-options.ts.snapshot.ts index 0efdd5c99..c62552cb2 100644 --- a/packages/openapi-typescript-plugin/src/__snapshots__/no-extra-options.ts.snapshot.ts +++ b/packages/openapi-typescript-plugin/src/__snapshots__/no-extra-options.ts.snapshot.ts @@ -174,7 +174,17 @@ export interface components { url: string; }; }; - responses: never; + responses: { + /** @description Unexpected error */ + DefaultErrorSchemaResponse: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorSchemaResponse"]; + }; + }; + }; parameters: { IdIn: string[]; /** @example 2023-06-04 */ @@ -262,15 +272,7 @@ export interface operations { "application/json": components["schemas"]["HTTPValidationError"]; }; }; - /** @description Unexpected error */ - default: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorSchemaResponse"]; - }; - }; + default: components["responses"]["DefaultErrorSchemaResponse"]; }; }; get_approval_policies_id: { @@ -514,15 +516,7 @@ export interface operations { "application/json": components["schemas"]["HTTPValidationError"]; }; }; - /** @description Internal Server Error */ - default: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorSchemaResponse"]; - }; - }; + default: components["responses"]["DefaultErrorSchemaResponse"]; }; }; post_files: { diff --git a/packages/openapi-typescript-plugin/src/__snapshots__/with-explicit-component-enum-exports.ts.snapshot.ts b/packages/openapi-typescript-plugin/src/__snapshots__/with-explicit-component-enum-exports.ts.snapshot.ts index 81b5bb3bb..f1931db31 100644 --- a/packages/openapi-typescript-plugin/src/__snapshots__/with-explicit-component-enum-exports.ts.snapshot.ts +++ b/packages/openapi-typescript-plugin/src/__snapshots__/with-explicit-component-enum-exports.ts.snapshot.ts @@ -89,7 +89,17 @@ export interface components { url: string; }; }; - responses: never; + responses: { + /** @description Unexpected error */ + DefaultErrorSchemaResponse: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorSchemaResponse"]; + }; + }; + }; parameters: { IdIn: string[]; /** @example 2023-06-04 */ @@ -160,15 +170,7 @@ export interface operations { "application/json": components["schemas"]["HTTPValidationError"]; }; }; - /** @description Internal Server Error */ - default: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorSchemaResponse"]; - }; - }; + default: components["responses"]["DefaultErrorSchemaResponse"]; }; }; post_files: { diff --git a/packages/openapi-typescript-plugin/src/__snapshots__/with-explicit-component-exports.ts.snapshot.ts b/packages/openapi-typescript-plugin/src/__snapshots__/with-explicit-component-exports.ts.snapshot.ts index 73c5519a5..f434166ea 100644 --- a/packages/openapi-typescript-plugin/src/__snapshots__/with-explicit-component-exports.ts.snapshot.ts +++ b/packages/openapi-typescript-plugin/src/__snapshots__/with-explicit-component-exports.ts.snapshot.ts @@ -89,7 +89,17 @@ export interface components { url: string; }; }; - responses: never; + responses: { + /** @description Unexpected error */ + DefaultErrorSchemaResponse: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorSchemaResponse"]; + }; + }; + }; parameters: { IdIn: string[]; /** @example 2023-06-04 */ @@ -160,15 +170,7 @@ export interface operations { "application/json": components["schemas"]["HTTPValidationError"]; }; }; - /** @description Internal Server Error */ - default: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorSchemaResponse"]; - }; - }; + default: components["responses"]["DefaultErrorSchemaResponse"]; }; }; post_files: { diff --git a/packages/openapi-typescript-plugin/src/__snapshots__/with-extra-options.ts.snapshot.ts b/packages/openapi-typescript-plugin/src/__snapshots__/with-extra-options.ts.snapshot.ts index e421b9a36..f399fe8c0 100644 --- a/packages/openapi-typescript-plugin/src/__snapshots__/with-extra-options.ts.snapshot.ts +++ b/packages/openapi-typescript-plugin/src/__snapshots__/with-extra-options.ts.snapshot.ts @@ -126,7 +126,17 @@ export interface components { url: string; }; }; - responses: never; + responses: { + /** @description Unexpected error */ + DefaultErrorSchemaResponse: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorSchemaResponse"]; + }; + }; + }; parameters: { IdIn: string[]; /** @example 2023-06-04 */ @@ -197,15 +207,7 @@ export interface operations { "application/json": components["schemas"]["HTTPValidationError"]; }; }; - /** @description Internal Server Error */ - default: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorSchemaResponse"]; - }; - }; + default: components["responses"]["DefaultErrorSchemaResponse"]; }; }; post_files: { diff --git a/packages/plugin/src/lib/open-api/__snapshots__/getServices.spec.ts.snap b/packages/plugin/src/lib/open-api/__snapshots__/getServices.spec.ts.snap index b41e095f2..3d7e73247 100644 --- a/packages/plugin/src/lib/open-api/__snapshots__/getServices.spec.ts.snap +++ b/packages/plugin/src/lib/open-api/__snapshots__/getServices.spec.ts.snap @@ -19,9 +19,7 @@ exports[`getServices > matches snapshot with "serviceNameBase: endpoint" 1`] = ` "422": [ "application/json", ], - "default": [ - "application/json", - ], + "default": null, }, "method": "post", "name": "postEntitiesIdDocuments", @@ -330,9 +328,7 @@ exports[`getServices > matches snapshot with "serviceNameBase: endpoint" 1`] = ` "422": [ "application/json", ], - "default": [ - "application/json", - ], + "default": null, }, "method": "get", "name": "getFiles", @@ -569,9 +565,7 @@ exports[`getServices > matches snapshot with "serviceNameBase: tags" 1`] = ` "422": [ "application/json", ], - "default": [ - "application/json", - ], + "default": null, }, "method": "post", "name": "postEntitiesIdDocuments", @@ -880,9 +874,7 @@ exports[`getServices > matches snapshot with "serviceNameBase: tags" 1`] = ` "422": [ "application/json", ], - "default": [ - "application/json", - ], + "default": null, }, "method": "get", "name": "getFiles", @@ -1119,9 +1111,7 @@ exports[`getServices > matches snapshot with custom \`postfixServices\` 1`] = ` "422": [ "application/json", ], - "default": [ - "application/json", - ], + "default": null, }, "method": "post", "name": "postEntitiesIdDocuments", @@ -1430,9 +1420,7 @@ exports[`getServices > matches snapshot with custom \`postfixServices\` 1`] = ` "422": [ "application/json", ], - "default": [ - "application/json", - ], + "default": null, }, "method": "get", "name": "getFiles", @@ -1666,9 +1654,7 @@ exports[`getServices > matches snapshot with custom \`servicesGlob\` 1`] = ` "422": [ "application/json", ], - "default": [ - "application/json", - ], + "default": null, }, "method": "get", "name": "getFiles", @@ -1905,9 +1891,7 @@ exports[`getServices > matches snapshot with default options 1`] = ` "422": [ "application/json", ], - "default": [ - "application/json", - ], + "default": null, }, "method": "post", "name": "postEntitiesIdDocuments", @@ -2216,9 +2200,7 @@ exports[`getServices > matches snapshot with default options 1`] = ` "422": [ "application/json", ], - "default": [ - "application/json", - ], + "default": null, }, "method": "get", "name": "getFiles", diff --git a/packages/tanstack-query-react-plugin/src/__snapshots__/explicit-import-extensions/services/FilesService.ts.snapshot.ts b/packages/tanstack-query-react-plugin/src/__snapshots__/explicit-import-extensions/services/FilesService.ts.snapshot.ts index b02b00381..240de0bed 100644 --- a/packages/tanstack-query-react-plugin/src/__snapshots__/explicit-import-extensions/services/FilesService.ts.snapshot.ts +++ b/packages/tanstack-query-react-plugin/src/__snapshots__/explicit-import-extensions/services/FilesService.ts.snapshot.ts @@ -1314,7 +1314,7 @@ type GetFilesSchema = { }; type GetFilesParameters = paths["/files"]["get"]["parameters"]; type GetFilesData = paths["/files"]["get"]["responses"]["200"]["content"]["application/json"]; -type GetFilesError = paths["/files"]["get"]["responses"]["405"]["content"]["application/json"] | paths["/files"]["get"]["responses"]["422"]["content"]["application/json"] | paths["/files"]["get"]["responses"]["default"]["content"]["application/json"]; +type GetFilesError = paths["/files"]["get"]["responses"]["405"]["content"]["application/json"] | paths["/files"]["get"]["responses"]["422"]["content"]["application/json"] | null; type PostFilesSchema = { method: "post"; url: "/files"; diff --git a/packages/tanstack-query-react-plugin/src/__snapshots__/queryable-write-operations/services/FilesService.ts.snapshot.ts b/packages/tanstack-query-react-plugin/src/__snapshots__/queryable-write-operations/services/FilesService.ts.snapshot.ts index 0dd761907..a1ea6bd86 100644 --- a/packages/tanstack-query-react-plugin/src/__snapshots__/queryable-write-operations/services/FilesService.ts.snapshot.ts +++ b/packages/tanstack-query-react-plugin/src/__snapshots__/queryable-write-operations/services/FilesService.ts.snapshot.ts @@ -2291,7 +2291,7 @@ type GetFilesSchema = { }; type GetFilesParameters = paths["/files"]["get"]["parameters"]; type GetFilesData = paths["/files"]["get"]["responses"]["200"]["content"]["application/json"]; -type GetFilesError = paths["/files"]["get"]["responses"]["405"]["content"]["application/json"] | paths["/files"]["get"]["responses"]["422"]["content"]["application/json"] | paths["/files"]["get"]["responses"]["default"]["content"]["application/json"]; +type GetFilesError = paths["/files"]["get"]["responses"]["405"]["content"]["application/json"] | paths["/files"]["get"]["responses"]["422"]["content"]["application/json"] | null; type PostFilesSchema = { method: "post"; url: "/files"; diff --git a/packages/test-fixtures/openapi.json b/packages/test-fixtures/openapi.json index 042bd62b5..8fdfb097f 100644 --- a/packages/test-fixtures/openapi.json +++ b/packages/test-fixtures/openapi.json @@ -120,12 +120,7 @@ } }, "default": { - "description": "Unexpected error", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorSchemaResponse" } - } - } + "$ref": "#/components/responses/DefaultErrorSchemaResponse" } }, "security": [{ "userToken": [] }, { "partnerToken": [] }] @@ -493,12 +488,7 @@ } }, "default": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorSchemaResponse" } - } - } + "$ref": "#/components/responses/DefaultErrorSchemaResponse" } }, "security": [{ "HTTPBearer": [] }] @@ -881,6 +871,16 @@ } } } + }, + "responses": { + "DefaultErrorSchemaResponse": { + "description": "Unexpected error", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/ErrorSchemaResponse" } + } + } + } } } } From 74d40937a1505f5d3643e404ab322d30088ce3d9 Mon Sep 17 00:00:00 2001 From: Aleksandr Batalov Date: Sat, 21 Jun 2025 03:44:16 +0400 Subject: [PATCH 2/3] feat(plugin): add support for the responses with the `$ref` specified --- .../src/lib/open-api/OpenAPISchemaType.ts | 3 +- .../__snapshots__/getServices.spec.ts.snap | 36 ++++++++++++++----- .../plugin/src/lib/open-api/getServices.ts | 7 ++++ .../services/FilesService.ts.snapshot.ts | 2 +- .../services/FilesService.ts.snapshot.ts | 2 +- 5 files changed, 38 insertions(+), 12 deletions(-) diff --git a/packages/plugin/src/lib/open-api/OpenAPISchemaType.ts b/packages/plugin/src/lib/open-api/OpenAPISchemaType.ts index d5e1b91bc..58c97c1ea 100644 --- a/packages/plugin/src/lib/open-api/OpenAPISchemaType.ts +++ b/packages/plugin/src/lib/open-api/OpenAPISchemaType.ts @@ -24,7 +24,8 @@ export type OpenAPISchemaType = { }; responses: { [statusCode in number | 'default']: { - description: string; + $ref?: string; + description?: string; content?: { [contentType: string]: | { diff --git a/packages/plugin/src/lib/open-api/__snapshots__/getServices.spec.ts.snap b/packages/plugin/src/lib/open-api/__snapshots__/getServices.spec.ts.snap index 3d7e73247..b41e095f2 100644 --- a/packages/plugin/src/lib/open-api/__snapshots__/getServices.spec.ts.snap +++ b/packages/plugin/src/lib/open-api/__snapshots__/getServices.spec.ts.snap @@ -19,7 +19,9 @@ exports[`getServices > matches snapshot with "serviceNameBase: endpoint" 1`] = ` "422": [ "application/json", ], - "default": null, + "default": [ + "application/json", + ], }, "method": "post", "name": "postEntitiesIdDocuments", @@ -328,7 +330,9 @@ exports[`getServices > matches snapshot with "serviceNameBase: endpoint" 1`] = ` "422": [ "application/json", ], - "default": null, + "default": [ + "application/json", + ], }, "method": "get", "name": "getFiles", @@ -565,7 +569,9 @@ exports[`getServices > matches snapshot with "serviceNameBase: tags" 1`] = ` "422": [ "application/json", ], - "default": null, + "default": [ + "application/json", + ], }, "method": "post", "name": "postEntitiesIdDocuments", @@ -874,7 +880,9 @@ exports[`getServices > matches snapshot with "serviceNameBase: tags" 1`] = ` "422": [ "application/json", ], - "default": null, + "default": [ + "application/json", + ], }, "method": "get", "name": "getFiles", @@ -1111,7 +1119,9 @@ exports[`getServices > matches snapshot with custom \`postfixServices\` 1`] = ` "422": [ "application/json", ], - "default": null, + "default": [ + "application/json", + ], }, "method": "post", "name": "postEntitiesIdDocuments", @@ -1420,7 +1430,9 @@ exports[`getServices > matches snapshot with custom \`postfixServices\` 1`] = ` "422": [ "application/json", ], - "default": null, + "default": [ + "application/json", + ], }, "method": "get", "name": "getFiles", @@ -1654,7 +1666,9 @@ exports[`getServices > matches snapshot with custom \`servicesGlob\` 1`] = ` "422": [ "application/json", ], - "default": null, + "default": [ + "application/json", + ], }, "method": "get", "name": "getFiles", @@ -1891,7 +1905,9 @@ exports[`getServices > matches snapshot with default options 1`] = ` "422": [ "application/json", ], - "default": null, + "default": [ + "application/json", + ], }, "method": "post", "name": "postEntitiesIdDocuments", @@ -2200,7 +2216,9 @@ exports[`getServices > matches snapshot with default options 1`] = ` "422": [ "application/json", ], - "default": null, + "default": [ + "application/json", + ], }, "method": "get", "name": "getFiles", diff --git a/packages/plugin/src/lib/open-api/getServices.ts b/packages/plugin/src/lib/open-api/getServices.ts index 2ad5cf75c..af60c4b37 100644 --- a/packages/plugin/src/lib/open-api/getServices.ts +++ b/packages/plugin/src/lib/open-api/getServices.ts @@ -66,6 +66,13 @@ export const getServices = ( > >( (acc, [statusCode, response]) => { + if (response.$ref) { + response = resolveDocumentLocalRef( + response.$ref, + openApiJson + ) as typeof response; + } + const statusType = statusCode !== 'default' && // See "default" response https://swagger.io/docs/specification/describing-responses/#default Number(statusCode) < 400 diff --git a/packages/tanstack-query-react-plugin/src/__snapshots__/explicit-import-extensions/services/FilesService.ts.snapshot.ts b/packages/tanstack-query-react-plugin/src/__snapshots__/explicit-import-extensions/services/FilesService.ts.snapshot.ts index 240de0bed..b02b00381 100644 --- a/packages/tanstack-query-react-plugin/src/__snapshots__/explicit-import-extensions/services/FilesService.ts.snapshot.ts +++ b/packages/tanstack-query-react-plugin/src/__snapshots__/explicit-import-extensions/services/FilesService.ts.snapshot.ts @@ -1314,7 +1314,7 @@ type GetFilesSchema = { }; type GetFilesParameters = paths["/files"]["get"]["parameters"]; type GetFilesData = paths["/files"]["get"]["responses"]["200"]["content"]["application/json"]; -type GetFilesError = paths["/files"]["get"]["responses"]["405"]["content"]["application/json"] | paths["/files"]["get"]["responses"]["422"]["content"]["application/json"] | null; +type GetFilesError = paths["/files"]["get"]["responses"]["405"]["content"]["application/json"] | paths["/files"]["get"]["responses"]["422"]["content"]["application/json"] | paths["/files"]["get"]["responses"]["default"]["content"]["application/json"]; type PostFilesSchema = { method: "post"; url: "/files"; diff --git a/packages/tanstack-query-react-plugin/src/__snapshots__/queryable-write-operations/services/FilesService.ts.snapshot.ts b/packages/tanstack-query-react-plugin/src/__snapshots__/queryable-write-operations/services/FilesService.ts.snapshot.ts index a1ea6bd86..0dd761907 100644 --- a/packages/tanstack-query-react-plugin/src/__snapshots__/queryable-write-operations/services/FilesService.ts.snapshot.ts +++ b/packages/tanstack-query-react-plugin/src/__snapshots__/queryable-write-operations/services/FilesService.ts.snapshot.ts @@ -2291,7 +2291,7 @@ type GetFilesSchema = { }; type GetFilesParameters = paths["/files"]["get"]["parameters"]; type GetFilesData = paths["/files"]["get"]["responses"]["200"]["content"]["application/json"]; -type GetFilesError = paths["/files"]["get"]["responses"]["405"]["content"]["application/json"] | paths["/files"]["get"]["responses"]["422"]["content"]["application/json"] | null; +type GetFilesError = paths["/files"]["get"]["responses"]["405"]["content"]["application/json"] | paths["/files"]["get"]["responses"]["422"]["content"]["application/json"] | paths["/files"]["get"]["responses"]["default"]["content"]["application/json"]; type PostFilesSchema = { method: "post"; url: "/files"; From 8f9062121e10915da5fde6941cdb48e67a08a29f Mon Sep 17 00:00:00 2001 From: Aleksandr Batalov Date: Sat, 21 Jun 2025 15:48:12 +0400 Subject: [PATCH 3/3] docs(changeset): Add support for responses with `$ref` specification. --- .changeset/true-weeks-love.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/true-weeks-love.md diff --git a/.changeset/true-weeks-love.md b/.changeset/true-weeks-love.md new file mode 100644 index 000000000..68e7b9953 --- /dev/null +++ b/.changeset/true-weeks-love.md @@ -0,0 +1,6 @@ +--- +'@openapi-qraft/test-fixtures': patch +'@openapi-qraft/plugin': patch +--- + +Add support for responses with `$ref` specification.