@@ -48,6 +48,7 @@ function buildRegexForDynamicRoute(routePath: string): { pattern: string; paramN
4848 const segments = routePath . split ( '/' ) . filter ( Boolean ) ;
4949 const regexSegments : string [ ] = [ ] ;
5050 const paramNames : string [ ] = [ ] ;
51+ let hasOptionalCatchall = false ;
5152
5253 for ( const segment of segments ) {
5354 if ( segment . startsWith ( ':' ) ) {
@@ -57,7 +58,8 @@ function buildRegexForDynamicRoute(routePath: string): { pattern: string; paramN
5758 // Optional catchall: matches zero or more segments
5859 const cleanParamName = paramName . slice ( 0 , - 2 ) ;
5960 paramNames . push ( cleanParamName ) ;
60- regexSegments . push ( '(.*)' ) ;
61+ // Handling this special case in pattern construction below
62+ hasOptionalCatchall = true ;
6163 } else if ( paramName . endsWith ( '*' ) ) {
6264 // Required catchall: matches one or more segments
6365 const cleanParamName = paramName . slice ( 0 , - 1 ) ;
@@ -74,7 +76,16 @@ function buildRegexForDynamicRoute(routePath: string): { pattern: string; paramN
7476 }
7577 }
7678
77- const pattern = `^/${ regexSegments . join ( '/' ) } $` ;
79+ let pattern : string ;
80+ if ( hasOptionalCatchall ) {
81+ // For optional catchall, make the trailing slash and segments optional
82+ // This allows matching both /catchall and /catchall/anything
83+ const staticParts = regexSegments . join ( '/' ) ;
84+ pattern = `^/${ staticParts } (?:/(.*))?$` ;
85+ } else {
86+ pattern = `^/${ regexSegments . join ( '/' ) } $` ;
87+ }
88+
7889 return { pattern, paramNames } ;
7990}
8091
0 commit comments