Skip to content

Comments

fix: merge paths with non-conflicting HTTP methods instead of prefixing#3436

Merged
mrlubos merged 3 commits intomainfrom
copilot/fix-path-collision-prefix
Feb 23, 2026
Merged

fix: merge paths with non-conflicting HTTP methods instead of prefixing#3436
mrlubos merged 3 commits intomainfrom
copilot/fix-path-collision-prefix

Conversation

Copy link
Contributor

Copilot AI commented Feb 23, 2026

When merging multiple OpenAPI specs, path collisions were resolved by always adding a source prefix to the path — even when the colliding paths had completely different HTTP methods that could safely coexist under the same path key.

Changes

  • packages/json-schema-ref-parser/src/index.ts: In mergeMany(), path collision handling now checks whether the incoming path's HTTP methods actually overlap with the already-merged path before prefixing. Non-conflicting methods are merged in-place via Object.assign; only true method conflicts fall back to the prefix strategy.

  • packages/json-schema-ref-parser/src/__tests__/bundle.test.ts: Added two mergeMany test cases — one confirming non-conflicting methods (e.g. POST + DELETE) merge under the same path, and one confirming genuine method conflicts still produce a prefixed path.

Example

Given two specs both defining /pet/{petId} — one with post, one with delete — the merged result is now:

{
  "/pet/{petId}": {
    "post": { ... },
    "delete": { ... }
  }
}

Previously, the second spec's path was incorrectly renamed to /{prefix}/pet/{petId}.

Original prompt

This section details on the original issue you should resolve

<issue_title>path collision are adding prefix without checking the method</issue_title>
<issue_description>### Description

When there is collision in paths, it will automatically append the prefix (code) however, it doesn't check if the methods collide too, sometimes different method might be in different spec:

