expediate 1.0.4 → 1.0.5
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/LICENSE +16 -16
- package/README.md +417 -30
- package/dist/apis.d.ts +138 -21
- package/dist/apis.d.ts.map +1 -1
- package/dist/apis.js +172 -79
- package/dist/apis.js.map +1 -1
- package/dist/cjs/apis.js +327 -0
- package/dist/cjs/git.js +293 -0
- package/dist/cjs/index.js +2583 -0
- package/dist/cjs/jwt-auth.js +532 -0
- package/dist/cjs/middleware.js +511 -0
- package/dist/cjs/mimetypes.json +1 -0
- package/dist/cjs/misc.js +787 -0
- package/dist/cjs/openapi.js +485 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/router.js +898 -0
- package/dist/cjs/static.js +669 -0
- package/dist/git.d.ts +71 -8
- package/dist/git.d.ts.map +1 -1
- package/dist/git.js +127 -72
- package/dist/git.js.map +1 -1
- package/dist/index.d.ts +17 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -24
- package/dist/index.js.map +1 -1
- package/dist/jwt-auth.d.ts +147 -57
- package/dist/jwt-auth.d.ts.map +1 -1
- package/dist/jwt-auth.js +445 -205
- package/dist/jwt-auth.js.map +1 -1
- package/dist/middleware.d.ts +476 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/middleware.js +647 -0
- package/dist/middleware.js.map +1 -0
- package/dist/mimetypes.json +1 -1
- package/dist/misc.d.ts +112 -5
- package/dist/misc.d.ts.map +1 -1
- package/dist/misc.js +235 -102
- package/dist/misc.js.map +1 -1
- package/dist/openapi.d.ts +290 -0
- package/dist/openapi.d.ts.map +1 -0
- package/dist/openapi.js +481 -0
- package/dist/openapi.js.map +1 -0
- package/dist/router.d.ts +405 -46
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +658 -153
- package/dist/router.js.map +1 -1
- package/dist/static.d.ts +1 -1
- package/dist/static.d.ts.map +1 -1
- package/dist/static.js +88 -84
- package/dist/static.js.map +1 -1
- package/package.json +21 -4
- package/.npmignore +0 -16
package/dist/router.d.ts
CHANGED
|
@@ -1,7 +1,65 @@
|
|
|
1
1
|
import * as http from 'http';
|
|
2
|
-
import
|
|
2
|
+
import * as https from 'https';
|
|
3
|
+
import * as http2 from 'http2';
|
|
4
|
+
import { BodyOptions, FormPart } from './misc.js';
|
|
3
5
|
/** A key-value map of arbitrary string values. */
|
|
4
6
|
type StringMap = Record<string, string>;
|
|
7
|
+
/**
|
|
8
|
+
* Options accepted by `createRouter()`.
|
|
9
|
+
*/
|
|
10
|
+
interface RouterOptions {
|
|
11
|
+
/**
|
|
12
|
+
* Secret string used to sign and verify signed cookies.
|
|
13
|
+
*
|
|
14
|
+
* Required when any route calls `res.cookie(name, val, { signed: true })`.
|
|
15
|
+
* When absent, attempting to set a signed cookie throws at runtime.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* const app = createRouter({ secret: process.env.COOKIE_SECRET });
|
|
20
|
+
* app.get('/set', (_req, res) =>
|
|
21
|
+
* res.cookie('session', 'user-id', { signed: true }).send('ok'));
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
secret?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Global request timeout in milliseconds.
|
|
27
|
+
*
|
|
28
|
+
* When a request handler does not start writing a response within this
|
|
29
|
+
* period, the socket is marked idle and a **408 Request Timeout** response
|
|
30
|
+
* is sent automatically. The timeout is reset on every response write.
|
|
31
|
+
*
|
|
32
|
+
* Set to `0` or omit to disable the timeout entirely.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* const app = createRouter({ timeout: 30_000 }); // 30 s
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
timeout?: number;
|
|
40
|
+
/**
|
|
41
|
+
* Trust the `X-Forwarded-For` header when resolving `req.ip`.
|
|
42
|
+
*
|
|
43
|
+
* When `true`, `req.ip` is set to the **first** (leftmost) value in the
|
|
44
|
+
* `X-Forwarded-For` header, which is the IP address reported by the
|
|
45
|
+
* outermost client. This is the correct setting when the server sits behind
|
|
46
|
+
* a reverse proxy (e.g. nginx, AWS ALB) that injects this header.
|
|
47
|
+
*
|
|
48
|
+
* When `false` (default), `req.ip` contains the raw socket remote address
|
|
49
|
+
* and the `X-Forwarded-For` header is ignored. Use this mode when the
|
|
50
|
+
* server is directly internet-facing to prevent IP spoofing.
|
|
51
|
+
*
|
|
52
|
+
* @default false
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts
|
|
56
|
+
* // Behind a trusted reverse proxy
|
|
57
|
+
* const app = createRouter({ trustProxy: true });
|
|
58
|
+
* app.get('/me', (req, res) => res.send(req.ip));
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
trustProxy?: boolean;
|
|
62
|
+
}
|
|
5
63
|
/**
|
|
6
64
|
* Extended HTTP incoming message that carries parsed routing metadata.
|
|
7
65
|
* Augments the standard `http.IncomingMessage` with fields populated by
|
|
@@ -25,16 +83,64 @@ interface RouterRequest extends http.IncomingMessage {
|
|
|
25
83
|
params: StringMap;
|
|
26
84
|
/**
|
|
27
85
|
* Structured query buckets:
|
|
28
|
-
* - `url` — parameters parsed from the query string.
|
|
86
|
+
* - `url` — parameters parsed from the query string. Repeated keys
|
|
87
|
+
* (e.g. `?tag=a&tag=b`) produce an array value.
|
|
29
88
|
* - `route` — named parameters captured from the route pattern.
|
|
30
89
|
*/
|
|
31
90
|
queries: {
|
|
32
|
-
url?:
|
|
91
|
+
url?: Record<string, string | string[]>;
|
|
33
92
|
route?: StringMap;
|
|
34
93
|
};
|
|
35
|
-
/**
|
|
36
|
-
|
|
94
|
+
/**
|
|
95
|
+
* Parsed cookies sent with the request.
|
|
96
|
+
*
|
|
97
|
+
* Values are decoded automatically:
|
|
98
|
+
* - `j:` prefixed values are JSON-parsed and returned as their JS type.
|
|
99
|
+
* - `s:` prefixed values are HMAC-verified using the router secret; if
|
|
100
|
+
* valid, the inner value (decoded in turn) is returned. Cookies that
|
|
101
|
+
* fail verification are **not** included in this map.
|
|
102
|
+
* - Plain string values are returned unchanged.
|
|
103
|
+
*/
|
|
104
|
+
cookies: Record<string, unknown>;
|
|
105
|
+
/**
|
|
106
|
+
*
|
|
107
|
+
*/
|
|
108
|
+
body?: any;
|
|
109
|
+
/**
|
|
110
|
+
* Read and parse the request body as JSON.
|
|
111
|
+
*
|
|
112
|
+
* Returns the parsed value, or `null` when the request has no body.
|
|
113
|
+
* Rejects with `{ status, message }` on parse or transport errors.
|
|
114
|
+
*/
|
|
37
115
|
json(opts?: BodyOptions): Promise<unknown | null>;
|
|
116
|
+
/**
|
|
117
|
+
* The IP address of the remote client.
|
|
118
|
+
*
|
|
119
|
+
* - When the router is created with `{ trustProxy: true }`, this is the
|
|
120
|
+
* **first** value from the `X-Forwarded-For` header (the originating
|
|
121
|
+
* client address as reported by the proxy chain).
|
|
122
|
+
* - Otherwise this is the raw TCP socket remote address
|
|
123
|
+
* (`req.socket?.remoteAddress`), which cannot be spoofed by the client.
|
|
124
|
+
*
|
|
125
|
+
* Always an empty string when neither source is available.
|
|
126
|
+
*/
|
|
127
|
+
ip: string;
|
|
128
|
+
/**
|
|
129
|
+
* Read and decode the request body as plain text.
|
|
130
|
+
*
|
|
131
|
+
* Returns the body string (decoded using the charset in `Content-Type`,
|
|
132
|
+
* defaulting to UTF-8), or `null` when the request has no body.
|
|
133
|
+
* Rejects with `{ status, message }` on transport errors.
|
|
134
|
+
*/
|
|
135
|
+
text(opts?: BodyOptions): Promise<string | null>;
|
|
136
|
+
/**
|
|
137
|
+
* Read and parse the request body as `multipart/form-data`.
|
|
138
|
+
*
|
|
139
|
+
* Returns an array of {@link FormPart} objects, or `null` when the request
|
|
140
|
+
* has no body. Rejects with `{ status, message }` on parse or transport
|
|
141
|
+
* errors.
|
|
142
|
+
*/
|
|
143
|
+
formData(opts?: BodyOptions): Promise<FormPart[] | null>;
|
|
38
144
|
}
|
|
39
145
|
/**
|
|
40
146
|
* Extended HTTP server response with convenience helpers.
|
|
@@ -46,6 +152,7 @@ interface RouterResponse extends http.ServerResponse {
|
|
|
46
152
|
* Equivalent to `res.write(data); res.end()`.
|
|
47
153
|
*/
|
|
48
154
|
send(data?: string): void;
|
|
155
|
+
/** Serialise `data` as JSON, set `Content-Type: application/json`, and end. */
|
|
49
156
|
json(data: unknown): void;
|
|
50
157
|
/**
|
|
51
158
|
* Set the HTTP status code and optional response headers, then return
|
|
@@ -59,10 +166,72 @@ interface RouterResponse extends http.ServerResponse {
|
|
|
59
166
|
* Returns `this` to allow chaining.
|
|
60
167
|
*/
|
|
61
168
|
cookie(name: string, value: string | object, options?: CookieOptions): this;
|
|
169
|
+
/**
|
|
170
|
+
* Trigger a file download in the client's browser.
|
|
171
|
+
*
|
|
172
|
+
* Sets the `Content-Disposition: attachment` header (which prompts a
|
|
173
|
+
* "Save As" dialog in browsers), then streams the file at `filepath` using
|
|
174
|
+
* {@link sendFile}.
|
|
175
|
+
*
|
|
176
|
+
* @param filepath - Absolute or relative filesystem path to the file to send.
|
|
177
|
+
* @param filename - Override the file name advertised to the browser.
|
|
178
|
+
* Defaults to `path.basename(filepath)`.
|
|
179
|
+
*
|
|
180
|
+
* @example
|
|
181
|
+
* ```ts
|
|
182
|
+
* app.get('/invoice', (_req, res) =>
|
|
183
|
+
* res.download('/var/reports/2024-Q1.pdf', 'invoice-2024-Q1.pdf'));
|
|
184
|
+
* ```
|
|
185
|
+
*/
|
|
186
|
+
download(filepath: string, filename?: string): void;
|
|
187
|
+
/**
|
|
188
|
+
* Set the `Content-Type` response header and return `this` for chaining.
|
|
189
|
+
*
|
|
190
|
+
* The value is set verbatim — include the charset when needed
|
|
191
|
+
* (e.g. `'text/html; charset=utf-8'`).
|
|
192
|
+
*
|
|
193
|
+
* @param mime - The MIME type string to set.
|
|
194
|
+
* @returns `this` for chaining.
|
|
195
|
+
*
|
|
196
|
+
* @example
|
|
197
|
+
* ```ts
|
|
198
|
+
* res.type('text/csv').send(csvData);
|
|
199
|
+
* res.type('application/octet-stream').send(binaryData);
|
|
200
|
+
* ```
|
|
201
|
+
*/
|
|
202
|
+
type(mime: string): this;
|
|
203
|
+
/**
|
|
204
|
+
* Set the `ETag` response header.
|
|
205
|
+
*
|
|
206
|
+
* By default a **weak** ETag is produced (`W/"value"`), which indicates that
|
|
207
|
+
* the two representations are semantically equivalent but not byte-for-byte
|
|
208
|
+
* identical. Pass `true` as the second argument for a **strong** ETag
|
|
209
|
+
* (`"value"`), which implies byte-level equivalence and is required when
|
|
210
|
+
* byte-range requests must be validated.
|
|
211
|
+
*
|
|
212
|
+
* Returns `this` so calls can be chained before `res.send()` or `res.json()`.
|
|
213
|
+
*
|
|
214
|
+
* @param value - The opaque ETag value (without quotes or `W/` prefix).
|
|
215
|
+
* @param strong - When `true`, produce a strong ETag. Defaults to `false`.
|
|
216
|
+
* @returns `this` for chaining.
|
|
217
|
+
*
|
|
218
|
+
* @example
|
|
219
|
+
* ```ts
|
|
220
|
+
* // Weak ETag (default) — most appropriate for dynamic responses
|
|
221
|
+
* res.etag(user.updatedAt.toISOString()).json(user);
|
|
222
|
+
*
|
|
223
|
+
* // Strong ETag — use when the response body is content-addressed
|
|
224
|
+
* res.etag(sha256hex, true).send(fileContent);
|
|
225
|
+
* ```
|
|
226
|
+
*/
|
|
227
|
+
etag(value: string, strong?: boolean): this;
|
|
62
228
|
}
|
|
63
229
|
/** Options accepted by `res.cookie()`. */
|
|
64
230
|
interface CookieOptions {
|
|
65
|
-
/**
|
|
231
|
+
/**
|
|
232
|
+
* Sign the cookie value with HMAC-SHA256 using the router's `secret`.
|
|
233
|
+
* Requires `secret` to be passed to `createRouter()`.
|
|
234
|
+
*/
|
|
66
235
|
signed?: boolean;
|
|
67
236
|
/** Expiry date for the cookie. */
|
|
68
237
|
expires?: Date;
|
|
@@ -70,11 +239,29 @@ interface CookieOptions {
|
|
|
70
239
|
maxAge?: number;
|
|
71
240
|
/** Cookie path (defaults to `'/'`). */
|
|
72
241
|
path?: string;
|
|
242
|
+
/** Marks the cookie as `HttpOnly` (not accessible via `document.cookie`). */
|
|
243
|
+
httpOnly?: boolean;
|
|
244
|
+
/** Marks the cookie as `Secure` (only sent over HTTPS). */
|
|
245
|
+
secure?: boolean;
|
|
246
|
+
/** `SameSite` attribute value (`'Strict'`, `'Lax'`, or `'None'`). */
|
|
247
|
+
sameSite?: 'Strict' | 'Lax' | 'None';
|
|
73
248
|
}
|
|
74
|
-
/**
|
|
249
|
+
/**
|
|
250
|
+
* Options for HTTPS / HTTP/2 servers passed to `router.listen()`.
|
|
251
|
+
*
|
|
252
|
+
* When both `key` and `cert` are present, `listen()` creates a TLS server.
|
|
253
|
+
* Setting `http2: true` additionally upgrades to HTTP/2 (`http2.createSecureServer`).
|
|
254
|
+
*/
|
|
75
255
|
interface TlsOptions {
|
|
76
256
|
key: string | Buffer;
|
|
77
257
|
cert: string | Buffer;
|
|
258
|
+
/**
|
|
259
|
+
* When `true`, an HTTP/2 secure server (`http2.createSecureServer`) is
|
|
260
|
+
* created instead of an HTTPS/1.1 server. Requires `key` and `cert`.
|
|
261
|
+
* The existing middleware API is compatible with HTTP/2 request/response
|
|
262
|
+
* objects at runtime.
|
|
263
|
+
*/
|
|
264
|
+
http2?: boolean;
|
|
78
265
|
[key: string]: unknown;
|
|
79
266
|
}
|
|
80
267
|
/**
|
|
@@ -82,14 +269,58 @@ interface TlsOptions {
|
|
|
82
269
|
* and a `next` callback to hand control to the next registered middleware.
|
|
83
270
|
*/
|
|
84
271
|
type Middleware = (req: RouterRequest, res: RouterResponse, next: NextFunction) => void;
|
|
85
|
-
/**
|
|
86
|
-
|
|
272
|
+
/**
|
|
273
|
+
* Callback used to pass control to the next matching middleware.
|
|
274
|
+
*
|
|
275
|
+
* When called **without** arguments (or with `undefined`), the router
|
|
276
|
+
* continues to the next matching layer as usual.
|
|
277
|
+
*
|
|
278
|
+
* When called **with** a non-null argument, the argument is treated as an
|
|
279
|
+
* error: remaining middleware and routes are skipped and the handler
|
|
280
|
+
* registered via {@link Router.onError} is invoked. If no error handler
|
|
281
|
+
* has been registered, a plain **500** response is sent.
|
|
282
|
+
*
|
|
283
|
+
* @example
|
|
284
|
+
* ```ts
|
|
285
|
+
* router.use('/protected', (req, _res, next) => {
|
|
286
|
+
* if (!req.headers.authorization) return next(new Error('Unauthorized'));
|
|
287
|
+
* next(); // proceed normally
|
|
288
|
+
* });
|
|
289
|
+
* ```
|
|
290
|
+
*/
|
|
291
|
+
type NextFunction = (err?: unknown) => void;
|
|
292
|
+
/**
|
|
293
|
+
* Handler invoked when a middleware throws, an async middleware rejects,
|
|
294
|
+
* or `next(err)` is called with a non-null argument.
|
|
295
|
+
*
|
|
296
|
+
* Register it with {@link Router.onError}.
|
|
297
|
+
*
|
|
298
|
+
* @param err - The thrown value or the argument passed to `next()`.
|
|
299
|
+
* @param req - The current request.
|
|
300
|
+
* @param res - The current response (not yet ended — the handler must end it).
|
|
301
|
+
*/
|
|
302
|
+
type ErrorHandler = (err: unknown, req: RouterRequest, res: RouterResponse) => void;
|
|
87
303
|
/**
|
|
88
304
|
* A value that can be registered as a route handler: a single `Middleware`
|
|
89
305
|
* function, a `Router` instance (whose `listener` will be used), or an array
|
|
90
306
|
* of either. Arrays may not be nested.
|
|
91
307
|
*/
|
|
92
308
|
type MiddlewareArg = Middleware | Router | (Middleware | Router)[];
|
|
309
|
+
/**
|
|
310
|
+
* Sanitised description of a single registered route, as returned by
|
|
311
|
+
* {@link Router.routes}.
|
|
312
|
+
*/
|
|
313
|
+
interface RouteInfo {
|
|
314
|
+
/** HTTP method this layer is restricted to, or `null` for any method. */
|
|
315
|
+
method: string | null;
|
|
316
|
+
/** The original path pattern as supplied by the caller. */
|
|
317
|
+
path: string | RegExp;
|
|
318
|
+
/**
|
|
319
|
+
* `true` for prefix-style (`use`) registrations where the matched prefix
|
|
320
|
+
* is stripped from `req.path`; `false` for exact-method routes.
|
|
321
|
+
*/
|
|
322
|
+
stripPath: boolean;
|
|
323
|
+
}
|
|
93
324
|
/**
|
|
94
325
|
* Internal representation of a single registered route.
|
|
95
326
|
* One layer is created per middleware function for every `router.get(...)` /
|
|
@@ -137,15 +368,39 @@ interface Layer {
|
|
|
137
368
|
*/
|
|
138
369
|
interface Router {
|
|
139
370
|
/**
|
|
140
|
-
*
|
|
371
|
+
* The path prefix this router was created with, if any.
|
|
372
|
+
*
|
|
373
|
+
* Set by passing a string as the first argument to `createRouter()`:
|
|
374
|
+
* ```ts
|
|
375
|
+
* const v1 = createRouter('/api/v1');
|
|
376
|
+
* console.log(v1.prefix); // '/api/v1'
|
|
377
|
+
* ```
|
|
378
|
+
* When a prefixed router is passed to `parent.use(v1)`, the parent uses
|
|
379
|
+
* this prefix as the mount path automatically.
|
|
380
|
+
*/
|
|
381
|
+
readonly prefix?: string;
|
|
382
|
+
/**
|
|
383
|
+
* Register prefix-style middleware scoped to `path`.
|
|
384
|
+
*
|
|
141
385
|
* The matched path prefix is stripped from `req.path` before the middleware
|
|
142
|
-
*
|
|
386
|
+
* runs, so nested routers only see the remaining suffix.
|
|
143
387
|
* Equivalent to Express's `app.use()`.
|
|
388
|
+
*
|
|
389
|
+
* **No-path shortcut:** when the first argument is a `Router` or `Middleware`
|
|
390
|
+
* (not a string or RegExp), the path defaults to the router's own
|
|
391
|
+
* {@link prefix} (or `'/'` if no prefix was set). This lets you mount a
|
|
392
|
+
* prefixed sub-router without repeating the path:
|
|
393
|
+
*
|
|
394
|
+
* ```ts
|
|
395
|
+
* const v1 = createRouter('/api/v1');
|
|
396
|
+
* v1.get('/users', handler);
|
|
397
|
+
* app.use(v1); // same as app.use('/api/v1', v1)
|
|
398
|
+
* ```
|
|
144
399
|
*/
|
|
145
|
-
use(path: string | RegExp, ...args: MiddlewareArg[]): void;
|
|
400
|
+
use(path: string | RegExp | MiddlewareArg, ...args: MiddlewareArg[]): void;
|
|
146
401
|
/**
|
|
147
|
-
* Register middleware for all HTTP methods.
|
|
148
|
-
* Unlike `use`,
|
|
402
|
+
* Register middleware for all HTTP methods without stripping `req.path`.
|
|
403
|
+
* Unlike `use`, the full path remains visible to every chained middleware.
|
|
149
404
|
*/
|
|
150
405
|
all(path: string | RegExp, ...args: MiddlewareArg[]): void;
|
|
151
406
|
/** Register middleware for `GET` requests. */
|
|
@@ -159,11 +414,111 @@ interface Router {
|
|
|
159
414
|
/** Register middleware for `PATCH` requests. */
|
|
160
415
|
patch(path: string | RegExp, ...args: MiddlewareArg[]): void;
|
|
161
416
|
/**
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
417
|
+
* Register a global error handler for this router.
|
|
418
|
+
*
|
|
419
|
+
* The handler is called whenever:
|
|
420
|
+
* - A middleware throws synchronously.
|
|
421
|
+
* - An `async` middleware returns a rejected `Promise`.
|
|
422
|
+
* - Any middleware calls `next(err)` with a non-null argument.
|
|
423
|
+
*
|
|
424
|
+
* Only one handler is active at a time; subsequent calls replace the
|
|
425
|
+
* previous one. The handler **must** end the response.
|
|
426
|
+
*
|
|
427
|
+
* @example
|
|
428
|
+
* ```ts
|
|
429
|
+
* app.onError((err, _req, res) => {
|
|
430
|
+
* const status = (err as any)?.status ?? 500;
|
|
431
|
+
* res.status(status).json({ error: String(err) });
|
|
432
|
+
* });
|
|
433
|
+
* ```
|
|
434
|
+
*/
|
|
435
|
+
onError(handler: ErrorHandler): void;
|
|
436
|
+
/**
|
|
437
|
+
* Register a custom handler for requests that match no registered route.
|
|
438
|
+
*
|
|
439
|
+
* When no route matches and no `done()` callback was supplied to the
|
|
440
|
+
* listener, this handler is invoked instead of the built-in
|
|
441
|
+
* `Cannot METHOD /path` 404 response.
|
|
442
|
+
*
|
|
443
|
+
* Registering a not-found handler is an explicit, documented alternative to
|
|
444
|
+
* the `app.all('*', handler)` workaround — without the subtle path-stripping
|
|
445
|
+
* interactions that glob `use()` layers introduce.
|
|
446
|
+
*
|
|
447
|
+
* @example
|
|
448
|
+
* ```ts
|
|
449
|
+
* app.setNotFound((_req, res) =>
|
|
450
|
+
* res.status(404).json({ error: 'Not Found' }));
|
|
451
|
+
* ```
|
|
165
452
|
*/
|
|
166
|
-
|
|
453
|
+
setNotFound(handler: Middleware): void;
|
|
454
|
+
/**
|
|
455
|
+
* Return a read-only snapshot of all routes registered on this router.
|
|
456
|
+
*
|
|
457
|
+
* Useful for tooling, documentation generation, and debugging. The array
|
|
458
|
+
* is a fresh copy — mutating it does not affect the live route table.
|
|
459
|
+
*
|
|
460
|
+
* @returns An array of {@link RouteInfo} objects, one per registered layer,
|
|
461
|
+
* in registration order.
|
|
462
|
+
*
|
|
463
|
+
* @example
|
|
464
|
+
* ```ts
|
|
465
|
+
* app.get('/users', handler);
|
|
466
|
+
* app.post('/users', handler);
|
|
467
|
+
* console.log(app.routes());
|
|
468
|
+
* // [
|
|
469
|
+
* // { method: 'GET', path: '/users', stripPath: false },
|
|
470
|
+
* // { method: 'POST', path: '/users', stripPath: false },
|
|
471
|
+
* // ]
|
|
472
|
+
* ```
|
|
473
|
+
*/
|
|
474
|
+
routes(): RouteInfo[];
|
|
475
|
+
/**
|
|
476
|
+
* Gracefully shut down the HTTP(S) server created by `router.listen()`.
|
|
477
|
+
*
|
|
478
|
+
* Stops accepting new connections and waits for all existing connections to
|
|
479
|
+
* close naturally. After `timeout` milliseconds, any remaining sockets are
|
|
480
|
+
* forcibly destroyed so the process is not kept alive indefinitely.
|
|
481
|
+
*
|
|
482
|
+
* If `router.listen()` was never called on this router (e.g. it is a
|
|
483
|
+
* sub-router mounted inside a parent), `shutdown()` resolves immediately
|
|
484
|
+
* without doing anything.
|
|
485
|
+
*
|
|
486
|
+
* @param timeout - Grace period in milliseconds before sockets are forcibly
|
|
487
|
+
* destroyed. Defaults to `5000`. Pass `0` to skip the forced teardown.
|
|
488
|
+
* @returns A `Promise` that resolves when the server has fully stopped.
|
|
489
|
+
*
|
|
490
|
+
* @example
|
|
491
|
+
* ```ts
|
|
492
|
+
* const app = createRouter();
|
|
493
|
+
* app.listen(3000);
|
|
494
|
+
* process.on('SIGTERM', () => app.shutdown(10_000));
|
|
495
|
+
* ```
|
|
496
|
+
*/
|
|
497
|
+
shutdown(timeout?: number): Promise<void>;
|
|
498
|
+
/**
|
|
499
|
+
* Start listening on the given port and return the underlying server instance.
|
|
500
|
+
*
|
|
501
|
+
* When `opts` contains both `key` and `cert`:
|
|
502
|
+
* - An **HTTPS** server is created (TLS, HTTP/1.1).
|
|
503
|
+
* - Setting `opts.http2 = true` additionally upgrades to **HTTP/2**
|
|
504
|
+
* (`http2.createSecureServer`).
|
|
505
|
+
*
|
|
506
|
+
* When `opts` is absent or contains neither key nor cert, a plain **HTTP**
|
|
507
|
+
* server is used.
|
|
508
|
+
*
|
|
509
|
+
* @returns The underlying server instance. Use it for graceful shutdown,
|
|
510
|
+
* port discovery, or attaching additional event listeners.
|
|
511
|
+
*
|
|
512
|
+
* @example
|
|
513
|
+
* ```ts
|
|
514
|
+
* // Discover the OS-assigned ephemeral port
|
|
515
|
+
* const server = router.listen(0, () => {
|
|
516
|
+
* const { port } = server.address() as AddressInfo;
|
|
517
|
+
* console.log(`Listening on port ${port}`);
|
|
518
|
+
* });
|
|
519
|
+
* ```
|
|
520
|
+
*/
|
|
521
|
+
listen(port: number, opts?: TlsOptions | (() => void), cb?: () => void): http.Server | https.Server | http2.Http2SecureServer;
|
|
167
522
|
/**
|
|
168
523
|
* The underlying `(req, res, next)` function, allowing this router to be
|
|
169
524
|
* mounted as middleware inside another router:
|
|
@@ -179,49 +534,53 @@ interface Router {
|
|
|
179
534
|
* mounted inside another router:
|
|
180
535
|
* ```ts
|
|
181
536
|
* parent.use('/api', child);
|
|
537
|
+
* // or, if child has a prefix:
|
|
538
|
+
* parent.use(child);
|
|
539
|
+
* ```
|
|
540
|
+
*
|
|
541
|
+
* **Prefix shorthand:**
|
|
542
|
+
* Pass a path string as the first argument to associate a prefix with this
|
|
543
|
+
* router. The prefix is used automatically when the router is mounted via
|
|
544
|
+
* `parent.use(child)`:
|
|
545
|
+
* ```ts
|
|
546
|
+
* const v1 = createRouter('/api/v1');
|
|
547
|
+
* v1.get('/users', handler); // handler is reached at /api/v1/users
|
|
548
|
+
* app.use(v1); // same as app.use('/api/v1', v1)
|
|
182
549
|
* ```
|
|
183
550
|
*
|
|
184
551
|
* **Path patterns** accepted by all route-registration methods:
|
|
185
552
|
* - Plain strings with optional `:name` segments — e.g. `'/users/:id'`.
|
|
186
|
-
* Each `:name` is compiled to a named capture group and exposed in
|
|
187
|
-
* `req.params` on a match.
|
|
188
553
|
* - Glob strings following `.gitignore` rules — e.g. `'/**\/*.php'`.
|
|
189
|
-
* Supported wildcards: `?` (one non-slash char), `*` (any non-slash chars),
|
|
190
|
-
* `**` (any chars, including slashes).
|
|
191
554
|
* - `RegExp` objects — used directly; named groups become route parameters.
|
|
192
555
|
*
|
|
193
|
-
* **
|
|
194
|
-
*
|
|
195
|
-
*
|
|
196
|
-
* - A `Router` instance (its `listener` is registered automatically).
|
|
197
|
-
* - An array of either of the above.
|
|
556
|
+
* **Error handling:**
|
|
557
|
+
* Register a global error handler with `router.onError()`. It is called
|
|
558
|
+
* when any middleware throws, rejects, or calls `next(err)`.
|
|
198
559
|
*
|
|
199
|
-
* **
|
|
200
|
-
*
|
|
201
|
-
* invoking middleware. Nested routers therefore only see the remaining suffix.
|
|
202
|
-
* - `all` / `get` / `post` / `put` / `delete` / `patch` — leave `req.path` intact
|
|
203
|
-
* so that multiple middlewares registered for the same exact path can each
|
|
204
|
-
* match and be invoked in sequence via `next()`.
|
|
560
|
+
* **Graceful shutdown:**
|
|
561
|
+
* Call `router.shutdown()` to stop the server created by `router.listen()`.
|
|
205
562
|
*
|
|
206
|
-
* @
|
|
207
|
-
*
|
|
563
|
+
* @param prefixOrOpts - Optional path prefix string (e.g. `'/api/v1'`) **or**
|
|
564
|
+
* an {@link RouterOptions} object.
|
|
565
|
+
* @param opts - Options when `prefixOrOpts` is a string.
|
|
566
|
+
* @returns A fully initialised `Router`.
|
|
208
567
|
*
|
|
209
568
|
* @example
|
|
210
569
|
* ```ts
|
|
211
|
-
* const
|
|
212
|
-
*
|
|
213
|
-
*
|
|
570
|
+
* const app = createRouter({ secret: process.env.COOKIE_SECRET, timeout: 30_000 });
|
|
571
|
+
*
|
|
572
|
+
* const v1 = createRouter('/api/v1');
|
|
573
|
+
* v1.get('/users', handler);
|
|
214
574
|
*
|
|
215
|
-
*
|
|
216
|
-
* app.
|
|
217
|
-
* app.
|
|
218
|
-
* app.get('/**\/*.php', (req, res) => // glob pattern
|
|
219
|
-
* res.status(403).send('Forbidden'));
|
|
575
|
+
* app.use(v1);
|
|
576
|
+
* app.onError((err, _req, res) => res.status(500).json({ error: String(err) }));
|
|
577
|
+
* app.setNotFound((_req, res) => res.status(404).json({ error: 'Not Found' }));
|
|
220
578
|
*
|
|
221
|
-
* app.listen(3000, () => console.log('Listening
|
|
579
|
+
* app.listen(3000, () => console.log('Listening'));
|
|
580
|
+
* process.on('SIGTERM', () => app.shutdown(10_000));
|
|
222
581
|
* ```
|
|
223
582
|
*/
|
|
224
|
-
declare function createRouter(): Router;
|
|
583
|
+
declare function createRouter(prefixOrOpts?: string | RouterOptions, opts?: RouterOptions): Router;
|
|
225
584
|
export default createRouter;
|
|
226
|
-
export type { Router, RouterRequest, RouterResponse, Middleware, MiddlewareArg, NextFunction, Layer, CookieOptions, TlsOptions, StringMap, };
|
|
585
|
+
export type { Router, RouterOptions, RouterRequest, RouterResponse, Middleware, MiddlewareArg, NextFunction, ErrorHandler, Layer, RouteInfo, CookieOptions, TlsOptions, StringMap, };
|
|
227
586
|
//# sourceMappingURL=router.d.ts.map
|
package/dist/router.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"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"}
|