npm / rou3
rou3
What changed in rou3 0.10 to 0.12, from its official release notes, upgrade guides and advisories. Sources checked 2026-10-20.
34 breaking1 security2 deprecations1 new APIs and options1 performance1 behavior and defaults7 fixes and other
See which of these apply to your code, ranked, in your agent:
npx @unstale/cli initrou3 0.1223 changes
Breaking changes 16
Literal pattern text is percent-encoded once when a route is added; lookup paths are neither decoded nor encoded.
Dot segments, including
%2eforms, are resolved when routes are added and removed; lookup paths are unchanged unlessnormalize: true.The wildcard is now a greedy catch-all that spans segments, so trailing
*rules apply at every depth.A written
(.*)is now a greedy catch-all like*;:name(.*)is keyed by the name, and both match across segments.A bare
**is now an unnamed capture keyed by its numbered position; a zero-segment match omits the key, andparams._is deprecated.An optional parameter following a capture in the same segment is matched in place, while the preceding capture is greedy.
A regex group after a
{…}group ending in a parameter is now an unnamed capture next to the parameter, rather than that parameter's constraint.A pattern starting with a
{/…}group is now absolute and no longer receives an extra/in front./a/*and/a/**now compare as equal; named catch-all comparisons also have updated equality and subset results.Named catch-alls
:name+,:name*and**:nameno longer accept empty segments; affected paths fall through to a less specific route or no match.It reads an unnamed catch-all back as
**while still accepting old_groups, and throws for literals or patterns that routes cannot represent.A route can contain only one catch-all among
*,**,:x+,:x*,(.*)or:x(.*); routes with more than one throw.Raw tabs, LF and CR in patterns now throw;
--and&&in a constraint character class also throw.A
*route node is keyed as/**, and parameter segments use numbered keys such as:_0and:_1.Generated regexes use percent-encoded literal text, name
**groups_0,_1, …, and use URLPattern-style named catch-all expressions.On engines without duplicate named groups, patterns requiring an uninlinable group around a trailing
*now throw.
Security 1
Generated regexes for parameters sharing a segment no longer backtrack polynomially, closing the stated ReDoS class.
Deprecations 1
The
_parameter key for a bare**capture is deprecated; readparams["0"] ?? ""instead or name the capture.
Performance 1
Segments with several parameters now match in linear time in
findRouteand compiled matchers.
Behavior and default changes 1
Constrained and literal in-segment parameters now rank above plain ones on the same node, regardless of registration order.
Fixes and other changes 3
Each
addRoutecall is listed once; duplicate variants are replaced by the variantfindRoutepicks.Trailing whole-segment catch-alls are typed
string | undefined;**<text>is one key, and the**key has a deprecated_?: stringalternative.With normalization enabled, a trailing
.or..keeps its trailing slash, matching WHATWG URL behavior.
rou3 0.1117 changes
Breaking changes 12
Generated route data now passes through JSON.stringify, producing valid code for JSON-serializable data and throwing a rou3 error for functions, symbols, or bigints.
Method-agnostic routes are always considered alongside method routes; the more specific route wins, with method routes winning ties. findAllRoutes and compiled matchAll return both.
The package now declares Node.js >=20.19.0 as its engine requirement.
Hand-written regexes must be anchored, and regexes with u or v flags are rejected because they cannot be represented as whole-path routes or equivalent constraints.
Required params no longer match empty segments; use *, **, :name*, or a constraint that allows empty when empty values are needed.
Falsy route data such as 0, false, and an empty string is returned as-is instead of null; missing data remains null.
Regex constraints now throw for anchors, look-arounds, backreferences, and capturing groups because constraint and whole-path matching otherwise disagree.
Outside regex constraints, any \x means a literal x; \ is a literal backslash, while \/ and a trailing \ throw.
When a segment has several params, the first now matches as little as possible, which can change how values are split.
A ? on a param that does not start its segment makes only that param optional; use a group to make the whole segment optional.
Param names now follow [A-Za-z_]\w*; -, {, and } end a name. InferRouteParams reads names the same way, so runtime params and inferred types may change.
addRoute and routeToRegExp now throw rou3 errors for syntax that previously had surprising or unclear meanings, including invalid modifiers, names, duplicate params, and malformed groups.
Deprecations 1
RouterCompilerOptions is deprecated in favor of CompileRouterToStringOptions and CompileRouterOptions.
New APIs and options 1
The compiler now accepts an options object with functionName, matchAll, and serialize; the old positional form still works but is deprecated.
Fixes and other changes 3
Calling compileRouter with matchAll: true is now typed as returning an array.
Each call returns fresh match objects, so mutating one result no longer affects later lookups.
Each call returns a fresh { data, params } object, including static matches and params: false results, so mutating one result no longer affects later lookups.
rou3 0.107 changes
Breaking changes 6
Wildcards can have following segments, which are matched from the end of the path; only one
**is allowed, and routes with following segments affect match ranking.Lookup ignores at most one trailing slash; repeated trailing slashes no longer match, and a route with an empty parameter can match
/users//.With
normalize: true, path normalization drops..segments that would go above the root.Removing a route removes only the given pattern, rather than every route on the same node and method.
Generated regexes now match exactly the paths
findRoutematches, retain segments after**, and may have different text; some routes no longer use look-behind.Duplicate param names now produce a
rou3:error instead of a rawSyntaxError; optional groups followed by more route content no longer emit duplicate group names on Node 22.
Fixes and other changes 1
Optional params and a trailing bare
*can bestring | undefined; inferred param names now omit constraints and modifiers.