diff --git a/packages/codemode/src/openapi/index.ts b/packages/codemode/src/openapi/index.ts index 1da5779cb446..bdf000718483 100644 --- a/packages/codemode/src/openapi/index.ts +++ b/packages/codemode/src/openapi/index.ts @@ -53,7 +53,6 @@ export const fromSpec = (options: Options): Result => { if (!isRecord(pathValue)) continue for (const [method, operationValue] of Object.entries(pathValue)) { if (!methods.has(method) || !isRecord(operationValue)) continue - const segments = operationPath(method, path, operationValue, used, namespaces) const operation: Operation = { operationId: nonEmptyString(operationValue.operationId), method: method.toUpperCase(), @@ -99,6 +98,7 @@ export const fromSpec = (options: Options): Result => { auth: options.auth, headers: options.headers ?? {}, } + const segments = operationPath(method, path, operationValue, used, namespaces) used.add(segments.join(".")) for (const index of segments.slice(0, -1).keys()) namespaces.add(segments.slice(0, index + 1).join(".")) setTool( diff --git a/packages/codemode/test/openapi.test.ts b/packages/codemode/test/openapi.test.ts index da705977bfae..e8b6ec5d4ea1 100644 --- a/packages/codemode/test/openapi.test.ts +++ b/packages/codemode/test/openapi.test.ts @@ -278,6 +278,30 @@ describe("OpenAPI.fromSpec", () => { expect(Tool.isTool(toolAt(result.tools, "group.operation.other"))).toBe(true) }) + test("does not reserve names for unsupported operations between duplicate operation IDs", () => { + const operation = { operationId: "group.item", responses: { 200: { description: "Success" } } } + for (const unsupported of [false, true]) { + const result = OpenAPI.fromSpec({ + baseUrl, + spec: { + openapi: "3.1.0", + paths: { + "/first": { get: operation }, + ...(unsupported ? { "/unsupported": { get: { ...operation, "x-websocket": true } } } : {}), + "/last": { get: operation }, + }, + }, + }) + + expect(Object.keys(result.tools)).toEqual(["group", "group_item_2"]) + expect(toolAt(result.tools, "group.item")).toMatchObject({ _tag: "CodeModeTool", description: "GET /first" }) + expect(toolAt(result.tools, "group_item_2")).toMatchObject({ _tag: "CodeModeTool", description: "GET /last" }) + expect(result.skipped).toEqual( + unsupported ? [{ method: "GET", path: "/unsupported", reason: "WebSocket operations are not supported" }] : [], + ) + } + }) + test("synthesizes flat operation IDs from methods and paths", () => { const response = { responses: { 200: { description: "Success" } } } const tools = OpenAPI.fromSpec({