From 5c60e8bb25655c7c11d93060e2991063f0d4451b Mon Sep 17 00:00:00 2001 From: Brendan Allan Date: Sat, 18 May 2024 17:35:19 +0800 Subject: [PATCH 1/6] reintroduce flat routing --- packages/start/src/router/routes.ts | 45 +++++++++++++++++++---------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/packages/start/src/router/routes.ts b/packages/start/src/router/routes.ts index 0a907dcc9..e0f93bfdc 100644 --- a/packages/start/src/router/routes.ts +++ b/packages/start/src/router/routes.ts @@ -33,7 +33,16 @@ function defineRoutes(fileRoutes: Route[]) { }); if (!parentRoute) { - routes.push({ ...route, id, path: id.replace(/\/\([^)/]+\)/g, "").replace(/\([^)/]+\)/g, "") }); + routes.push({ + ...route, + id, + path: id + // strip out escape group for escaping nested routes - e.g. foo(bar) -> foo + .replace(/\/\([^)/]+\)/g, "") + .replace(/\([^)/]+\)/g, "") + // replace . with / for flat routes - e.g. foo.bar -> foo/bar + .replace(/\./g, "/") + }); return routes; } processRoute( @@ -70,18 +79,24 @@ function containsHTTP(route: Route) { } const router = createRouter({ - routes: (fileRoutes as unknown as Route[]).reduce((memo, route) => { - if (!containsHTTP(route)) return memo; - let path = route.path.replace(/\/\([^)/]+\)/g, "").replace(/\([^)/]+\)/g, "").replace(/\*([^/]*)/g, (_, m) => `**:${m}`); - if (/:[^/]*\?/g.test(path)) { - throw new Error(`Optional parameters are not supported in API routes: ${path}`); - } - if (memo[path]) { - throw new Error( - `Duplicate API routes for "${path}" found at "${memo[path]!.route.path}" and "${route.path}"` - ); - } - memo[path] = { route }; - return memo; - }, {} as Record) + routes: (fileRoutes as unknown as Route[]).reduce( + (memo, route) => { + if (!containsHTTP(route)) return memo; + let path = route.path + .replace(/\/\([^)/]+\)/g, "") + .replace(/\([^)/]+\)/g, "") + .replace(/\*([^/]*)/g, (_, m) => `**:${m}`); + if (/:[^/]*\?/g.test(path)) { + throw new Error(`Optional parameters are not supported in API routes: ${path}`); + } + if (memo[path]) { + throw new Error( + `Duplicate API routes for "${path}" found at "${memo[path]!.route.path}" and "${route.path}"` + ); + } + memo[path] = { route }; + return memo; + }, + {} as Record + ) }); From 51abb95c6f316ce1ed9503b2d29f52d0d4816a84 Mon Sep 17 00:00:00 2001 From: Brendan Allan Date: Sat, 18 May 2024 17:40:51 +0800 Subject: [PATCH 2/6] Create fifty-ways-think.md --- .changeset/fifty-ways-think.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/fifty-ways-think.md diff --git a/.changeset/fifty-ways-think.md b/.changeset/fifty-ways-think.md new file mode 100644 index 000000000..ddd84e0c3 --- /dev/null +++ b/.changeset/fifty-ways-think.md @@ -0,0 +1,5 @@ +--- +"@solidjs/start": patch +--- + +Reintroduce flat routing From 32b24c66eb13120e791e06ec34c8d8f15fac681a Mon Sep 17 00:00:00 2001 From: Brendan Allan Date: Mon, 20 May 2024 14:33:20 +0800 Subject: [PATCH 3/6] don't replace ... in flat routing --- packages/start/src/router/routes.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/start/src/router/routes.ts b/packages/start/src/router/routes.ts index e0f93bfdc..94830e8ab 100644 --- a/packages/start/src/router/routes.ts +++ b/packages/start/src/router/routes.ts @@ -41,7 +41,8 @@ function defineRoutes(fileRoutes: Route[]) { .replace(/\/\([^)/]+\)/g, "") .replace(/\([^)/]+\)/g, "") // replace . with / for flat routes - e.g. foo.bar -> foo/bar - .replace(/\./g, "/") + // lookahead for + .replace(/(? Date: Mon, 20 May 2024 14:35:07 +0800 Subject: [PATCH 4/6] splat handling comment --- packages/start/src/router/routes.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/start/src/router/routes.ts b/packages/start/src/router/routes.ts index 94830e8ab..f37596e25 100644 --- a/packages/start/src/router/routes.ts +++ b/packages/start/src/router/routes.ts @@ -41,7 +41,7 @@ function defineRoutes(fileRoutes: Route[]) { .replace(/\/\([^)/]+\)/g, "") .replace(/\([^)/]+\)/g, "") // replace . with / for flat routes - e.g. foo.bar -> foo/bar - // lookahead for + // ensures that ... of splat routes is not replaced .replace(/(? Date: Mon, 20 May 2024 14:38:07 +0800 Subject: [PATCH 5/6] don't use lookbehind regex --- packages/start/src/router/routes.ts | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/start/src/router/routes.ts b/packages/start/src/router/routes.ts index f37596e25..be7cf9bfe 100644 --- a/packages/start/src/router/routes.ts +++ b/packages/start/src/router/routes.ts @@ -33,17 +33,17 @@ function defineRoutes(fileRoutes: Route[]) { }); if (!parentRoute) { - routes.push({ - ...route, - id, - path: id - // strip out escape group for escaping nested routes - e.g. foo(bar) -> foo - .replace(/\/\([^)/]+\)/g, "") - .replace(/\([^)/]+\)/g, "") - // replace . with / for flat routes - e.g. foo.bar -> foo/bar - // ensures that ... of splat routes is not replaced - .replace(/(? foo + .replace(/\/\([^)/]+\)/g, "") + .replace(/\([^)/]+\)/g, "") + // replace . with / for flat routes - e.g. foo.bar -> foo/bar + .replace(/\./g, "/") + // converts any splat route ... that got replaced back from /// + // this could be avoided with a lookbehind regex but safar has only supported them since mid 2023 + .replace("///", "..."); + + routes.push({ ...route, id, path }); return routes; } processRoute( From 59094aafb20d31686af9d001fc92d240edbecf37 Mon Sep 17 00:00:00 2001 From: Brendan Allan Date: Mon, 20 May 2024 14:59:51 +0800 Subject: [PATCH 6/6] move flat routing replacement to fs router --- packages/start/config/fs-router.js | 55 +++++++++++++---------------- packages/start/src/router/routes.ts | 7 +--- 2 files changed, 26 insertions(+), 36 deletions(-) diff --git a/packages/start/config/fs-router.js b/packages/start/config/fs-router.js index efefd87a4..c6e48b76e 100644 --- a/packages/start/config/fs-router.js +++ b/packages/start/config/fs-router.js @@ -1,22 +1,31 @@ import { analyzeModule, BaseFileSystemRouter, cleanPath } from "vinxi/fs-router"; +function toPathBase(src, config) { + const routePath = cleanPath(src, config) + // remove the initial slash + .slice(1) + .replace(/index$/, "") + // replace . with / for flat routes - e.g. foo.bar -> foo/bar + .replace(/\./g, "/") + // converts any splat route ... that got replaced back from /// + // this could be avoided with a lookbehind regex but safar has only supported them since mid 2023 + .replace(/\/\/\//g, "...") + .replace(/\[([^\/]+)\]/g, (_, m) => { + if (m.length > 3 && m.startsWith("...")) { + return `*${m.slice(3)}`; + } + if (m.length > 2 && m.startsWith("[") && m.endsWith("]")) { + return `:${m.slice(1, -1)}?`; + } + return `:${m}`; + }); + + return routePath?.length > 0 ? `/${routePath}` : "/"; +} + export class SolidStartClientFileRouter extends BaseFileSystemRouter { toPath(src) { - const routePath = cleanPath(src, this.config) - // remove the initial slash - .slice(1) - .replace(/index$/, "") - .replace(/\[([^\/]+)\]/g, (_, m) => { - if (m.length > 3 && m.startsWith("...")) { - return `*${m.slice(3)}`; - } - if (m.length > 2 && m.startsWith("[") && m.endsWith("]")) { - return `:${m.slice(1, -1)}?`; - } - return `:${m}`; - }); - - return routePath?.length > 0 ? `/${routePath}` : "/"; + return toPathBase(src, this.config); } toRoute(src) { @@ -72,21 +81,7 @@ function createHTTPHandlers(src, exports) { export class SolidStartServerFileRouter extends BaseFileSystemRouter { toPath(src) { - const routePath = cleanPath(src, this.config) - // remove the initial slash - .slice(1) - .replace(/index$/, "") - .replace(/\[([^\/]+)\]/g, (_, m) => { - if (m.length > 3 && m.startsWith("...")) { - return `*${m.slice(3)}`; - } - if (m.length > 2 && m.startsWith("[") && m.endsWith("]")) { - return `:${m.slice(1, -1)}?`; - } - return `:${m}`; - }); - - return routePath?.length > 0 ? `/${routePath}` : "/"; + return toPathBase(src, this.config); } toRoute(src) { diff --git a/packages/start/src/router/routes.ts b/packages/start/src/router/routes.ts index be7cf9bfe..b010a5a7a 100644 --- a/packages/start/src/router/routes.ts +++ b/packages/start/src/router/routes.ts @@ -36,12 +36,7 @@ function defineRoutes(fileRoutes: Route[]) { const path = id // strip out escape group for escaping nested routes - e.g. foo(bar) -> foo .replace(/\/\([^)/]+\)/g, "") - .replace(/\([^)/]+\)/g, "") - // replace . with / for flat routes - e.g. foo.bar -> foo/bar - .replace(/\./g, "/") - // converts any splat route ... that got replaced back from /// - // this could be avoided with a lookbehind regex but safar has only supported them since mid 2023 - .replace("///", "..."); + .replace(/\([^)/]+\)/g, ""); routes.push({ ...route, id, path }); return routes;