From 69e91a36dfbf5fca650344963a7d7923b5e57155 Mon Sep 17 00:00:00 2001 From: Gregory Merlet Date: Fri, 27 Jun 2025 14:50:46 +0200 Subject: [PATCH 1/4] fix: add support for discriminator in oneOf schemas and update model imports --- .../typescript-fetch/modelOneOf.mustache | 4 +- .../resources/3_0/typescript-fetch/oneOf.yaml | 39 ++++++++++++++++++- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/typescript-fetch/modelOneOf.mustache b/modules/openapi-generator/src/main/resources/typescript-fetch/modelOneOf.mustache index 721f0fc7b767..e5160a8174e9 100644 --- a/modules/openapi-generator/src/main/resources/typescript-fetch/modelOneOf.mustache +++ b/modules/openapi-generator/src/main/resources/typescript-fetch/modelOneOf.mustache @@ -1,5 +1,5 @@ {{#hasImports}} -{{#imports}} +{{#oneOfModels}} import type { {{{.}}} } from './{{.}}{{importFileExtension}}'; import { instanceOf{{{.}}}, @@ -7,7 +7,7 @@ import { {{{.}}}FromJSONTyped, {{{.}}}ToJSON, } from './{{.}}{{importFileExtension}}'; -{{/imports}} +{{/oneOfModels}} {{/hasImports}} {{>modelOneOfInterfaces}} diff --git a/modules/openapi-generator/src/test/resources/3_0/typescript-fetch/oneOf.yaml b/modules/openapi-generator/src/test/resources/3_0/typescript-fetch/oneOf.yaml index ba0dd51d792f..958b601804dc 100644 --- a/modules/openapi-generator/src/test/resources/3_0/typescript-fetch/oneOf.yaml +++ b/modules/openapi-generator/src/test/resources/3_0/typescript-fetch/oneOf.yaml @@ -25,6 +25,16 @@ paths: application/json: schema: $ref: '#/components/schemas/TestArrayResponse' + /test-discriminator: + get: + operationId: testDiscriminator + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/TestDiscriminatorResponse' components: schemas: TestArrayResponse: @@ -38,6 +48,15 @@ components: - type: array items: type: string + TestDiscriminatorResponse: + discriminator: + propertyName: discriminatorField + mapping: + optionOne: "#/components/schemas/OptionOne" + optionTwo: "#/components/schemas/OptionTwo" + oneOf: + - $ref: "#/components/schemas/OptionOne" + - $ref: "#/components/schemas/OptionTwo" TestResponse: oneOf: - $ref: "#/components/schemas/TestA" @@ -56,4 +75,22 @@ components: bar: type: string required: - - bar \ No newline at end of file + - bar + OptionOne: + type: object + properties: + discriminatorField: + enum: + - "optionOne" + type: string + required: + - discriminatorField + OptionTwo: + type: object + properties: + discriminatorField: + enum: + - "optionTwo" + type: string + required: + - discriminatorField \ No newline at end of file From 2e42fa89dea9fa1c8cab1b3f25820152fde140d5 Mon Sep 17 00:00:00 2001 From: Gregory Merlet Date: Fri, 27 Jun 2025 14:52:57 +0200 Subject: [PATCH 2/4] chore: generate samples --- .../builds/oneOf/.openapi-generator/FILES | 3 + .../builds/oneOf/apis/DefaultApi.ts | 30 ++++++++ .../builds/oneOf/models/OptionOne.ts | 76 +++++++++++++++++++ .../builds/oneOf/models/OptionTwo.ts | 76 +++++++++++++++++++ .../builds/oneOf/models/TestArrayResponse.ts | 14 ---- .../oneOf/models/TestDiscriminatorResponse.ts | 72 ++++++++++++++++++ .../builds/oneOf/models/index.ts | 3 + 7 files changed, 260 insertions(+), 14 deletions(-) create mode 100644 samples/client/petstore/typescript-fetch/builds/oneOf/models/OptionOne.ts create mode 100644 samples/client/petstore/typescript-fetch/builds/oneOf/models/OptionTwo.ts create mode 100644 samples/client/petstore/typescript-fetch/builds/oneOf/models/TestDiscriminatorResponse.ts diff --git a/samples/client/petstore/typescript-fetch/builds/oneOf/.openapi-generator/FILES b/samples/client/petstore/typescript-fetch/builds/oneOf/.openapi-generator/FILES index 6bb15a3adfc7..037062f16b80 100644 --- a/samples/client/petstore/typescript-fetch/builds/oneOf/.openapi-generator/FILES +++ b/samples/client/petstore/typescript-fetch/builds/oneOf/.openapi-generator/FILES @@ -1,9 +1,12 @@ apis/DefaultApi.ts apis/index.ts index.ts +models/OptionOne.ts +models/OptionTwo.ts models/TestA.ts models/TestArrayResponse.ts models/TestB.ts +models/TestDiscriminatorResponse.ts models/TestResponse.ts models/index.ts runtime.ts diff --git a/samples/client/petstore/typescript-fetch/builds/oneOf/apis/DefaultApi.ts b/samples/client/petstore/typescript-fetch/builds/oneOf/apis/DefaultApi.ts index be5025be118c..4d855b758fb7 100644 --- a/samples/client/petstore/typescript-fetch/builds/oneOf/apis/DefaultApi.ts +++ b/samples/client/petstore/typescript-fetch/builds/oneOf/apis/DefaultApi.ts @@ -16,11 +16,14 @@ import * as runtime from '../runtime'; import type { TestArrayResponse, + TestDiscriminatorResponse, TestResponse, } from '../models/index'; import { TestArrayResponseFromJSON, TestArrayResponseToJSON, + TestDiscriminatorResponseFromJSON, + TestDiscriminatorResponseToJSON, TestResponseFromJSON, TestResponseToJSON, } from '../models/index'; @@ -84,4 +87,31 @@ export class DefaultApi extends runtime.BaseAPI { return await response.value(); } + /** + */ + async testDiscriminatorRaw(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + + let urlPath = `/test-discriminator`; + + const response = await this.request({ + path: urlPath, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => TestDiscriminatorResponseFromJSON(jsonValue)); + } + + /** + */ + async testDiscriminator(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.testDiscriminatorRaw(initOverrides); + return await response.value(); + } + } diff --git a/samples/client/petstore/typescript-fetch/builds/oneOf/models/OptionOne.ts b/samples/client/petstore/typescript-fetch/builds/oneOf/models/OptionOne.ts new file mode 100644 index 000000000000..3c0c832ab9ca --- /dev/null +++ b/samples/client/petstore/typescript-fetch/builds/oneOf/models/OptionOne.ts @@ -0,0 +1,76 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * testing oneOf without discriminator + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { mapValues } from '../runtime'; +/** + * + * @export + * @interface OptionOne + */ +export interface OptionOne { + /** + * + * @type {string} + * @memberof OptionOne + */ + discriminatorField: OptionOneDiscriminatorFieldEnum; +} + + +/** + * @export + */ +export const OptionOneDiscriminatorFieldEnum = { + OptionOne: 'optionOne' +} as const; +export type OptionOneDiscriminatorFieldEnum = typeof OptionOneDiscriminatorFieldEnum[keyof typeof OptionOneDiscriminatorFieldEnum]; + + +/** + * Check if a given object implements the OptionOne interface. + */ +export function instanceOfOptionOne(value: object): value is OptionOne { + if (!('discriminatorField' in value) || value['discriminatorField'] === undefined) return false; + return true; +} + +export function OptionOneFromJSON(json: any): OptionOne { + return OptionOneFromJSONTyped(json, false); +} + +export function OptionOneFromJSONTyped(json: any, ignoreDiscriminator: boolean): OptionOne { + if (json == null) { + return json; + } + return { + + 'discriminatorField': json['discriminatorField'], + }; +} + +export function OptionOneToJSON(json: any): OptionOne { + return OptionOneToJSONTyped(json, false); +} + +export function OptionOneToJSONTyped(value?: OptionOne | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + + return { + + 'discriminatorField': value['discriminatorField'], + }; +} + diff --git a/samples/client/petstore/typescript-fetch/builds/oneOf/models/OptionTwo.ts b/samples/client/petstore/typescript-fetch/builds/oneOf/models/OptionTwo.ts new file mode 100644 index 000000000000..a6cafacf2ada --- /dev/null +++ b/samples/client/petstore/typescript-fetch/builds/oneOf/models/OptionTwo.ts @@ -0,0 +1,76 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * testing oneOf without discriminator + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { mapValues } from '../runtime'; +/** + * + * @export + * @interface OptionTwo + */ +export interface OptionTwo { + /** + * + * @type {string} + * @memberof OptionTwo + */ + discriminatorField: OptionTwoDiscriminatorFieldEnum; +} + + +/** + * @export + */ +export const OptionTwoDiscriminatorFieldEnum = { + OptionTwo: 'optionTwo' +} as const; +export type OptionTwoDiscriminatorFieldEnum = typeof OptionTwoDiscriminatorFieldEnum[keyof typeof OptionTwoDiscriminatorFieldEnum]; + + +/** + * Check if a given object implements the OptionTwo interface. + */ +export function instanceOfOptionTwo(value: object): value is OptionTwo { + if (!('discriminatorField' in value) || value['discriminatorField'] === undefined) return false; + return true; +} + +export function OptionTwoFromJSON(json: any): OptionTwo { + return OptionTwoFromJSONTyped(json, false); +} + +export function OptionTwoFromJSONTyped(json: any, ignoreDiscriminator: boolean): OptionTwo { + if (json == null) { + return json; + } + return { + + 'discriminatorField': json['discriminatorField'], + }; +} + +export function OptionTwoToJSON(json: any): OptionTwo { + return OptionTwoToJSONTyped(json, false); +} + +export function OptionTwoToJSONTyped(value?: OptionTwo | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + + return { + + 'discriminatorField': value['discriminatorField'], + }; +} + diff --git a/samples/client/petstore/typescript-fetch/builds/oneOf/models/TestArrayResponse.ts b/samples/client/petstore/typescript-fetch/builds/oneOf/models/TestArrayResponse.ts index 0848d99781c3..756fc0817b36 100644 --- a/samples/client/petstore/typescript-fetch/builds/oneOf/models/TestArrayResponse.ts +++ b/samples/client/petstore/typescript-fetch/builds/oneOf/models/TestArrayResponse.ts @@ -12,20 +12,6 @@ * Do not edit the class manually. */ -import type { TestA } from './TestA'; -import { - instanceOfTestA, - TestAFromJSON, - TestAFromJSONTyped, - TestAToJSON, -} from './TestA'; -import type { TestB } from './TestB'; -import { - instanceOfTestB, - TestBFromJSON, - TestBFromJSONTyped, - TestBToJSON, -} from './TestB'; /** * @type TestArrayResponse diff --git a/samples/client/petstore/typescript-fetch/builds/oneOf/models/TestDiscriminatorResponse.ts b/samples/client/petstore/typescript-fetch/builds/oneOf/models/TestDiscriminatorResponse.ts new file mode 100644 index 000000000000..c6be9b26c5e3 --- /dev/null +++ b/samples/client/petstore/typescript-fetch/builds/oneOf/models/TestDiscriminatorResponse.ts @@ -0,0 +1,72 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * testing oneOf without discriminator + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import type { OptionOne } from './OptionOne'; +import { + instanceOfOptionOne, + OptionOneFromJSON, + OptionOneFromJSONTyped, + OptionOneToJSON, +} from './OptionOne'; +import type { OptionTwo } from './OptionTwo'; +import { + instanceOfOptionTwo, + OptionTwoFromJSON, + OptionTwoFromJSONTyped, + OptionTwoToJSON, +} from './OptionTwo'; + +/** + * @type TestDiscriminatorResponse + * + * @export + */ +export type TestDiscriminatorResponse = { discriminatorField: 'optionOne' } & OptionOne | { discriminatorField: 'optionTwo' } & OptionTwo; + +export function TestDiscriminatorResponseFromJSON(json: any): TestDiscriminatorResponse { + return TestDiscriminatorResponseFromJSONTyped(json, false); +} + +export function TestDiscriminatorResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): TestDiscriminatorResponse { + if (json == null) { + return json; + } + switch (json['discriminatorField']) { + case 'optionOne': + return Object.assign({}, OptionOneFromJSONTyped(json, true), { discriminatorField: 'optionOne' } as const); + case 'optionTwo': + return Object.assign({}, OptionTwoFromJSONTyped(json, true), { discriminatorField: 'optionTwo' } as const); + default: + return json; + } +} + +export function TestDiscriminatorResponseToJSON(json: any): any { + return TestDiscriminatorResponseToJSONTyped(json, false); +} + +export function TestDiscriminatorResponseToJSONTyped(value?: TestDiscriminatorResponse | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + switch (value['discriminatorField']) { + case 'optionOne': + return Object.assign({}, OptionOneToJSON(value), { discriminatorField: 'optionOne' } as const); + case 'optionTwo': + return Object.assign({}, OptionTwoToJSON(value), { discriminatorField: 'optionTwo' } as const); + default: + return json; + } +} + diff --git a/samples/client/petstore/typescript-fetch/builds/oneOf/models/index.ts b/samples/client/petstore/typescript-fetch/builds/oneOf/models/index.ts index 7ba8efbbf0ef..79f8303e9ed5 100644 --- a/samples/client/petstore/typescript-fetch/builds/oneOf/models/index.ts +++ b/samples/client/petstore/typescript-fetch/builds/oneOf/models/index.ts @@ -1,6 +1,9 @@ /* tslint:disable */ /* eslint-disable */ +export * from './OptionOne'; +export * from './OptionTwo'; export * from './TestA'; export * from './TestArrayResponse'; export * from './TestB'; +export * from './TestDiscriminatorResponse'; export * from './TestResponse'; From e80b263452512e8fe634634226bde6b74d194aed Mon Sep 17 00:00:00 2001 From: Gregory Merlet Date: Fri, 27 Jun 2025 14:57:16 +0200 Subject: [PATCH 3/4] fix: enhance model imports for oneOf arrays in mustache templates --- .../resources/typescript-fetch/modelOneOf.mustache | 9 +++++++++ .../builds/oneOf/models/TestArrayResponse.ts | 14 ++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/modules/openapi-generator/src/main/resources/typescript-fetch/modelOneOf.mustache b/modules/openapi-generator/src/main/resources/typescript-fetch/modelOneOf.mustache index e5160a8174e9..59e13e15ca8e 100644 --- a/modules/openapi-generator/src/main/resources/typescript-fetch/modelOneOf.mustache +++ b/modules/openapi-generator/src/main/resources/typescript-fetch/modelOneOf.mustache @@ -1,4 +1,13 @@ {{#hasImports}} +{{#oneOfArrays}} + import type { {{{.}}} } from './{{.}}{{importFileExtension}}'; + import { + instanceOf{{{.}}}, + {{{.}}}FromJSON, + {{{.}}}FromJSONTyped, + {{{.}}}ToJSON, + } from './{{.}}{{importFileExtension}}'; +{{/oneOfArrays}} {{#oneOfModels}} import type { {{{.}}} } from './{{.}}{{importFileExtension}}'; import { diff --git a/samples/client/petstore/typescript-fetch/builds/oneOf/models/TestArrayResponse.ts b/samples/client/petstore/typescript-fetch/builds/oneOf/models/TestArrayResponse.ts index 756fc0817b36..9dc1d912f55b 100644 --- a/samples/client/petstore/typescript-fetch/builds/oneOf/models/TestArrayResponse.ts +++ b/samples/client/petstore/typescript-fetch/builds/oneOf/models/TestArrayResponse.ts @@ -12,6 +12,20 @@ * Do not edit the class manually. */ + import type { TestA } from './TestA'; + import { + instanceOfTestA, + TestAFromJSON, + TestAFromJSONTyped, + TestAToJSON, + } from './TestA'; + import type { TestB } from './TestB'; + import { + instanceOfTestB, + TestBFromJSON, + TestBFromJSONTyped, + TestBToJSON, + } from './TestB'; /** * @type TestArrayResponse From 5681036d6bfb6844e395af4203bd9acbbebc5659 Mon Sep 17 00:00:00 2001 From: Gregory Merlet Date: Fri, 27 Jun 2025 15:02:47 +0200 Subject: [PATCH 4/4] fix: correct import formatting in mustache templates and TypeScript files --- .../resources/typescript-fetch/modelOneOf.mustache | 6 +++--- .../builds/oneOf/models/TestArrayResponse.ts | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/typescript-fetch/modelOneOf.mustache b/modules/openapi-generator/src/main/resources/typescript-fetch/modelOneOf.mustache index 59e13e15ca8e..1d35933047a3 100644 --- a/modules/openapi-generator/src/main/resources/typescript-fetch/modelOneOf.mustache +++ b/modules/openapi-generator/src/main/resources/typescript-fetch/modelOneOf.mustache @@ -1,12 +1,12 @@ {{#hasImports}} {{#oneOfArrays}} - import type { {{{.}}} } from './{{.}}{{importFileExtension}}'; - import { +import type { {{{.}}} } from './{{.}}{{importFileExtension}}'; +import { instanceOf{{{.}}}, {{{.}}}FromJSON, {{{.}}}FromJSONTyped, {{{.}}}ToJSON, - } from './{{.}}{{importFileExtension}}'; +} from './{{.}}{{importFileExtension}}'; {{/oneOfArrays}} {{#oneOfModels}} import type { {{{.}}} } from './{{.}}{{importFileExtension}}'; diff --git a/samples/client/petstore/typescript-fetch/builds/oneOf/models/TestArrayResponse.ts b/samples/client/petstore/typescript-fetch/builds/oneOf/models/TestArrayResponse.ts index 9dc1d912f55b..0848d99781c3 100644 --- a/samples/client/petstore/typescript-fetch/builds/oneOf/models/TestArrayResponse.ts +++ b/samples/client/petstore/typescript-fetch/builds/oneOf/models/TestArrayResponse.ts @@ -12,20 +12,20 @@ * Do not edit the class manually. */ - import type { TestA } from './TestA'; - import { +import type { TestA } from './TestA'; +import { instanceOfTestA, TestAFromJSON, TestAFromJSONTyped, TestAToJSON, - } from './TestA'; - import type { TestB } from './TestB'; - import { +} from './TestA'; +import type { TestB } from './TestB'; +import { instanceOfTestB, TestBFromJSON, TestBFromJSONTyped, TestBToJSON, - } from './TestB'; +} from './TestB'; /** * @type TestArrayResponse