diff --git a/.changeset/khaki-coins-travel.md b/.changeset/khaki-coins-travel.md new file mode 100644 index 0000000..b0730e5 --- /dev/null +++ b/.changeset/khaki-coins-travel.md @@ -0,0 +1,5 @@ +--- +"next-ws": patch +--- + +Fix incorrect priority on route matching diff --git a/src/server/helpers/match.ts b/src/server/helpers/match.ts index 0373327..b2b8e46 100644 --- a/src/server/helpers/match.ts +++ b/src/server/helpers/match.ts @@ -57,12 +57,35 @@ export function findMatchingRoute( ...nextServer.getAppPathRoutes(), }; - let matchedRoute = undefined; - for (const [routePath, [filePath]] of Object.entries(appPathRoutes)) { - if (!routePath || !filePath) continue; + const sortedRoutes = Object.entries(appPathRoutes) + .filter(([routePath, file]) => routePath && file?.length) + .sort(([a], [b]) => scoreRoute(b) - scoreRoute(a)); + + for (const [routePath, [filePath]] of sortedRoutes) { + if (!filePath) continue; const realPath = `${basePath}${routePath}`; const routeParams = getRouteParams(realPath, requestPathname); - if (routeParams) matchedRoute = { filename: filePath, params: routeParams }; + if (routeParams) { + return { filename: filePath, params: routeParams }; + } } - return matchedRoute; + return undefined; +} + +function scoreRoute(routePath: string) { + const parts = routePath.split('/').filter(Boolean); + + let score = 0; + // Root path + if (parts.length === 0) score = Infinity; + for (const part of parts) { + // Optional catch-all + if (part.startsWith('[[...')) score += -1; + // Catch-all + else if (part.startsWith('[...')) score += 0; + else if (part.startsWith('[')) score += 2; + else score += 3; + } + + return score + parts.length; }