Repository navigation
feat: add regExpToRoute() to convert PCRE regex back to route pattern - #188
Conversation
Inverse of routeToRegExp(). Tree-shakeable (zero core-bundle impact); round-trips every non-fallback regexp fixture. Alternation-fallback forms are not reversible and throw. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
# Conflicts: # test/bench/bundle.test.ts
β¦table constraints Address two correctness bugs found in independent review: - ROUTE_SPECIAL omitted `? + | ^ $ [ ]`, so a literal metachar sharing a segment with a param was emitted raw and routeToRegExp reinterpreted it as an operator (e.g. `/a\+:id` round-tripped to a `+` quantifier). - Inline param constraints containing `/` (and unnamed `[^/]+`) produced routes rou3 cannot express; now throw instead of returning corrupt output. Adds regression tests and lets automd document the new export. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
π WalkthroughWalkthroughAdds a new ChangesregExpToRoute utility
Estimated code review effort: 4 (Complex) | ~50 minutes Poem
π₯ Pre-merge checks | β 5β Passed checks (5 passed)
β¨ Finishing Touchesπ Generate docstrings
π§ͺ Generate unit tests (beta)
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. Comment |
Codecov Reportβ Patch coverage is
π’ Thoughts on this report? Let us know! |
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
reverseSegment() literalized any token it didn't recognize, so several
common PCRE constructs silently produced a wrong route (or crashed with
an internal TypeError), contradicting the "throws a clear rou3: error"
guarantee. Make it a whitelist parser: only named/bare groups,
escaped-punctuation literals and plain literal chars are accepted.
Now rejected with a rou3: error:
- structural look-arounds ((?= (?! (?<= (?<!) and other (?...) constructs
- backreferences / metaclass escapes outside a constraint (\k<x>, \1, \d,
\w, \b)
- bare unescaped regex operators at segment level (. ^ $ * + ? | [ ] { })
- match-affecting flags (i/m/s); g/y/u/v/d stay ignored
Also extend support: bare (unnamed) capturing groups now map like their
(?<_N>...) equivalents ((\d+) -> (\d+), ([^/]*) -> *). Constraint bodies
stay opaque and round-trip verbatim.
Adds regression tests (proven to fail first) and documents the
reject-by-default contract in AGENTS.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
π§Ή Nitpick comments (1)
src/regexp-to-route.ts (1)
1-309: π Maintainability & Code Quality | π΅ Trivial | βοΈ Poor tradeoffModule exceeds the 200-line single-file limit.
This module is ~309 lines. Consider extracting the scanning helpers (
matchNamedGroup,readGroup,segmentEnd) and/or the token classifiers (paramToken,optionalParam,matchRepeat,constraint,escapeLiteral) into a sibling module, keeping the exportedregExpToRouteand its immediate segment loop here. Low priority given the parser's cohesion.As per coding guidelines: "Split logic across files and avoid long single-file modules (over 200 lines)."
π€ Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/regexp-to-route.ts` around lines 1 - 309, The module is over the single-file size limit, so split the parsing helpers out of regExpToRoute into a sibling module to reduce this file below the threshold. Move the scanning utilities like matchNamedGroup, readGroup, and segmentEnd, and optionally the token classifiers such as paramToken, optionalParam, matchRepeat, constraint, and escapeLiteral, while keeping regExpToRoute and its main loop here. Preserve the current behavior by importing the extracted helpers back into this module.Source: Coding guidelines
π€ Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@src/regexp-to-route.ts`:
- Around line 1-309: The module is over the single-file size limit, so split the
parsing helpers out of regExpToRoute into a sibling module to reduce this file
below the threshold. Move the scanning utilities like matchNamedGroup,
readGroup, and segmentEnd, and optionally the token classifiers such as
paramToken, optionalParam, matchRepeat, constraint, and escapeLiteral, while
keeping regExpToRoute and its main loop here. Preserve the current behavior by
importing the extracted helpers back into this module.
βΉοΈ Review info
βοΈ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 38245c9f-b103-407d-8186-6cf8cec74625
π Files selected for processing (6)
AGENTS.mdREADME.mdsrc/index.tssrc/regexp-to-route.tstest/bench/bundle.test.tstest/regexp-to-route.test.ts
Summary
Adds
regExpToRoute()β the inverse of the existingrouteToRegExp(). It parses an anchored, PCRE-compatibleRegExp(or itssourcestring) back into a rou3 route pattern.rou3; tree-shakeable β zero impact on the core bundle (only pulled in when imported).routeToRegExp()emits; hand-written regexes following the same conventions convert too. Constructs outside the dialect throw a clearrou3:error rather than returning corrupt output.Mapping
(?<param>[^/]+):param(?<id>\d+):id(\d+)(?<_0>[^/]*)*(?<_0>\d+)(\d+)\/?(?<_>.*)/\/?(?<name>.+)**/**:name(?:\/(?<id>[^/]+))?:id?(?:\/(?<rest>.*))?:rest*\/(?<rest>.+):rest+(?<id>\d+(?:\/\d+)*):id(\d+)+(?:s)?/(?:\/bar)?{s}?/{/bar}?Round-trip guarantee
routeToRegExp(regExpToRoute(regex)).source === regex.sourceholds for every non-fallback fixture intest/_regexp-cases.ts. The non-reversible alternation-fallback forms (PCRE2_DUPLICATE_NAME_ROUTES, e.g./media/*{.webp}?) throw.Review fixes included
An independent review surfaced two correctness bugs, both fixed here with regression tests:
? + | ^ $ [ ]) sharing a segment with a param were emitted raw and reinterpreted as operators β now re-escaped./(and unnamed[^/]+) are unrepresentable as routes β now throw instead of returning corrupt output.Tests
test/regexp-to-route.test.ts: round-trips all reversible fixtures + core constructs, literal-metachar round-trips, and the throw paths. Full suite green, types + lint clean.π€ Generated with Claude Code
Summary by CodeRabbit
New Features
Documentation
Tests