@rhythmjs/router 0.0.13 → 0.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/fetch.d.ts +1 -1
- package/dist/rhythm-router.js +28 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ The HTTP layer of Rhythm, the Bun-native backend framework: web-standard (`Reque
|
|
|
4
4
|
|
|
5
5
|
Route patterns follow rou3's conventions: `:name` params (`:name?` optional, `:id(\\d+)` regex-constrained), `*` for one unnamed segment (captured as `params["0"]`), and `**` for the rest of the path (`params._`, or `params.name` with `**:name`). Param values are the raw path segments, undecoded.
|
|
6
6
|
|
|
7
|
-
`RhythmRouter` is not an app and does not extend `Rhythm`; it is a controller that compiles routes and middleware down to a single middleware (`.middleware()`). It shares the core middleware contract (`compose`, `Middleware`, `derive`; `next()` takes no arguments, extend the context with `derive()`), but has no `
|
|
7
|
+
`RhythmRouter` is not an app and does not extend `Rhythm`; it is a controller that compiles routes and middleware down to a single middleware (`.middleware()`). It shares the core middleware contract (`compose`, `Middleware`, `derive`; `next()` takes no arguments, extend the context with `derive()`), but has no a startup `context` or `register()`, and it can't be served on its own: a `Rhythm` app is always the host that owns the lifecycle and the adapters.
|
|
8
8
|
|
|
9
9
|
## Example
|
|
10
10
|
|
|
@@ -31,7 +31,7 @@ A fuller runnable version, including nested prefixes and a fallback route, is at
|
|
|
31
31
|
- **`ctx.params`**: captured `:name` path segments, added once a route matches.
|
|
32
32
|
- **Nesting is `.use(child.middleware())`**: a router mounts into another router (or into the app) as a compiled middleware. The mount is opaque, so the parent's prefix is **not** applied to the child's routes: the child carries its own absolute prefix (`new RhythmRouter({ prefix: "/api/users" })`). On a miss the child falls through to `next()`, so the parent's later middleware and routes still run, and the child keeps working standalone.
|
|
33
33
|
- **Registration order is execution order**: a `.use()` middleware wraps only the routes registered after it, and runs only when one of them matches the request's method and path (so a guard in a `/projects` router never answers `/docs`); a mounted router (`.use(child.middleware())`) always runs; routes registered before it are untouched, and a matched route that doesn't call `next()` returns without reaching anything registered later. Consecutive routes share one rou3 lookup; an unmatched request falls through, entry by entry, to the outer `next()`.
|
|
34
|
-
- **A router is a controller, not a module**: it has no `
|
|
34
|
+
- **A router is a controller, not a module**: it has no a startup `context` or `register()`, and it cannot be `register()`ed into a `Rhythm` app either; `register()` composes `Rhythm` modules only. A router mounts into an app exactly one way: koa-style, via `.use(router.middleware())`.
|
|
35
35
|
|
|
36
36
|
## API
|
|
37
37
|
|
package/dist/fetch.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { Rhythm } from "@rhythmjs/rhythm";
|
|
2
2
|
import { type RhythmHttpContext } from "./context";
|
|
3
|
-
export declare function toFetchHandler<TContext extends RhythmHttpContext
|
|
3
|
+
export declare function toFetchHandler<TContext extends RhythmHttpContext>(app: Rhythm<RhythmHttpContext, any, TContext>): (request: Request) => Promise<Response>;
|
|
4
4
|
export declare function errorToResponse(error: unknown): Response;
|
package/dist/rhythm-router.js
CHANGED
|
@@ -6,10 +6,26 @@ import { addRoute, createRouter, findRoute } from "rou3";
|
|
|
6
6
|
function joinPath(prefix, path) {
|
|
7
7
|
if (!prefix)
|
|
8
8
|
return path;
|
|
9
|
+
if (path === "/" || path === "")
|
|
10
|
+
return prefix;
|
|
9
11
|
const trimmedPrefix = prefix.endsWith("/") ? prefix.slice(0, -1) : prefix;
|
|
10
12
|
const normalizedPath = path.startsWith("/") ? path : `/${path}`;
|
|
11
13
|
return `${trimmedPrefix}${normalizedPath}`;
|
|
12
14
|
}
|
|
15
|
+
function mountedRoutes(router, tree, seen = new Set) {
|
|
16
|
+
if (seen.has(router))
|
|
17
|
+
return;
|
|
18
|
+
seen.add(router);
|
|
19
|
+
for (const entry of router.entries) {
|
|
20
|
+
if (entry.kind === "route")
|
|
21
|
+
addRoute(tree, entry.method, entry.path, true);
|
|
22
|
+
else {
|
|
23
|
+
const child = sourceOf(entry.fn);
|
|
24
|
+
if (child instanceof RhythmRouter)
|
|
25
|
+
mountedRoutes(child, tree, seen);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
13
29
|
|
|
14
30
|
class RhythmRouter {
|
|
15
31
|
#options;
|
|
@@ -74,8 +90,18 @@ class RhythmRouter {
|
|
|
74
90
|
const entry = this.#entries[i];
|
|
75
91
|
if (entry.kind === "middleware") {
|
|
76
92
|
const { fn } = entry;
|
|
77
|
-
const
|
|
78
|
-
|
|
93
|
+
const source = sourceOf(fn);
|
|
94
|
+
if (source) {
|
|
95
|
+
if (source instanceof RhythmRouter) {
|
|
96
|
+
const tree = createRouter();
|
|
97
|
+
mountedRoutes(source, tree);
|
|
98
|
+
trees.push(tree);
|
|
99
|
+
}
|
|
100
|
+
stack.push(fn);
|
|
101
|
+
} else {
|
|
102
|
+
const from = trees.length;
|
|
103
|
+
stack.push((ctx, next) => reaches(ctx, from) ? fn(ctx, next) : next());
|
|
104
|
+
}
|
|
79
105
|
i++;
|
|
80
106
|
continue;
|
|
81
107
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rhythmjs/router",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.14",
|
|
4
4
|
"description": "Bun-native HTTP router for the Rhythm middleware kernel, matching with rou3 and serving with Bun.serve.",
|
|
5
5
|
"homepage": "https://rhythm.js.org/router",
|
|
6
6
|
"license": "ISC",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"rou3": "^0.11.0",
|
|
41
|
-
"@rhythmjs/rhythm": "0.0.
|
|
41
|
+
"@rhythmjs/rhythm": "0.0.15"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@types/bun": "^1.2.0",
|