express-fastify-runtime 0.1.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/LICENSE +21 -0
- package/README.md +326 -0
- package/changelog/README.md +5 -0
- package/changelog/log-2025-02-07.md +10 -0
- package/changelog/log-2026-06-25.md +151 -0
- package/dist/app/ExpressLikeApp.d.ts +9 -0
- package/dist/app/ExpressLikeApp.d.ts.map +1 -0
- package/dist/app/ExpressLikeApp.js +64 -0
- package/dist/app/ExpressLikeApp.js.map +1 -0
- package/dist/app/RouteStore.d.ts +17 -0
- package/dist/app/RouteStore.d.ts.map +1 -0
- package/dist/app/RouteStore.js +43 -0
- package/dist/app/RouteStore.js.map +1 -0
- package/dist/app/classify.d.ts +8 -0
- package/dist/app/classify.d.ts.map +1 -0
- package/dist/app/classify.js +25 -0
- package/dist/app/classify.js.map +1 -0
- package/dist/app/compile.d.ts +25 -0
- package/dist/app/compile.d.ts.map +1 -0
- package/dist/app/compile.js +195 -0
- package/dist/app/compile.js.map +1 -0
- package/dist/app/flattenRouter.d.ts +51 -0
- package/dist/app/flattenRouter.d.ts.map +1 -0
- package/dist/app/flattenRouter.js +126 -0
- package/dist/app/flattenRouter.js.map +1 -0
- package/dist/app/introspectExpress.d.ts +29 -0
- package/dist/app/introspectExpress.d.ts.map +1 -0
- package/dist/app/introspectExpress.js +60 -0
- package/dist/app/introspectExpress.js.map +1 -0
- package/dist/examples/auth.d.ts +6 -0
- package/dist/examples/auth.d.ts.map +1 -0
- package/dist/examples/auth.js +26 -0
- package/dist/examples/auth.js.map +1 -0
- package/dist/examples/logging.d.ts +6 -0
- package/dist/examples/logging.d.ts.map +1 -0
- package/dist/examples/logging.js +25 -0
- package/dist/examples/logging.js.map +1 -0
- package/dist/examples/uploads.d.ts +6 -0
- package/dist/examples/uploads.d.ts.map +1 -0
- package/dist/examples/uploads.js +21 -0
- package/dist/examples/uploads.js.map +1 -0
- package/dist/express/engine.d.ts +6 -0
- package/dist/express/engine.d.ts.map +1 -0
- package/dist/express/engine.js +14 -0
- package/dist/express/engine.js.map +1 -0
- package/dist/express/middleware.d.ts +15 -0
- package/dist/express/middleware.d.ts.map +1 -0
- package/dist/express/middleware.js +32 -0
- package/dist/express/middleware.js.map +1 -0
- package/dist/express/mount.d.ts +35 -0
- package/dist/express/mount.d.ts.map +1 -0
- package/dist/express/mount.js +78 -0
- package/dist/express/mount.js.map +1 -0
- package/dist/fastify/adapters/middleware.d.ts +8 -0
- package/dist/fastify/adapters/middleware.d.ts.map +1 -0
- package/dist/fastify/adapters/middleware.js +29 -0
- package/dist/fastify/adapters/middleware.js.map +1 -0
- package/dist/fastify/adapters/request.d.ts +19 -0
- package/dist/fastify/adapters/request.d.ts.map +1 -0
- package/dist/fastify/adapters/request.js +258 -0
- package/dist/fastify/adapters/request.js.map +1 -0
- package/dist/fastify/adapters/response.d.ts +19 -0
- package/dist/fastify/adapters/response.d.ts.map +1 -0
- package/dist/fastify/adapters/response.js +667 -0
- package/dist/fastify/adapters/response.js.map +1 -0
- package/dist/fastify/register.d.ts +12 -0
- package/dist/fastify/register.d.ts.map +1 -0
- package/dist/fastify/register.js +15 -0
- package/dist/fastify/register.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/runtime/decorators.d.ts +7 -0
- package/dist/runtime/decorators.d.ts.map +1 -0
- package/dist/runtime/decorators.js +17 -0
- package/dist/runtime/decorators.js.map +1 -0
- package/dist/runtime/errorHandler.d.ts +13 -0
- package/dist/runtime/errorHandler.d.ts.map +1 -0
- package/dist/runtime/errorHandler.js +95 -0
- package/dist/runtime/errorHandler.js.map +1 -0
- package/dist/runtime/expressLane.d.ts +40 -0
- package/dist/runtime/expressLane.d.ts.map +1 -0
- package/dist/runtime/expressLane.js +71 -0
- package/dist/runtime/expressLane.js.map +1 -0
- package/dist/runtime/fast.d.ts +43 -0
- package/dist/runtime/fast.d.ts.map +1 -0
- package/dist/runtime/fast.js +150 -0
- package/dist/runtime/fast.js.map +1 -0
- package/dist/runtime/lifecycle.d.ts +10 -0
- package/dist/runtime/lifecycle.d.ts.map +1 -0
- package/dist/runtime/lifecycle.js +152 -0
- package/dist/runtime/lifecycle.js.map +1 -0
- package/dist/runtime/populateExpress.d.ts +7 -0
- package/dist/runtime/populateExpress.d.ts.map +1 -0
- package/dist/runtime/populateExpress.js +27 -0
- package/dist/runtime/populateExpress.js.map +1 -0
- package/dist/types/express.d.ts +97 -0
- package/dist/types/express.d.ts.map +1 -0
- package/dist/types/express.js +12 -0
- package/dist/types/express.js.map +1 -0
- package/dist/types/internal.d.ts +60 -0
- package/dist/types/internal.d.ts.map +1 -0
- package/dist/types/internal.js +7 -0
- package/dist/types/internal.js.map +1 -0
- package/dist/utils/assert.d.ts +6 -0
- package/dist/utils/assert.d.ts.map +1 -0
- package/dist/utils/assert.js +17 -0
- package/dist/utils/assert.js.map +1 -0
- package/dist/utils/detect.d.ts +14 -0
- package/dist/utils/detect.d.ts.map +1 -0
- package/dist/utils/detect.js +64 -0
- package/dist/utils/detect.js.map +1 -0
- package/dist/utils/maxListeners.d.ts +28 -0
- package/dist/utils/maxListeners.d.ts.map +1 -0
- package/dist/utils/maxListeners.js +50 -0
- package/dist/utils/maxListeners.js.map +1 -0
- package/dist/utils/patchRouterLayer.d.ts +12 -0
- package/dist/utils/patchRouterLayer.d.ts.map +1 -0
- package/dist/utils/patchRouterLayer.js +96 -0
- package/dist/utils/patchRouterLayer.js.map +1 -0
- package/dist/utils/path.d.ts +6 -0
- package/dist/utils/path.d.ts.map +1 -0
- package/dist/utils/path.js +23 -0
- package/dist/utils/path.js.map +1 -0
- package/dist/utils/runtimeLogger.d.ts +15 -0
- package/dist/utils/runtimeLogger.d.ts.map +1 -0
- package/dist/utils/runtimeLogger.js +28 -0
- package/dist/utils/runtimeLogger.js.map +1 -0
- package/dist/utils/unwrap.d.ts +12 -0
- package/dist/utils/unwrap.d.ts.map +1 -0
- package/dist/utils/unwrap.js +24 -0
- package/dist/utils/unwrap.js.map +1 -0
- package/package.json +94 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Example: auth middleware (Fastify-safe).
|
|
4
|
+
* Same API as Express; runs on Fastify lane.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const index_1 = require("../index");
|
|
8
|
+
const app = (0, index_1.createApp)();
|
|
9
|
+
// Auth middleware – safe for Fastify
|
|
10
|
+
app.use((req, res, next) => {
|
|
11
|
+
const token = req.get('authorization');
|
|
12
|
+
if (!token) {
|
|
13
|
+
res.status(401).json({ error: 'Unauthorized' });
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
req.user = { id: '1', name: 'User' };
|
|
17
|
+
next();
|
|
18
|
+
});
|
|
19
|
+
app.get('/me', (req, res) => {
|
|
20
|
+
const user = req.user;
|
|
21
|
+
res.json({ user });
|
|
22
|
+
});
|
|
23
|
+
app.listen(3000, () => {
|
|
24
|
+
console.log('Auth example: http://localhost:3000/me');
|
|
25
|
+
});
|
|
26
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/examples/auth.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAEH,oCAAqC;AAGrC,MAAM,GAAG,GAAG,IAAA,iBAAS,GAAE,CAAC;AAExB,qCAAqC;AACrC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAmB,EAAE,GAAoB,EAAE,IAAkB,EAAE,EAAE;IACxE,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACvC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC;QAChD,OAAO;IACT,CAAC;IACA,GAA2C,CAAC,IAAI,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC9E,IAAI,EAAE,CAAC;AACT,CAAC,CAAC,CAAC;AAEH,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,GAAmB,EAAE,GAAoB,EAAE,EAAE;IAC3D,MAAM,IAAI,GAAI,GAA2C,CAAC,IAAI,CAAC;IAC/D,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;AACrB,CAAC,CAAC,CAAC;AAEH,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;IACpB,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;AACxD,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logging.d.ts","sourceRoot":"","sources":["../../src/examples/logging.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Example: morgan-style logging (Fastify-safe).
|
|
4
|
+
* Same API as Express; runs on Fastify lane.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const index_1 = require("../index");
|
|
8
|
+
const app = (0, index_1.createApp)();
|
|
9
|
+
// Logging middleware – safe for Fastify
|
|
10
|
+
app.use((req, res, next) => {
|
|
11
|
+
const start = Date.now();
|
|
12
|
+
res.on('finish', () => {
|
|
13
|
+
const ms = Date.now() - start;
|
|
14
|
+
const raw = req;
|
|
15
|
+
console.log(`${raw.method} ${raw.url} ${res.statusCode} - ${ms}ms`);
|
|
16
|
+
});
|
|
17
|
+
next();
|
|
18
|
+
});
|
|
19
|
+
app.get('/', (_req, res) => {
|
|
20
|
+
res.json({ ok: true });
|
|
21
|
+
});
|
|
22
|
+
app.listen(3001, () => {
|
|
23
|
+
console.log('Logging example: http://localhost:3001/');
|
|
24
|
+
});
|
|
25
|
+
//# sourceMappingURL=logging.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logging.js","sourceRoot":"","sources":["../../src/examples/logging.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAEH,oCAAqC;AAGrC,MAAM,GAAG,GAAG,IAAA,iBAAS,GAAE,CAAC;AAExB,wCAAwC;AACxC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAmB,EAAE,GAAoB,EAAE,IAAkB,EAAE,EAAE;IACxE,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACzB,GAAG,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;QACpB,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;QAC9B,MAAM,GAAG,GAAG,GAAyD,CAAC;QACtE,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,UAAU,MAAM,EAAE,IAAI,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;IACH,IAAI,EAAE,CAAC;AACT,CAAC,CAAC,CAAC;AAEH,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAoB,EAAE,GAAoB,EAAE,EAAE;IAC1D,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;AACzB,CAAC,CAAC,CAAC;AAEH,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;IACpB,OAAO,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAC;AACzD,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uploads.d.ts","sourceRoot":"","sources":["../../src/examples/uploads.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Example: file uploads (Express-required).
|
|
4
|
+
* Uses Express lane for multer / multipart; same API as Express.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const index_1 = require("../index");
|
|
8
|
+
const app = (0, index_1.createApp)();
|
|
9
|
+
// Multer-like middleware would be express-required and run on Express lane.
|
|
10
|
+
// For demo we use a simple JSON body route (Fastify) and a placeholder "upload" (Express).
|
|
11
|
+
app.use((_req, _res, next) => {
|
|
12
|
+
next();
|
|
13
|
+
});
|
|
14
|
+
app.post('/api/upload', (_req, res) => {
|
|
15
|
+
// In real app: multer runs on Express lane; handler runs after.
|
|
16
|
+
res.json({ message: 'Upload would run on Express lane with multer' });
|
|
17
|
+
});
|
|
18
|
+
app.listen(3002, () => {
|
|
19
|
+
console.log('Uploads example: http://localhost:3002/api/upload');
|
|
20
|
+
});
|
|
21
|
+
//# sourceMappingURL=uploads.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uploads.js","sourceRoot":"","sources":["../../src/examples/uploads.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAEH,oCAAqC;AAGrC,MAAM,GAAG,GAAG,IAAA,iBAAS,GAAE,CAAC;AAExB,4EAA4E;AAC5E,2FAA2F;AAC3F,GAAG,CAAC,GAAG,CAAC,CAAC,IAAoB,EAAE,IAAqB,EAAE,IAAkB,EAAE,EAAE;IAC1E,IAAI,EAAE,CAAC;AACT,CAAC,CAAC,CAAC;AAEH,GAAG,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,IAAoB,EAAE,GAAoB,EAAE,EAAE;IACrE,gEAAgE;IAChE,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,8CAA8C,EAAE,CAAC,CAAC;AACxE,CAAC,CAAC,CAAC;AAEH,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;IACpB,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC;AACnE,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/express/engine.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,OAAO,MAAM,SAAS,CAAC;AAE9B,wBAAgB,mBAAmB,IAAI,OAAO,CAAC,WAAW,CAEzD"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Real Express app instance. Not a reimplementation.
|
|
4
|
+
*/
|
|
5
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
6
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.createExpressEngine = createExpressEngine;
|
|
10
|
+
const express_1 = __importDefault(require("express"));
|
|
11
|
+
function createExpressEngine() {
|
|
12
|
+
return (0, express_1.default)();
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/express/engine.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;AAIH,kDAEC;AAJD,sDAA8B;AAE9B,SAAgB,mBAAmB;IACjC,OAAO,IAAA,iBAAO,GAAE,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Passthrough helpers for Express middleware (e.g. express.json interception).
|
|
3
|
+
*/
|
|
4
|
+
import type { ExpressHandler } from '../types/express';
|
|
5
|
+
/**
|
|
6
|
+
* Detect express.json() so we can map it to Fastify JSON parser instead of Express lane.
|
|
7
|
+
* Express 4: bodyParser.json / express; Express 5: named jsonParser, body calls read(req, res, next, parse).
|
|
8
|
+
* Unwraps APM-wrapped handlers (OpenTelemetry/Sentry) so a wrapped jsonParser is still recognized.
|
|
9
|
+
*/
|
|
10
|
+
export declare function isExpressJson(fn: ExpressHandler): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* No-op for express.json() when we use Fastify's built-in JSON; keeps middleware stack shape.
|
|
13
|
+
*/
|
|
14
|
+
export declare function expressJsonPassthrough(): ExpressHandler;
|
|
15
|
+
//# sourceMappingURL=middleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/express/middleware.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGvD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,cAAc,GAAG,OAAO,CAQzD;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,cAAc,CAEvD"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Passthrough helpers for Express middleware (e.g. express.json interception).
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.isExpressJson = isExpressJson;
|
|
7
|
+
exports.expressJsonPassthrough = expressJsonPassthrough;
|
|
8
|
+
const unwrap_1 = require("../utils/unwrap");
|
|
9
|
+
/**
|
|
10
|
+
* Detect express.json() so we can map it to Fastify JSON parser instead of Express lane.
|
|
11
|
+
* Express 4: bodyParser.json / express; Express 5: named jsonParser, body calls read(req, res, next, parse).
|
|
12
|
+
* Unwraps APM-wrapped handlers (OpenTelemetry/Sentry) so a wrapped jsonParser is still recognized.
|
|
13
|
+
*/
|
|
14
|
+
function isExpressJson(fn) {
|
|
15
|
+
if (typeof fn !== 'function')
|
|
16
|
+
return false;
|
|
17
|
+
const target = (0, unwrap_1.unwrapHandler)(fn);
|
|
18
|
+
if (typeof target !== 'function')
|
|
19
|
+
return false;
|
|
20
|
+
const name = target.name ?? '';
|
|
21
|
+
const str = target.toString();
|
|
22
|
+
if (name === 'jsonParser')
|
|
23
|
+
return true; // Express 5
|
|
24
|
+
return str.includes('json') && (str.includes('bodyParser') || str.includes('express'));
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* No-op for express.json() when we use Fastify's built-in JSON; keeps middleware stack shape.
|
|
28
|
+
*/
|
|
29
|
+
function expressJsonPassthrough() {
|
|
30
|
+
return (req, res, next) => next();
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/express/middleware.ts"],"names":[],"mappings":";AAAA;;GAEG;;AAUH,sCAQC;AAKD,wDAEC;AAtBD,4CAAgD;AAEhD;;;;GAIG;AACH,SAAgB,aAAa,CAAC,EAAkB;IAC9C,IAAI,OAAO,EAAE,KAAK,UAAU;QAAE,OAAO,KAAK,CAAC;IAC3C,MAAM,MAAM,GAAG,IAAA,sBAAa,EAAC,EAAE,CAAC,CAAC;IACjC,IAAI,OAAO,MAAM,KAAK,UAAU;QAAE,OAAO,KAAK,CAAC;IAC/C,MAAM,IAAI,GAAI,MAAuC,CAAC,IAAI,IAAI,EAAE,CAAC;IACjE,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC9B,IAAI,IAAI,KAAK,YAAY;QAAE,OAAO,IAAI,CAAC,CAAC,YAAY;IACpD,OAAO,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;AACzF,CAAC;AAED;;GAEG;AACH,SAAgB,sBAAsB;IACpC,OAAO,CAAC,GAA8C,EAAE,GAA+C,EAAE,IAA6C,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;AACpK,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Proxy Fastify → Express when request is not handled by Fastify lane.
|
|
3
|
+
* We pass the real Node req/res (request.raw, reply.raw) so Express APIs like res.render(),
|
|
4
|
+
* res.sendFile(), and view engines work. Express treats them as the real IncomingMessage/ServerResponse.
|
|
5
|
+
*
|
|
6
|
+
* We must wait for Express to finish (call next or send the response) before returning from
|
|
7
|
+
* the notFoundHandler; otherwise Fastify sends its default response and then Express tries to
|
|
8
|
+
* send again → "Cannot set headers after they are sent".
|
|
9
|
+
*
|
|
10
|
+
* Body: Fastify parses application/json (and other types) by default and consumes the request
|
|
11
|
+
* stream. So when we pass request.raw to Express, the body stream is already consumed and
|
|
12
|
+
* express.json() would read nothing. We attach Fastify's parsed body to the request we pass
|
|
13
|
+
* so req.body is available on the Express lane.
|
|
14
|
+
*/
|
|
15
|
+
import type { IncomingMessage } from 'node:http';
|
|
16
|
+
import type { FastifyInstance } from 'fastify';
|
|
17
|
+
import type { Application } from 'express';
|
|
18
|
+
/** Request with optional body (Express lane uses raw + body from Fastify). */
|
|
19
|
+
export type IncomingMessageWithBody = IncomingMessage & {
|
|
20
|
+
body?: unknown;
|
|
21
|
+
};
|
|
22
|
+
/** Options for mountExpress (e.g. diagnostics). */
|
|
23
|
+
export interface MountExpressOptions {
|
|
24
|
+
/** When true, log that the request is handled on the Express lane. */
|
|
25
|
+
diagnostics?: boolean;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Mount Express app so that unhandled Fastify requests are proxied to it.
|
|
29
|
+
* Uses the raw Node request/response so Express middleware and res.render() work.
|
|
30
|
+
* Awaits until Express calls the done callback (or the response is finished) so Fastify
|
|
31
|
+
* does not send a default response before Express has sent.
|
|
32
|
+
* Attaches Fastify's parsed request.body to the request so req.body is available in Express.
|
|
33
|
+
*/
|
|
34
|
+
export declare function mountExpress(fastify: FastifyInstance, expressApp: Application, options?: MountExpressOptions): void;
|
|
35
|
+
//# sourceMappingURL=mount.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mount.d.ts","sourceRoot":"","sources":["../../src/express/mount.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAkB,MAAM,WAAW,CAAC;AACjE,OAAO,KAAK,EAAE,eAAe,EAAgC,MAAM,SAAS,CAAC;AAC7E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAU3C,8EAA8E;AAC9E,MAAM,MAAM,uBAAuB,GAAG,eAAe,GAAG;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAE3E,mDAAmD;AACnD,MAAM,WAAW,mBAAmB;IAClC,sEAAsE;IACtE,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,eAAe,EACxB,UAAU,EAAE,WAAW,EACvB,OAAO,CAAC,EAAE,mBAAmB,GAC5B,IAAI,CAyDN"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Proxy Fastify → Express when request is not handled by Fastify lane.
|
|
4
|
+
* We pass the real Node req/res (request.raw, reply.raw) so Express APIs like res.render(),
|
|
5
|
+
* res.sendFile(), and view engines work. Express treats them as the real IncomingMessage/ServerResponse.
|
|
6
|
+
*
|
|
7
|
+
* We must wait for Express to finish (call next or send the response) before returning from
|
|
8
|
+
* the notFoundHandler; otherwise Fastify sends its default response and then Express tries to
|
|
9
|
+
* send again → "Cannot set headers after they are sent".
|
|
10
|
+
*
|
|
11
|
+
* Body: Fastify parses application/json (and other types) by default and consumes the request
|
|
12
|
+
* stream. So when we pass request.raw to Express, the body stream is already consumed and
|
|
13
|
+
* express.json() would read nothing. We attach Fastify's parsed body to the request we pass
|
|
14
|
+
* so req.body is available on the Express lane.
|
|
15
|
+
*/
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.mountExpress = mountExpress;
|
|
18
|
+
const maxListeners_1 = require("../utils/maxListeners");
|
|
19
|
+
/**
|
|
20
|
+
* Mount Express app so that unhandled Fastify requests are proxied to it.
|
|
21
|
+
* Uses the raw Node request/response so Express middleware and res.render() work.
|
|
22
|
+
* Awaits until Express calls the done callback (or the response is finished) so Fastify
|
|
23
|
+
* does not send a default response before Express has sent.
|
|
24
|
+
* Attaches Fastify's parsed request.body to the request so req.body is available in Express.
|
|
25
|
+
*/
|
|
26
|
+
function mountExpress(fastify, expressApp, options) {
|
|
27
|
+
const diagnostics = options?.diagnostics === true;
|
|
28
|
+
fastify.setNotFoundHandler(async (request, reply) => {
|
|
29
|
+
if (diagnostics) {
|
|
30
|
+
const method = request.method ?? "GET";
|
|
31
|
+
const url = request.url ?? "/";
|
|
32
|
+
console.log(`[express-fastify-runtime] Express lane: ${method} ${url}`);
|
|
33
|
+
}
|
|
34
|
+
(0, maxListeners_1.applyMaxListeners)(request.raw, reply.raw);
|
|
35
|
+
const raw = request.raw;
|
|
36
|
+
const res = reply.raw;
|
|
37
|
+
// Fastify has already consumed the body stream; attach parsed body so Express sees req.body.
|
|
38
|
+
// Define body as non-writable so express.json() cannot overwrite with empty when it reads
|
|
39
|
+
// the already-consumed stream. No Proxy — avoids per-property access overhead on Express lane.
|
|
40
|
+
const bodyFromFastify = await Promise.resolve(request.body);
|
|
41
|
+
const req = raw;
|
|
42
|
+
if (bodyFromFastify !== undefined) {
|
|
43
|
+
Object.defineProperty(raw, 'body', {
|
|
44
|
+
value: bodyFromFastify,
|
|
45
|
+
writable: false,
|
|
46
|
+
configurable: true,
|
|
47
|
+
enumerable: true,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
await new Promise((resolve, reject) => {
|
|
51
|
+
let settled = false;
|
|
52
|
+
const finish = () => {
|
|
53
|
+
if (settled)
|
|
54
|
+
return;
|
|
55
|
+
settled = true;
|
|
56
|
+
resolve();
|
|
57
|
+
};
|
|
58
|
+
res.once('finish', finish);
|
|
59
|
+
res.once('close', finish);
|
|
60
|
+
const done = (err) => {
|
|
61
|
+
if (settled)
|
|
62
|
+
return;
|
|
63
|
+
settled = true;
|
|
64
|
+
if (err && !reply.sent) {
|
|
65
|
+
reply.send(err).then(resolve, reject);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (!reply.sent) {
|
|
69
|
+
reply.code(404).send().then(resolve, reject);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
resolve();
|
|
73
|
+
};
|
|
74
|
+
expressApp(req, res, done);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=mount.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mount.js","sourceRoot":"","sources":["../../src/express/mount.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;GAaG;;AA8BH,oCA6DC;AAtFD,wDAA0D;AAkB1D;;;;;;GAMG;AACH,SAAgB,YAAY,CAC1B,OAAwB,EACxB,UAAuB,EACvB,OAA6B;IAE7B,MAAM,WAAW,GAAG,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;IAElD,OAAO,CAAC,kBAAkB,CAAC,KAAK,EAAE,OAAuB,EAAE,KAAmB,EAAE,EAAE;QAChF,IAAI,WAAW,EAAE,CAAC;YAChB,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,KAAK,CAAC;YACvC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC;YAC/B,OAAO,CAAC,GAAG,CAAC,2CAA2C,MAAM,IAAI,GAAG,EAAE,CAAC,CAAC;QAC1E,CAAC;QAED,IAAA,gCAAiB,EAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;QAE1C,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;QACxB,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC;QAEtB,6FAA6F;QAC7F,0FAA0F;QAC1F,+FAA+F;QAC/F,MAAM,eAAe,GAAG,MAAM,OAAO,CAAC,OAAO,CAAE,OAA8B,CAAC,IAAI,CAAC,CAAC;QACpF,MAAM,GAAG,GAAG,GAA8B,CAAC;QAC3C,IAAI,eAAe,KAAK,SAAS,EAAE,CAAC;YAClC,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE;gBACjC,KAAK,EAAE,eAAe;gBACtB,QAAQ,EAAE,KAAK;gBACf,YAAY,EAAE,IAAI;gBAClB,UAAU,EAAE,IAAI;aACjB,CAAC,CAAC;QACL,CAAC;QAED,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC1C,IAAI,OAAO,GAAG,KAAK,CAAC;YACpB,MAAM,MAAM,GAAG,GAAG,EAAE;gBAClB,IAAI,OAAO;oBAAE,OAAO;gBACpB,OAAO,GAAG,IAAI,CAAC;gBACf,OAAO,EAAE,CAAC;YACZ,CAAC,CAAC;YAEF,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YAC3B,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAE1B,MAAM,IAAI,GAAG,CAAC,GAAW,EAAE,EAAE;gBAC3B,IAAI,OAAO;oBAAE,OAAO;gBACpB,OAAO,GAAG,IAAI,CAAC;gBACf,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;oBACvB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;oBACtC,OAAO;gBACT,CAAC;gBACD,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;oBAChB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;oBAC7C,OAAO;gBACT,CAAC;gBACD,OAAO,EAAE,CAAC;YACZ,CAAC,CAAC;YAED,UAAgD,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QACpE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* (req, res, next) → async hook for Fastify preHandler.
|
|
3
|
+
*/
|
|
4
|
+
import type { FastifyRequest, FastifyReply } from 'fastify';
|
|
5
|
+
import type { ExpressRequest, ExpressResponse, NextFunction } from '../../types/express';
|
|
6
|
+
export type MiddlewareRunner = (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => void | Promise<void>;
|
|
7
|
+
export declare function toPreHandler(run: MiddlewareRunner, adaptReq: (r: FastifyRequest) => ExpressRequest, adaptRes: (reply: FastifyReply, req: FastifyRequest) => ExpressResponse): (request: FastifyRequest, reply: FastifyReply) => Promise<void>;
|
|
8
|
+
//# sourceMappingURL=middleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../../src/fastify/adapters/middleware.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAIzF,MAAM,MAAM,gBAAgB,GAAG,CAC7B,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,eAAe,EACpB,IAAI,EAAE,YAAY,KACf,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE1B,wBAAgB,YAAY,CAC1B,GAAG,EAAE,gBAAgB,EACrB,QAAQ,EAAE,CAAC,CAAC,EAAE,cAAc,KAAK,cAAc,EAC/C,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,cAAc,KAAK,eAAe,IAEtC,SAAS,cAAc,EAAE,OAAO,YAAY,KAAG,OAAO,CAAC,IAAI,CAAC,CAiB9F"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* (req, res, next) → async hook for Fastify preHandler.
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.toPreHandler = toPreHandler;
|
|
7
|
+
function toPreHandler(run, adaptReq, adaptRes) {
|
|
8
|
+
return async function preHandler(request, reply) {
|
|
9
|
+
const req = adaptReq(request);
|
|
10
|
+
const res = adaptRes(reply, request);
|
|
11
|
+
await new Promise((resolve, reject) => {
|
|
12
|
+
const next = (err) => {
|
|
13
|
+
if (err)
|
|
14
|
+
reject(err);
|
|
15
|
+
else
|
|
16
|
+
resolve();
|
|
17
|
+
};
|
|
18
|
+
const result = run(req, res, next);
|
|
19
|
+
const p = result;
|
|
20
|
+
if (p != null && typeof p.then === 'function') {
|
|
21
|
+
p.then(() => resolve(), reject);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
resolve();
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../../src/fastify/adapters/middleware.ts"],"names":[],"mappings":";AAAA;;GAEG;;AAaH,oCAsBC;AAtBD,SAAgB,YAAY,CAC1B,GAAqB,EACrB,QAA+C,EAC/C,QAAuE;IAEvE,OAAO,KAAK,UAAU,UAAU,CAAC,OAAuB,EAAE,KAAmB;QAC3E,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC9B,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACrC,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC1C,MAAM,IAAI,GAAiB,CAAC,GAAqB,EAAE,EAAE;gBACnD,IAAI,GAAG;oBAAE,MAAM,CAAC,GAAG,CAAC,CAAC;;oBAChB,OAAO,EAAE,CAAC;YACjB,CAAC,CAAC;YACF,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;YACnC,MAAM,CAAC,GAAG,MAA8B,CAAC;YACzC,IAAI,CAAC,IAAI,IAAI,IAAI,OAAQ,CAAsB,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBACnE,CAAmB,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,EAAE,MAAM,CAAC,CAAC;YACrD,CAAC;iBAAM,CAAC;gBACN,OAAO,EAAE,CAAC;YACZ,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FastifyRequest → Express-like req.
|
|
3
|
+
* Full Express 5.x request API so existing apps work unchanged.
|
|
4
|
+
* Reusable: one req object per createRequestAdapter(), mutated per request (zero alloc).
|
|
5
|
+
* Aligns with Express 5.2.1 (see docs/EXPRESS_REFERENCE.md); uses accepts, type-is, range-parser.
|
|
6
|
+
*/
|
|
7
|
+
import type { FastifyRequest } from 'fastify';
|
|
8
|
+
import type { ExpressRequest } from '../../types/express';
|
|
9
|
+
export declare function adaptRequest(fastifyReq: FastifyRequest): ExpressRequest;
|
|
10
|
+
/**
|
|
11
|
+
* Returns a request adapter that builds a FRESH Express-like req per request (methods
|
|
12
|
+
* shared via prototype, state per instance).
|
|
13
|
+
*
|
|
14
|
+
* CRITICAL: a new instance is created per request. A single shared/mutated req object
|
|
15
|
+
* corrupts concurrent async requests (a later request would overwrite an earlier one
|
|
16
|
+
* still in flight).
|
|
17
|
+
*/
|
|
18
|
+
export declare function createRequestAdapter(): (fastifyReq: FastifyRequest) => ExpressRequest;
|
|
19
|
+
//# sourceMappingURL=request.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../../src/fastify/adapters/request.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AA4D1D,wBAAgB,YAAY,CAAC,UAAU,EAAE,cAAc,GAAG,cAAc,CAoDvE;AAmHD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,IAAI,CAAC,UAAU,EAAE,cAAc,KAAK,cAAc,CAsBrF"}
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* FastifyRequest → Express-like req.
|
|
4
|
+
* Full Express 5.x request API so existing apps work unchanged.
|
|
5
|
+
* Reusable: one req object per createRequestAdapter(), mutated per request (zero alloc).
|
|
6
|
+
* Aligns with Express 5.2.1 (see docs/EXPRESS_REFERENCE.md); uses accepts, type-is, range-parser.
|
|
7
|
+
*/
|
|
8
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
9
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.adaptRequest = adaptRequest;
|
|
13
|
+
exports.createRequestAdapter = createRequestAdapter;
|
|
14
|
+
const accepts_1 = __importDefault(require("accepts"));
|
|
15
|
+
const range_parser_1 = __importDefault(require("range-parser"));
|
|
16
|
+
const type_is_1 = __importDefault(require("type-is"));
|
|
17
|
+
/** Express: Referer and Referrer are interchangeable. */
|
|
18
|
+
function getHeader(headers, name) {
|
|
19
|
+
if (!name || typeof name !== 'string')
|
|
20
|
+
return undefined;
|
|
21
|
+
const lc = name.toLowerCase();
|
|
22
|
+
if (lc === 'referer' || lc === 'referrer') {
|
|
23
|
+
return headers.referrer || headers.referer;
|
|
24
|
+
}
|
|
25
|
+
const v = headers[lc];
|
|
26
|
+
return typeof v === 'string' ? v : Array.isArray(v) ? v[0] : undefined;
|
|
27
|
+
}
|
|
28
|
+
/** Parse Cookie header into key-value object. */
|
|
29
|
+
function parseCookieHeader(cookieHeader) {
|
|
30
|
+
if (!cookieHeader || typeof cookieHeader !== 'string')
|
|
31
|
+
return {};
|
|
32
|
+
const out = {};
|
|
33
|
+
for (const part of cookieHeader.split(';')) {
|
|
34
|
+
const eq = part.indexOf('=');
|
|
35
|
+
if (eq === -1)
|
|
36
|
+
continue;
|
|
37
|
+
const key = part.slice(0, eq).trim();
|
|
38
|
+
const val = part.slice(eq + 1).trim();
|
|
39
|
+
if (key)
|
|
40
|
+
out[key] = decodeURIComponent(val);
|
|
41
|
+
}
|
|
42
|
+
return out;
|
|
43
|
+
}
|
|
44
|
+
/** Derive protocol from x-forwarded-proto or socket. */
|
|
45
|
+
function getProtocol(raw) {
|
|
46
|
+
const proto = raw.headers['x-forwarded-proto']?.split(',')[0]?.trim();
|
|
47
|
+
if (proto === 'https' || proto === 'http')
|
|
48
|
+
return proto;
|
|
49
|
+
return raw.socket?.encrypted ? 'https' : 'http';
|
|
50
|
+
}
|
|
51
|
+
/** Derive ip from x-forwarded-for (first) or socket.remoteAddress. */
|
|
52
|
+
function getIp(raw) {
|
|
53
|
+
const forwarded = raw.headers['x-forwarded-for']?.split(',')[0]?.trim();
|
|
54
|
+
if (forwarded)
|
|
55
|
+
return forwarded;
|
|
56
|
+
const addr = raw.socket?.remoteAddress;
|
|
57
|
+
if (addr)
|
|
58
|
+
return addr.startsWith('::ffff:') ? addr.slice(7) : addr;
|
|
59
|
+
return '';
|
|
60
|
+
}
|
|
61
|
+
/** Parse x-forwarded-for into array (trust proxy). */
|
|
62
|
+
function getIps(raw) {
|
|
63
|
+
const forwarded = raw.headers['x-forwarded-for'];
|
|
64
|
+
if (!forwarded)
|
|
65
|
+
return [];
|
|
66
|
+
const list = (typeof forwarded === 'string' ? forwarded : forwarded.join(',')).split(',');
|
|
67
|
+
return list.map((s) => s.trim()).filter(Boolean);
|
|
68
|
+
}
|
|
69
|
+
/** Hostname from Host header (without port). */
|
|
70
|
+
function getHostname(raw) {
|
|
71
|
+
const host = raw.headers.host ?? '';
|
|
72
|
+
return host.split(':')[0] || '';
|
|
73
|
+
}
|
|
74
|
+
function adaptRequest(fastifyReq) {
|
|
75
|
+
const raw = fastifyReq.raw;
|
|
76
|
+
const req = Object.create(raw);
|
|
77
|
+
req.get = req.header = (name) => getHeader(raw.headers, name);
|
|
78
|
+
req.accepts = function (...types) {
|
|
79
|
+
const acc = (0, accepts_1.default)(req);
|
|
80
|
+
return acc.types.apply(acc, types);
|
|
81
|
+
};
|
|
82
|
+
req.acceptsEncodings = function (...encodings) {
|
|
83
|
+
const acc = (0, accepts_1.default)(req);
|
|
84
|
+
return acc.encodings.apply(acc, encodings);
|
|
85
|
+
};
|
|
86
|
+
req.acceptsCharsets = function (...charsets) {
|
|
87
|
+
const acc = (0, accepts_1.default)(req);
|
|
88
|
+
return acc.charsets.apply(acc, charsets);
|
|
89
|
+
};
|
|
90
|
+
req.acceptsLanguages = function (...langs) {
|
|
91
|
+
const acc = (0, accepts_1.default)(req);
|
|
92
|
+
return acc.languages.apply(acc, langs);
|
|
93
|
+
};
|
|
94
|
+
req.range = function (size, options) {
|
|
95
|
+
const r = req.get('Range');
|
|
96
|
+
if (!r)
|
|
97
|
+
return undefined;
|
|
98
|
+
return (0, range_parser_1.default)(size, r, options);
|
|
99
|
+
};
|
|
100
|
+
req.is = function (types) {
|
|
101
|
+
const arr = Array.isArray(types) ? types : [].slice.call(arguments);
|
|
102
|
+
return (0, type_is_1.default)(req, arr);
|
|
103
|
+
};
|
|
104
|
+
req.query =
|
|
105
|
+
fastifyReq.query ?? {};
|
|
106
|
+
req.params =
|
|
107
|
+
fastifyReq.params ?? {};
|
|
108
|
+
req.body = fastifyReq.body;
|
|
109
|
+
const rawUrl = raw.url ?? '/';
|
|
110
|
+
req.url = rawUrl;
|
|
111
|
+
req.originalUrl = rawUrl;
|
|
112
|
+
req.baseUrl = '';
|
|
113
|
+
req.path = rawUrl.split('?')[0] || '/';
|
|
114
|
+
req.protocol = getProtocol(raw);
|
|
115
|
+
req.secure = req.protocol === 'https';
|
|
116
|
+
req.ip = getIp(raw);
|
|
117
|
+
req.ips = getIps(raw);
|
|
118
|
+
req.hostname = getHostname(raw);
|
|
119
|
+
req.host = raw.headers.host ?? '';
|
|
120
|
+
req.xhr =
|
|
121
|
+
raw.headers['x-requested-with']?.toLowerCase() === 'xmlhttprequest';
|
|
122
|
+
req.fresh = false;
|
|
123
|
+
req.stale = true;
|
|
124
|
+
req.cookies = parseCookieHeader(raw.headers.cookie);
|
|
125
|
+
req.signedCookies = {};
|
|
126
|
+
return req;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Shared request prototype: methods/getters defined ONCE. Per-request state (_raw, url,
|
|
130
|
+
* query, params, body) lives on each instance. Derived values (protocol, ip, cookies,
|
|
131
|
+
* hostname, ...) are LAZY getters so we never compute them for requests that don't read
|
|
132
|
+
* them. Common native IncomingMessage fields are delegated to this._raw for compatibility.
|
|
133
|
+
*/
|
|
134
|
+
const requestProto = {
|
|
135
|
+
get(name) {
|
|
136
|
+
return getHeader(this._raw?.headers ?? {}, name);
|
|
137
|
+
},
|
|
138
|
+
header(name) {
|
|
139
|
+
return getHeader(this._raw?.headers ?? {}, name);
|
|
140
|
+
},
|
|
141
|
+
get method() {
|
|
142
|
+
return this._raw?.method;
|
|
143
|
+
},
|
|
144
|
+
get headers() {
|
|
145
|
+
return this._raw?.headers ?? {};
|
|
146
|
+
},
|
|
147
|
+
get rawHeaders() {
|
|
148
|
+
return this._raw?.rawHeaders;
|
|
149
|
+
},
|
|
150
|
+
get httpVersion() {
|
|
151
|
+
return this._raw?.httpVersion;
|
|
152
|
+
},
|
|
153
|
+
get socket() {
|
|
154
|
+
return this._raw?.socket;
|
|
155
|
+
},
|
|
156
|
+
get connection() {
|
|
157
|
+
return this._raw?.socket;
|
|
158
|
+
},
|
|
159
|
+
get complete() {
|
|
160
|
+
return this._raw?.complete;
|
|
161
|
+
},
|
|
162
|
+
get aborted() {
|
|
163
|
+
return this._raw?.aborted ?? false;
|
|
164
|
+
},
|
|
165
|
+
get path() {
|
|
166
|
+
return (this.url || '/').split('?')[0] || '/';
|
|
167
|
+
},
|
|
168
|
+
get protocol() {
|
|
169
|
+
const raw = this._raw;
|
|
170
|
+
return raw ? getProtocol(raw) : 'http';
|
|
171
|
+
},
|
|
172
|
+
get secure() {
|
|
173
|
+
return this.protocol === 'https';
|
|
174
|
+
},
|
|
175
|
+
get ip() {
|
|
176
|
+
const raw = this._raw;
|
|
177
|
+
return raw ? getIp(raw) : '';
|
|
178
|
+
},
|
|
179
|
+
get ips() {
|
|
180
|
+
const raw = this._raw;
|
|
181
|
+
return raw ? getIps(raw) : [];
|
|
182
|
+
},
|
|
183
|
+
get hostname() {
|
|
184
|
+
const raw = this._raw;
|
|
185
|
+
return raw ? getHostname(raw) : '';
|
|
186
|
+
},
|
|
187
|
+
get host() {
|
|
188
|
+
return this._raw?.headers?.host ?? '';
|
|
189
|
+
},
|
|
190
|
+
get xhr() {
|
|
191
|
+
return (this._raw?.headers?.['x-requested-with']?.toLowerCase() ===
|
|
192
|
+
'xmlhttprequest');
|
|
193
|
+
},
|
|
194
|
+
get fresh() {
|
|
195
|
+
return false;
|
|
196
|
+
},
|
|
197
|
+
get stale() {
|
|
198
|
+
return true;
|
|
199
|
+
},
|
|
200
|
+
get cookies() {
|
|
201
|
+
const raw = this._raw;
|
|
202
|
+
return raw ? parseCookieHeader(raw.headers.cookie) : {};
|
|
203
|
+
},
|
|
204
|
+
get signedCookies() {
|
|
205
|
+
return {};
|
|
206
|
+
},
|
|
207
|
+
accepts(...types) {
|
|
208
|
+
const acc = (0, accepts_1.default)(this);
|
|
209
|
+
return acc.types.apply(acc, types);
|
|
210
|
+
},
|
|
211
|
+
acceptsEncodings(...encodings) {
|
|
212
|
+
const acc = (0, accepts_1.default)(this);
|
|
213
|
+
return acc.encodings.apply(acc, encodings);
|
|
214
|
+
},
|
|
215
|
+
acceptsCharsets(...charsets) {
|
|
216
|
+
const acc = (0, accepts_1.default)(this);
|
|
217
|
+
return acc.charsets.apply(acc, charsets);
|
|
218
|
+
},
|
|
219
|
+
acceptsLanguages(...langs) {
|
|
220
|
+
const acc = (0, accepts_1.default)(this);
|
|
221
|
+
return acc.languages.apply(acc, langs);
|
|
222
|
+
},
|
|
223
|
+
range(size, options) {
|
|
224
|
+
const r = this.get('Range');
|
|
225
|
+
if (!r)
|
|
226
|
+
return undefined;
|
|
227
|
+
return (0, range_parser_1.default)(size, r, options);
|
|
228
|
+
},
|
|
229
|
+
is(types) {
|
|
230
|
+
const arr = Array.isArray(types) ? types : [].slice.call(arguments);
|
|
231
|
+
return (0, type_is_1.default)(this, arr);
|
|
232
|
+
},
|
|
233
|
+
};
|
|
234
|
+
/**
|
|
235
|
+
* Returns a request adapter that builds a FRESH Express-like req per request (methods
|
|
236
|
+
* shared via prototype, state per instance).
|
|
237
|
+
*
|
|
238
|
+
* CRITICAL: a new instance is created per request. A single shared/mutated req object
|
|
239
|
+
* corrupts concurrent async requests (a later request would overwrite an earlier one
|
|
240
|
+
* still in flight).
|
|
241
|
+
*/
|
|
242
|
+
function createRequestAdapter() {
|
|
243
|
+
return (fastifyReq) => {
|
|
244
|
+
const req = Object.create(requestProto);
|
|
245
|
+
req._raw = fastifyReq.raw;
|
|
246
|
+
const rawUrl = fastifyReq.raw?.url ?? '/';
|
|
247
|
+
req.url = rawUrl;
|
|
248
|
+
req.originalUrl = rawUrl;
|
|
249
|
+
req.baseUrl = '';
|
|
250
|
+
req.query =
|
|
251
|
+
fastifyReq.query ?? {};
|
|
252
|
+
req.params =
|
|
253
|
+
fastifyReq.params ?? {};
|
|
254
|
+
req.body = fastifyReq.body;
|
|
255
|
+
return req;
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
//# sourceMappingURL=request.js.map
|