@fougere/http 0.1.0-alpha.0 → 0.2.0-alpha.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.
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Express adapter — bridges an Express app to the HttpRouter interface.
3
+ *
4
+ * The one that is not Web-standard, and that is the whole substance of this file.
5
+ * Hono hands over `c.req.raw`, Fastify parses the body for us; Express hands a
6
+ * Node `IncomingMessage` and parses nothing unless the app happens to have mounted
7
+ * `express.json()`. So the conversion lives here — read the stream when nobody
8
+ * else did, and build the `Request` the interface promises.
9
+ *
10
+ * Working with or without `express.json()` is deliberate: an adapter that only
11
+ * works when the host app is configured a particular way is a footgun, and this
12
+ * one is meant to be dropped into an app that already exists.
13
+ */
14
+ import { type HttpRouter } from './router.js';
15
+ interface ExpressLike {
16
+ use(...handlers: Function[]): void;
17
+ get(path: string, handler: Function): void;
18
+ post(path: string, handler: Function): void;
19
+ put(path: string, handler: Function): void;
20
+ patch(path: string, handler: Function): void;
21
+ delete(path: string, handler: Function): void;
22
+ }
23
+ /** Drain the Node stream. Only reached when no body parser ran before us. */
24
+ export declare function readRawBody(req: any): Promise<string>;
25
+ /**
26
+ * The JSON body of an Express request, whoever parsed it.
27
+ *
28
+ * Exported because two consumers need the same Express fact: this adapter, and the
29
+ * middlewares in `@fougere/app/express`. `express.json()` may or may not have run —
30
+ * an adapter that only works when the host app is configured a particular way is a
31
+ * footgun — so this trusts `req.body` when it is there and drains the stream when it
32
+ * is not. Parsed once per request: a drained stream answers empty the second time.
33
+ */
34
+ export declare function readExpressBody(req: any): Promise<unknown>;
35
+ /**
36
+ * Create an HttpRouter backed by an Express app.
37
+ *
38
+ * ```ts
39
+ * import express from 'express'
40
+ * import { createExpressRouter } from '@fougere/http'
41
+ *
42
+ * const app = express()
43
+ * const router = createExpressRouter(app)
44
+ * ```
45
+ */
46
+ export declare function createExpressRouter(app: ExpressLike): HttpRouter;
47
+ export {};
48
+ //# sourceMappingURL=express.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"express.d.ts","sourceRoot":"","sources":["../src/express.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAsB,KAAK,UAAU,EAA4F,MAAM,aAAa,CAAC;AAE5J,UAAU,WAAW;IACnB,GAAG,CAAC,GAAG,QAAQ,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IACnC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC3C,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC5C,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC3C,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC7C,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,GAAG,IAAI,CAAC;CAC/C;AAYD,6EAA6E;AAC7E,wBAAgB,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,CAkBrD;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,CAkB1D;AA6CD;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,WAAW,GAAG,UAAU,CAsDhE"}
@@ -0,0 +1,181 @@
1
+ /**
2
+ * Express adapter — bridges an Express app to the HttpRouter interface.
3
+ *
4
+ * The one that is not Web-standard, and that is the whole substance of this file.
5
+ * Hono hands over `c.req.raw`, Fastify parses the body for us; Express hands a
6
+ * Node `IncomingMessage` and parses nothing unless the app happens to have mounted
7
+ * `express.json()`. So the conversion lives here — read the stream when nobody
8
+ * else did, and build the `Request` the interface promises.
9
+ *
10
+ * Working with or without `express.json()` is deliberate: an adapter that only
11
+ * works when the host app is configured a particular way is a footgun, and this
12
+ * one is meant to be dropped into an app that already exists.
13
+ */
14
+ import { MalformedJsonError } from './router.js';
15
+ const METHOD_MAP = {
16
+ GET: 'get',
17
+ POST: 'post',
18
+ PUT: 'put',
19
+ PATCH: 'patch',
20
+ DELETE: 'delete',
21
+ };
22
+ const MAX_BODY_BYTES = 1024 * 1024;
23
+ /** Drain the Node stream. Only reached when no body parser ran before us. */
24
+ export function readRawBody(req) {
25
+ return new Promise((resolve, reject) => {
26
+ const chunks = [];
27
+ let size = 0;
28
+ let exceeded = false;
29
+ req.on('data', (chunk) => {
30
+ if (exceeded)
31
+ return;
32
+ size += chunk.length;
33
+ if (size > MAX_BODY_BYTES) {
34
+ exceeded = true;
35
+ reject(Object.assign(new Error('Payload too large'), { statusCode: 413 }));
36
+ return;
37
+ }
38
+ chunks.push(Buffer.from(chunk));
39
+ });
40
+ req.on('end', () => { if (!exceeded)
41
+ resolve(Buffer.concat(chunks).toString('utf8')); });
42
+ req.on('error', reject);
43
+ });
44
+ }
45
+ /**
46
+ * The JSON body of an Express request, whoever parsed it.
47
+ *
48
+ * Exported because two consumers need the same Express fact: this adapter, and the
49
+ * middlewares in `@fougere/app/express`. `express.json()` may or may not have run —
50
+ * an adapter that only works when the host app is configured a particular way is a
51
+ * footgun — so this trusts `req.body` when it is there and drains the stream when it
52
+ * is not. Parsed once per request: a drained stream answers empty the second time.
53
+ */
54
+ export function readExpressBody(req) {
55
+ if (req.__fougereBody)
56
+ return req.__fougereBody;
57
+ const verb = String(req.method ?? 'GET').toUpperCase();
58
+ req.__fougereBody = (async () => {
59
+ if (verb === 'GET' || verb === 'HEAD')
60
+ return {};
61
+ if (req.body !== undefined && req.body !== null)
62
+ return req.body;
63
+ const contentType = String(req.headers?.['content-type'] ?? '');
64
+ if (!contentType.toLowerCase().includes('json'))
65
+ return {};
66
+ const raw = await readRawBody(req);
67
+ if (!raw)
68
+ return {};
69
+ try {
70
+ return JSON.parse(raw);
71
+ }
72
+ catch (cause) {
73
+ throw new MalformedJsonError({ cause });
74
+ }
75
+ })();
76
+ return req.__fougereBody;
77
+ }
78
+ function buildContext(req) {
79
+ const host = req.headers?.host ?? 'localhost';
80
+ const protocol = req.protocol ?? 'http';
81
+ const url = `${protocol}://${host}${req.originalUrl ?? req.url}`;
82
+ // Kept as a plain string: a real request may be HEAD or OPTIONS, which the
83
+ // interface's `HttpMethod` does not name. Casting here would have made the
84
+ // "does this verb carry a body" question unaskable — it is asked below.
85
+ const verb = req.method.toUpperCase();
86
+ const headers = new Headers(Object.entries(req.headers ?? {})
87
+ .filter((entry) => typeof entry[1] === 'string'));
88
+ // One reader for both consumers — see `readExpressBody`.
89
+ const body = () => readExpressBody(req);
90
+ return {
91
+ // The Request carries no body: Express may have consumed the stream already,
92
+ // and a Request built around a drained one lies. `body()` is the honest reader,
93
+ // and it is what every consumer in this repo calls.
94
+ request: new Request(url, { method: verb, headers }),
95
+ method: verb,
96
+ path: req.path ?? (req.originalUrl ?? req.url ?? '').split('?')[0],
97
+ params: req.params ?? {},
98
+ query: Object.fromEntries(Object.entries(req.query ?? {}).map(([key, value]) => [key, String(Array.isArray(value) ? value[0] : value)])),
99
+ body,
100
+ state: {},
101
+ };
102
+ }
103
+ function sendResponse(res, result) {
104
+ if (result.headers) {
105
+ for (const [key, value] of Object.entries(result.headers))
106
+ res.set(key, value);
107
+ }
108
+ res.status(result.status);
109
+ // `raw` means "do not JSON-serialize" — `send` on a string writes it as-is, and
110
+ // the content-type rides in `headers`, stated by the producer rather than guessed.
111
+ if (result.raw)
112
+ res.send(result.data);
113
+ else
114
+ res.json(result.data);
115
+ }
116
+ /**
117
+ * Create an HttpRouter backed by an Express app.
118
+ *
119
+ * ```ts
120
+ * import express from 'express'
121
+ * import { createExpressRouter } from '@fougere/http'
122
+ *
123
+ * const app = express()
124
+ * const router = createExpressRouter(app)
125
+ * ```
126
+ */
127
+ export function createExpressRouter(app) {
128
+ const globalMiddlewares = [];
129
+ const scopedMiddlewares = [];
130
+ // Run matching middlewares as an onion chain around the handler
131
+ function runMiddlewares(ctx, handler) {
132
+ const matching = [
133
+ ...globalMiddlewares,
134
+ ...scopedMiddlewares.filter((s) => ctx.path.startsWith(s.path)).map((s) => s.mw),
135
+ ];
136
+ let index = 0;
137
+ const next = () => {
138
+ if (index < matching.length)
139
+ return matching[index++](ctx, next);
140
+ return handler(ctx);
141
+ };
142
+ return next();
143
+ }
144
+ return {
145
+ use(...args) {
146
+ const [pathOrMw, maybeMw] = args;
147
+ if (typeof pathOrMw === 'string') {
148
+ // Strip a trailing /* — prefix matching here is `startsWith`, as in the
149
+ // Fastify adapter, and Express 5 spells its own splat differently anyway.
150
+ scopedMiddlewares.push({ path: pathOrMw.replace(/\/\*$/, ''), mw: maybeMw });
151
+ }
152
+ else {
153
+ globalMiddlewares.push(pathOrMw);
154
+ }
155
+ },
156
+ on(method, path, handler) {
157
+ app[METHOD_MAP[method]](path, async (req, res, next) => {
158
+ try {
159
+ sendResponse(res, await runMiddlewares(buildContext(req), handler));
160
+ }
161
+ catch (err) {
162
+ // This adapter is the one that parses JSON, so it is the one that answers
163
+ // for it — same 400 the Hono adapter gives, which is the other self-parsing
164
+ // one. Fastify's own parser answers before we ever see the request.
165
+ if (err instanceof MalformedJsonError) {
166
+ sendResponse(res, { status: 400, data: { code: 'BAD_REQUEST', message: 'Malformed JSON body' } });
167
+ return;
168
+ }
169
+ if (err?.statusCode === 413) {
170
+ sendResponse(res, { status: 413, data: { code: 'PAYLOAD_TOO_LARGE', message: 'Payload too large' } });
171
+ return;
172
+ }
173
+ // Anything else goes to Express's error pipeline rather than crashing the
174
+ // process — an app that already has an error handler keeps using it.
175
+ next(err);
176
+ }
177
+ });
178
+ },
179
+ };
180
+ }
181
+ //# sourceMappingURL=express.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"express.js","sourceRoot":"","sources":["../src/express.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -2,5 +2,6 @@ export type { HttpMethod, RequestContext, ResponseResult, Handler, Next, Middlew
2
2
  export { MalformedJsonError } from './router.js';
