From abf8ad853992232af7a5442651981c56ef81d4f1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 18 Feb 2026 23:57:21 +0000 Subject: [PATCH] fix: simplify schemaNameTransform logic and add prettier-ignore to docs Co-authored-by: mrlubos <12529395+mrlubos@users.noreply.github.com> --- docs/openapi-ts/configuration/parser.md | 14 +++--- .../openapi-ts-tests/main/test/3.0.x.test.ts | 17 +++++++ .../index.ts | 3 ++ .../types.gen.ts | 39 ++++++++++++++++ .../src/openApi/shared/transforms/schemas.ts | 10 ++--- .../transforms-schemas-name-collision.yaml | 44 +++++++++++++++++++ 6 files changed, 111 insertions(+), 16 deletions(-) create mode 100644 packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/transforms-schemas-name-collision/index.ts create mode 100644 packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/transforms-schemas-name-collision/types.gen.ts create mode 100644 specs/3.0.x/transforms-schemas-name-collision.yaml diff --git a/docs/openapi-ts/configuration/parser.md b/docs/openapi-ts/configuration/parser.md index ec1778e2a..d91a8a670 100644 --- a/docs/openapi-ts/configuration/parser.md +++ b/docs/openapi-ts/configuration/parser.md @@ -453,22 +453,17 @@ Sometimes your schema names are auto-generated or follow a naming convention tha ::: code-group + ```js [function] export default { input: 'hey-api/backend', // sign up at app.heyapi.dev output: 'src/client', parser: { transforms: { - schemaName: (name) => { - // [!code ++] + schemaName: (name) => { // [!code ++] // Strip version markers: ServiceRoot_v1_20_0_ServiceRoot → ServiceRoot // [!code ++] - let clean = name.replace( - /([A-Za-z\d]+)_v\d+_\d+_\d+_([A-Za-z\d]*)/g, - ( - _, - p1, - p2, // [!code ++] - ) => (p2.startsWith(p1) ? p2 : p1 + p2), // [!code ++] + let clean = name.replace(/([A-Za-z\d]+)_v\d+_\d+_\d+_([A-Za-z\d]*)/g, (_, p1, p2) => // [!code ++] + p2.startsWith(p1) ? p2 : p1 + p2, // [!code ++] ); // [!code ++] // Deduplicate prefixes: Foo_Foo → Foo // [!code ++] const m = clean.match(/^([A-Za-z\d]+)_\1([A-Za-z\d]*)$/); // [!code ++] @@ -479,6 +474,7 @@ export default { }, }; ``` + ```js [template] export default { diff --git a/packages/openapi-ts-tests/main/test/3.0.x.test.ts b/packages/openapi-ts-tests/main/test/3.0.x.test.ts index c870ba89d..7f2d5e89f 100644 --- a/packages/openapi-ts-tests/main/test/3.0.x.test.ts +++ b/packages/openapi-ts-tests/main/test/3.0.x.test.ts @@ -612,6 +612,23 @@ describe(`OpenAPI ${version}`, () => { }), description: 'handles schema name transforms', }, + { + config: createConfig({ + input: 'transforms-schemas-name-collision.yaml', + output: 'transforms-schemas-name-collision', + parser: { + transforms: { + schemaName: (name: string) => + // Try to rename all _vX_User schemas to "User" + // This should cause collisions since "User" already exists + name.replace(/_v\d+_User$/, '') + , + }, + }, + plugins: ['@hey-api/typescript'], + }), + description: 'handles schema name collision prevention', + }, { config: createConfig({ input: 'security-api-key.yaml', diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/transforms-schemas-name-collision/index.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/transforms-schemas-name-collision/index.ts new file mode 100644 index 000000000..80371cc73 --- /dev/null +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/transforms-schemas-name-collision/index.ts @@ -0,0 +1,3 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export type { ClientOptions, GetTestData, GetTestResponse, GetTestResponses, User, UserV1User, UserV2User } from './types.gen'; diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/transforms-schemas-name-collision/types.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/transforms-schemas-name-collision/types.gen.ts new file mode 100644 index 000000000..2abb98d38 --- /dev/null +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/transforms-schemas-name-collision/types.gen.ts @@ -0,0 +1,39 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export type ClientOptions = { + baseUrl: `${string}://${string}` | (string & {}); +}; + +export type UserV1User = { + id?: string; + version?: 'v1'; +}; + +export type User = { + name?: string; +}; + +export type UserV2User = { + email?: string; + version?: 'v2'; +}; + +export type GetTestData = { + body?: never; + path?: never; + query?: never; + url: '/test'; +}; + +export type GetTestResponses = { + /** + * Success + */ + 200: { + user1?: UserV1User; + user2?: User; + user3?: UserV2User; + }; +}; + +export type GetTestResponse = GetTestResponses[keyof GetTestResponses]; diff --git a/packages/shared/src/openApi/shared/transforms/schemas.ts b/packages/shared/src/openApi/shared/transforms/schemas.ts index 66d3dae4b..568bf3cc9 100644 --- a/packages/shared/src/openApi/shared/transforms/schemas.ts +++ b/packages/shared/src/openApi/shared/transforms/schemas.ts @@ -75,20 +75,16 @@ export const schemaNameTransform = ({ // Skip if name doesn't change if (newName === oldName) { - newNames.add(oldName); continue; } - // Skip if new name collides with an existing schema or another renamed schema - if (oldName in schemasObj && newName in schemasObj && oldName !== newName) { - // Collision with existing schema - skip rename - newNames.add(oldName); + // Skip if new name collides with an existing schema + if (newName in schemasObj) { continue; } + // Skip if new name collides with another renamed schema if (newNames.has(newName)) { - // Collision with another renamed schema - skip rename - newNames.add(oldName); continue; } diff --git a/specs/3.0.x/transforms-schemas-name-collision.yaml b/specs/3.0.x/transforms-schemas-name-collision.yaml new file mode 100644 index 000000000..46e308a78 --- /dev/null +++ b/specs/3.0.x/transforms-schemas-name-collision.yaml @@ -0,0 +1,44 @@ +openapi: 3.0.3 +info: + title: Schema Name Collision Test + version: 1.0.0 +paths: + /test: + get: + responses: + '200': + description: Success + content: + application/json: + schema: + type: object + properties: + user1: + $ref: '#/components/schemas/User_v1_User' + user2: + $ref: '#/components/schemas/User' + user3: + $ref: '#/components/schemas/User_v2_User' +components: + schemas: + User_v1_User: + type: object + properties: + id: + type: string + version: + type: string + enum: ['v1'] + User: + type: object + properties: + name: + type: string + User_v2_User: + type: object + properties: + email: + type: string + version: + type: string + enum: ['v2'] -- 2.51.2