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.

Merge pull request #2216 from hey-api/fix/parser-patch-meta

fix(parser): add meta and version options to input.patch

authored by

Lubos and committed by
GitHub
4d43c099 0eb8683b

+169 -15
+5
.changeset/strong-donkeys-give.md
··· 1 + --- 2 + '@hey-api/openapi-ts': patch 3 + --- 4 + 5 + fix(parser): add `meta` and `version` options to input.patch
+3
packages/openapi-ts-tests/test/openapi-ts.config.ts
··· 42 42 // pagination: { 43 43 // keywords: ['aa'], 44 44 // }, 45 + // patch: { 46 + // version: () => '3.1.1', 47 + // }, 45 48 // path: { 46 49 // components: {}, 47 50 // info: {
+2 -1
packages/openapi-ts/src/openApi/2.0.x/index.ts
··· 1 1 export { parseV2_0_X } from './parser'; 2 2 export type { OpenApiV2_0_X } from './types/spec'; 3 3 4 - import type { SchemaObject } from './types/spec'; 4 + import type { InfoObject, SchemaObject } from './types/spec'; 5 5 6 6 export interface OpenApiV2_0_XTypes { 7 + InfoObject: InfoObject; 7 8 SchemaObject: SchemaObject; 8 9 }
+2
packages/openapi-ts/src/openApi/3.0.x/index.ts
··· 2 2 export type { OpenApiV3_0_X } from './types/spec'; 3 3 4 4 import type { 5 + InfoObject, 5 6 ParameterObject, 6 7 ReferenceObject, 7 8 RequestBodyObject, ··· 10 11 } from './types/spec'; 11 12 12 13 export interface OpenApiV3_0_XTypes { 14 + InfoObject: InfoObject; 13 15 ParameterObject: ParameterObject; 14 16 ReferenceObject: ReferenceObject; 15 17 RequestBodyObject: RequestBodyObject;
+2
packages/openapi-ts/src/openApi/3.1.x/index.ts
··· 2 2 export type { OpenApiV3_1_X } from './types/spec'; 3 3 4 4 import type { 5 + InfoObject, 5 6 ParameterObject, 6 7 ReferenceObject, 7 8 RequestBodyObject, ··· 10 11 } from './types/spec'; 11 12 12 13 export interface OpenApiV3_1_XTypes { 14 + InfoObject: InfoObject; 13 15 ParameterObject: ParameterObject; 14 16 ReferenceObject: ReferenceObject; 15 17 RequestBodyObject: RequestBodyObject;
+64
packages/openapi-ts/src/openApi/shared/utils/__tests__/patch.test.ts
··· 383 383 type: 'string', 384 384 }); 385 385 }); 386 + 387 + it('applies meta patch function', () => { 388 + const metaFn = vi.fn((meta) => { 389 + meta.title = 'Changed Title'; 390 + }); 391 + const spec: OpenApi.V3_1_X = { 392 + ...specMetadataV3, 393 + }; 394 + patchOpenApiSpec({ 395 + patchOptions: { 396 + meta: metaFn, 397 + }, 398 + spec, 399 + }); 400 + expect(metaFn).toHaveBeenCalledOnce(); 401 + expect(spec.info.title).toBe('Changed Title'); 402 + }); 403 + 404 + it('applies version patch function', () => { 405 + const versionFn = vi.fn((version) => `patched-${version}`); 406 + const spec: OpenApi.V3_1_X = { 407 + ...specMetadataV3, 408 + }; 409 + patchOpenApiSpec({ 410 + patchOptions: { 411 + version: versionFn, 412 + }, 413 + spec, 414 + }); 415 + expect(versionFn).toHaveBeenCalledOnce(); 416 + expect(spec.openapi).toBe('patched-3.1.0'); 417 + }); 386 418 }); 387 419 388 420 describe('OpenAPI v2', () => { ··· 541 573 expect(fn).toHaveBeenCalledWith({ 542 574 type: 'string', 543 575 }); 576 + }); 577 + 578 + it('applies meta patch function', () => { 579 + const metaFn = vi.fn((meta) => { 580 + meta.title = 'Changed Title'; 581 + }); 582 + const spec: OpenApi.V2_0_X = { 583 + ...specMetadataV2, 584 + }; 585 + patchOpenApiSpec({ 586 + patchOptions: { 587 + meta: metaFn, 588 + }, 589 + spec, 590 + }); 591 + expect(metaFn).toHaveBeenCalledOnce(); 592 + expect(spec.info.title).toBe('Changed Title'); 593 + }); 594 + 595 + it('applies version patch function', () => { 596 + const versionFn = vi.fn((version) => `patched-${version}`); 597 + const spec: OpenApi.V2_0_X = { 598 + ...specMetadataV2, 599 + }; 600 + patchOpenApiSpec({ 601 + patchOptions: { 602 + version: versionFn, 603 + }, 604 + spec, 605 + }); 606 + expect(versionFn).toHaveBeenCalledOnce(); 607 + expect(spec.swagger).toBe('patched-2.0'); 544 608 }); 545 609 }); 546 610
+30 -14
packages/openapi-ts/src/openApi/shared/utils/patch.ts
··· 15 15 const spec = _spec as OpenApi.V2_0_X | OpenApi.V3_0_X | OpenApi.V3_1_X; 16 16 17 17 if ('swagger' in spec) { 18 - if (spec.definitions && patchOptions?.schemas) { 18 + if (patchOptions.version && spec.swagger) { 19 + spec.swagger = patchOptions.version(spec.swagger) as typeof spec.swagger; 20 + } 21 + 22 + if (patchOptions.meta && spec.info) { 23 + patchOptions.meta(spec.info); 24 + } 25 + 26 + if (patchOptions.schemas && spec.definitions) { 19 27 for (const key in patchOptions.schemas) { 20 28 const patchFn = patchOptions.schemas[key]!; 21 29 const schema = spec.definitions[key]; ··· 27 35 return; 28 36 } 29 37 38 + if (patchOptions.version && spec.openapi) { 39 + spec.openapi = patchOptions.version(spec.openapi) as typeof spec.openapi; 40 + } 41 + 42 + if (patchOptions.meta && spec.info) { 43 + patchOptions.meta(spec.info); 44 + } 45 + 30 46 if (spec.components) { 31 - if (spec.components.parameters && patchOptions.parameters) { 47 + if (patchOptions.schemas && spec.components.schemas) { 48 + for (const key in patchOptions.schemas) { 49 + const patchFn = patchOptions.schemas[key]!; 50 + const schema = spec.components.schemas[key]; 51 + if (schema && typeof schema === 'object') { 52 + patchFn(schema); 53 + } 54 + } 55 + } 56 + 57 + if (patchOptions.parameters && spec.components.parameters) { 32 58 for (const key in patchOptions.parameters) { 33 59 const patchFn = patchOptions.parameters[key]!; 34 60 const schema = spec.components.parameters[key]; ··· 38 64 } 39 65 } 40 66 41 - if (spec.components.requestBodies && patchOptions.requestBodies) { 67 + if (patchOptions.requestBodies && spec.components.requestBodies) { 42 68 for (const key in patchOptions.requestBodies) { 43 69 const patchFn = patchOptions.requestBodies[key]!; 44 70 const schema = spec.components.requestBodies[key]; ··· 48 74 } 49 75 } 50 76 51 - if (spec.components.responses && patchOptions.responses) { 77 + if (patchOptions.responses && spec.components.responses) { 52 78 for (const key in patchOptions.responses) { 53 79 const patchFn = patchOptions.responses[key]!; 54 80 const schema = spec.components.responses[key]; 55 - if (schema && typeof schema === 'object') { 56 - patchFn(schema); 57 - } 58 - } 59 - } 60 - 61 - if (spec.components.schemas && patchOptions?.schemas) { 62 - for (const key in patchOptions.schemas) { 63 - const patchFn = patchOptions.schemas[key]!; 64 - const schema = spec.components.schemas[key]; 65 81 if (schema && typeof schema === 'object') { 66 82 patchFn(schema); 67 83 }
+8
packages/openapi-ts/src/openApi/types.d.ts
··· 10 10 export type V3_1_X = OpenApiV3_1_X; 11 11 } 12 12 13 + export namespace OpenApiMetaObject { 14 + export type V2_0_X = OpenApiV2_0_XTypes['InfoObject']; 15 + 16 + export type V3_0_X = OpenApiV3_0_XTypes['InfoObject']; 17 + 18 + export type V3_1_X = OpenApiV3_1_XTypes['InfoObject']; 19 + } 20 + 13 21 export namespace OpenApiParameterObject { 14 22 export type V3_0_X = 15 23 | OpenApiV3_0_XTypes['ParameterObject']
+53
packages/openapi-ts/src/types/input.d.ts
··· 1 1 import type { 2 + OpenApiMetaObject, 2 3 OpenApiParameterObject, 3 4 OpenApiRequestBodyObject, 4 5 OpenApiResponseObject, ··· 246 247 } 247 248 248 249 export interface Patch { 250 + /** 251 + * Patch the OpenAPI meta object in place. Useful for modifying general metadata such as title, description, version, or custom fields before further processing. 252 + * 253 + * @param meta The OpenAPI meta object for the current version. 254 + */ 255 + meta?: ( 256 + meta: 257 + | OpenApiMetaObject.V2_0_X 258 + | OpenApiMetaObject.V3_0_X 259 + | OpenApiMetaObject.V3_1_X, 260 + ) => void; 261 + /** 262 + * Patch OpenAPI parameters in place. The key is the parameter name, and the function receives the parameter object to modify directly. 263 + * 264 + * @example 265 + * parameters: { 266 + * limit: (parameter) => { 267 + * parameter.schema.type = 'integer'; 268 + * } 269 + * } 270 + */ 249 271 parameters?: Record< 250 272 string, 251 273 ( 252 274 parameter: OpenApiParameterObject.V3_0_X | OpenApiParameterObject.V3_1_X, 253 275 ) => void 254 276 >; 277 + /** 278 + * Patch OpenAPI request bodies in place. The key is the request body name, and the function receives the request body object to modify directly. 279 + * 280 + * @example 281 + * requestBodies: { 282 + * CreateUserRequest: (requestBody) => { 283 + * requestBody.required = true; 284 + * } 285 + * } 286 + */ 255 287 requestBodies?: Record< 256 288 string, 257 289 ( ··· 260 292 | OpenApiRequestBodyObject.V3_1_X, 261 293 ) => void 262 294 >; 295 + /** 296 + * Patch OpenAPI responses in place. The key is the response name, and the function receives the response object to modify directly. 297 + * 298 + * @example 299 + * responses: { 300 + * NotFound: (response) => { 301 + * response.description = 'Resource not found.'; 302 + * } 303 + * } 304 + */ 263 305 responses?: Record< 264 306 string, 265 307 ( ··· 303 345 | OpenApiSchemaObject.V3_1_X, 304 346 ) => void 305 347 >; 348 + /** 349 + * Patch the OpenAPI version string. The function receives the current version and should return the new version string. 350 + * Useful for normalizing or overriding the version value before further processing. 351 + * 352 + * @param version The current OpenAPI version string. 353 + * @returns The new version string to use. 354 + * 355 + * @example 356 + * version: (version) => version.replace(/^v/, '') 357 + */ 358 + version?: (version: string) => string; 306 359 } 307 360 308 361 export interface Watch {