3
3
  export { createHonoRouter } from './hono.js';
4
4
  export { createFastifyRouter } from './fastify.js';
5
+ export { createExpressRouter, readExpressBody } from './express.js';
5
6
  export { httpLogger } from './logger.js';
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,UAAU,EACV,cAAc,EACd,cAAc,EACd,OAAO,EACP,IAAI,EACJ,UAAU,EACV,UAAU,GACX,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,UAAU,EACV,cAAc,EACd,cAAc,EACd,OAAO,EACP,IAAI,EACJ,UAAU,EACV,UAAU,GACX,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  export { MalformedJsonError } from './router.js';
2
2
  export { createHonoRouter } from './hono.js';
3
3
  export { createFastifyRouter } from './fastify.js';
4
+ export { createExpressRouter, readExpressBody } from './express.js';
4
5
  export { httpLogger } from './logger.js';
5
6
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,14 @@
1
1
  {
2
2
  "name": "@fougere/http",
3
- "version": "0.1.0-alpha.0",
3
+ "version": "0.2.0-alpha.0",
4
4
  "description": "HTTP router and middleware.",
5
+ "keywords": [
6
+ "fougere",
7
+ "typescript",
8
+ "http",
9
+ "router",
10
+ "middleware"
11
+ ],
5
12
  "license": "MIT",
6
13
  "repository": {
7
14
  "type": "git",