expediate 0.0.3 → 1.0.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/dist/misc.d.ts ADDED
@@ -0,0 +1,203 @@
1
+ import type { RouterRequest, Middleware } from './router.js';
2
+ /**
3
+ * A JSON reviver function, matching the second parameter of `JSON.parse`.
4
+ * Receives each key/value pair during parsing and may return a transformed
5
+ * value.
6
+ */
7
+ type Reviver = (key: string, value: unknown) => unknown;
8
+ /**
9
+ * Options shared by all body-parsing middleware factories
10
+ * ({@link json}, {@link formData}, {@link parseBody}).
11
+ */
12
+ export interface BodyOptions {
13
+ /**
14
+ * When `true` (default), compressed request bodies (`gzip`, `deflate`) are
15
+ * automatically decompressed before parsing. Set to `false` to reject
16
+ * compressed bodies with 415 Unsupported Media Type.
17
+ */
18
+ inflate?: boolean;
19
+ /**
20
+ * Maximum accepted body size. Accepts a number (bytes) or a human-readable
21
+ * string such as `'100kb'`, `'2mb'`, or `'1gb'`.
22
+ * Defaults to `'100kb'` (102 400 bytes).
23
+ */
24
+ limit?: string | number;
25
+ /**
26
+ * Optional JSON reviver passed as the second argument to `JSON.parse`.
27
+ * Only meaningful for {@link json} and {@link parseBody} when the body is
28
+ * `application/json`.
29
+ */
30
+ reviver?: Reviver | null;
31
+ /**
32
+ * When `true` (default), JSON parsing is restricted to objects and arrays.
33
+ * Bare primitives (strings, numbers, booleans) at the top level are
34
+ * rejected. Has no effect on non-JSON bodies.
35
+ *
36
+ * @remarks Currently reserved for future enforcement; not yet applied.
37
+ */
38
+ strict?: boolean;
39
+ }
40
+ /**
41
+ * Options for the {@link logger} middleware factory.
42
+ */
43
+ export interface LoggerOptions {
44
+ /**
45
+ * When `true`, starts a timer per request. If the response is not finished
46
+ * within {@link trackTimeout} milliseconds, a `LOST` warning line is logged.
47
+ * Recommended for development only — keeping a `setTimeout` per request has
48
+ * a non-trivial memory cost in production.
49
+ * Defaults to `false`.
50
+ */
51
+ track?: boolean;
52
+ /**
53
+ * Timeout in milliseconds before a tracked request is considered lost.
54
+ * Only used when {@link track} is `true`.
55
+ * Defaults to `30 000` ms (30 seconds).
56
+ */
57
+ trackTimeout?: number;
58
+ /**
59
+ * Extract a user identity string from the request for inclusion in the log
60
+ * line. Receives the augmented `RouterRequest` and should return a short
61
+ * string (e.g. a username, session ID, or `'-'` for anonymous).
62
+ * Defaults to always returning `'-'`.
63
+ *
64
+ * @example
65
+ * ```ts
66
+ * user: (req) => (req as any).authUser ?? '-'
67
+ * ```
68
+ */
69
+ user?: (req: RouterRequest) => string;
70
+ /**
71
+ * BCP 47 locale tag used when formatting the request timestamp.
72
+ * Passed as the first argument to `Intl.DateTimeFormat`.
73
+ * Defaults to `'en-GB'`.
74
+ */
75
+ locale?: string;
76
+ /**
77
+ * Date/time format options passed as the second argument to
78
+ * `Intl.DateTimeFormat`. Override this to change which fields are shown in
79
+ * the timestamp.
80
+ * Defaults to `{ month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit' }`.
81
+ */
82
+ dateFormat?: Intl.DateTimeFormatOptions;
83
+ /**
84
+ * Custom logging function. Receives the fully-formatted log line as a
85
+ * single string. Defaults to `console.log`.
86
+ */
87
+ logger?: (msg: string) => void;
88
+ }
89
+ /**
90
+ * A single part extracted from a `multipart/form-data` body.
91
+ */
92
+ export interface FormPart {
93
+ /**
94
+ * Raw part headers (e.g. `Content-Disposition`, `Content-Type`).
95
+ * Keys are lowercased; values are trimmed.
96
+ */
97
+ headers: Record<string, string>;
98
+ /**
99
+ * Raw binary content of the part (everything after the blank header line).
100
+ */
101
+ content: Buffer;
102
+ }
103
+ /**
104
+ * Middleware factory that parses a `application/json` request body and
105
+ * assigns the parsed value to `req.body`.
106
+ *
107
+ * Also attaches a `res.json(data)` helper to the response object so that
108
+ * handlers can send JSON responses conveniently:
109
+ * ```ts
110
+ * res.json({ ok: true });
111
+ * ```
112
+ *
113
+ * Behaviour:
114
+ * - Requests without a body (`Content-Length: 0` or absent) are passed
115
+ * through to `next()` without touching `req.body`.
116
+ * - Bodies larger than `opts.limit` receive **413 Content Too Large**.
117
+ * - Bodies with an unsupported `Content-Encoding` receive
118
+ * **415 Unsupported Media Type**.
119
+ * - Bodies whose `Content-Type` is not `application/json` receive
120
+ * **415 Unsupported Media Type**.
121
+ * - Parse errors receive **500 Internal Server Error**.
122
+ *
123
+ * @param opts - Optional configuration (see {@link BodyOptions}).
124
+ * @returns An Express-compatible middleware function.
125
+ */
126
+ export declare function json(opts?: BodyOptions): Middleware;
127
+ /**
128
+ * Middleware factory that parses a `multipart/form-data` request body and
129
+ * assigns an array of {@link FormPart} objects to `req.body`.
130
+ *
131
+ * Each element in `req.body` exposes:
132
+ * - `headers` — the part's MIME headers (e.g. `Content-Disposition`).
133
+ * - `content` — the raw binary content of the part as a `Buffer`.
134
+ *
135
+ * Behaviour:
136
+ * - Requests without a body are passed through to `next()`.
137
+ * - Bodies larger than `opts.limit` receive **413 Content Too Large**.
138
+ * - Bodies with a missing or malformed `boundary` parameter receive
139
+ * **400 Bad Request**.
140
+ * - Parse errors receive **500 Internal Server Error**.
141
+ *
142
+ * @param opts - Optional configuration (see {@link BodyOptions}).
143
+ * @returns An Express-compatible middleware function.
144
+ */
145
+ export declare function formData(opts?: BodyOptions): Middleware;
146
+ /**
147
+ * Middleware factory that auto-detects the `Content-Type` of the request body
148
+ * and parses it using the appropriate parser.
149
+ *
150
+ * Supported MIME types:
151
+ * - `application/json` → parsed as JSON; result is a JS value.
152
+ * - `multipart/form-data` → parsed as multipart; result is `FormPart[]`.
153
+ * - `text/plain` → decoded as text; result is a string.
154
+ *
155
+ * Requests with an unsupported MIME type receive **415 Unsupported Media Type**.
156
+ * All other error conditions behave identically to {@link json} and
157
+ * {@link formData}.
158
+ *
159
+ * @param opts - Optional configuration (see {@link BodyOptions}).
160
+ * @returns An Express-compatible middleware function.
161
+ */
162
+ export declare function parseBody(opts?: BodyOptions): Middleware;
163
+ /**
164
+ * Middleware factory that logs one line per completed HTTP request to the
165
+ * console (or a custom logger function).
166
+ *
167
+ * Each log line contains:
168
+ * - Timestamp (formatted with `Intl.DateTimeFormat`).
169
+ * - HTTP status code (ANSI-coloured by status class).
170
+ * - HTTP method and request path.
171
+ * - Client IP address (honours `X-Forwarded-For`).
172
+ * - User identity (from `opts.user` or `'-'`).
173
+ * - Elapsed time in milliseconds.
174
+ * - Response `Content-Length` (or `'-'` when absent).
175
+ *
176
+ * **Lost-request tracking:** when `opts.track` is `true`, a timer is started
177
+ * for each request. If the response is not finished within `opts.trackTimeout`
178
+ * milliseconds, a `LOST` warning line is emitted. This is useful in
179
+ * development to surface handlers that never call `res.end()`.
180
+ *
181
+ * @param opts - Optional configuration (see {@link LoggerOptions}).
182
+ * @returns An Express-compatible middleware function.
183
+ *
184
+ * @example
185
+ * ```ts
186
+ * app.use('/', logger({
187
+ * track: true,
188
+ * trackTimeout: 30_000,
189
+ * user: (req) => (req as any).authUser ?? '-',
190
+ * locale: 'en-US',
191
+ * logger: (msg) => process.stderr.write(msg + '\n'),
192
+ * }));
193
+ * ```
194
+ */
195
+ export declare function logger(opts?: LoggerOptions): Middleware;
196
+ declare const _default: {
197
+ json: typeof json;
198
+ formData: typeof formData;
199
+ parseBody: typeof parseBody;
200
+ logger: typeof logger;
201
+ };
202
+ export default _default;
203
+ //# sourceMappingURL=misc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"misc.d.ts","sourceRoot":"","sources":["../src/misc.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,aAAa,EAAkB,UAAU,EAAE,MAAM,aAAa,CAAC;AAM7E;;;;GAIG;AACH,KAAK,OAAO,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;AAExD;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACzB;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAKD;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;;;;;;OAUG;IACH,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,aAAa,KAAK,MAAM,CAAC;IACtC;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,IAAI,CAAC,qBAAqB,CAAC;IACxC;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;CACjB;AAuXD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,IAAI,CAAC,IAAI,CAAC,EAAE,WAAW,GAAG,UAAU,CAmBnD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,QAAQ,CAAC,IAAI,CAAC,EAAE,WAAW,GAAG,UAAU,CAcvD;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,SAAS,CAAC,IAAI,CAAC,EAAE,WAAW,GAAG,UAAU,CAiBxD;AA4BD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,MAAM,CAAC,IAAI,CAAC,EAAE,aAAa,GAAG,UAAU,CAkDvD;;;;;;;AAED,wBAAqD"}