From d97fc2e06353c467307a7c82680ab278c2ebc4a3 Mon Sep 17 00:00:00 2001 From: kahirokunn Date: Tue, 28 Nov 2023 10:55:36 +0100 Subject: [PATCH] feat: improve oneOf schema handling This introduces an enhancement to better handle the oneOf schema in OpenAPI definitions. - Added a new OpenAPI test fixture - oneOfMerge.yaml - Updated logic in the codegen script where oneOf schemas are encountered. The properties of the schema are now deeply merged to accommodate different variations. - Added a new test case to confirm the improved handling of oneOf schemas. more details: https://github.com/oazapfts/oazapfts/pull/503#issuecomment-1828480622 fix: https://github.com/oazapfts/oazapfts/issues/495 -- Signed-off-by: kahiro okina --- src/codegen/__fixtures__/oneOfMerge.yaml | 36 ++++++++++++++++++++++++ src/codegen/generate.ts | 9 +++++- src/codegen/index.test.ts | 7 +++++ 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 src/codegen/__fixtures__/oneOfMerge.yaml 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(