From f99c7b8070be2b3e11682a51c90d99ddf3f2feea Mon Sep 17 00:00:00 2001 From: Jostein Stuhaug Date: Mon, 18 Aug 2025 16:03:35 +0200 Subject: [PATCH 1/4] Expansion of testcases to demonstrate problem. Adds ref with non-ascii typename to testcases with discriminator mapping that. Before fix these generate type unions where the mapping is ignored for the non-ascii typename. --- .../specs/3.0.x/discriminator-any-of.yaml | 5 +++++ .../specs/3.0.x/discriminator-mapped-many.yaml | 9 +++++++++ .../specs/3.0.x/discriminator-one-of.yaml | 5 +++++ .../specs/3.1.x/discriminator-any-of.yaml | 5 +++++ .../specs/3.1.x/discriminator-mapped-many.yaml | 9 +++++++++ .../specs/3.1.x/discriminator-one-of.yaml | 5 +++++ 6 files changed, 38 insertions(+) diff --git a/packages/openapi-ts-tests/specs/3.0.x/discriminator-any-of.yaml b/packages/openapi-ts-tests/specs/3.0.x/discriminator-any-of.yaml index c852f95043..93a7ed2ef3 100644 --- a/packages/openapi-ts-tests/specs/3.0.x/discriminator-any-of.yaml +++ b/packages/openapi-ts-tests/specs/3.0.x/discriminator-any-of.yaml @@ -16,6 +16,9 @@ components: Bar: allOf: - $ref: '#/components/schemas/Qux' + Spæcial: + allOf: + - $ref: '#/components/schemas/Qux' Qux: type: object properties: @@ -35,8 +38,10 @@ components: anyOf: - $ref: '#/components/schemas/Bar' - $ref: '#/components/schemas/Baz' + - $ref: '#/components/schemas/Spæcial' discriminator: propertyName: type mapping: bar: '#/components/schemas/Bar' baz: '#/components/schemas/Baz' + 'non-ascii': '#/components/schemas/Spæcial' diff --git a/packages/openapi-ts-tests/specs/3.0.x/discriminator-mapped-many.yaml b/packages/openapi-ts-tests/specs/3.0.x/discriminator-mapped-many.yaml index f51ea89d6b..7686c70839 100644 --- a/packages/openapi-ts-tests/specs/3.0.x/discriminator-mapped-many.yaml +++ b/packages/openapi-ts-tests/specs/3.0.x/discriminator-mapped-many.yaml @@ -8,12 +8,14 @@ components: oneOf: - $ref: '#/components/schemas/Bar' - $ref: '#/components/schemas/Baz' + - $ref: '#/components/schemas/Spæcial' discriminator: propertyName: foo mapping: one: '#/components/schemas/Bar' two: '#/components/schemas/Bar' three: '#/components/schemas/Baz' + four: '#/components/schemas/Spæcial' Bar: type: object properties: @@ -29,3 +31,10 @@ components: type: string enum: - three + Spæcial: + type: object + properties: + foo: + type: string + enum: + - four diff --git a/packages/openapi-ts-tests/specs/3.0.x/discriminator-one-of.yaml b/packages/openapi-ts-tests/specs/3.0.x/discriminator-one-of.yaml index 30732a2eac..5c0fca60b9 100644 --- a/packages/openapi-ts-tests/specs/3.0.x/discriminator-one-of.yaml +++ b/packages/openapi-ts-tests/specs/3.0.x/discriminator-one-of.yaml @@ -16,6 +16,9 @@ components: Bar: allOf: - $ref: '#/components/schemas/Qux' + Spæcial: + allOf: + - $ref: '#/components/schemas/Qux' Qux: type: object properties: @@ -35,8 +38,10 @@ components: oneOf: - $ref: '#/components/schemas/Bar' - $ref: '#/components/schemas/Baz' + - $ref: '#/components/schemas/Spæcial' discriminator: propertyName: type mapping: bar: '#/components/schemas/Bar' baz: '#/components/schemas/Baz' + 'non-ascii': '#/components/schemas/Spæcial' diff --git a/packages/openapi-ts-tests/specs/3.1.x/discriminator-any-of.yaml b/packages/openapi-ts-tests/specs/3.1.x/discriminator-any-of.yaml index d5e9be83d9..cf71d9d186 100644 --- a/packages/openapi-ts-tests/specs/3.1.x/discriminator-any-of.yaml +++ b/packages/openapi-ts-tests/specs/3.1.x/discriminator-any-of.yaml @@ -16,6 +16,9 @@ components: Bar: allOf: - $ref: '#/components/schemas/Qux' + Spæcial: + allOf: + - $ref: '#/components/schemas/Qux' Qux: type: object properties: @@ -35,8 +38,10 @@ components: anyOf: - $ref: '#/components/schemas/Bar' - $ref: '#/components/schemas/Baz' + - $ref: '#/components/schemas/Spæcial' discriminator: propertyName: type mapping: bar: '#/components/schemas/Bar' baz: '#/components/schemas/Baz' + 'non-ascii': '#/components/schemas/Spæcial' diff --git a/packages/openapi-ts-tests/specs/3.1.x/discriminator-mapped-many.yaml b/packages/openapi-ts-tests/specs/3.1.x/discriminator-mapped-many.yaml index 5000d4f350..42c383bbe6 100644 --- a/packages/openapi-ts-tests/specs/3.1.x/discriminator-mapped-many.yaml +++ b/packages/openapi-ts-tests/specs/3.1.x/discriminator-mapped-many.yaml @@ -8,12 +8,14 @@ components: oneOf: - $ref: '#/components/schemas/Bar' - $ref: '#/components/schemas/Baz' + - $ref: '#/components/schemas/Spæcial' discriminator: propertyName: foo mapping: one: '#/components/schemas/Bar' two: '#/components/schemas/Bar' three: '#/components/schemas/Baz' + four: '#/components/schemas/Spæcial' Bar: type: object properties: @@ -29,3 +31,10 @@ components: type: string enum: - three + Spæcial: + type: object + properties: + foo: + type: string + enum: + - four diff --git a/packages/openapi-ts-tests/specs/3.1.x/discriminator-one-of.yaml b/packages/openapi-ts-tests/specs/3.1.x/discriminator-one-of.yaml index a60d120c14..27d2db8715 100644 --- a/packages/openapi-ts-tests/specs/3.1.x/discriminator-one-of.yaml +++ b/packages/openapi-ts-tests/specs/3.1.x/discriminator-one-of.yaml @@ -16,6 +16,9 @@ components: Bar: allOf: - $ref: '#/components/schemas/Qux' + Spæcial: + allOf: + - $ref: '#/components/schemas/Qux' Qux: type: object properties: @@ -35,8 +38,10 @@ components: oneOf: - $ref: '#/components/schemas/Bar' - $ref: '#/components/schemas/Baz' + - $ref: '#/components/schemas/Spæcial' discriminator: propertyName: type mapping: bar: '#/components/schemas/Bar' baz: '#/components/schemas/Baz' + 'non-ascii': '#/components/schemas/Spæcial' From 05ed45ac756526461fc74a4c64e3060da96cc7bf Mon Sep 17 00:00:00 2001 From: Jostein Stuhaug Date: Mon, 18 Aug 2025 16:07:04 +0200 Subject: [PATCH 2/4] Use resolved ref value when resolving discriminator values. So that the ref has been resolved with "decodeURI" in parseRef. Without this change, discriminator mapping for non-ascii typenames did not work. --- packages/openapi-ts/src/openApi/3.0.x/parser/schema.ts | 8 ++++---- packages/openapi-ts/src/openApi/3.1.x/parser/schema.ts | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/openapi-ts/src/openApi/3.0.x/parser/schema.ts b/packages/openapi-ts/src/openApi/3.0.x/parser/schema.ts index 5bd54e8b2e..2e697a644b 100644 --- a/packages/openapi-ts/src/openApi/3.0.x/parser/schema.ts +++ b/packages/openapi-ts/src/openApi/3.0.x/parser/schema.ts @@ -538,9 +538,9 @@ const parseAnyOf = ({ ); // `$ref` should be defined with discriminators - if (schema.discriminator && '$ref' in compositionSchema) { + if (schema.discriminator && irCompositionSchema.$ref != null) { const values = discriminatorValues( - compositionSchema.$ref, + irCompositionSchema.$ref, schema.discriminator.mapping, ); const valueSchemas: ReadonlyArray = values.map( @@ -719,9 +719,9 @@ const parseOneOf = ({ ); // `$ref` should be defined with discriminators - if (schema.discriminator && '$ref' in compositionSchema) { + if (schema.discriminator && irCompositionSchema.$ref != null) { const values = discriminatorValues( - compositionSchema.$ref, + irCompositionSchema.$ref, schema.discriminator.mapping, ); const valueSchemas: ReadonlyArray = values.map( diff --git a/packages/openapi-ts/src/openApi/3.1.x/parser/schema.ts b/packages/openapi-ts/src/openApi/3.1.x/parser/schema.ts index 87a687fd97..03b0003914 100644 --- a/packages/openapi-ts/src/openApi/3.1.x/parser/schema.ts +++ b/packages/openapi-ts/src/openApi/3.1.x/parser/schema.ts @@ -541,9 +541,9 @@ const parseAnyOf = ({ }); // `$ref` should be defined with discriminators - if (schema.discriminator && compositionSchema.$ref) { + if (schema.discriminator && irCompositionSchema.$ref != null) { const values = discriminatorValues( - compositionSchema.$ref, + irCompositionSchema.$ref, schema.discriminator.mapping, ); const valueSchemas: ReadonlyArray = values.map( @@ -697,9 +697,9 @@ const parseOneOf = ({ }); // `$ref` should be defined with discriminators - if (schema.discriminator && compositionSchema.$ref) { + if (schema.discriminator && irCompositionSchema.$ref != null) { const values = discriminatorValues( - compositionSchema.$ref, + irCompositionSchema.$ref, schema.discriminator.mapping, ); const valueSchemas: ReadonlyArray = values.map( From e6df695b28ec893b898f94f9ee3ab95840b4183f Mon Sep 17 00:00:00 2001 From: Jostein Stuhaug Date: Mon, 18 Aug 2025 16:12:26 +0200 Subject: [PATCH 3/4] Updated test snapshots after fix for discriminator mapping. --- .../__snapshots__/3.0.x/discriminator-any-of/types.gen.ts | 6 +++++- .../3.0.x/discriminator-mapped-many/types.gen.ts | 8 +++++++- .../__snapshots__/3.0.x/discriminator-one-of/types.gen.ts | 6 +++++- .../__snapshots__/3.1.x/discriminator-any-of/types.gen.ts | 6 +++++- .../3.1.x/discriminator-mapped-many/types.gen.ts | 8 +++++++- .../__snapshots__/3.1.x/discriminator-one-of/types.gen.ts | 6 +++++- 6 files changed, 34 insertions(+), 6 deletions(-) diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/discriminator-any-of/types.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/discriminator-any-of/types.gen.ts index cdd9c641f1..77b8b2695a 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/discriminator-any-of/types.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/discriminator-any-of/types.gen.ts @@ -10,6 +10,8 @@ export type Baz = Qux; export type Bar = Qux; +export type Spæcial = Qux; + export type Qux = { id: string; type: Quux; @@ -21,7 +23,9 @@ export type Quuz = ({ type?: 'bar'; } & Bar) | ({ type?: 'baz'; -} & Baz); +} & Baz) | ({ + type?: 'non-ascii'; +} & Spæcial); export type ClientOptions = { baseUrl: `${string}://${string}` | (string & {}); diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/discriminator-mapped-many/types.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/discriminator-mapped-many/types.gen.ts index e48cc7825d..5e54fdd48f 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/discriminator-mapped-many/types.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/discriminator-mapped-many/types.gen.ts @@ -4,7 +4,9 @@ export type Foo = ({ foo: 'one' | 'two'; } & Bar) | ({ foo: 'three'; -} & Baz); +} & Baz) | ({ + foo: 'four'; +} & Spæcial); export type Bar = { foo?: 'one' | 'two'; @@ -14,6 +16,10 @@ export type Baz = { foo?: 'three'; }; +export type Spæcial = { + foo?: 'four'; +}; + export type ClientOptions = { baseUrl: `${string}://${string}` | (string & {}); }; \ No newline at end of file diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/discriminator-one-of/types.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/discriminator-one-of/types.gen.ts index c739a4d957..2604947adc 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/discriminator-one-of/types.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/discriminator-one-of/types.gen.ts @@ -10,6 +10,8 @@ export type Baz = Qux; export type Bar = Qux; +export type Spæcial = Qux; + export type Qux = { id: string; type: Quux; @@ -21,7 +23,9 @@ export type Quuz = ({ type: 'bar'; } & Bar) | ({ type: 'baz'; -} & Baz); +} & Baz) | ({ + type: 'non-ascii'; +} & Spæcial); export type ClientOptions = { baseUrl: `${string}://${string}` | (string & {}); diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/discriminator-any-of/types.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/discriminator-any-of/types.gen.ts index cdd9c641f1..77b8b2695a 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/discriminator-any-of/types.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/discriminator-any-of/types.gen.ts @@ -10,6 +10,8 @@ export type Baz = Qux; export type Bar = Qux; +export type Spæcial = Qux; + export type Qux = { id: string; type: Quux; @@ -21,7 +23,9 @@ export type Quuz = ({ type?: 'bar'; } & Bar) | ({ type?: 'baz'; -} & Baz); +} & Baz) | ({ + type?: 'non-ascii'; +} & Spæcial); export type ClientOptions = { baseUrl: `${string}://${string}` | (string & {}); diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/discriminator-mapped-many/types.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/discriminator-mapped-many/types.gen.ts index e48cc7825d..5e54fdd48f 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/discriminator-mapped-many/types.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/discriminator-mapped-many/types.gen.ts @@ -4,7 +4,9 @@ export type Foo = ({ foo: 'one' | 'two'; } & Bar) | ({ foo: 'three'; -} & Baz); +} & Baz) | ({ + foo: 'four'; +} & Spæcial); export type Bar = { foo?: 'one' | 'two'; @@ -14,6 +16,10 @@ export type Baz = { foo?: 'three'; }; +export type Spæcial = { + foo?: 'four'; +}; + export type ClientOptions = { baseUrl: `${string}://${string}` | (string & {}); }; \ No newline at end of file diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/discriminator-one-of/types.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/discriminator-one-of/types.gen.ts index c739a4d957..2604947adc 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/discriminator-one-of/types.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/discriminator-one-of/types.gen.ts @@ -10,6 +10,8 @@ export type Baz = Qux; export type Bar = Qux; +export type Spæcial = Qux; + export type Qux = { id: string; type: Quux; @@ -21,7 +23,9 @@ export type Quuz = ({ type: 'bar'; } & Bar) | ({ type: 'baz'; -} & Baz); +} & Baz) | ({ + type: 'non-ascii'; +} & Spæcial); export type ClientOptions = { baseUrl: `${string}://${string}` | (string & {}); From 82af768a102409f981006a4b6f0219f9d86256dc Mon Sep 17 00:00:00 2001 From: Lubos Date: Mon, 18 Aug 2025 23:21:56 +0800 Subject: [PATCH 4/4] Create two-toys-join.md --- .changeset/two-toys-join.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/two-toys-join.md diff --git a/.changeset/two-toys-join.md b/.changeset/two-toys-join.md new file mode 100644 index 0000000000..6c5cb175a9 --- /dev/null +++ b/.changeset/two-toys-join.md @@ -0,0 +1,5 @@ +--- +"@hey-api/openapi-ts": patch +--- + +fix(parser): handle non-ascii characters in discriminator