Skip to content

Commit 0226b81

Browse files
WIP
1 parent bd4547e commit 0226b81

File tree

7 files changed

+73
-19
lines changed

7 files changed

+73
-19
lines changed

src/app.ts

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ export class App<State> {
243243
fns = middlewares;
244244
}
245245

246-
const segment = getOrCreateSegment(this.#root, path);
246+
const segment = getOrCreateSegment(this.#root, path, false);
247247
segment.middlewares.push(...fns);
248248

249249
return this;
@@ -259,12 +259,11 @@ export class App<State> {
259259
return this;
260260
}
261261

262-
error(
262+
onError(
263263
path: string,
264264
routeOrMiddleware: Route<State> | MiddlewareFn<State>,
265265
): this {
266-
if (!path.endsWith("/")) path += "/";
267-
const segment = getOrCreateSegment(this.#root, path);
266+
const segment = getOrCreateSegment(this.#root, path, true);
268267
segment.errorRoute = typeof routeOrMiddleware === "function"
269268
? { handler: routeOrMiddleware }
270269
: routeOrMiddleware;
@@ -275,7 +274,7 @@ export class App<State> {
275274
}
276275

277276
appWrapper(component: RouteComponent<State>) {
278-
const segment = getOrCreateSegment<State>(this.#root, "");
277+
const segment = getOrCreateSegment<State>(this.#root, "", false);
279278
segment.app = component;
280279
}
281280

@@ -284,15 +283,14 @@ export class App<State> {
284283
component: RouteComponent<State>,
285284
config?: LayoutConfig,
286285
): this {
287-
if (!path.endsWith("/")) path += "/";
288-
const segment = getOrCreateSegment<State>(this.#root, path);
286+
const segment = getOrCreateSegment<State>(this.#root, path, true);
289287
segment.layout = { component, config: config ?? null };
290288

291289
return this;
292290
}
293291

294292
route(path: string, route: Route<State>): this {
295-
const segment = getOrCreateSegment<State>(this.#root, path);
293+
const segment = getOrCreateSegment<State>(this.#root, path, false);
296294
const middlewares = segmentToMiddlewares(segment);
297295

298296
ensureHandler(route);
@@ -347,7 +345,7 @@ export class App<State> {
347345
fns: MiddlewareFn<State>[],
348346
unshift = false,
349347
) {
350-
const segment = getOrCreateSegment<State>(this.#root, path);
348+
const segment = getOrCreateSegment<State>(this.#root, path, false);
351349
const result = segmentToMiddlewares(segment);
352350

353351
result.push(...fns);
@@ -367,7 +365,7 @@ export class App<State> {
367365

368366
mountApp(path: string, app: App<State>): this {
369367
const segmentPath = mergePath(path, `/__${INTERNAL_ID++}/`);
370-
const segment = getOrCreateSegment(this.#root, segmentPath);
368+
const segment = getOrCreateSegment(this.#root, segmentPath, true);
371369
const fns = segmentToMiddlewares(segment);
372370

373371
const routes = app.#routeDefs;

src/app_test.tsx

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,3 +569,42 @@ Deno.test("App - overwrite default 404 handler", async () => {
569569
res = await server.get("/thrower");
570570
expect(await res.text()).toEqual("bar");
571571
});
572+
573+
Deno.test("App - uses error route", async () => {
574+
const app = new App()
575+
.onError("*", () => new Response("error route", { status: 200 }))
576+
.get("/thrower", () => {
577+
throw new HttpError(404);
578+
});
579+
580+
const server = new FakeServer(app.handler());
581+
582+
let res = await server.get("/invalid");
583+
expect(await res.text()).toEqual("error route");
584+
585+
res = await server.get("/thrower");
586+
expect(await res.text()).toEqual("error route");
587+
});
588+
589+
Deno.test("App - uses notFound route on 404", async () => {
590+
const app = new App()
591+
.notFound(() => new Response("not found route", { status: 404 }))
592+
.onError("*", () => new Response("error route", { status: 500 }))
593+
.get("/thrower", () => {
594+
throw new HttpError(404);
595+
})
596+
.get("/thrower_2", () => {
597+
throw new HttpError(500);
598+
});
599+
600+
const server = new FakeServer(app.handler());
601+
602+
let res = await server.get("/invalid");
603+
expect(await res.text()).toEqual("not found route");
604+
605+
res = await server.get("/thrower");
606+
expect(await res.text()).toEqual("not found route");
607+
608+
res = await server.get("/thrower_2");
609+
expect(await res.text()).toEqual("error route");
610+
});

src/plugins/fs_routes/mod.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ export async function fsRoutes<State>(
212212
keepGroups: true,
213213
});
214214
errorPaths.add(pattern);
215-
app.error(pattern, {
215+
app.onError(pattern, {
216216
config: routeMod.config ?? undefined,
217217
component: routeMod.component ?? undefined,
218218
// deno-lint-ignore no-explicit-any
@@ -233,7 +233,7 @@ export async function fsRoutes<State>(
233233
});
234234
if (errorPaths.has(pattern)) continue;
235235

236-
app.error(pattern, {
236+
app.onError(pattern, {
237237
config: routeMod.config ?? undefined,
238238
component: routeMod.component ?? undefined,
239239
// deno-lint-ignore no-explicit-any

src/router.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,10 +281,14 @@ export function pathToPattern(
281281
return route;
282282
}
283283

284-
export function patternToSegments(path: string, root: string): string[] {
284+
export function patternToSegments(
285+
path: string,
286+
root: string,
287+
includeLast: boolean = false,
288+
): string[] {
285289
const out: string[] = [root];
286290

287-
if (path === "/") return out;
291+
if (path === "/" || path === "*" || path === "/*") return out;
288292

289293
let start = -1;
290294
for (let i = 0; i < path.length; i++) {
@@ -299,6 +303,10 @@ export function patternToSegments(path: string, root: string): string[] {
299303
}
300304
}
301305

306+
if (includeLast && start < path.length - 1) {
307+
out.push(path.slice(start + 1));
308+
}
309+
302310
return out;
303311
}
304312

src/router_test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ Deno.test("patternToSegments", () => {
150150
expect(patternToSegments("/:foo/:bar", "")).toEqual(["", ":foo"]);
151151
expect(patternToSegments("/:foo-:bar/foo", "")).toEqual(["", ":foo-:bar"]);
152152
expect(patternToSegments("/foo/", "")).toEqual(["", "foo"]);
153+
154+
expect(patternToSegments("/foo/bar", "", true)).toEqual(["", "foo", "bar"]);
153155
});
154156

155157
Deno.test("mergePath", () => {

src/segments.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,11 @@ export function newSegment<State>(
5252
export function getOrCreateSegment<State>(
5353
root: Segment<State>,
5454
path: string,
55+
includeLast: boolean,
5556
): Segment<State> {
5657
let current = root;
5758

58-
const segments = patternToSegments(path, root.pattern);
59+
const segments = patternToSegments(path, root.pattern, includeLast);
5960
for (let i = 0; i < segments.length; i++) {
6061
const seg = segments[i];
6162
if (seg === root.pattern) {

src/segments_test.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,32 @@ import { getOrCreateSegment, newSegment } from "./segments.ts";
33

44
Deno.test("findOrCreateSegment - root", () => {
55
const root = newSegment("", null);
6-
const found = getOrCreateSegment(root, "");
6+
const found = getOrCreateSegment(root, "", false);
77
expect(found).toEqual(root);
88
});
99

1010
Deno.test("findOrCreateSegment - /foo/bar", () => {
1111
const root = newSegment("", null);
12-
const found = getOrCreateSegment(root, "/foo/bar");
12+
const found = getOrCreateSegment(root, "/foo/bar", false);
1313
expect(found).toEqual(root.children.get("foo"));
1414
});
1515

1616
Deno.test("findOrCreateSegment - /:foo/bar/:baz", () => {
1717
const root = newSegment("", null);
18-
const found = getOrCreateSegment(root, "/:foo/bar/:baz");
18+
const found = getOrCreateSegment(root, "/:foo/bar/:baz", false);
1919
expect(found).toEqual(
2020
root.children.get(":foo")?.children.get("bar"),
2121
);
2222
});
2323

2424
Deno.test("findOrCreateSegment - /foo/bar/", () => {
2525
const root = newSegment("", null);
26-
const found = getOrCreateSegment(root, "/foo/bar/");
26+
const found = getOrCreateSegment(root, "/foo/bar/", false);
27+
expect(found).toEqual(root.children.get("foo")?.children.get("bar"));
28+
});
29+
30+
Deno.test("findOrCreateSegment - /foo/bar with last", () => {
31+
const root = newSegment("", null);
32+
const found = getOrCreateSegment(root, "/foo/bar", true);
2733
expect(found).toEqual(root.children.get("foo")?.children.get("bar"));
2834
});

0 commit comments

Comments
 (0)