Skip to content

feat!: migrate to @msw/url#2678

Merged
kettanaito merged 8 commits intofeat/3.0from
fix/use-msw-url
Apr 6, 2026
Merged

feat!: migrate to @msw/url#2678
kettanaito merged 8 commits intofeat/3.0from
fix/use-msw-url

Conversation

@kettanaito
Copy link
Copy Markdown
Member

@kettanaito kettanaito commented Mar 19, 2026

⚠️ BREAKING CHANGES

  • You can no longer list RegExp tokens in string predicates for requests. You can still provide a RegExp instance for matching, listing those tokens. The mix isn't supported anymore.

Changes

  • Migrates from path-to-regexp to an in-house @msw/url. Path matching is no longer regexp-based but token-based. Better performance, fewer vulnerabilities.
  • Improves path matching performance in certain scenarios (@msw/url is faster than path-to-regexp in most scenarios, in others the performance is roughly the same).
  • Refactors the related functionality in MSW.
  • No breaking changes expected.

Todos

  • Rewrite matchRequestUrl.test.ts. No need to assert what matchPattern does already. Actually test what the function does: handles RegExp, cleans urls, normalizes the path, and 1-2 simple absolute/relative url matches for posterity.
  • Check the params value for matching against RegExp in path-to-regexp. If it returned index-based capturing groups, implement that.

Comment thread src/core/utils/matching/matchRequestUrl.ts Outdated
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Mar 20, 2026

Open in StackBlitz

npm i https://pkg.pr.new/msw@2678

commit: 294e290

@kettanaito kettanaito changed the title fix: migrate to @msw/url feat!: migrate to @msw/url Mar 20, 2026
@kettanaito kettanaito added the BREAKING CHANGE Pull request introducing breaking changes. label Mar 20, 2026
@kettanaito kettanaito added this to the 3.0 milestone Mar 20, 2026
@kettanaito kettanaito changed the base branch from main to feat/3.0 April 6, 2026 10:55
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 6, 2026

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and accurately summarizes the main change: migration from path-to-regexp to @msw/url with a breaking change indicator.
Linked Issues check ✅ Passed The PR successfully addresses issue #2204 by migrating to @msw/url, which uses token-based pattern matching instead of regexp-based, enabling wildcard port matching (e.g., 'localhost:*') that previously failed with path-to-regexp.
Out of Scope Changes check ✅ Passed All changes are in scope: dependency migration (@msw/url addition, path-to-regexp removal), implementation refactoring (matchRequestUrl, normalizePath), and corresponding test updates align with the migration objectives.
Description check ✅ Passed The PR description clearly relates to the changeset: it explains the migration from path-to-regexp to @msw/url, lists breaking changes, and describes the refactoring of URL matching functionality reflected in the code changes.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/use-msw-url

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/core/utils/matching/normalizePath.ts (1)

13-21: Use function overloads instead of a generic return type for normalizePath.

The current signature <P extends Path>(path: P): P claims the function returns the same type as the input. However, cleanUrl() transforms string inputs by removing query parameters and hashes. This breaks the parametricity contract—callers passing string literals like "/user" expect that literal type back, but they receive a normalized string instead. Overloads preserve the string vs RegExp distinction without making this false guarantee.

Proposed fix
-export function normalizePath<P extends Path>(path: P, baseUrl?: string): P {
+export function normalizePath(path: RegExp, baseUrl?: string): RegExp
+export function normalizePath(path: string, baseUrl?: string): string
+export function normalizePath(path: Path, baseUrl?: string): Path {
   // RegExp paths do not need normalization.
   if (path instanceof RegExp) {
     return path
   }
 
   const maybeAbsoluteUrl = getAbsoluteUrl(path, baseUrl)
 
-  return cleanUrl(maybeAbsoluteUrl) as P
+  return cleanUrl(maybeAbsoluteUrl)
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/core/utils/matching/normalizePath.ts` around lines 13 - 21, The function
normalizePath currently uses a generic <P extends Path>(path: P): P which
incorrectly promises to return the exact input type; replace this with explicit
overloads: declare normalizePath(path: RegExp, baseUrl?: string): RegExp and
normalizePath(path: string, baseUrl?: string): string, then keep a single
implementation signature normalizePath(path: Path, baseUrl?: string): Path that
performs the runtime logic (the RegExp instanceof check, call to getAbsoluteUrl,
and return cleanUrl(maybeAbsoluteUrl) as Path). This preserves correct typing
for RegExp vs string callers while keeping the existing implementation using
getAbsoluteUrl and cleanUrl.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/core/utils/matching/matchRequestUrl.test.ts`:
- Around line 4-71: The test suite removed coverage for wildcard-port and
baseUrl-relative string matching; add back tests in matchRequestUrl.test.ts that
call matchRequestUrl to assert the wildcard-port pattern (e.g., matching new
URL('http://localhost:1234') against the string 'http://localhost:*' yields
matches: true, params: {}), and a test that asserts a baseUrl-relative string
pattern (e.g., matching new URL('http://example.com/base/path') against a
relative pattern like '/base/path' or a baseUrl-relative string) returns
matches: true with empty params; place these alongside the existing RegExp and
string tests using the same matchRequestUrl invocation to ensure regression
coverage for wildcard ports and base-relative string patterns.

In `@src/core/utils/matching/matchRequestUrl.ts`:
- Around line 29-38: The RegExp branch in matchRequestUrl incorrectly uses
matchAll when pattern.flags includes('g'), causing false positives and corrupted
params; change the logic to always perform a single-match with a non-global
RegExp: construct or reuse a RegExp without the 'g' flag (e.g., new
RegExp(pattern.source, pattern.flags.replace('g',''))) and call
cleanUrl.match(...) once, set matches = match != null, and build params from
(match ?? []).slice(1) as before so capture groups map correctly; remove the
matchAll/flat handling and ensure you reference the existing pattern, match,
cleanUrl, and params variables in the matchRequestUrl function.

---

Nitpick comments:
In `@src/core/utils/matching/normalizePath.ts`:
- Around line 13-21: The function normalizePath currently uses a generic <P
extends Path>(path: P): P which incorrectly promises to return the exact input
type; replace this with explicit overloads: declare normalizePath(path: RegExp,
baseUrl?: string): RegExp and normalizePath(path: string, baseUrl?: string):
string, then keep a single implementation signature normalizePath(path: Path,
baseUrl?: string): Path that performs the runtime logic (the RegExp instanceof
check, call to getAbsoluteUrl, and return cleanUrl(maybeAbsoluteUrl) as Path).
This preserves correct typing for RegExp vs string callers while keeping the
existing implementation using getAbsoluteUrl and cleanUrl.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: ead8705b-60a3-4632-b0d4-66a175a86913

📥 Commits

Reviewing files that changed from the base of the PR and between dd5dc3d and 956fed2.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (6)
  • package.json
  • src/core/utils/matching/matchRequestUrl.test.ts
  • src/core/utils/matching/matchRequestUrl.ts
  • src/core/utils/matching/normalizePath.ts
  • test/node/rest-api/request/matching/all.node.test.ts
  • test/node/rest-api/request/matching/path-params-optional.node.test.ts

Comment thread src/core/utils/matching/matchRequestUrl.test.ts
Comment thread src/core/utils/matching/matchRequestUrl.ts
@kettanaito kettanaito merged commit bf45da8 into feat/3.0 Apr 6, 2026
22 checks passed
@kettanaito kettanaito deleted the fix/use-msw-url branch April 6, 2026 12:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

BREAKING CHANGE Pull request introducing breaking changes.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Using the wildcard token to try to match random ports doesn't work if preceded by a colon

1 participant