Skip to content

Conversation

@hakanshehu
Copy link

@hakanshehu hakanshehu commented Nov 4, 2025

This PR proposes a fix for issue #5755 , where custom params passed to declarative route masks are ignored. When the masked params differ from the original URL params, the masked URL can display undefined instead of the expected values.

I don't have full context on all internal router behaviors, so please treat this as a proposal. If there's a better approach, I’m happy to adjust the implementation.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 4, 2025

Walkthrough

The router's mask application logic now extracts and applies custom parameters from mask definitions, enabling dynamic per-mask parameter composition instead of ignoring maskParams and falling back to original URL parameters.

Changes

Cohort / File(s) Summary
Route masking parameter handling
packages/router-core/src/router.ts
Enhanced mask application to extract maskParams from mask definitions and compute nextParams based on maskParams type (false/null → empty, true → use existing, otherwise → merge with current). Applies computed parameters to maskedDest.params instead of original params.

Sequence Diagram(s)

sequenceDiagram
    participant Router as Router
    participant Mask as Mask Definition
    participant Dest as Destination
    
    Router->>Mask: Check for matching mask
    activate Mask
    Mask-->>Router: Mask found with custom params
    deactivate Mask
    
    rect rgb(200, 220, 255)
    Note over Router,Dest: NEW: Extract & compute mask params
    Router->>Router: Extract maskParams from mask
    alt maskParams === false or null
        Router->>Router: nextParams = {}
    else maskParams === true or undefined
        Router->>Router: nextParams = current params
    else maskParams is object
        Router->>Router: nextParams = merge(maskParams, current)
    end
    end
    
    Router->>Dest: Apply nextParams to maskedDest
    Dest-->>Router: Masked destination with custom params
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

  • Verify maskParams extraction logic handles all cases (false, null, true, undefined, object)
  • Confirm parameter merging via functionalUpdate produces expected results
  • Check that existing maskProps and route properties remain unaffected

Poem

🐰 A mask found its missing voice today,
With params now flowing the proper way!
No more undefined in the URL's sight,
The router hops forward—finally right!

Pre-merge checks and finishing touches

✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: using custom params from declarative masks when building URLs, which directly addresses the linked issue.
Linked Issues check ✅ Passed The PR directly implements the fix for issue #5755 by extracting and applying maskParams during route masking, enabling custom parameter composition as required.
Out of Scope Changes check ✅ Passed All changes in router.ts are focused on the route masking parameter logic required by the linked issue; no unrelated modifications detected.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Contributor

@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: 1

🧹 Nitpick comments (2)
packages/router-core/src/router.ts (2)

1800-1801: Clarify the comment to cover all maskParams cases.

The comment mentions "params function" but the logic handles multiple scenarios (false, null, true, undefined, function, object). Consider updating it to describe all cases for better maintainability.

-          // If mask has a params function, call it with the matched params as context
-          // Otherwise, use the matched params or the provided params value
+          // Compute params for the masked destination:
+          // - false/null: no params
+          // - true/undefined: use matched params
+          // - function/object: merge matched params with the result of functionalUpdate

1807-1807: Consider using spread operator to avoid mutation.

Object.assign(params, ...) mutates the params object. While this may not cause issues in the current scope, using the spread operator would be safer and align better with immutability principles.

-                : Object.assign(params, functionalUpdate(maskParams, params))
+                : { ...params, ...functionalUpdate(maskParams, params) }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6baffeb and 20e3b3b.

📒 Files selected for processing (1)
  • packages/router-core/src/router.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript in strict mode with extensive type safety across the codebase

Files:

  • packages/router-core/src/router.ts
packages/router-core/**

📄 CodeRabbit inference engine (AGENTS.md)

Keep framework-agnostic core router logic in packages/router-core/

Files:

  • packages/router-core/src/router.ts
🧬 Code graph analysis (1)
packages/router-core/src/router.ts (1)
packages/router-core/src/utils.ts (1)
  • functionalUpdate (203-212)

Comment on lines +1798 to +1812
const { from: _from, params: maskParams, ...maskProps } = foundMask

// If mask has a params function, call it with the matched params as context
// Otherwise, use the matched params or the provided params value
const nextParams =
maskParams === false || maskParams === null
? {}
: (maskParams ?? true) === true
? params
: Object.assign(params, functionalUpdate(maskParams, params))

maskedDest = {
from: opts.from,
...maskProps,
params,
params: nextParams,
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Logic correctly applies custom mask params to resolve issue #5755.

The implementation properly extracts and applies maskParams from the mask definition, enabling dynamic parameter composition per mask. This fixes the reported issue where mask params were being ignored.

Please verify that all maskParams scenarios are covered in tests:

  • maskParams: false or null → empty params
  • maskParams: true or undefined → matched params preserved
  • maskParams: (params) => {...} → function transformation applied
  • maskParams: {...} → object merged with matched params

Run the following script to check for existing test coverage of mask params:


🏁 Script executed:

#!/bin/bash
# Search for tests related to route mask params functionality
rg -n -C3 --type=ts --type=tsx 'maskParams|mask.*params|routeMask.*param' -g '*test*' -g '*spec*'

Length of output: 27


🏁 Script executed:

#!/bin/bash
# Search for tests related to route mask params functionality using corrected syntax
rg -n -C3 --type=ts 'maskParams|mask.*params|routeMask' -g '*test*' -g '*spec*'

Length of output: 6422


🏁 Script executed:

#!/bin/bash
# Find test files related to router or mask functionality
fd -e ts -e js '(test|spec)' -path '*router*' -o -path '*mask*'

Length of output: 168


🏁 Script executed:

#!/bin/bash
# Search for maskParams usage anywhere in the codebase to understand scope
rg -n 'maskParams' --type=ts

Length of output: 417


🏁 Script executed:

#!/bin/bash
# Search for createRouteMask definition to understand maskParams support
rg -n -A20 'function createRouteMask|const createRouteMask' --type=ts

Length of output: 2871


🏁 Script executed:

#!/bin/bash
# Search for mask type definition
rg -n 'type.*[Mm]ask|interface.*[Mm]ask' --type=ts -A5 | head -100

Length of output: 2021


🏁 Script executed:

#!/bin/bash
# Look for any tests passing functions as mask params
rg -n 'params.*=>|mask.*function' --type=ts -g '*test*' -g '*spec*' -C2

Length of output: 173798


🏁 Script executed:

#!/bin/bash
# Check RouteMask and ToMaskOptions type definitions for maskParams support
rg -n -A10 'type RouteMask<|type ToMaskOptions<|interface ToMaskOptions' --type=ts packages/router-core/src/

Length of output: 1377


🏁 Script executed:

#!/bin/bash
# Search for functionalUpdate utility used in the maskParams logic
rg -n -B5 -A5 'functionalUpdate' packages/router-core/src/router.ts | head -50

Length of output: 1549


Add tests for maskParams feature before merging.

The implementation correctly handles all four maskParams scenarios (false/null, true/undefined, function transformation, and object merge), following established patterns in the codebase. However, there is no test coverage for this new feature.

Add tests covering:

  • maskParams: false or null → empty params
  • maskParams: true or undefined → matched params preserved
  • maskParams: (params) => {...} → function transformation applied
  • maskParams: {...} → object merged with matched params
🤖 Prompt for AI Agents
In packages/router-core/src/router.ts around lines 1798 to 1812, the new
maskParams handling logic lacks test coverage; add unit tests that exercise all
four branches: (1) maskParams false and null should produce an empty params
object, (2) maskParams true and undefined should preserve the matched params,
(3) maskParams as a function should receive the matched params and the returned
value should be used, and (4) maskParams as an object should be merged with
matched params via the same functionalUpdate semantics. Create tests in the
router-core test suite (e.g., packages/router-core/__tests__ or
tests/router.spec.ts), mock or construct route matches and call the code paths
that produce maskedDest, asserting the resulting maskedDest.params for each
scenario; include edge cases for falsy/undefined returns from the function and
ensure merge semantics match Object.assign(functionalUpdate(...), params).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant