@rhythmjs/router 0.0.20 → 0.0.22
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 +6 -2
- package/dist/path.js +5 -1
- package/dist/pathname.d.ts +1 -0
- package/dist/rhythm-router-t7qys9ar.js +20 -0
- package/dist/rhythm-router.js +20 -10
- package/package.json +11 -8
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
The HTTP layer of Rhythm, the Bun-native backend framework: web-standard (`Request`/`Response`) routing on top of the `@rhythmjs/rhythm` kernel, served on `Bun.serve`. `RhythmRouter` matches routes with [rou3](https://github.com/h3js/rou3), the router that powers h3 (a static segment always wins over a `:param` segment, regardless of registration order).
|
|
4
4
|
|
|
5
|
-
Route patterns follow rou3's conventions: `:name` params (`:name?` optional, `:id(\\d+)` regex-constrained), `*` for
|
|
5
|
+
Route patterns follow rou3's conventions: `:name` params (`:name?` optional, `:id(\\d+)` regex-constrained), `*` for an unnamed wildcard (captured as `params["0"]`; with the installed rou3 it spans several segments, so use `:name` for exactly one segment), and `**` for the rest of the path (`params._`, or `params.name` with `**:name`). Param values are URI-decoded; a malformed escape does not match.
|
|
6
6
|
|
|
7
7
|
`RhythmRouter` is a `Pipeline`, like `Rhythm`: it has request-time `use()` middleware and routes, but no startup phase. Startup work (`register`, `decorate`, `include`) belongs to the `Rhythm` app that mounts it with `mount(router)`.
|
|
8
8
|
|
|
@@ -118,4 +118,8 @@ Directory routes (`{ dir }`, path must end in `/*`) come with content types, `La
|
|
|
118
118
|
|
|
119
119
|
### WebSockets
|
|
120
120
|
|
|
121
|
-
[`@rhythmjs/ws`](https://github.com/rhythmjs/ws)
|
|
121
|
+
[`@rhythmjs/ws`](https://github.com/rhythmjs/ws) is a pipeline like the router: mount it beside your routers with `mount(ws)`, and pass `websocket` to the same `Bun.serve` call. Its routes call Bun's `ctx.server.upgrade()`, which is why the fetch handler must be given the server (`fetch: toFetchHandler(app)`).
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
Bun.serve({ fetch: toFetchHandler(new Rhythm().use(mount(router)).use(mount(ws))), websocket });
|
|
125
|
+
```
|
package/dist/path.js
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
// @bun
|
|
2
|
+
import {
|
|
3
|
+
pathnameOf
|
|
4
|
+
} from "./rhythm-router-t7qys9ar.js";
|
|
5
|
+
|
|
2
6
|
// src/path.ts
|
|
3
7
|
import { addRoute, createRouter, findRoute } from "rou3";
|
|
4
8
|
function pathIs(pattern) {
|
|
@@ -6,7 +10,7 @@ function pathIs(pattern) {
|
|
|
6
10
|
throw new TypeError(`path must start with "/", got "${pattern}"`);
|
|
7
11
|
const router = createRouter();
|
|
8
12
|
addRoute(router, "", pattern, true);
|
|
9
|
-
return (ctx) => findRoute(router, ctx.request.method,
|
|
13
|
+
return (ctx) => findRoute(router, ctx.request.method, pathnameOf(ctx.request.url)) !== undefined;
|
|
10
14
|
}
|
|
11
15
|
export {
|
|
12
16
|
pathIs
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function pathnameOf(url: string): string;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// src/pathname.ts
|
|
3
|
+
var NEEDS_PARSING = /[\\\u0000- \u007f-\uFFFF"<>^`{|}]|\/\.|%2e/i;
|
|
4
|
+
function pathnameOf(url) {
|
|
5
|
+
const authority = url.indexOf("://") + 3;
|
|
6
|
+
const start = url.indexOf("/", authority);
|
|
7
|
+
if (authority < 3 || start === -1)
|
|
8
|
+
return new URL(url).pathname;
|
|
9
|
+
let end = url.length;
|
|
10
|
+
const query = url.indexOf("?", start);
|
|
11
|
+
if (query !== -1)
|
|
12
|
+
end = query;
|
|
13
|
+
const hash = url.indexOf("#", start);
|
|
14
|
+
if (hash !== -1 && hash < end)
|
|
15
|
+
end = hash;
|
|
16
|
+
const pathname = url.slice(start, end);
|
|
17
|
+
return NEEDS_PARSING.test(pathname) ? new URL(url).pathname : pathname;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { pathnameOf };
|
package/dist/rhythm-router.js
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
// @bun
|
|
2
|
+
import {
|
|
3
|
+
pathnameOf
|
|
4
|
+
} from "./rhythm-router-t7qys9ar.js";
|
|
5
|
+
|
|
2
6
|
// src/rhythm-router.ts
|
|
3
7
|
import { addRoute, createRouter, findRoute } from "rou3";
|
|
4
8
|
import {
|
|
@@ -7,9 +11,12 @@ import {
|
|
|
7
11
|
} from "@rhythmjs/rhythm";
|
|
8
12
|
function decodeParams(params) {
|
|
9
13
|
const decoded = {};
|
|
14
|
+
if (!params)
|
|
15
|
+
return decoded;
|
|
10
16
|
try {
|
|
11
|
-
for (const
|
|
12
|
-
|
|
17
|
+
for (const key in params) {
|
|
18
|
+
const value = params[key];
|
|
19
|
+
decoded[key] = value.includes("%") ? decodeURIComponent(value) : value;
|
|
13
20
|
}
|
|
14
21
|
} catch {
|
|
15
22
|
return;
|
|
@@ -42,18 +49,21 @@ class RhythmRouter extends Pipeline {
|
|
|
42
49
|
}
|
|
43
50
|
callback() {
|
|
44
51
|
const run = this.chain();
|
|
45
|
-
return
|
|
52
|
+
return (input) => {
|
|
46
53
|
const ctx = input;
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
54
|
+
try {
|
|
55
|
+
const match = this.#match(ctx);
|
|
56
|
+
if (!match)
|
|
57
|
+
return Promise.resolve(ctx);
|
|
58
|
+
Object.assign(ctx, { params: match.params });
|
|
59
|
+
return run(ctx, () => match.route(ctx)).then(() => ctx);
|
|
60
|
+
} catch (error) {
|
|
61
|
+
return Promise.reject(error);
|
|
62
|
+
}
|
|
53
63
|
};
|
|
54
64
|
}
|
|
55
65
|
#match(ctx) {
|
|
56
|
-
const found = findRoute(this.#routes, ctx.request.method,
|
|
66
|
+
const found = findRoute(this.#routes, ctx.request.method, pathnameOf(ctx.request.url));
|
|
57
67
|
if (!found)
|
|
58
68
|
return;
|
|
59
69
|
const params = decodeParams(found.params);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rhythmjs/router",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.22",
|
|
4
4
|
"description": "Bun-native HTTP router for Rhythm: RhythmRouter plus a fetch handler for Bun.serve, matching with rou3.",
|
|
5
5
|
"homepage": "https://rhythm.js.org/router",
|
|
6
6
|
"license": "ISC",
|
|
@@ -36,8 +36,16 @@
|
|
|
36
36
|
"publishConfig": {
|
|
37
37
|
"access": "public"
|
|
38
38
|
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"clean": "rm -rf dist",
|
|
41
|
+
"prebuild": "bun run clean",
|
|
42
|
+
"build": "bun build src/rhythm-router.ts src/context.ts src/fetch.ts src/path.ts --outdir dist --root src --format esm --target bun --packages external --splitting && tsc -p tsconfig.build.json",
|
|
43
|
+
"prepublishOnly": "bun run typecheck && bun test && bun run build",
|
|
44
|
+
"typecheck": "tsc --noEmit",
|
|
45
|
+
"test": "bun test"
|
|
46
|
+
},
|
|
39
47
|
"dependencies": {
|
|
40
|
-
"@rhythmjs/rhythm": "
|
|
48
|
+
"@rhythmjs/rhythm": "workspace:*",
|
|
41
49
|
"rou3": "^1.0.0"
|
|
42
50
|
},
|
|
43
51
|
"devDependencies": {
|
|
@@ -47,10 +55,5 @@
|
|
|
47
55
|
},
|
|
48
56
|
"engines": {
|
|
49
57
|
"bun": ">=1.2.0"
|
|
50
|
-
},
|
|
51
|
-
"scripts": {
|
|
52
|
-
"build": "rm -rf dist && bun build src/rhythm-router.ts src/context.ts src/fetch.ts src/path.ts --outdir dist --root src --format esm --target bun --packages external --splitting && tsc -p tsconfig.build.json",
|
|
53
|
-
"typecheck": "tsc --noEmit",
|
|
54
|
-
"test": "bun test"
|
|
55
58
|
}
|
|
56
|
-
}
|
|
59
|
+
}
|