From df1fd864b2fe6eeffcd5f0d633ec8ddf3c467900 Mon Sep 17 00:00:00 2001 From: Gregory Schier Date: Wed, 19 Aug 2026 07:10:32 -0700 Subject: [PATCH] Support OpenAPI 3.2 QUERY and additional operations (#591) --- plugins/importer-openapi/src/index.ts | 25 ++++++++++++++++---- plugins/importer-openapi/tests/index.test.ts | 22 +++++++++++++++++ 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/plugins/importer-openapi/src/index.ts b/plugins/importer-openapi/src/index.ts index 417cd496..c6ad51c0 100644 --- a/plugins/importer-openapi/src/index.ts +++ b/plugins/importer-openapi/src/index.ts @@ -21,7 +21,7 @@ type ImportResources = { httpRequests: AtLeast[]; }; -const HTTP_METHODS = ["delete", "get", "head", "options", "patch", "post", "put", "trace"]; +const HTTP_METHODS = ["delete", "get", "head", "options", "patch", "post", "put", "query", "trace"]; const BODY_CONTENT_TYPE_PREFERENCE = [ "application/json", "application/x-www-form-urlencoded", @@ -103,10 +103,7 @@ export async function convertOpenApi(contents: string): Promise { + const operation = importState.resolve(pathItem[method]); + return isRecord(operation) ? [{ method, operation }] : []; + }); + + for (const [method, rawOperation] of Object.entries(toRecord(pathItem.additionalOperations))) { + if (HTTP_METHODS.includes(method.toLowerCase())) continue; + const operation = importState.resolve(rawOperation); + if (isRecord(operation)) operations.push({ method, operation }); + } + return operations; +} + /** * Two operations sharing a summary are indistinguishable once imported, so the * colliding ones get their route appended. Names that are already unique within diff --git a/plugins/importer-openapi/tests/index.test.ts b/plugins/importer-openapi/tests/index.test.ts index b9dd9977..4fbbd08b 100644 --- a/plugins/importer-openapi/tests/index.test.ts +++ b/plugins/importer-openapi/tests/index.test.ts @@ -13,6 +13,28 @@ describe("importer-openapi", () => { .readdirSync(realWorldFixturesPath) .filter((fixture) => fixture.endsWith(".yaml")); + test("Imports OpenAPI 3.2 QUERY and additional operations", async () => { + const imported = await convertOpenApi( + JSON.stringify({ + openapi: "3.2.0", + info: { title: "OpenAPI 3.2 Operations", version: "1.0.0" }, + paths: { + "/resources": { + query: { summary: "Query resources", responses: {} }, + additionalOperations: { + COPY: { summary: "Copy resources", responses: {} }, + }, + }, + }, + }), + ); + + expect(imported?.resources.httpRequests).toEqual([ + expect.objectContaining({ method: "QUERY", name: "Query resources", url: "/resources" }), + expect.objectContaining({ method: "COPY", name: "Copy resources", url: "/resources" }), + ]); + }); + test("Maps operation description to request description", async () => { const imported = await convertOpenApi( JSON.stringify({