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.

fix: merge paths with non-conflicting HTTP methods instead of adding prefix

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

+116 -10
+82
packages/json-schema-ref-parser/src/__tests__/bundle.test.ts
··· 308 308 } 309 309 }); 310 310 }); 311 + 312 + describe('mergeMany', () => { 313 + it('merges paths with non-conflicting methods under the same path', async () => { 314 + const refParser = new $RefParser(); 315 + const spec1 = { 316 + info: { title: 'Spec 1', version: '1.0.0' }, 317 + paths: { 318 + '/pet/{petId}': { 319 + post: { 320 + operationId: 'updatePetWithForm', 321 + responses: { '405': { description: 'Invalid input' } }, 322 + }, 323 + }, 324 + }, 325 + swagger: '2.0', 326 + }; 327 + const spec2 = { 328 + info: { title: 'Spec 2', version: '1.0.0' }, 329 + paths: { 330 + '/pet/{petId}': { 331 + delete: { 332 + operationId: 'deletePet', 333 + responses: { 334 + '400': { description: 'Invalid ID supplied' }, 335 + '404': { description: 'Pet not found' }, 336 + }, 337 + }, 338 + }, 339 + }, 340 + swagger: '2.0', 341 + }; 342 + 343 + const merged = (await refParser.bundleMany({ pathOrUrlOrSchemas: [spec1, spec2] })) as any; 344 + 345 + // Both methods should be under the same path (no prefix added) 346 + expect(merged.paths['/pet/{petId}']).toBeDefined(); 347 + expect(merged.paths['/pet/{petId}'].post).toBeDefined(); 348 + expect(merged.paths['/pet/{petId}'].delete).toBeDefined(); 349 + 350 + // No prefixed path should be created 351 + const pathKeys = Object.keys(merged.paths); 352 + expect(pathKeys).toHaveLength(1); 353 + }); 354 + 355 + it('adds prefix to path when HTTP methods conflict', async () => { 356 + const refParser = new $RefParser(); 357 + const spec1 = { 358 + info: { title: 'Spec 1', version: '1.0.0' }, 359 + paths: { 360 + '/pet/{petId}': { 361 + get: { 362 + operationId: 'getPetById', 363 + responses: { '200': { description: 'OK' } }, 364 + }, 365 + }, 366 + }, 367 + swagger: '2.0', 368 + }; 369 + const spec2 = { 370 + info: { title: 'Spec 2', version: '1.0.0' }, 371 + paths: { 372 + '/pet/{petId}': { 373 + get: { 374 + operationId: 'getPet', 375 + responses: { '200': { description: 'Success' } }, 376 + }, 377 + }, 378 + }, 379 + swagger: '2.0', 380 + }; 381 + 382 + const merged = (await refParser.bundleMany({ pathOrUrlOrSchemas: [spec1, spec2] })) as any; 383 + 384 + // The conflicting path should be prefixed 385 + const pathKeys = Object.keys(merged.paths); 386 + expect(pathKeys).toHaveLength(2); 387 + expect(merged.paths['/pet/{petId}']).toBeDefined(); 388 + const prefixedKey = pathKeys.find((k) => k !== '/pet/{petId}'); 389 + expect(prefixedKey).toBeDefined(); 390 + expect(merged.paths[prefixedKey!].get).toBeDefined(); 391 + }); 392 + }); 311 393 });
+34 -10
packages/json-schema-ref-parser/src/index.ts
··· 527 527 } 528 528 } 529 529 530 + const HTTP_METHODS = new Set([ 531 + 'delete', 532 + 'get', 533 + 'head', 534 + 'options', 535 + 'patch', 536 + 'post', 537 + 'put', 538 + 'trace', 539 + ]); 540 + 530 541 const srcPaths = (schema.paths || {}) as Record<string, any>; 531 542 for (const [p, item] of Object.entries(srcPaths)) { 532 - let targetPath = p; 533 543 if (merged.paths[p]) { 534 - const trimmed = p.startsWith('/') ? p.substring(1) : p; 535 - targetPath = `/${prefix}/${trimmed}`; 544 + const newMethods = Object.keys(item as object).filter((k) => HTTP_METHODS.has(k)); 545 + const hasMethodConflict = newMethods.some((m) => merged.paths[p][m] !== undefined); 546 + const rewritten = cloneAndRewrite( 547 + item, 548 + refMap, 549 + tagMap, 550 + prefix, 551 + url.stripHash(sourcePath), 552 + ); 553 + if (hasMethodConflict) { 554 + const trimmed = p.startsWith('/') ? p.substring(1) : p; 555 + merged.paths[`/${prefix}/${trimmed}`] = rewritten; 556 + } else { 557 + Object.assign(merged.paths[p], rewritten); 558 + } 559 + } else { 560 + merged.paths[p] = cloneAndRewrite( 561 + item, 562 + refMap, 563 + tagMap, 564 + prefix, 565 + url.stripHash(sourcePath), 566 + ); 536 567 } 537 - merged.paths[targetPath] = cloneAndRewrite( 538 - item, 539 - refMap, 540 - tagMap, 541 - prefix, 542 - url.stripHash(sourcePath), 543 - ); 544 568 } 545 569 } 546 570