diff --git a/src/codegen/__fixtures__/oneOfMerge.yaml b/src/codegen/__fixtures__/oneOfMerge.yaml new file mode 100644 index 00000000..a7da117f --- /dev/null +++ b/src/codegen/__fixtures__/oneOfMerge.yaml @@ -0,0 +1,36 @@ +openapi: 3.0.3 +info: + title: OneOfMerge + version: 0.1.0 +paths: + /mix: + get: + description: stats + parameters: + - name: param1 + in: query + schema: + oneOf: + - required: + - c + properties: + a: + type: string + - required: + - b + properties: + b: + type: string + required: + - d + properties: + c: + type: string + d: + enum: + - enum1 + - enum2 + type: string + responses: + "200": + description: ok diff --git a/src/codegen/generate.ts b/src/codegen/generate.ts index 0570e6f8..6155d583 100644 --- a/src/codegen/generate.ts +++ b/src/codegen/generate.ts @@ -5,6 +5,7 @@ import { OpenAPIV3 } from "openapi-types"; import * as cg from "./tscodegen"; import generateServers, { defaultBaseUrl } from "./generateServers"; import { Opts } from "."; +import merge from "deepmerge"; export const verbs = [ "GET", @@ -574,8 +575,14 @@ export default class ApiGenerator { } if (schema.oneOf) { + const clone = { ...schema }; + delete clone.oneOf; // oneOf -> union - return this.getUnionType(schema.oneOf, schema.discriminator, onlyMode); + return this.getUnionType( + schema.oneOf.map((variant) => merge(variant as any, clone as any)), + schema.discriminator, + onlyMode, + ); } if (schema.anyOf) { // anyOf -> union diff --git a/src/codegen/index.test.ts b/src/codegen/index.test.ts index 2f904605..d7dda327 100644 --- a/src/codegen/index.test.ts +++ b/src/codegen/index.test.ts @@ -115,6 +115,13 @@ describe("generateSource", () => { expect(src).toContain("PathsFilterGetParameters0SchemaOneOf0"); }); + it("should merge properties within oneOf schema variations", async () => { + const src = await generate("/__fixtures__/oneOfMerge.yaml"); + expect(src).toContain( + '{ param1?: { a?: string; c: string; d: "enum1" | "enum2"; } | { b: string; c?: string; d: "enum1" | "enum2"; }' + ); + }); + it("should support parameters specified with content", async () => { const src = await generate("/__fixtures__/contentParams.json"); expect(src).toContain(