@usetoki/toki 0.1.2 → 0.2.0
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 +43 -3
- package/dist/core/app.d.ts +42 -0
- package/dist/{app.js → core/app.js} +73 -190
- package/dist/core/app.js.map +1 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/{pipeline.d.ts → core/pipeline.d.ts} +2 -2
- package/dist/{pipeline.js → core/pipeline.js} +2 -2
- package/dist/core/pipeline.js.map +1 -0
- package/dist/{app.d.ts → core/scope.d.ts} +22 -48
- package/dist/core/scope.js +196 -0
- package/dist/core/scope.js.map +1 -0
- package/dist/{types.d.ts → core/types.d.ts} +3 -3
- package/dist/core/types.js.map +1 -0
- package/dist/http/cookies.js.map +1 -0
- package/dist/http/forms.js.map +1 -0
- package/dist/{group.d.ts → http/group.d.ts} +1 -1
- package/dist/http/group.js.map +1 -0
- package/dist/http/inject.js.map +1 -0
- package/dist/{request.d.ts → http/request.d.ts} +2 -2
- package/dist/{request.js → http/request.js} +28 -7
- package/dist/http/request.js.map +1 -0
- package/dist/{response.d.ts → http/response.d.ts} +2 -2
- package/dist/http/response.js.map +1 -0
- package/dist/http/schema.js.map +1 -0
- package/dist/{static.d.ts → http/static.d.ts} +1 -1
- package/dist/http/static.js.map +1 -0
- package/dist/index.d.ts +22 -19
- package/dist/index.js +11 -9
- package/dist/index.js.map +1 -1
- package/dist/{native.d.ts → native/native.d.ts} +23 -1
- package/dist/{native.js → native/native.js} +2 -1
- package/dist/native/native.js.map +1 -0
- package/dist/{jwt.d.ts → security/jwt.d.ts} +1 -1
- package/dist/{jwt.js → security/jwt.js} +1 -1
- package/dist/security/jwt.js.map +1 -0
- package/dist/{middleware.d.ts → security/middleware.d.ts} +1 -1
- package/dist/{middleware.js → security/middleware.js} +1 -1
- package/dist/security/middleware.js.map +1 -0
- package/dist/websocket/websocket.d.ts +64 -0
- package/dist/websocket/websocket.js +145 -0
- package/dist/websocket/websocket.js.map +1 -0
- package/package.json +12 -12
- package/dist/app.js.map +0 -1
- package/dist/cookies.js.map +0 -1
- package/dist/forms.js.map +0 -1
- package/dist/group.js.map +0 -1
- package/dist/inject.js.map +0 -1
- package/dist/jwt.js.map +0 -1
- package/dist/logger.js.map +0 -1
- package/dist/middleware.js.map +0 -1
- package/dist/native.js.map +0 -1
- package/dist/pipeline.js.map +0 -1
- package/dist/request.js.map +0 -1
- package/dist/response.js.map +0 -1
- package/dist/schema.js.map +0 -1
- package/dist/static.js.map +0 -1
- package/dist/types.js.map +0 -1
- /package/dist/{logger.d.ts → core/logger.d.ts} +0 -0
- /package/dist/{logger.js → core/logger.js} +0 -0
- /package/dist/{types.js → core/types.js} +0 -0
- /package/dist/{cookies.d.ts → http/cookies.d.ts} +0 -0
- /package/dist/{cookies.js → http/cookies.js} +0 -0
- /package/dist/{forms.d.ts → http/forms.d.ts} +0 -0
- /package/dist/{forms.js → http/forms.js} +0 -0
- /package/dist/{group.js → http/group.js} +0 -0
- /package/dist/{inject.d.ts → http/inject.d.ts} +0 -0
- /package/dist/{inject.js → http/inject.js} +0 -0
- /package/dist/{response.js → http/response.js} +0 -0
- /package/dist/{schema.d.ts → http/schema.d.ts} +0 -0
- /package/dist/{schema.js → http/schema.js} +0 -0
- /package/dist/{static.js → http/static.js} +0 -0
package/README.md
CHANGED
|
@@ -38,6 +38,7 @@ console.log("listening on http://127.0.0.1:3000");
|
|
|
38
38
|
- 🗂️ **Static files** — MIME, `ETag` / `304`, `HEAD`, traversal-safe, with pre-computed gzip/brotli.
|
|
39
39
|
- 🗜️ **Compression** — gzip + brotli, negotiated per `Accept-Encoding`, off the event loop.
|
|
40
40
|
- 🌊 **Streaming** — `reply.stream` over chunked transfer encoding, with native backpressure.
|
|
41
|
+
- 🔭 **WebSockets** — full RFC 6455 in native code: framing, masking, fragmentation, ping/pong, close codes, subprotocols, and a per-IP message-size guard.
|
|
41
42
|
- 🛡️ **Hardened** — schema validation, JWT, a native per-IP rate limiter, slowloris guard, configurable limits.
|
|
42
43
|
- 🧪 **Testable** — `app.inject()` runs a real request in-process, no port needed.
|
|
43
44
|
|
|
@@ -117,10 +118,45 @@ app.listen(3000, { host: "0.0.0.0", maxBodyBytes: 5_000_000 });
|
|
|
117
118
|
| `headerTimeoutMs` | 0 | Close a connection stalled mid-request, in ms; `0` disables (slowloris guard). |
|
|
118
119
|
| `reusePort` | `false` | `SO_REUSEPORT` for kernel-balanced multi-worker scaling (Linux/BSD). |
|
|
119
120
|
| `rateLimit` | — | `{ max, windowMs }` — native per-IP limiter; over-limit requests get a `429` before reaching JS. |
|
|
121
|
+
| `unixPath` | — | Bind a unix-domain socket at this path instead of TCP (the port is ignored). Ideal for a reverse proxy → app on the same host. |
|
|
122
|
+
| `maxWsMessageBytes` | 16 MiB | Largest accepted WebSocket message; a larger one is closed with `1009`. |
|
|
123
|
+
| `wsCompression` | `false` | Offer `permessage-deflate` (RFC 7692) when a client requests it. |
|
|
120
124
|
|
|
121
125
|
`createApp({ logger, requestTimeoutMs })` configures the app; `app.listen` returns a
|
|
122
126
|
handle whose `close()` shuts the server down gracefully.
|
|
123
127
|
|
|
128
|
+
## 🔭 WebSockets
|
|
129
|
+
|
|
130
|
+
`app.ws(path, handler)` registers a WebSocket endpoint. The handler runs once per
|
|
131
|
+
connection with the live socket and the upgrade request; the framing, masking,
|
|
132
|
+
fragmentation, ping/pong, and close handshake all run in native code, so handlers
|
|
133
|
+
only ever see complete messages.
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
app.ws("/chat", { protocols: ["chat"] }, (socket, req) => {
|
|
137
|
+
console.log(`connected from ${req.ip} as ${socket.protocol}`);
|
|
138
|
+
|
|
139
|
+
socket.on("message", (data, isBinary) => {
|
|
140
|
+
socket.send(isBinary ? data : `echo: ${data.toString()}`);
|
|
141
|
+
});
|
|
142
|
+
socket.on("close", (code, reason) => console.log("closed", code, reason));
|
|
143
|
+
});
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
- **Send:** `socket.send(string | Uint8Array)` (returns the write backlog in bytes),
|
|
147
|
+
`socket.ping()`, `socket.pong()`, `socket.close(code?)`.
|
|
148
|
+
- **Events:** `message` `(data, isBinary)`, `close` `(code, reason)`, `ping`, `pong`,
|
|
149
|
+
and `drain` (fires when a backpressured socket's write queue empties).
|
|
150
|
+
- **State:** `socket.data` is a free-form per-connection bag; `socket.protocol` is the
|
|
151
|
+
negotiated subprotocol.
|
|
152
|
+
- **Compression:** set `wsCompression: true` in `listen` to offer `permessage-deflate`
|
|
153
|
+
(RFC 7692). It's negotiated per connection and applied transparently — handlers send
|
|
154
|
+
and receive plain data.
|
|
155
|
+
- The `Buffer` passed to `message` / `ping` / `pong` is a view over native memory
|
|
156
|
+
valid only during the call — copy it (`Buffer.from(data)` / `data.toString()`) to keep it.
|
|
157
|
+
|
|
158
|
+
A plain `GET` to a WebSocket path (no `Upgrade` header) gets `426 Upgrade Required`.
|
|
159
|
+
|
|
124
160
|
## 🧭 Native vs JavaScript — the boundary
|
|
125
161
|
|
|
126
162
|
The shared, heavy logic is native: HTTP parsing, routing, the MIME table, ETag and
|
|
@@ -151,9 +187,13 @@ addon for any platform from one host.
|
|
|
151
187
|
|
|
152
188
|
| Folder | What |
|
|
153
189
|
| --- | --- |
|
|
154
|
-
| `src/` |
|
|
155
|
-
| `
|
|
156
|
-
| `
|
|
190
|
+
| `src/core/` | Engine state, the libuv hot path, and server lifecycle (`engine`, `loop`, `server`). |
|
|
191
|
+
| `src/http/` | HTTP layer — `parser`, `router`, `request`, `response`, `static`, `stream`, `mime`. |
|
|
192
|
+
| `src/websocket/` | WebSocket wire format (`frame`) and the session/dispatch layer (`session`). |
|
|
193
|
+
| `src/security/` | The native rate limiter. |
|
|
194
|
+
| `src/ffi/` | Hand-declared N-API and libuv bindings. |
|
|
195
|
+
| `ts/` | TypeScript framework layer (`core/`, `http/`, `websocket/`, `security/`, `native/`) → `dist/`. |
|
|
196
|
+
| `__test__/` | Node test suite (`node:test`, run as `.ts`); Zig unit tests live in `*.test.zig` beside their module. |
|
|
157
197
|
| `examples/` | A runnable, self-checking example per feature. |
|
|
158
198
|
|
|
159
199
|
## 🧪 Examples
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type InjectOptions, type InjectResponse } from "../http/inject.js";
|
|
2
|
+
import { Scope, type Route } from "./scope.js";
|
|
3
|
+
import { type ServerOptions } from "../native/native.js";
|
|
4
|
+
import { type StaticOptions } from "../http/static.js";
|
|
5
|
+
import type { Handler, LifecycleHook, ListenHandle, Logger, TokiOptions } from "./types.js";
|
|
6
|
+
/**
|
|
7
|
+
* The application. Register routes (optionally with a validation schema and
|
|
8
|
+
* route-scoped hooks), global hooks, middleware, and plugins, then
|
|
9
|
+
* {@link Toki.listen}. The pipeline stays synchronous until a step returns a
|
|
10
|
+
* `Promise`, keeping the common sync request on the fast path.
|
|
11
|
+
*/
|
|
12
|
+
export declare class Toki extends Scope {
|
|
13
|
+
#private;
|
|
14
|
+
constructor(options?: TokiOptions);
|
|
15
|
+
/** @internal */
|
|
16
|
+
get _logger(): Logger;
|
|
17
|
+
/** @internal */
|
|
18
|
+
_pushRoute(route: Route): void;
|
|
19
|
+
/** @internal */
|
|
20
|
+
_decorate(name: string, value: unknown): void;
|
|
21
|
+
/** @internal */
|
|
22
|
+
_setNotFound(handler: Handler): void;
|
|
23
|
+
/** @internal */
|
|
24
|
+
_mountStatic(prefix: string, dir: string, options?: StaticOptions): void;
|
|
25
|
+
/** Run `fn` once at {@link Toki.listen}, before serving. */
|
|
26
|
+
onReady(fn: LifecycleHook): this;
|
|
27
|
+
/** Run `fn` when the server closes. */
|
|
28
|
+
onClose(fn: LifecycleHook): this;
|
|
29
|
+
/** Load all registered plugins, awaiting async ones. Call before {@link Toki.listen}
|
|
30
|
+
* when any plugin is async; `listen` loads sync plugins on its own. */
|
|
31
|
+
ready(): Promise<void>;
|
|
32
|
+
/** Bind `port` and serve. Returns a handle whose `close()` stops the server. */
|
|
33
|
+
listen(port: number, options?: ServerOptions): ListenHandle;
|
|
34
|
+
/**
|
|
35
|
+
* Inject a request in-process for testing. Sends a real request over loopback so
|
|
36
|
+
* the full native path runs, auto-binding an ephemeral port when not already
|
|
37
|
+
* listening. Returns the captured response.
|
|
38
|
+
*/
|
|
39
|
+
inject(options: InjectOptions | string): Promise<InjectResponse>;
|
|
40
|
+
}
|
|
41
|
+
/** Create a new application. */
|
|
42
|
+
export declare function createApp(options?: TokiOptions): Toki;
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { inject } from "./inject.js";
|
|
1
|
+
import { inject } from "../http/inject.js";
|
|
3
2
|
import { resolveLogger } from "./logger.js";
|
|
4
|
-
import {
|
|
5
|
-
import { native, } from "
|
|
6
|
-
import {
|
|
7
|
-
import { TokiRequest } from "
|
|
8
|
-
import { isStreamResponse, isTokiResponse, reply, toNative } from "
|
|
9
|
-
import {
|
|
10
|
-
|
|
3
|
+
import { Scope } from "./scope.js";
|
|
4
|
+
import { native, } from "../native/native.js";
|
|
5
|
+
import { isThenable, materialize, runAfter, runBefore, runSerialization, validationStep, } from "./pipeline.js";
|
|
6
|
+
import { TokiRequest } from "../http/request.js";
|
|
7
|
+
import { isStreamResponse, isTokiResponse, reply, toNative } from "../http/response.js";
|
|
8
|
+
import { TokiWebSocket, WS_EVENT } from "../websocket/websocket.js";
|
|
9
|
+
import { buildStaticEntries } from "../http/static.js";
|
|
10
|
+
// shared by every streaming response; TextEncoder is stateless across encode() calls
|
|
11
|
+
const streamEncoder = new TextEncoder();
|
|
11
12
|
// must match `not_found_index` in Zig
|
|
12
13
|
const NOT_FOUND_INDEX = 0xffffffff;
|
|
13
14
|
// pause a stream producer once the connection's write backlog passes this (1 MiB)
|
|
@@ -26,181 +27,6 @@ function streamHeaderBlock(stream, staged) {
|
|
|
26
27
|
function asArray(value) {
|
|
27
28
|
return value === undefined ? [] : Array.isArray(value) ? value : [value];
|
|
28
29
|
}
|
|
29
|
-
/**
|
|
30
|
-
* Encapsulated registration scope: own hooks, middleware, request decorators,
|
|
31
|
-
* error handler, and path prefix. Routes here run the hook chains of this scope
|
|
32
|
-
* and all ancestors. The root app ({@link Toki}) is itself a scope; {@link
|
|
33
|
-
* Scope.register} creates children.
|
|
34
|
-
*/
|
|
35
|
-
export class Scope {
|
|
36
|
-
parent;
|
|
37
|
-
prefix;
|
|
38
|
-
onRequest = [];
|
|
39
|
-
preParsing = [];
|
|
40
|
-
middleware = [];
|
|
41
|
-
preValidation = [];
|
|
42
|
-
preHandler = [];
|
|
43
|
-
preSerialization = [];
|
|
44
|
-
onResponse = [];
|
|
45
|
-
onSend = [];
|
|
46
|
-
onTimeout = [];
|
|
47
|
-
requestDecorators = {};
|
|
48
|
-
contentTypeParsers = [];
|
|
49
|
-
plugins = [];
|
|
50
|
-
errorHandler;
|
|
51
|
-
constructor(parent, prefix) {
|
|
52
|
-
this.parent = parent;
|
|
53
|
-
this.prefix = prefix;
|
|
54
|
-
}
|
|
55
|
-
get root() {
|
|
56
|
-
return this.parent ? this.parent.root : this;
|
|
57
|
-
}
|
|
58
|
-
get log() {
|
|
59
|
-
return this.root._logger;
|
|
60
|
-
}
|
|
61
|
-
get(path, a, b) {
|
|
62
|
-
return this.#add("GET", path, a, b);
|
|
63
|
-
}
|
|
64
|
-
post(path, a, b) {
|
|
65
|
-
return this.#add("POST", path, a, b);
|
|
66
|
-
}
|
|
67
|
-
put(path, a, b) {
|
|
68
|
-
return this.#add("PUT", path, a, b);
|
|
69
|
-
}
|
|
70
|
-
patch(path, a, b) {
|
|
71
|
-
return this.#add("PATCH", path, a, b);
|
|
72
|
-
}
|
|
73
|
-
delete(path, a, b) {
|
|
74
|
-
return this.#add("DELETE", path, a, b);
|
|
75
|
-
}
|
|
76
|
-
head(path, handler) {
|
|
77
|
-
return this.#add("HEAD", path, handler);
|
|
78
|
-
}
|
|
79
|
-
options(path, handler) {
|
|
80
|
-
return this.#add("OPTIONS", path, handler);
|
|
81
|
-
}
|
|
82
|
-
route(method, path, handler) {
|
|
83
|
-
return this.#add(method, path, handler);
|
|
84
|
-
}
|
|
85
|
-
#add(method, path, a, b) {
|
|
86
|
-
const [options, handler] = typeof a === "function" ? [{}, a] : [a, b];
|
|
87
|
-
this.root._pushRoute({
|
|
88
|
-
method,
|
|
89
|
-
path: joinPaths(this.prefix, path),
|
|
90
|
-
handler,
|
|
91
|
-
options,
|
|
92
|
-
groupMiddleware: NO_MIDDLEWARE,
|
|
93
|
-
scope: this,
|
|
94
|
-
});
|
|
95
|
-
return this;
|
|
96
|
-
}
|
|
97
|
-
/** Add middleware; runs before every handler in this scope and descendants. */
|
|
98
|
-
use(middleware) {
|
|
99
|
-
this.middleware.push(middleware);
|
|
100
|
-
return this;
|
|
101
|
-
}
|
|
102
|
-
addHook(name, fn) {
|
|
103
|
-
switch (name) {
|
|
104
|
-
case "onResponse":
|
|
105
|
-
this.onResponse.push(fn);
|
|
106
|
-
break;
|
|
107
|
-
case "onSend":
|
|
108
|
-
this.onSend.push(fn);
|
|
109
|
-
break;
|
|
110
|
-
case "preParsing":
|
|
111
|
-
this.preParsing.push(fn);
|
|
112
|
-
break;
|
|
113
|
-
case "preValidation":
|
|
114
|
-
this.preValidation.push(fn);
|
|
115
|
-
break;
|
|
116
|
-
case "preHandler":
|
|
117
|
-
this.preHandler.push(fn);
|
|
118
|
-
break;
|
|
119
|
-
case "preSerialization":
|
|
120
|
-
this.preSerialization.push(fn);
|
|
121
|
-
break;
|
|
122
|
-
case "onTimeout":
|
|
123
|
-
this.onTimeout.push(fn);
|
|
124
|
-
break;
|
|
125
|
-
default:
|
|
126
|
-
this.onRequest.push(fn);
|
|
127
|
-
}
|
|
128
|
-
return this;
|
|
129
|
-
}
|
|
130
|
-
/** Set the error handler for routes in this scope (alias: `onError`). */
|
|
131
|
-
setErrorHandler(handler) {
|
|
132
|
-
this.errorHandler = handler;
|
|
133
|
-
return this;
|
|
134
|
-
}
|
|
135
|
-
onError(handler) {
|
|
136
|
-
return this.setErrorHandler(handler);
|
|
137
|
-
}
|
|
138
|
-
/** Attach a property to every request handled in this scope. */
|
|
139
|
-
decorateRequest(name, value) {
|
|
140
|
-
this.requestDecorators[name] = value;
|
|
141
|
-
return this;
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* Register a body parser for one or more content types, consulted by
|
|
145
|
-
* `req.parseBody()`. `type` matches case-insensitively as a prefix (e.g.
|
|
146
|
-
* `"application/xml"`), a `RegExp`, or `"*"` for any. A child scope overrides
|
|
147
|
-
* an ancestor for the same type.
|
|
148
|
-
*/
|
|
149
|
-
addContentTypeParser(type, parser) {
|
|
150
|
-
const tests = Array.isArray(type) ? type : [type];
|
|
151
|
-
for (const t of tests) {
|
|
152
|
-
this.contentTypeParsers.push({ test: contentTypeMatcher(t), parser });
|
|
153
|
-
}
|
|
154
|
-
return this;
|
|
155
|
-
}
|
|
156
|
-
/** Attach a property to the application instance (app-global, not encapsulated). */
|
|
157
|
-
decorate(name, value) {
|
|
158
|
-
this.root._decorate(name, value);
|
|
159
|
-
return this;
|
|
160
|
-
}
|
|
161
|
-
/** Set the handler for unmatched routes (app-global). */
|
|
162
|
-
setNotFoundHandler(handler) {
|
|
163
|
-
this.root._setNotFound(handler);
|
|
164
|
-
return this;
|
|
165
|
-
}
|
|
166
|
-
/** Enable CORS: stage headers on every response and answer preflight `OPTIONS`. */
|
|
167
|
-
cors(options = {}) {
|
|
168
|
-
this.use(corsHeaders(options));
|
|
169
|
-
this.options("/*", corsPreflight(options));
|
|
170
|
-
return this;
|
|
171
|
-
}
|
|
172
|
-
/** Serve files under `dir` at `urlPrefix` (joined with this scope's prefix). */
|
|
173
|
-
static(urlPrefix, dir, options) {
|
|
174
|
-
this.root._mountStatic(joinPaths(this.prefix, urlPrefix), dir, options);
|
|
175
|
-
return this;
|
|
176
|
-
}
|
|
177
|
-
/** Register a prefixed group of routes with its own middleware. */
|
|
178
|
-
group(prefix, build) {
|
|
179
|
-
const group = new RouteGroup(prefix, (method, path, handler, middleware) => {
|
|
180
|
-
this.root._pushRoute({
|
|
181
|
-
method,
|
|
182
|
-
path: joinPaths(this.prefix, path),
|
|
183
|
-
handler,
|
|
184
|
-
options: {},
|
|
185
|
-
groupMiddleware: middleware,
|
|
186
|
-
scope: this,
|
|
187
|
-
});
|
|
188
|
-
});
|
|
189
|
-
build(group);
|
|
190
|
-
return this;
|
|
191
|
-
}
|
|
192
|
-
/**
|
|
193
|
-
* Register a plugin into a fresh child scope. The plugin receives that scope as
|
|
194
|
-
* its `instance`; routes/hooks/decorators it adds are encapsulated there (and
|
|
195
|
-
* inherited by its own children), not leaked to the parent. Async plugins load
|
|
196
|
-
* during {@link Toki.ready}. `opts.prefix` mounts the plugin's routes under a path.
|
|
197
|
-
*/
|
|
198
|
-
register(plugin, opts = {}) {
|
|
199
|
-
const prefix = joinPaths(this.prefix, typeof opts.prefix === "string" ? opts.prefix : "/");
|
|
200
|
-
this.plugins.push({ plugin, opts, scope: new Scope(this, prefix) });
|
|
201
|
-
return this;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
30
|
/**
|
|
205
31
|
* The application. Register routes (optionally with a validation schema and
|
|
206
32
|
* route-scoped hooks), global hooks, middleware, and plugins, then
|
|
@@ -217,6 +43,11 @@ export class Toki extends Scope {
|
|
|
217
43
|
#notFoundHandler;
|
|
218
44
|
#compiled = [];
|
|
219
45
|
#compiledNotFound;
|
|
46
|
+
// handler per native route index (undefined for non-ws routes), and live sockets by id
|
|
47
|
+
#wsHandlers = [];
|
|
48
|
+
#wsSockets = new Map();
|
|
49
|
+
// caps inflation of a compressed ws message (set from listen options)
|
|
50
|
+
#wsMaxMessage = 16 * 1024 * 1024;
|
|
220
51
|
#booted = false;
|
|
221
52
|
#boundPort = 0;
|
|
222
53
|
#listening = false;
|
|
@@ -282,7 +113,16 @@ export class Toki extends Scope {
|
|
|
282
113
|
serverOptions.rateLimitMax = options.rateLimit.max;
|
|
283
114
|
serverOptions.rateLimitWindowMs = options.rateLimit.windowMs;
|
|
284
115
|
}
|
|
285
|
-
|
|
116
|
+
const wsRouteIndices = [];
|
|
117
|
+
const wsProtocols = [];
|
|
118
|
+
this.#routes.forEach((route, index) => {
|
|
119
|
+
if (route.webSocket) {
|
|
120
|
+
wsRouteIndices.push(index);
|
|
121
|
+
wsProtocols.push((route.webSocket.options.protocols ?? []).join(","));
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
this.#wsMaxMessage = options.maxWsMessageBytes ?? this.#wsMaxMessage;
|
|
125
|
+
this.#boundPort = native.listen(port, methods, paths, (raw) => this.#dispatch(raw), staticEntries, serverOptions, (id, event, a, b, c) => this.#wsDispatch(id, event, a, b, c), wsRouteIndices, wsProtocols);
|
|
286
126
|
this.#listening = true;
|
|
287
127
|
return {
|
|
288
128
|
close: () => {
|
|
@@ -315,6 +155,7 @@ export class Toki extends Scope {
|
|
|
315
155
|
}
|
|
316
156
|
#compileAll() {
|
|
317
157
|
this.#compiled = this.#routes.map((route) => this.#compile(route));
|
|
158
|
+
this.#wsHandlers = this.#routes.map((route) => route.webSocket?.handler);
|
|
318
159
|
this.#compiledNotFound =
|
|
319
160
|
this.#notFoundHandler !== undefined
|
|
320
161
|
? this.#compileNotFound(this.#notFoundHandler)
|
|
@@ -358,7 +199,8 @@ export class Toki extends Scope {
|
|
|
358
199
|
const onTimeout = [];
|
|
359
200
|
for (const s of chain)
|
|
360
201
|
onTimeout.push(...s.onTimeout);
|
|
361
|
-
const
|
|
202
|
+
const merged = Object.assign({}, ...chain.map((s) => s.requestDecorators));
|
|
203
|
+
const decorators = Object.keys(merged).length > 0 ? merged : undefined;
|
|
362
204
|
let errorHandler;
|
|
363
205
|
for (const s of chain) {
|
|
364
206
|
if (s.errorHandler)
|
|
@@ -393,7 +235,7 @@ export class Toki extends Scope {
|
|
|
393
235
|
serialization: [...this.preSerialization],
|
|
394
236
|
onTimeout: [...this.onTimeout],
|
|
395
237
|
parsers: [...this.contentTypeParsers],
|
|
396
|
-
decorators: this.requestDecorators,
|
|
238
|
+
decorators: Object.keys(this.requestDecorators).length > 0 ? this.requestDecorators : undefined,
|
|
397
239
|
...(this.errorHandler ? { errorHandler: this.errorHandler } : {}),
|
|
398
240
|
defaultStatus: 404,
|
|
399
241
|
};
|
|
@@ -404,7 +246,8 @@ export class Toki extends Scope {
|
|
|
404
246
|
return toNative(reply.empty(raw.routeIndex === NOT_FOUND_INDEX ? 404 : 500));
|
|
405
247
|
}
|
|
406
248
|
const req = new TokiRequest(raw, { log: this.#loggerInstance, parsers: route.parsers });
|
|
407
|
-
|
|
249
|
+
if (route.decorators !== undefined)
|
|
250
|
+
Object.assign(req, route.decorators);
|
|
408
251
|
try {
|
|
409
252
|
const outcome = this.#run(req, route);
|
|
410
253
|
if (isThenable(outcome)) {
|
|
@@ -439,6 +282,47 @@ export class Toki extends Scope {
|
|
|
439
282
|
return this.#safeToNative(this.#handleError(req, error, route.errorHandler), req);
|
|
440
283
|
}
|
|
441
284
|
}
|
|
285
|
+
// routes native WebSocket events to the live socket; one bad listener is logged,
|
|
286
|
+
// never allowed to escape into the native dispatch call
|
|
287
|
+
#wsDispatch(wsId, event, a, b, c) {
|
|
288
|
+
try {
|
|
289
|
+
switch (event) {
|
|
290
|
+
case WS_EVENT.open: {
|
|
291
|
+
const raw = a;
|
|
292
|
+
const handler = this.#wsHandlers[raw.routeIndex];
|
|
293
|
+
if (handler === undefined)
|
|
294
|
+
return;
|
|
295
|
+
const socket = new TokiWebSocket(wsId, b ?? "", c === 1, this.#wsMaxMessage);
|
|
296
|
+
this.#wsSockets.set(wsId, socket);
|
|
297
|
+
handler(socket, new TokiRequest(raw, { log: this.#loggerInstance }));
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
case WS_EVENT.message: {
|
|
301
|
+
const flags = a;
|
|
302
|
+
this.#wsSockets.get(wsId)?._message(b, (flags & 1) !== 0, (flags & 2) !== 0);
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
case WS_EVENT.close: {
|
|
306
|
+
const socket = this.#wsSockets.get(wsId);
|
|
307
|
+
this.#wsSockets.delete(wsId);
|
|
308
|
+
socket?._close(a, b ?? "");
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
case WS_EVENT.ping:
|
|
312
|
+
this.#wsSockets.get(wsId)?._ping(b);
|
|
313
|
+
return;
|
|
314
|
+
case WS_EVENT.pong:
|
|
315
|
+
this.#wsSockets.get(wsId)?._pong(b);
|
|
316
|
+
return;
|
|
317
|
+
case WS_EVENT.drain:
|
|
318
|
+
this.#wsSockets.get(wsId)?._drain();
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
catch (error) {
|
|
323
|
+
this.#loggerInstance.error("websocket handler threw", { error: String(error) });
|
|
324
|
+
}
|
|
325
|
+
}
|
|
442
326
|
#submit(id, req, result) {
|
|
443
327
|
if (isStreamResponse(result)) {
|
|
444
328
|
this.#driveSafe(id, req, result);
|
|
@@ -495,10 +379,9 @@ export class Toki extends Scope {
|
|
|
495
379
|
}
|
|
496
380
|
async #drive(id, req, stream) {
|
|
497
381
|
native.startStream(id, stream.status, streamHeaderBlock(stream, req.stagedResponseHeaders));
|
|
498
|
-
const encoder = new TextEncoder();
|
|
499
382
|
try {
|
|
500
383
|
for await (const chunk of stream.source) {
|
|
501
|
-
const bytes = typeof chunk === "string" ?
|
|
384
|
+
const bytes = typeof chunk === "string" ? streamEncoder.encode(chunk) : chunk;
|
|
502
385
|
if (bytes.length === 0) {
|
|
503
386
|
continue;
|
|
504
387
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../../ts/core/app.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../ts/core/logger.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,GAA6B,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;AAEtF,qEAAqE;AACrE,MAAM,CAAC,MAAM,YAAY,GAAW;IAClC,KAAK,KAAI,CAAC;IACV,IAAI,KAAI,CAAC;IACT,IAAI,KAAI,CAAC;IACT,KAAK,KAAI,CAAC;IACV,KAAK;QACH,OAAO,YAAY,CAAC;IACtB,CAAC;CACF,CAAC;AAEF,oEAAoE;AACpE,MAAM,UAAU,mBAAmB,CACjC,QAAkB,MAAM,EACxB,WAAoC,EAAE;IAEtC,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAEhC,SAAS,GAAG,CAAC,EAAY,EAAE,OAAe,EAAE,MAAgC;QAC1E,IAAI,MAAM,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC;YAC3B,OAAO;QACT,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,QAAQ,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;QACjF,IAAI,EAAE,KAAK,OAAO,IAAI,EAAE,KAAK,MAAM,EAAE,CAAC;YACpC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;QACpC,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IAED,OAAO;QACL,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;QACnC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;QACjC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;QACjC,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;QACnC,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,mBAAmB,CAAC,KAAK,EAAE,EAAE,GAAG,QAAQ,EAAE,GAAG,KAAK,EAAE,CAAC;KACxE,CAAC;AACJ,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,aAAa,CAAC,MAA6B;IACzD,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;QAC7C,OAAO,YAAY,CAAC;IACtB,CAAC;IACD,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/B,OAAO,mBAAmB,CAAC,MAAM,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { TokiRequest } from "
|
|
2
|
-
import { type JSONSchema, type RouteSchema } from "
|
|
1
|
+
import type { TokiRequest } from "../http/request.js";
|
|
2
|
+
import { type JSONSchema, type RouteSchema } from "../http/schema.js";
|
|
3
3
|
import type { HandlerResult, Middleware, ResponseHook, SerializationHook, TokiResponse } from "./types.js";
|
|
4
4
|
export declare function isThenable<T>(value: unknown): value is Promise<T>;
|
|
5
5
|
/** What `materialize` needs off a compiled route — a CompiledRoute satisfies it. */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { isTokiResponse, jsonResponse, normalize, reply } from "
|
|
2
|
-
import { serialize, validate } from "
|
|
1
|
+
import { isTokiResponse, jsonResponse, normalize, reply } from "../http/response.js";
|
|
2
|
+
import { serialize, validate } from "../http/schema.js";
|
|
3
3
|
export function isThenable(value) {
|
|
4
4
|
return (value != null &&
|
|
5
5
|
(typeof value === "object" || typeof value === "function") &&
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../../ts/core/pipeline.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,22 +1,28 @@
|
|
|
1
|
-
import { RouteGroup } from "
|
|
2
|
-
import
|
|
3
|
-
import { type CorsOptions } from "
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import type { BodyParser, ContentTypeParserEntry, ErrorHandler, Handler,
|
|
7
|
-
interface Route {
|
|
1
|
+
import { RouteGroup } from "../http/group.js";
|
|
2
|
+
import type { StaticOptions } from "../http/static.js";
|
|
3
|
+
import { type CorsOptions } from "../security/middleware.js";
|
|
4
|
+
import type { WebSocketHandler, WebSocketOptions } from "../websocket/websocket.js";
|
|
5
|
+
import type { Toki } from "./app.js";
|
|
6
|
+
import type { BodyParser, ContentTypeParserEntry, ErrorHandler, Handler, Logger, Middleware, PluginOptions, ResponseHook, RouteMethod, RouteOptions, SerializationHook, TimeoutHook } from "./types.js";
|
|
7
|
+
export interface Route {
|
|
8
8
|
readonly method: RouteMethod;
|
|
9
9
|
readonly path: string;
|
|
10
10
|
readonly handler: Handler;
|
|
11
11
|
readonly options: RouteOptions;
|
|
12
12
|
readonly groupMiddleware: readonly Middleware[];
|
|
13
13
|
readonly scope: Scope;
|
|
14
|
+
readonly webSocket?: {
|
|
15
|
+
readonly handler: WebSocketHandler;
|
|
16
|
+
readonly options: WebSocketOptions;
|
|
17
|
+
};
|
|
14
18
|
}
|
|
15
|
-
interface PluginEntry {
|
|
19
|
+
export interface PluginEntry {
|
|
16
20
|
readonly plugin: TokiPlugin;
|
|
17
21
|
readonly opts: PluginOptions;
|
|
18
22
|
readonly scope: Scope;
|
|
19
23
|
}
|
|
24
|
+
/** The registration surface a plugin receives (the application or a child scope). */
|
|
25
|
+
export type TokiInstance = Scope;
|
|
20
26
|
/** Registers routes/hooks/decorators on the encapsulated `instance`. */
|
|
21
27
|
export type TokiPlugin = (instance: TokiInstance, opts: PluginOptions) => void | Promise<void>;
|
|
22
28
|
/**
|
|
@@ -58,6 +64,14 @@ export declare class Scope {
|
|
|
58
64
|
head(path: string, handler: Handler): this;
|
|
59
65
|
options(path: string, handler: Handler): this;
|
|
60
66
|
route(method: RouteMethod, path: string, handler: Handler): this;
|
|
67
|
+
/**
|
|
68
|
+
* Register a WebSocket endpoint. The handler runs once per accepted connection
|
|
69
|
+
* with the live `TokiWebSocket` and the upgrade `TokiRequest`; attach
|
|
70
|
+
* `message` / `close` / `ping` / `pong` / `drain` listeners on it. A plain GET
|
|
71
|
+
* to the same path (no `Upgrade` header) gets a `426 Upgrade Required`.
|
|
72
|
+
*/
|
|
73
|
+
ws(path: string, handler: WebSocketHandler): this;
|
|
74
|
+
ws(path: string, options: WebSocketOptions, handler: WebSocketHandler): this;
|
|
61
75
|
/** Add middleware; runs before every handler in this scope and descendants. */
|
|
62
76
|
use(middleware: Middleware): this;
|
|
63
77
|
/** Register a lifecycle hook scoped to this instance. */
|
|
@@ -95,43 +109,3 @@ export declare class Scope {
|
|
|
95
109
|
*/
|
|
96
110
|
register(plugin: TokiPlugin, opts?: PluginOptions): this;
|
|
97
111
|
}
|
|
98
|
-
/** The registration surface a plugin receives (the application or a child scope). */
|
|
99
|
-
export type TokiInstance = Scope;
|
|
100
|
-
/**
|
|
101
|
-
* The application. Register routes (optionally with a validation schema and
|
|
102
|
-
* route-scoped hooks), global hooks, middleware, and plugins, then
|
|
103
|
-
* {@link Toki.listen}. The pipeline stays synchronous until a step returns a
|
|
104
|
-
* `Promise`, keeping the common sync request on the fast path.
|
|
105
|
-
*/
|
|
106
|
-
export declare class Toki extends Scope {
|
|
107
|
-
#private;
|
|
108
|
-
constructor(options?: TokiOptions);
|
|
109
|
-
/** @internal */
|
|
110
|
-
get _logger(): Logger;
|
|
111
|
-
/** @internal */
|
|
112
|
-
_pushRoute(route: Route): void;
|
|
113
|
-
/** @internal */
|
|
114
|
-
_decorate(name: string, value: unknown): void;
|
|
115
|
-
/** @internal */
|
|
116
|
-
_setNotFound(handler: Handler): void;
|
|
117
|
-
/** @internal */
|
|
118
|
-
_mountStatic(prefix: string, dir: string, options?: StaticOptions): void;
|
|
119
|
-
/** Run `fn` once at {@link Toki.listen}, before serving. */
|
|
120
|
-
onReady(fn: LifecycleHook): this;
|
|
121
|
-
/** Run `fn` when the server closes. */
|
|
122
|
-
onClose(fn: LifecycleHook): this;
|
|
123
|
-
/** Load all registered plugins, awaiting async ones. Call before {@link Toki.listen}
|
|
124
|
-
* when any plugin is async; `listen` loads sync plugins on its own. */
|
|
125
|
-
ready(): Promise<void>;
|
|
126
|
-
/** Bind `port` and serve. Returns a handle whose `close()` stops the server. */
|
|
127
|
-
listen(port: number, options?: ServerOptions): ListenHandle;
|
|
128
|
-
/**
|
|
129
|
-
* Inject a request in-process for testing. Sends a real request over loopback so
|
|
130
|
-
* the full native path runs, auto-binding an ephemeral port when not already
|
|
131
|
-
* listening. Returns the captured response.
|
|
132
|
-
*/
|
|
133
|
-
inject(options: InjectOptions | string): Promise<InjectResponse>;
|
|
134
|
-
}
|
|
135
|
-
/** Create a new application. */
|
|
136
|
-
export declare function createApp(options?: TokiOptions): Toki;
|
|
137
|
-
export {};
|