fork of hey-api/openapi-ts because I need some additional things
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

refactor: flatten transforms.schemas.name to transforms.schemaName

Co-authored-by: mrlubos <12529395+mrlubos@users.noreply.github.com>

+59 -119
+12 -28
docs/openapi-ts/configuration/parser.md
··· 447 447 448 448 You can customize the naming and casing pattern for `requests` and `responses` schemas using the `.name` and `.case` options. 449 449 450 - ### Schemas 450 + ### Schema Name 451 451 452 - 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. 452 + 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. 453 453 454 454 This is useful for: 455 455 ··· 466 466 output: 'src/client', 467 467 parser: { 468 468 transforms: { 469 - schemas: { 470 - name: (name) => { 471 - // Strip version markers: ServiceRoot_v1_20_0_ServiceRoot → ServiceRoot 472 - let clean = name.replace(/([A-Za-z\d]+)_v\d+_\d+_\d+_([A-Za-z\d]*)/g, (_, p1, p2) => 473 - p2.startsWith(p1) ? p2 : p1 + p2, 474 - ); 475 - // Deduplicate prefixes: Foo_Foo → Foo 476 - const m = clean.match(/^([A-Za-z\d]+)_\1([A-Za-z\d]*)$/); 477 - if (m) clean = m[1] + m[2]; 478 - return clean; 479 - }, 469 + schemaName: (name) => { 470 + // Strip version markers: ServiceRoot_v1_20_0_ServiceRoot → ServiceRoot 471 + let clean = name.replace(/([A-Za-z\d]+)_v\d+_\d+_\d+_([A-Za-z\d]*)/g, (_, p1, p2) => 472 + p2.startsWith(p1) ? p2 : p1 + p2, 473 + ); 474 + // Deduplicate prefixes: Foo_Foo → Foo 475 + const m = clean.match(/^([A-Za-z\d]+)_\1([A-Za-z\d]*)$/); 476 + if (m) clean = m[1] + m[2]; 477 + return clean; 480 478 }, 481 479 }, 482 480 }, ··· 489 487 output: 'src/client', 490 488 parser: { 491 489 transforms: { 492 - schemas: { 493 - name: 'Api{{name}}', // Add "Api" prefix to all schemas 494 - }, 495 - }, 496 - }, 497 - }; 498 - ``` 499 - 500 - ```js [disabled] 501 - export default { 502 - input: 'hey-api/backend', // sign up at app.heyapi.dev 503 - output: 'src/client', 504 - parser: { 505 - transforms: { 506 - schemas: false, // [!code ++] 490 + schemaName: 'Api{{name}}', // Add "Api" prefix to all schemas 507 491 }, 508 492 }, 509 493 };
+9 -11
packages/openapi-ts-tests/main/test/2.0.x.test.ts
··· 293 293 output: 'transforms-schemas-name', 294 294 parser: { 295 295 transforms: { 296 - schemas: { 297 - name: (name: string) => { 298 - // Strip version markers: User_v1_0_0_User → User 299 - let clean = name.replace(/([A-Za-z\d]+)_v\d+_\d+_\d+_([A-Za-z\d]*)/g, (_, p1, p2) => 300 - p2.startsWith(p1) ? p2 : p1 + p2, 301 - ); 302 - // Deduplicate prefixes: Foo_Foo → Foo 303 - const m = clean.match(/^([A-Za-z\d]+)_\1([A-Za-z\d]*)$/); 304 - if (m) clean = m[1] + m[2]; 305 - return clean; 306 - }, 296 + schemaName: (name: string) => { 297 + // Strip version markers: User_v1_0_0_User → User 298 + let clean = name.replace(/([A-Za-z\d]+)_v\d+_\d+_\d+_([A-Za-z\d]*)/g, (_, p1, p2) => 299 + p2.startsWith(p1) ? p2 : p1 + p2, 300 + ); 301 + // Deduplicate prefixes: Foo_Foo → Foo 302 + const m = clean.match(/^([A-Za-z\d]+)_\1([A-Za-z\d]*)$/); 303 + if (m) clean = m[1] + m[2]; 304 + return clean; 307 305 }, 308 306 }, 309 307 },
+9 -11
packages/openapi-ts-tests/main/test/3.0.x.test.ts
··· 596 596 output: 'transforms-schemas-name', 597 597 parser: { 598 598 transforms: { 599 - schemas: { 600 - name: (name: string) => { 601 - // Strip version markers: User_v1_0_0_User → User 602 - let clean = name.replace(/([A-Za-z\d]+)_v\d+_\d+_\d+_([A-Za-z\d]*)/g, (_, p1, p2) => 603 - p2.startsWith(p1) ? p2 : p1 + p2, 604 - ); 605 - // Deduplicate prefixes: Foo_Foo → Foo 606 - const m = clean.match(/^([A-Za-z\d]+)_\1([A-Za-z\d]*)$/); 607 - if (m) clean = m[1] + m[2]; 608 - return clean; 609 - }, 599 + schemaName: (name: string) => { 600 + // Strip version markers: User_v1_0_0_User → User 601 + let clean = name.replace(/([A-Za-z\d]+)_v\d+_\d+_\d+_([A-Za-z\d]*)/g, (_, p1, p2) => 602 + p2.startsWith(p1) ? p2 : p1 + p2, 603 + ); 604 + // Deduplicate prefixes: Foo_Foo → Foo 605 + const m = clean.match(/^([A-Za-z\d]+)_\1([A-Za-z\d]*)$/); 606 + if (m) clean = m[1] + m[2]; 607 + return clean; 610 608 }, 611 609 }, 612 610 },
+3 -25
packages/shared/src/config/parser/config.ts
··· 36 36 name: '{{name}}', 37 37 }, 38 38 }, 39 - schemas: { 40 - enabled: false, 41 - name: '{{name}}', 42 - }, 39 + schemaName: undefined, 43 40 }, 44 41 validate_EXPERIMENTAL: false, 45 42 }, ··· 141 138 }, 142 139 value: fields.readWrite, 143 140 }), 144 - schemas: valueToObject({ 145 - defaultValue: { 146 - ...(defaultValue.schemas as Extract< 147 - typeof defaultValue.schemas, 148 - Record<string, unknown> 149 - >), 150 - enabled: 151 - fields.schemas !== undefined 152 - ? Boolean(fields.schemas) 153 - : ( 154 - defaultValue.schemas as Extract< 155 - typeof defaultValue.schemas, 156 - Record<string, unknown> 157 - > 158 - ).enabled, 159 - }, 160 - mappers: { 161 - boolean: (enabled: boolean) => ({ enabled }), 162 - }, 163 - value: fields.schemas, 164 - }), 141 + schemaName: 142 + fields.schemaName !== undefined ? fields.schemaName : defaultValue.schemaName, 165 143 }), 166 144 }, 167 145 value: fields.transforms,
+6 -38
packages/shared/src/config/parser/types.ts
··· 188 188 * @example 189 189 * ```ts 190 190 * { 191 - * schemas: { 192 - * name: (name) => name.replace(/_v\d+_\d+_\d+_/, '_') 193 - * } 191 + * schemaName: (name) => name.replace(/_v\d+_\d+_\d+_/, '_') 194 192 * } 195 193 * ``` 196 194 * 197 - * @default false 195 + * @default undefined 198 196 */ 199 - schemas?: 200 - | boolean 201 - | { 202 - /** 203 - * Whether this feature is enabled. 204 - * 205 - * @default false 206 - */ 207 - enabled?: boolean; 208 - /** 209 - * Customize the generated name of schema components. 210 - * When provided, this transformer is called for each schema key 211 - * in `components.schemas` to compute the new name. 212 - * 213 - * If the new name conflicts with an existing schema, the rename 214 - * is skipped for that schema. 215 - * 216 - * @default undefined 217 - */ 218 - name?: NameTransformer; 219 - }; 197 + schemaName?: NameTransformer; 220 198 }; 221 199 /** 222 200 * **This is an experimental feature.** ··· 325 303 /** 326 304 * Rename schema component keys and automatically update all `$ref` pointers 327 305 * throughout the specification. 306 + * 307 + * @default undefined 328 308 */ 329 - schemas: FeatureToggle & { 330 - /** 331 - * Customize the generated name of schema components. 332 - * When provided, this transformer is called for each schema key 333 - * in `components.schemas` to compute the new name. 334 - * 335 - * If the new name conflicts with an existing schema, the rename 336 - * is skipped for that schema. 337 - * 338 - * @default '{{name}}' 339 - */ 340 - name: NameTransformer; 341 - }; 309 + schemaName?: NameTransformer; 342 310 }; 343 311 /** 344 312 * **This is an experimental feature.**
+2 -2
packages/shared/src/openApi/shared/transforms/index.ts
··· 8 8 const { logger } = context; 9 9 const eventTransformOpenApiSpec = logger.timeEvent('transform-openapi-spec'); 10 10 11 - if (context.config.parser.transforms.schemas.enabled) { 11 + if (context.config.parser.transforms.schemaName) { 12 12 schemasTransform({ 13 - config: context.config.parser.transforms.schemas, 13 + schemaName: context.config.parser.transforms.schemaName, 14 14 spec: context.spec, 15 15 }); 16 16 }
+18 -4
packages/shared/src/openApi/shared/transforms/schemas.ts
··· 3 3 import { getSchemasObject } from '../utils/transforms'; 4 4 import { specToSchemasPointerNamespace } from './utils'; 5 5 6 - type SchemasConfig = Parser['transforms']['schemas']; 6 + type SchemaNameConfig = Parser['transforms']['schemaName']; 7 7 8 8 /** 9 9 * Recursively walks the entire spec object and replaces all $ref strings ··· 38 38 * 4. Renames schema keys in the schemas object 39 39 * 5. Updates all $ref pointers throughout the spec to use the new names 40 40 * 41 - * @param config - The schemas transform config 41 + * @param schemaName - The schema name transformer 42 42 * @param spec - The OpenAPI spec object to transform 43 43 */ 44 - export const schemasTransform = ({ config, spec }: { config: SchemasConfig; spec: unknown }) => { 44 + export const schemasTransform = ({ 45 + schemaName, 46 + spec, 47 + }: { 48 + schemaName: SchemaNameConfig; 49 + spec: unknown; 50 + }) => { 51 + if (!schemaName) { 52 + return; 53 + } 54 + 45 55 const schemasObj = getSchemasObject(spec); 46 56 if (!schemasObj) { 47 57 return; ··· 56 66 const renameMap: Record<string, string> = {}; 57 67 const newNames = new Set<string>(); 58 68 69 + // Create a simple config object for applyNaming 70 + const namingConfig = 71 + typeof schemaName === 'function' ? { name: schemaName } : { name: schemaName }; 72 + 59 73 // First pass: compute all new names and check for collisions 60 74 for (const oldName of Object.keys(schemasObj)) { 61 - const newName = applyNaming(oldName, config); 75 + const newName = applyNaming(oldName, namingConfig); 62 76 63 77 // Skip if name doesn't change 64 78 if (newName === oldName) {