From f9544fb8b18b87471b2555312c0ef8cf671b27c7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 18 Feb 2026 22:48:36 +0000 Subject: [PATCH] refactor: flatten transforms.schemas.name to transforms.schemaName Co-authored-by: mrlubos <12529395+mrlubos@users.noreply.github.com> --- docs/openapi-ts/configuration/parser.md | 40 +++++------------ .../openapi-ts-tests/main/test/2.0.x.test.ts | 20 ++++----- .../openapi-ts-tests/main/test/3.0.x.test.ts | 20 ++++----- packages/shared/src/config/parser/config.ts | 28 ++---------- packages/shared/src/config/parser/types.ts | 44 +++---------------- .../src/openApi/shared/transforms/index.ts | 4 +- .../src/openApi/shared/transforms/schemas.ts | 22 ++++++++-- 7 files changed, 59 insertions(+), 119 deletions(-) diff --git a/docs/openapi-ts/configuration/parser.md b/docs/openapi-ts/configuration/parser.md index 1ceb6f4eb..7387a5835 100644 --- a/docs/openapi-ts/configuration/parser.md +++ b/docs/openapi-ts/configuration/parser.md @@ -447,9 +447,9 @@ export default { You can customize the naming and casing pattern for `requests` and `responses` schemas using the `.name` and `.case` options. -### Schemas +### Schema Name -Sometimes your schema names are auto-generated or follow a naming convention that produces verbose or awkward type names. The `schemas` transform allows you to rename schema component keys throughout the specification, automatically updating all `$ref` pointers. +Sometimes your schema names are auto-generated or follow a naming convention that produces verbose or awkward type names. The `schemaName` transform allows you to rename schema component keys throughout the specification, automatically updating all `$ref` pointers. This is useful for: @@ -466,17 +466,15 @@ export default { output: 'src/client', parser: { transforms: { - schemas: { - name: (name) => { - // Strip version markers: ServiceRoot_v1_20_0_ServiceRoot → ServiceRoot - let clean = name.replace(/([A-Za-z\d]+)_v\d+_\d+_\d+_([A-Za-z\d]*)/g, (_, p1, p2) => - p2.startsWith(p1) ? p2 : p1 + p2, - ); - // Deduplicate prefixes: Foo_Foo → Foo - const m = clean.match(/^([A-Za-z\d]+)_\1([A-Za-z\d]*)$/); - if (m) clean = m[1] + m[2]; - return clean; - }, + schemaName: (name) => { + // Strip version markers: ServiceRoot_v1_20_0_ServiceRoot → ServiceRoot + let clean = name.replace(/([A-Za-z\d]+)_v\d+_\d+_\d+_([A-Za-z\d]*)/g, (_, p1, p2) => + p2.startsWith(p1) ? p2 : p1 + p2, + ); + // Deduplicate prefixes: Foo_Foo → Foo + const m = clean.match(/^([A-Za-z\d]+)_\1([A-Za-z\d]*)$/); + if (m) clean = m[1] + m[2]; + return clean; }, }, }, @@ -489,21 +487,7 @@ export default { output: 'src/client', parser: { transforms: { - schemas: { - name: 'Api{{name}}', // Add "Api" prefix to all schemas - }, - }, - }, -}; -``` - -```js [disabled] -export default { - input: 'hey-api/backend', // sign up at app.heyapi.dev - output: 'src/client', - parser: { - transforms: { - schemas: false, // [!code ++] + schemaName: 'Api{{name}}', // Add "Api" prefix to all schemas }, }, }; diff --git a/packages/openapi-ts-tests/main/test/2.0.x.test.ts b/packages/openapi-ts-tests/main/test/2.0.x.test.ts index 00e3a1d08..9edb12831 100644 --- a/packages/openapi-ts-tests/main/test/2.0.x.test.ts +++ b/packages/openapi-ts-tests/main/test/2.0.x.test.ts @@ -293,17 +293,15 @@ describe(`OpenAPI ${version}`, () => { output: 'transforms-schemas-name', parser: { transforms: { - schemas: { - name: (name: string) => { - // Strip version markers: User_v1_0_0_User → User - let clean = name.replace(/([A-Za-z\d]+)_v\d+_\d+_\d+_([A-Za-z\d]*)/g, (_, p1, p2) => - p2.startsWith(p1) ? p2 : p1 + p2, - ); - // Deduplicate prefixes: Foo_Foo → Foo - const m = clean.match(/^([A-Za-z\d]+)_\1([A-Za-z\d]*)$/); - if (m) clean = m[1] + m[2]; - return clean; - }, + schemaName: (name: string) => { + // Strip version markers: User_v1_0_0_User → User + let clean = name.replace(/([A-Za-z\d]+)_v\d+_\d+_\d+_([A-Za-z\d]*)/g, (_, p1, p2) => + p2.startsWith(p1) ? p2 : p1 + p2, + ); + // Deduplicate prefixes: Foo_Foo → Foo + const m = clean.match(/^([A-Za-z\d]+)_\1([A-Za-z\d]*)$/); + if (m) clean = m[1] + m[2]; + return clean; }, }, }, 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 97bcca952..c870ba89d 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 @@ -596,17 +596,15 @@ describe(`OpenAPI ${version}`, () => { output: 'transforms-schemas-name', parser: { transforms: { - schemas: { - name: (name: string) => { - // Strip version markers: User_v1_0_0_User → User - let clean = name.replace(/([A-Za-z\d]+)_v\d+_\d+_\d+_([A-Za-z\d]*)/g, (_, p1, p2) => - p2.startsWith(p1) ? p2 : p1 + p2, - ); - // Deduplicate prefixes: Foo_Foo → Foo - const m = clean.match(/^([A-Za-z\d]+)_\1([A-Za-z\d]*)$/); - if (m) clean = m[1] + m[2]; - return clean; - }, + schemaName: (name: string) => { + // Strip version markers: User_v1_0_0_User → User + let clean = name.replace(/([A-Za-z\d]+)_v\d+_\d+_\d+_([A-Za-z\d]*)/g, (_, p1, p2) => + p2.startsWith(p1) ? p2 : p1 + p2, + ); + // Deduplicate prefixes: Foo_Foo → Foo + const m = clean.match(/^([A-Za-z\d]+)_\1([A-Za-z\d]*)$/); + if (m) clean = m[1] + m[2]; + return clean; }, }, }, diff --git a/packages/shared/src/config/parser/config.ts b/packages/shared/src/config/parser/config.ts index 37ef4db88..a9c013800 100644 --- a/packages/shared/src/config/parser/config.ts +++ b/packages/shared/src/config/parser/config.ts @@ -36,10 +36,7 @@ export function getParser(userConfig: { parser?: UserParser }): Parser { name: '{{name}}', }, }, - schemas: { - enabled: false, - name: '{{name}}', - }, + schemaName: undefined, }, validate_EXPERIMENTAL: false, }, @@ -141,27 +138,8 @@ export function getParser(userConfig: { parser?: UserParser }): Parser { }, value: fields.readWrite, }), - schemas: valueToObject({ - defaultValue: { - ...(defaultValue.schemas as Extract< - typeof defaultValue.schemas, - Record - >), - enabled: - fields.schemas !== undefined - ? Boolean(fields.schemas) - : ( - defaultValue.schemas as Extract< - typeof defaultValue.schemas, - Record - > - ).enabled, - }, - mappers: { - boolean: (enabled: boolean) => ({ enabled }), - }, - value: fields.schemas, - }), + schemaName: + fields.schemaName !== undefined ? fields.schemaName : defaultValue.schemaName, }), }, value: fields.transforms, diff --git a/packages/shared/src/config/parser/types.ts b/packages/shared/src/config/parser/types.ts index 28fb7557d..a1f17a749 100644 --- a/packages/shared/src/config/parser/types.ts +++ b/packages/shared/src/config/parser/types.ts @@ -188,35 +188,13 @@ export type UserParser = { * @example * ```ts * { - * schemas: { - * name: (name) => name.replace(/_v\d+_\d+_\d+_/, '_') - * } + * schemaName: (name) => name.replace(/_v\d+_\d+_\d+_/, '_') * } * ``` * - * @default false + * @default undefined */ - schemas?: - | boolean - | { - /** - * Whether this feature is enabled. - * - * @default false - */ - enabled?: boolean; - /** - * Customize the generated name of schema components. - * When provided, this transformer is called for each schema key - * in `components.schemas` to compute the new name. - * - * If the new name conflicts with an existing schema, the rename - * is skipped for that schema. - * - * @default undefined - */ - name?: NameTransformer; - }; + schemaName?: NameTransformer; }; /** * **This is an experimental feature.** @@ -325,20 +303,10 @@ export type Parser = { /** * Rename schema component keys and automatically update all `$ref` pointers * throughout the specification. + * + * @default undefined */ - schemas: FeatureToggle & { - /** - * Customize the generated name of schema components. - * When provided, this transformer is called for each schema key - * in `components.schemas` to compute the new name. - * - * If the new name conflicts with an existing schema, the rename - * is skipped for that schema. - * - * @default '{{name}}' - */ - name: NameTransformer; - }; + schemaName?: NameTransformer; }; /** * **This is an experimental feature.** diff --git a/packages/shared/src/openApi/shared/transforms/index.ts b/packages/shared/src/openApi/shared/transforms/index.ts index b43440558..becd9a139 100644 --- a/packages/shared/src/openApi/shared/transforms/index.ts +++ b/packages/shared/src/openApi/shared/transforms/index.ts @@ -8,9 +8,9 @@ export const transformOpenApiSpec = ({ context }: { context: Context }) => { const { logger } = context; const eventTransformOpenApiSpec = logger.timeEvent('transform-openapi-spec'); - if (context.config.parser.transforms.schemas.enabled) { + if (context.config.parser.transforms.schemaName) { schemasTransform({ - config: context.config.parser.transforms.schemas, + schemaName: context.config.parser.transforms.schemaName, spec: context.spec, }); } diff --git a/packages/shared/src/openApi/shared/transforms/schemas.ts b/packages/shared/src/openApi/shared/transforms/schemas.ts index 272bf2c54..4efb66971 100644 --- a/packages/shared/src/openApi/shared/transforms/schemas.ts +++ b/packages/shared/src/openApi/shared/transforms/schemas.ts @@ -3,7 +3,7 @@ import { applyNaming } from '../../../utils/naming/naming'; import { getSchemasObject } from '../utils/transforms'; import { specToSchemasPointerNamespace } from './utils'; -type SchemasConfig = Parser['transforms']['schemas']; +type SchemaNameConfig = Parser['transforms']['schemaName']; /** * Recursively walks the entire spec object and replaces all $ref strings @@ -38,10 +38,20 @@ const rewriteRefs = (node: unknown, renameMap: Record) => { * 4. Renames schema keys in the schemas object * 5. Updates all $ref pointers throughout the spec to use the new names * - * @param config - The schemas transform config + * @param schemaName - The schema name transformer * @param spec - The OpenAPI spec object to transform */ -export const schemasTransform = ({ config, spec }: { config: SchemasConfig; spec: unknown }) => { +export const schemasTransform = ({ + schemaName, + spec, +}: { + schemaName: SchemaNameConfig; + spec: unknown; +}) => { + if (!schemaName) { + return; + } + const schemasObj = getSchemasObject(spec); if (!schemasObj) { return; @@ -56,9 +66,13 @@ export const schemasTransform = ({ config, spec }: { config: SchemasConfig; spec const renameMap: Record = {}; const newNames = new Set(); + // Create a simple config object for applyNaming + const namingConfig = + typeof schemaName === 'function' ? { name: schemaName } : { name: schemaName }; + // First pass: compute all new names and check for collisions for (const oldName of Object.keys(schemasObj)) { - const newName = applyNaming(oldName, config); + const newName = applyNaming(oldName, namingConfig); // Skip if name doesn't change if (newName === oldName) { -- 2.51.2