input:

  • swagger1.json
{
  "swagger": "2.0",
  "info": {
    "version": "1.0.7",
    "title": "Swagger Petstore",
    "description": "Filtered spec containing only POST /pet/{petId}"
  },
  "host": "petstore.swagger.io",
  "basePath": "/v2",
  "schemes": ["https", "http"],
  "paths": {
    "/pet/{petId}": {
      "post": {
        "tags": ["pet"],
        "summary": "Updates a pet in the store with form data",
        "description": "",
        "operationId": "updatePetWithForm",
        "consumes": ["application/x-www-form-urlencoded"],
        "produces": ["application/json", "application/xml"],
        "parameters": [
          {
            "name": "petId",
            "in": "path",
            "description": "ID of pet that needs to be updated",
            "required": true,
            "type": "integer",
            "format": "int64"
          },
          {
            "name": "name",
            "in": "formData",
            "description": "Updated name of the pet",
            "required": false,
            "type": "string"
          },
          {
            "name": "status",
            "in": "formData",
            "description": "Updated status of the pet",
            "required": false,
            "type": "string"
          }
        ],
        "responses": {
          "405": {
            "description": "Invalid input"
          }
        },
        "security": [
          {
            "petstore_auth": ["write:pets", "read:pets"]
          }
        ]
      }
    }
  },
  "securityDefinitions": {
    "petstore_auth": {
      "type": "oauth2",
      "authorizationUrl": "https://petstore.swagger.io/oauth/authorize",
      "flow": "implicit",
      "scopes": {
        "read:pets": "read your pets",
        "write:pets": "modify pets in your account"
      }
    }
  }
}
  • swagger2.json
{
  "swagger": "2.0",
  "info": {
    "version": "1.0.7",
    "title": "Swagger Petstore",
    "description": "Filtered spec containing only GET and DELETE for /pet/{petId}"
  },
  "host": "petstore.swagger.io",
  "basePath": "/v2",
  "schemes": ["https", "http"],
  "paths": {
    "/pet/{petId}": {
      "delete": {
        "tags": ["pet"],
        "summary": "Deletes a pet",
        "description": "",
        "operationId": "deletePet",
        "produces": ["application/json", "application/xml"],
        "parameters": [
          {
            "name": "api_key",
            "in": "header",
            "required": false,
            "type": "string"
          },
          {
            "name": "petId",
            "in": "path",
            "description": "Pet id to delete",
            "required": true,
            "type": "integer",
            "format": "int64"
          }
        ],
        "responses": {
          "400": {
            "description": "Invalid ID supplied"
          },
          "404": {
            "description": "Pet not found"
          }
        },
        "security": [
          {
            "petstore_auth": ["write:pets", "read:pets"]
          }
        ]
      }
    }
  },
  "securityDefinitions": {
    "api_key": {
      "type": "apiKey",
      "name": "api_key",
      "in": "header"
    },
    "petstore_auth": {
      "type": "oauth2",
      "authorizationUrl": "https://petstore.swagger.io/oauth/authorize",
      "flow": "implicit",
      "scopes": {
        "read:pets": "read your pets",
        "write:pets": "modify pets in your account"
      }
    }
  },
  "definitions": {
    "Category": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer",
          "format": "int64"
        },
        "name": {
          "type": "string"
        }
      }
    },
    "Pet": {
      "type": "object",
      "required": ["name", "photoUrls"],
      "properties": {
        "id": {
          "type": "integer",
          "format": "int64"
        },
        "category": {
          "$ref": "#/definitions/Category"
        },
        "name": {
          "type": "string",
          "example": "doggie"
        },
        "photoUrls": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "tags": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/Tag"
          }
        },
        "status": {
          "type": "string",
          "enum": ["available", "pending", "sold"]
        }
      }
    },
    "Tag": {
      "type": "object",
      "properties": {
        "id": {
        ...

</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

- Fixes hey-api/openapi-ts#3428

<!-- START COPILOT CODING AGENT TIPS -->
---

💬 We'd love your input! Share your thoughts on Copilot coding agent in our [2 minute survey](https://gh.io/copilot-coding-agent-survey).

@bolt-new-by-stackblitz
Copy link

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

@changeset-bot
Copy link

changeset-bot bot commented Feb 23, 2026

🦋 Changeset detected

Latest commit: b1a419a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 4 packages
Name Type
@hey-api/json-schema-ref-parser Patch
@hey-api/openapi-ts Patch
@hey-api/openapi-python Patch
@hey-api/shared Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link

vercel bot commented Feb 23, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
hey-api-docs Ready Ready Preview, Comment Feb 23, 2026 9:52am

Request Review

…prefix

Co-authored-by: mrlubos <12529395+mrlubos@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix path collision issue with method check fix: merge paths with non-conflicting HTTP methods instead of prefixing Feb 23, 2026
Copilot AI requested a review from mrlubos February 23, 2026 09:41
@mrlubos mrlubos marked this pull request as ready for review February 23, 2026 09:51
@pullfrog
Copy link

pullfrog bot commented Feb 23, 2026

Leaping into action...

Pullfrog  | View workflow run | Using OpenCode | Triggered by Pullfrogpullfrog.com𝕏

@dosubot dosubot bot added size:L This PR changes 100-499 lines, ignoring generated files. bug 🔥 Broken or incorrect behavior. labels Feb 23, 2026
@codecov
Copy link

codecov bot commented Feb 23, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 40.11%. Comparing base (55ccacf) to head (b1a419a).
⚠️ Report is 4 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3436      +/-   ##
==========================================
+ Coverage   39.37%   40.11%   +0.74%     
==========================================
  Files         476      476              
  Lines       17452    17459       +7     
  Branches     5278     5287       +9     
==========================================
+ Hits         6871     7004     +133     
+ Misses       8500     8414      -86     
+ Partials     2081     2041      -40     
Flag Coverage Δ
unittests 40.11% <100.00%> (+0.74%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Feb 23, 2026

Open in StackBlitz

@hey-api/codegen-core

npm i https://pkg.pr.new/hey-api/openapi-ts/@hey-api/codegen-core@3436

@hey-api/json-schema-ref-parser

npm i https://pkg.pr.new/hey-api/openapi-ts/@hey-api/json-schema-ref-parser@3436

@hey-api/nuxt

npm i https://pkg.pr.new/hey-api/openapi-ts/@hey-api/nuxt@3436

@hey-api/openapi-ts

npm i https://pkg.pr.new/hey-api/openapi-ts/@hey-api/openapi-ts@3436

@hey-api/shared

npm i https://pkg.pr.new/hey-api/openapi-ts/@hey-api/shared@3436

@hey-api/types

npm i https://pkg.pr.new/hey-api/openapi-ts/@hey-api/types@3436

@hey-api/vite-plugin

npm i https://pkg.pr.new/hey-api/openapi-ts/@hey-api/vite-plugin@3436

commit: b1a419a

@mrlubos mrlubos merged commit 2faab85 into main Feb 23, 2026
13 of 18 checks passed
@mrlubos mrlubos deleted the copilot/fix-path-collision-prefix branch February 23, 2026 10:05
@hey-api hey-api bot mentioned this pull request Feb 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug 🔥 Broken or incorrect behavior. size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants