Skip to content

route-pattern: PartPattern#10919

Closed
pcattori wants to merge 5 commits intopedro/route-patternfrom
pedro/experimental-part-pattern-parsing
Closed

route-pattern: PartPattern#10919
pcattori wants to merge 5 commits intopedro/route-patternfrom
pedro/experimental-part-pattern-parsing

Conversation

@pcattori
Copy link
Contributor

@pcattori pcattori commented Jan 5, 2026

Context

During the development of route-pattern, the design for the Route Pattern DSL changed many times. This wasn't unexpected, but it did mean that the matching APIs (ArrayMatcher, TrieMatcher, etc.) and parsing algorithms always had to "catch up" to the newest DSL changes. Over time, this led to some bolted-on bits and some gaps in the matching/parsing.

Additionally, the current ArrayMatcher and TrieMatcher aren't guaranteed to return the same "best" match. ArrayMatcher just bails as soon as it finds its first match and TrieMatcher does some ad-hoc scoring.

The goal moving forward is to spec out the parsing/matching (via unit tests + docs) and implement a simple, consistent ranking metric for ArrayMatcher, TrieMatcher, or any other matcher.

Here's my plan:

  • PartPattern.{parse,variants,toString} (this PR)
  • RoutePattern.{parse,join}
  • TrieMatcher.{add,matchAll} (w/o ranking)
  • Ranking + TrieMatcher.{match, matchAll}
  • ArrayMatcher.{add,match,matchAll}

PartPattern

As a first step towards this goal, this PR implements a new design for the parts of a Route Pattern that are allowed to use the pattern DSL. Today, that includes the protocol, hostname, and pathname, but in the future its likely that the protocol will be simplified to just accept the known network schemes (http, https, http(s), ws, wss, ws(s), ftp, ...).

Knowing that we want to eventually use PartPatterns within RoutePatterns to power a TrieMatcher, this new implementation aims for a simpler flat AST:

image

This AST representation has a couple benefits over the previous implementation:

Traversal is simpler and faster since its just a for-loop where you can decide to skip any optionals as you go. Specifically, variants (for construction trie branches) are trivial to implement.

Feature detection is simpler and faster. For example, does this part pattern have any params? Check ast.paramNames.length > 0? Any optionals? Check ast.optionals.size > 0. Etc.

Joining patterns is more efficient. Previously, RoutePattern.join reparsed the entire pathname on every invocation whereas with this AST, we can simple concatenate the two pathnames (adding a / text node between them as necessary) and quickly apply an offset to the second pattern's paramNames and optionals.

To be clear, the goal isn't necessary to be faster at parsing part patterns — that can come later with optimizations if needed — but to have a purpose-built structure for our DSL.

@pcattori pcattori force-pushed the pedro/experimental-part-pattern-parsing branch from ecd494f to d257cab Compare January 5, 2026 02:05
@pcattori pcattori marked this pull request as ready for review January 5, 2026 02:15
@pcattori pcattori changed the title route-pattern: experimental part pattern parsing route-pattern: part pattern parsing Jan 5, 2026
@pcattori pcattori mentioned this pull request Jan 5, 2026
14 tasks
@mjackson
Copy link
Member

mjackson commented Jan 6, 2026

Thanks for the work here, @pcattori. We are aligned on goals and I'm excited about this work.

I'd rather not merge anything to main until it's ready to ship. Even though this PR doesn't technically break anything, there isn't really anything in this PR we can ship right now either. I'd suggest we either:

  1. Keep iterating in this PR, pushing further commits as you flesh out your plan. The final commit could be to actually swap out lib with experimental and update all dependents. The PR might last a few weeks and could get long with comments, but that hasn't happened yet.

OR

  1. If you'd prefer multiple reviews over time as you do this work, feel free to setup your own feature branch (route-pattern-2 or pedro/route-pattern) and we just merge to that branch until it's ready for main. You can make as many PRs as you'd like to that branch and I'll be happy to give you reviews as we go.

It's totally up to you.

@pcattori
Copy link
Contributor Author

pcattori commented Jan 6, 2026

Ok cool let's do the feature branch for this then and not land into main just yet

@pcattori pcattori closed this Jan 6, 2026
@pcattori pcattori changed the title route-pattern: part pattern parsing route-pattern: PartPattern Jan 7, 2026
@pcattori pcattori reopened this Jan 7, 2026
@pcattori pcattori changed the base branch from main to pedro/route-pattern January 7, 2026 19:18
@pcattori pcattori force-pushed the pedro/experimental-part-pattern-parsing branch from d257cab to 8fa7520 Compare January 7, 2026 19:30
- track param names instead of param indices
- cache in `#variants`
- `get` for `.variants` instead of `.variants()`
@pcattori pcattori closed this Jan 8, 2026
@pcattori pcattori deleted the pedro/experimental-part-pattern-parsing branch January 8, 2026 17:25
@pcattori
Copy link
Contributor Author

pcattori commented Jan 8, 2026

superseded by #10935

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants