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,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Stores routes and middleware before compile. Immutable after listen().
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.RouteStore = void 0;
|
|
7
|
+
const express_1 = require("../types/express");
|
|
8
|
+
class RouteStore {
|
|
9
|
+
entries = [];
|
|
10
|
+
addMiddleware(path, ...handlers) {
|
|
11
|
+
this.entries.push({ type: 'middleware', path, handlers });
|
|
12
|
+
}
|
|
13
|
+
addRoute(method, path, ...handlers) {
|
|
14
|
+
const m = method.toLowerCase();
|
|
15
|
+
if (!express_1.HTTP_METHODS.includes(m) && m !== 'all') {
|
|
16
|
+
throw new TypeError(`Invalid method: ${method}`);
|
|
17
|
+
}
|
|
18
|
+
this.entries.push({ type: 'route', method: m, path, handlers });
|
|
19
|
+
}
|
|
20
|
+
/** Add a single entry (used when flattening Router). */
|
|
21
|
+
addEntry(entry) {
|
|
22
|
+
if (entry.type === 'route') {
|
|
23
|
+
this.addRoute(entry.method, entry.path, ...entry.handlers);
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
this.addMiddleware(entry.path, ...entry.handlers);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/** Add multiple entries (used when flattening Router). */
|
|
30
|
+
addEntries(entries) {
|
|
31
|
+
for (const entry of entries) {
|
|
32
|
+
this.addEntry(entry);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
getAll() {
|
|
36
|
+
return this.entries;
|
|
37
|
+
}
|
|
38
|
+
clear() {
|
|
39
|
+
this.entries = [];
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
exports.RouteStore = RouteStore;
|
|
43
|
+
//# sourceMappingURL=RouteStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RouteStore.js","sourceRoot":"","sources":["../../src/app/RouteStore.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAIH,8CAAiE;AAEjE,MAAa,UAAU;IACb,OAAO,GAAiB,EAAE,CAAC;IAEnC,aAAa,CAAC,IAAY,EAAE,GAAG,QAA0B;QACvD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,QAAQ,CAAC,MAAc,EAAE,IAAY,EAAE,GAAG,QAA0B;QAClE,MAAM,CAAC,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;QAC/B,IAAI,CAAC,sBAAY,CAAC,QAAQ,CAAC,CAAe,CAAC,IAAI,CAAC,KAAK,KAAK,EAAE,CAAC;YAC3D,MAAM,IAAI,SAAS,CAAC,mBAAmB,MAAM,EAAE,CAAC,CAAC;QACnD,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,wDAAwD;IACxD,QAAQ,CAAC,KAAiB;QACxB,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC3B,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,EAAE,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC7D,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,EAAE,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IAED,0DAA0D;IAC1D,UAAU,CAAC,OAA8B;QACvC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,KAAK;QACH,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;IACpB,CAAC;CACF;AAtCD,gCAsCC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Classify each route/middleware as safe (Fastify) or express-required.
|
|
3
|
+
* No guessing: if unsure → Express lane.
|
|
4
|
+
*/
|
|
5
|
+
import type { RouteEntry, ClassifiedRoute } from '../types/internal';
|
|
6
|
+
export declare function classifyRoute(entry: RouteEntry): ClassifiedRoute[];
|
|
7
|
+
export declare function classifyAll(entries: readonly RouteEntry[]): ClassifiedRoute[];
|
|
8
|
+
//# sourceMappingURL=classify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classify.d.ts","sourceRoot":"","sources":["../../src/app/classify.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGrE,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,eAAe,EAAE,CAOlE;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,GAAG,eAAe,EAAE,CAM7E"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Classify each route/middleware as safe (Fastify) or express-required.
|
|
4
|
+
* No guessing: if unsure → Express lane.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.classifyRoute = classifyRoute;
|
|
8
|
+
exports.classifyAll = classifyAll;
|
|
9
|
+
const detect_1 = require("../utils/detect");
|
|
10
|
+
function classifyRoute(entry) {
|
|
11
|
+
if (entry.type === 'middleware') {
|
|
12
|
+
const anyUnsafe = entry.handlers.some((fn) => (0, detect_1.isExpressRequired)(fn));
|
|
13
|
+
return [{ ...entry, lane: anyUnsafe ? 'express' : 'fastify', expressRequired: anyUnsafe }];
|
|
14
|
+
}
|
|
15
|
+
const anyUnsafe = entry.handlers.some((fn) => (0, detect_1.isExpressRequired)(fn));
|
|
16
|
+
return [{ ...entry, lane: anyUnsafe ? 'express' : 'fastify', expressRequired: anyUnsafe }];
|
|
17
|
+
}
|
|
18
|
+
function classifyAll(entries) {
|
|
19
|
+
const out = [];
|
|
20
|
+
for (const entry of entries) {
|
|
21
|
+
out.push(...classifyRoute(entry));
|
|
22
|
+
}
|
|
23
|
+
return out;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=classify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classify.js","sourceRoot":"","sources":["../../src/app/classify.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAKH,sCAOC;AAED,kCAMC;AAjBD,4CAAoD;AAEpD,SAAgB,aAAa,CAAC,KAAiB;IAC7C,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;QAChC,MAAM,SAAS,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAA,0BAAiB,EAAC,EAAE,CAAC,CAAC,CAAC;QACrE,OAAO,CAAC,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAAE,eAAe,EAAE,SAAS,EAAE,CAAC,CAAC;IAC7F,CAAC;IACD,MAAM,SAAS,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAA,0BAAiB,EAAC,EAAE,CAAC,CAAC,CAAC;IACrE,OAAO,CAAC,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAAE,eAAe,EAAE,SAAS,EAAE,CAAC,CAAC;AAC7F,CAAC;AAED,SAAgB,WAAW,CAAC,OAA8B;IACxD,MAAM,GAAG,GAAsB,EAAE,CAAC;IAClC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,GAAG,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;IACpC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compile classified routes to Fastify routes.
|
|
3
|
+
* Maximize work at compile/registration time; at runtime we only adapt req/res and run
|
|
4
|
+
* prebuilt handler chains. No runtime middleware resolution; single handler per route; sync-first.
|
|
5
|
+
*/
|
|
6
|
+
import type { FastifyInstance } from "fastify";
|
|
7
|
+
import type { ClassifiedRoute } from "../types/internal";
|
|
8
|
+
import type { ExpressRequest, ExpressResponse, NextFunction } from "../types/express";
|
|
9
|
+
import type { RequestAdapter } from "../types/internal";
|
|
10
|
+
import type { ResponseAdapter } from "../types/internal";
|
|
11
|
+
export type RunMiddleware = (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => void | Promise<void>;
|
|
12
|
+
export interface RegisterFastifyRoutesOptions {
|
|
13
|
+
diagnostics?: boolean;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Register compiled Fastify routes (safe route entries only).
|
|
17
|
+
*
|
|
18
|
+
* One Fastify handler per route (no separate preHandler stage). The full chain
|
|
19
|
+
* [applicable global middleware..., route handlers...] is precomputed at registration:
|
|
20
|
+
* - chain length 1 → call it directly (sync return, no Promise/chain) — the hot path.
|
|
21
|
+
* - chain length >1 → drive it with the continuation runner (correct for every middleware
|
|
22
|
+
* style, incl. callback-style next()).
|
|
23
|
+
*/
|
|
24
|
+
export declare function registerFastifyRoutes(fastify: FastifyInstance, classified: ClassifiedRoute[], adaptRequest: RequestAdapter, adaptResponse: ResponseAdapter, _runMiddleware: RunMiddleware, options?: RegisterFastifyRoutesOptions): void;
|
|
25
|
+
//# sourceMappingURL=compile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../src/app/compile.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EAEf,YAAY,EACb,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAKzD,MAAM,MAAM,aAAa,GAAG,CAC1B,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,eAAe,EACpB,IAAI,EAAE,YAAY,KACf,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAyG1B,MAAM,WAAW,4BAA4B;IAC3C,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,eAAe,EACxB,UAAU,EAAE,eAAe,EAAE,EAC7B,YAAY,EAAE,cAAc,EAC5B,aAAa,EAAE,eAAe,EAC9B,cAAc,EAAE,aAAa,EAC7B,OAAO,CAAC,EAAE,4BAA4B,GACrC,IAAI,CA+EN"}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Compile classified routes to Fastify routes.
|
|
4
|
+
* Maximize work at compile/registration time; at runtime we only adapt req/res and run
|
|
5
|
+
* prebuilt handler chains. No runtime middleware resolution; single handler per route; sync-first.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.registerFastifyRoutes = registerFastifyRoutes;
|
|
9
|
+
const path_1 = require("../utils/path");
|
|
10
|
+
const maxListeners_1 = require("../utils/maxListeners");
|
|
11
|
+
const middleware_1 = require("../express/middleware");
|
|
12
|
+
/** Path prefix match: middleware at /api applies to /api, /api/users, etc. */
|
|
13
|
+
function pathMatches(middlewarePath, routePath) {
|
|
14
|
+
const m = (0, path_1.normalizePath)(middlewarePath);
|
|
15
|
+
const r = (0, path_1.normalizePath)(routePath);
|
|
16
|
+
if (m === "/" || m === "")
|
|
17
|
+
return true;
|
|
18
|
+
return r === m || r.startsWith(m + "/");
|
|
19
|
+
}
|
|
20
|
+
/** Shared no-op next() for the single-handler fast path (stateless: only rethrows errors). */
|
|
21
|
+
const noopNext = (err) => {
|
|
22
|
+
if (err)
|
|
23
|
+
throw err;
|
|
24
|
+
};
|
|
25
|
+
const noop = () => { };
|
|
26
|
+
/**
|
|
27
|
+
* Run an Express-style handler chain the way Express's router does: continuation-based, but
|
|
28
|
+
* sync-first so the common case stays allocation-light.
|
|
29
|
+
*
|
|
30
|
+
* `next()` is the ONLY driver — a handler advances whenever it calls next(): synchronously,
|
|
31
|
+
* from an awaited promise, OR from a detached callback / setTimeout / microtask (classic
|
|
32
|
+
* callback style). A handler that ends the response without next() stops the chain (res.json/
|
|
33
|
+
* send/end signal us via res._onEnd). Errors (sync throw, next(err), or async rejection) are
|
|
34
|
+
* routed to Fastify's error handler.
|
|
35
|
+
*
|
|
36
|
+
* Returns `undefined` when the chain settles synchronously (no Promise allocated — the fast
|
|
37
|
+
* path), or a Promise when a handler defers work (async/await or a detached next()). The only
|
|
38
|
+
* thing that "hangs" is a handler that never calls next() and never responds — as in Express.
|
|
39
|
+
*/
|
|
40
|
+
function run(handlers, req, res) {
|
|
41
|
+
const r = res;
|
|
42
|
+
let i = 0;
|
|
43
|
+
let finished = false;
|
|
44
|
+
let syncError = null; // captured sync error, rethrown after the drive
|
|
45
|
+
let deferred = null;
|
|
46
|
+
// settle() is inlined into next()/_onEnd to keep per-request closures to a minimum (sync case
|
|
47
|
+
// allocates just _onEnd + next; the async rejection closure is only created if a handler defers).
|
|
48
|
+
const settle = (err) => {
|
|
49
|
+
if (finished)
|
|
50
|
+
return;
|
|
51
|
+
finished = true;
|
|
52
|
+
r._onEnd = undefined;
|
|
53
|
+
if (err === undefined) {
|
|
54
|
+
if (deferred)
|
|
55
|
+
deferred.resolve();
|
|
56
|
+
}
|
|
57
|
+
else if (deferred) {
|
|
58
|
+
deferred.reject(err);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
// next(err) is called from inside the handler that run()'s own try/catch wraps, so throwing
|
|
62
|
+
// here would be swallowed. Stash and rethrow once the synchronous drive unwinds.
|
|
63
|
+
syncError = { e: err };
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
// If a handler ends the response without calling next(), stop waiting (settle() = success).
|
|
67
|
+
r._onEnd = settle;
|
|
68
|
+
const next = (err) => {
|
|
69
|
+
if (err !== undefined && err !== null)
|
|
70
|
+
return settle(err);
|
|
71
|
+
if (i >= handlers.length)
|
|
72
|
+
return settle();
|
|
73
|
+
const fn = handlers[i++];
|
|
74
|
+
let ret;
|
|
75
|
+
try {
|
|
76
|
+
ret = fn(req, res, next);
|
|
77
|
+
}
|
|
78
|
+
catch (e) {
|
|
79
|
+
return settle(e);
|
|
80
|
+
}
|
|
81
|
+
if (ret != null && typeof ret.then === "function") {
|
|
82
|
+
ret.then(noop, (e) => settle(e));
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
next(); // drive synchronously
|
|
86
|
+
if (syncError)
|
|
87
|
+
throw syncError.e; // sync throw / next(err) → Fastify error handler
|
|
88
|
+
if (finished)
|
|
89
|
+
return; // settled synchronously → no Promise (fast path)
|
|
90
|
+
return new Promise((resolve, reject) => {
|
|
91
|
+
deferred = { resolve, reject };
|
|
92
|
+
if (finished)
|
|
93
|
+
resolve();
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
/** Path prefix match wrapper kept above; collect the applicable middleware for a route. */
|
|
97
|
+
function collectApplicableMiddleware(routePath, classified, routeIndex) {
|
|
98
|
+
const applicable = [];
|
|
99
|
+
for (let i = 0; i < classified.length && i < routeIndex; i++) {
|
|
100
|
+
const c = classified[i];
|
|
101
|
+
if (c.lane !== "fastify" || c.type !== "middleware")
|
|
102
|
+
continue;
|
|
103
|
+
const path = c.path === "/" ? "/" : (0, path_1.normalizePath)(c.path);
|
|
104
|
+
if (!pathMatches(path, routePath))
|
|
105
|
+
continue;
|
|
106
|
+
for (const h of c.handlers) {
|
|
107
|
+
// 4-arg Express error middleware runs via setErrorHandler, never in the normal chain.
|
|
108
|
+
if (typeof h === "function" && h.length === 4)
|
|
109
|
+
continue;
|
|
110
|
+
applicable.push(((0, middleware_1.isExpressJson)(h) ? (0, middleware_1.expressJsonPassthrough)() : h));
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return applicable;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Register compiled Fastify routes (safe route entries only).
|
|
117
|
+
*
|
|
118
|
+
* One Fastify handler per route (no separate preHandler stage). The full chain
|
|
119
|
+
* [applicable global middleware..., route handlers...] is precomputed at registration:
|
|
120
|
+
* - chain length 1 → call it directly (sync return, no Promise/chain) — the hot path.
|
|
121
|
+
* - chain length >1 → drive it with the continuation runner (correct for every middleware
|
|
122
|
+
* style, incl. callback-style next()).
|
|
123
|
+
*/
|
|
124
|
+
function registerFastifyRoutes(fastify, classified, adaptRequest, adaptResponse, _runMiddleware, options) {
|
|
125
|
+
const diagnostics = options?.diagnostics === true;
|
|
126
|
+
const ALL_METHODS = [
|
|
127
|
+
"GET",
|
|
128
|
+
"POST",
|
|
129
|
+
"PUT",
|
|
130
|
+
"PATCH",
|
|
131
|
+
"DELETE",
|
|
132
|
+
"HEAD",
|
|
133
|
+
"OPTIONS",
|
|
134
|
+
];
|
|
135
|
+
const expandMethods = (method) => method === "all" ? ALL_METHODS : [method.toUpperCase()];
|
|
136
|
+
// Count route entries per concrete method+path across ALL lanes. Express allows the same
|
|
137
|
+
// method+path to be declared more than once (the layers chain via next()); Fastify forbids
|
|
138
|
+
// duplicate method+path. Any method+path declared >1 time is left OFF the Fastify lane and
|
|
139
|
+
// handled by the real embedded Express app (which has every layer and runs them in order).
|
|
140
|
+
const methodPathCount = new Map();
|
|
141
|
+
for (const c of classified) {
|
|
142
|
+
if (c.type !== "route")
|
|
143
|
+
continue;
|
|
144
|
+
const p = (0, path_1.normalizePath)(c.path);
|
|
145
|
+
for (const m of expandMethods(c.method)) {
|
|
146
|
+
const key = m + " " + p;
|
|
147
|
+
methodPathCount.set(key, (methodPathCount.get(key) ?? 0) + 1);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
const routeEntries = classified.filter((c) => c.type === "route" && c.lane === "fastify");
|
|
151
|
+
for (const entry of routeEntries) {
|
|
152
|
+
if (entry.type !== "route")
|
|
153
|
+
continue;
|
|
154
|
+
const path = (0, path_1.normalizePath)(entry.path);
|
|
155
|
+
// baseUrl is constant per route — compute once at registration, not per request.
|
|
156
|
+
const baseUrlSegments = path.split("/").filter(Boolean);
|
|
157
|
+
const baseUrl = baseUrlSegments.length >= 1 ? "/" + baseUrlSegments[0] : "";
|
|
158
|
+
const routeIndex = classified.indexOf(entry);
|
|
159
|
+
// Only register methods that are declared exactly once for this path; duplicates (incl.
|
|
160
|
+
// all+method overlaps, or a same-path entry on the Express lane) defer to the Express lane.
|
|
161
|
+
const methods = expandMethods(entry.method).filter((m) => (methodPathCount.get(m + " " + path) ?? 0) === 1);
|
|
162
|
+
if (methods.length === 0)
|
|
163
|
+
continue;
|
|
164
|
+
const applicable = collectApplicableMiddleware(path, classified, routeIndex);
|
|
165
|
+
const routeHandlers = entry.handlers.map((h) => (0, middleware_1.isExpressJson)(h) ? (0, middleware_1.expressJsonPassthrough)() : h);
|
|
166
|
+
const chain = applicable.length ? applicable.concat(routeHandlers) : routeHandlers;
|
|
167
|
+
// Hot path: exactly one handler that doesn't take `next` (arity ≤ 2) can only respond
|
|
168
|
+
// synchronously or return a promise — call it directly, no runner/closures/Promise.
|
|
169
|
+
// Anything that takes `next` (or a multi-handler chain) goes through the continuation runner.
|
|
170
|
+
const fastSingle = chain.length === 1 && chain[0].length <= 2 ? chain[0] : null;
|
|
171
|
+
for (const m of methods) {
|
|
172
|
+
const logLane = diagnostics
|
|
173
|
+
? (request) => console.log(`[express-fastify-runtime] Fastify lane: ${m} ${request.url ?? path}`)
|
|
174
|
+
: null;
|
|
175
|
+
fastify.route({
|
|
176
|
+
method: m,
|
|
177
|
+
url: path,
|
|
178
|
+
handler: (request, reply) => {
|
|
179
|
+
if (logLane)
|
|
180
|
+
logLane(request);
|
|
181
|
+
(0, maxListeners_1.applyMaxListeners)(request.raw, reply.raw);
|
|
182
|
+
const req = adaptRequest(request);
|
|
183
|
+
const res = adaptResponse(reply, request);
|
|
184
|
+
res.req = req;
|
|
185
|
+
req.baseUrl = baseUrl;
|
|
186
|
+
if (fastSingle !== null) {
|
|
187
|
+
return fastSingle(req, res, noopNext);
|
|
188
|
+
}
|
|
189
|
+
return run(chain, req, res);
|
|
190
|
+
},
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
//# sourceMappingURL=compile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compile.js","sourceRoot":"","sources":["../../src/app/compile.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Flatten express.Router() into RouteStore entries so router routes and
|
|
3
|
+
* router.use() middleware can be classified and run on the Fastify lane when safe.
|
|
4
|
+
*
|
|
5
|
+
* When the router package's Layer is patched (see patchRouterLayer.ts), middleware
|
|
6
|
+
* layers expose layer._path so we can flatten router.use(path, fn) too. Otherwise
|
|
7
|
+
* we only flatten routers that have no middleware layers (route-only).
|
|
8
|
+
*/
|
|
9
|
+
import type { RouteEntry } from '../types/internal';
|
|
10
|
+
import type { ExpressHandler } from '../types/express';
|
|
11
|
+
/** Minimal Express Router shape (express + router package). */
|
|
12
|
+
export interface ExpressRouterLike {
|
|
13
|
+
stack: ExpressLayerLike[];
|
|
14
|
+
}
|
|
15
|
+
/** Layer: either middleware (no route) or route (has route). _path is set by our patch for middleware. */
|
|
16
|
+
export interface ExpressLayerLike {
|
|
17
|
+
path?: string;
|
|
18
|
+
/** Layer name — Express sets it from the original handler's name and KEEPS it even when an
|
|
19
|
+
* instrumentation library (e.g. OpenTelemetry/Sentry) wraps the handler. More reliable than
|
|
20
|
+
* handle.name for identifying Express built-ins. */
|
|
21
|
+
name?: string;
|
|
22
|
+
/** Set by patchRouterLayer when Layer(path, options, fn) is called with a string path. */
|
|
23
|
+
_path?: string;
|
|
24
|
+
/** router.use('/') creates a layer with slash: true. */
|
|
25
|
+
slash?: boolean;
|
|
26
|
+
handle: ExpressHandler | ExpressRouterLike;
|
|
27
|
+
route?: ExpressRouteLike;
|
|
28
|
+
}
|
|
29
|
+
/** Route has path, methods, and stack of method handlers. */
|
|
30
|
+
export interface ExpressRouteLike {
|
|
31
|
+
path: string;
|
|
32
|
+
methods: Record<string, boolean>;
|
|
33
|
+
stack: Array<{
|
|
34
|
+
method?: string;
|
|
35
|
+
name?: string;
|
|
36
|
+
handle: ExpressHandler;
|
|
37
|
+
}>;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Returns true if the value looks like an Express Router (has stack array).
|
|
41
|
+
*/
|
|
42
|
+
export declare function isExpressRouter(value: unknown): value is ExpressRouterLike;
|
|
43
|
+
/**
|
|
44
|
+
* Flatten a Router into RouteEntry[] when possible.
|
|
45
|
+
* - Route layers (router.get/post etc.) are always flattened when we have route.path.
|
|
46
|
+
* - Middleware layers (router.use) are flattened when we have the path (from Layer._path patch or slash).
|
|
47
|
+
* - Nested routers are flattened recursively.
|
|
48
|
+
* - If any middleware layer has no path we can read, return null and the caller mounts the router on Express lane.
|
|
49
|
+
*/
|
|
50
|
+
export declare function flattenRouter(router: ExpressRouterLike, mountPath: string): RouteEntry[] | null;
|
|
51
|
+
//# sourceMappingURL=flattenRouter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flattenRouter.d.ts","sourceRoot":"","sources":["../../src/app/flattenRouter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAoBvD,+DAA+D;AAC/D,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,gBAAgB,EAAE,CAAC;CAC3B;AAED,0GAA0G;AAC1G,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;wDAEoD;IACpD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0FAA0F;IAC1F,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wDAAwD;IACxD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,cAAc,GAAG,iBAAiB,CAAC;IAC3C,KAAK,CAAC,EAAE,gBAAgB,CAAC;CAC1B;AAED,6DAA6D;AAC7D,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,KAAK,EAAE,KAAK,CAAC;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,cAAc,CAAA;KAAE,CAAC,CAAC;CAC1E;AAID;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,iBAAiB,CAI1E;AAYD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,GAAG,UAAU,EAAE,GAAG,IAAI,CAoE/F"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Flatten express.Router() into RouteStore entries so router routes and
|
|
4
|
+
* router.use() middleware can be classified and run on the Fastify lane when safe.
|
|
5
|
+
*
|
|
6
|
+
* When the router package's Layer is patched (see patchRouterLayer.ts), middleware
|
|
7
|
+
* layers expose layer._path so we can flatten router.use(path, fn) too. Otherwise
|
|
8
|
+
* we only flatten routers that have no middleware layers (route-only).
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.isExpressRouter = isExpressRouter;
|
|
12
|
+
exports.flattenRouter = flattenRouter;
|
|
13
|
+
const expressLane_1 = require("../runtime/expressLane");
|
|
14
|
+
const middleware_1 = require("../express/middleware");
|
|
15
|
+
const path_1 = require("../utils/path");
|
|
16
|
+
/**
|
|
17
|
+
* Express body parsers, identified by layer/sub-layer `name` (Express preserves it even when an
|
|
18
|
+
* APM like OpenTelemetry/Sentry wraps the handler, so handle.name becomes e.g. "patched").
|
|
19
|
+
*
|
|
20
|
+
* - express.json() → Fastify already parses JSON, so on the Fastify lane the parser is a no-op
|
|
21
|
+
* (`expressJsonPassthrough`); req.body comes from Fastify. Otherwise the real jsonParser would
|
|
22
|
+
* try to read the already-consumed request stream and throw "argument stream must be a stream".
|
|
23
|
+
* - express.urlencoded()/raw()/text() read the raw stream and Fastify has no parser for those
|
|
24
|
+
* content types — they're left as-is so classify() (utils/detect) routes routes/middleware
|
|
25
|
+
* using them to the Express lane (real Express parses the body).
|
|
26
|
+
*/
|
|
27
|
+
function neutralizeJsonParser(name, handle) {
|
|
28
|
+
return name === 'jsonParser' ? (0, middleware_1.expressJsonPassthrough)() : handle;
|
|
29
|
+
}
|
|
30
|
+
const HTTP_METHODS = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options'];
|
|
31
|
+
/**
|
|
32
|
+
* Returns true if the value looks like an Express Router (has stack array).
|
|
33
|
+
*/
|
|
34
|
+
function isExpressRouter(value) {
|
|
35
|
+
if (value == null || typeof value !== 'function')
|
|
36
|
+
return false;
|
|
37
|
+
const obj = value;
|
|
38
|
+
return Array.isArray(obj.stack);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Get the path for a middleware layer. Uses _path (from our patch), or '/' when slash is true.
|
|
42
|
+
*/
|
|
43
|
+
function getMiddlewareLayerPath(layer) {
|
|
44
|
+
const path = layer._path;
|
|
45
|
+
if (typeof path === 'string')
|
|
46
|
+
return path;
|
|
47
|
+
if (layer.slash === true)
|
|
48
|
+
return '/';
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Flatten a Router into RouteEntry[] when possible.
|
|
53
|
+
* - Route layers (router.get/post etc.) are always flattened when we have route.path.
|
|
54
|
+
* - Middleware layers (router.use) are flattened when we have the path (from Layer._path patch or slash).
|
|
55
|
+
* - Nested routers are flattened recursively.
|
|
56
|
+
* - If any middleware layer has no path we can read, return null and the caller mounts the router on Express lane.
|
|
57
|
+
*/
|
|
58
|
+
function flattenRouter(router, mountPath) {
|
|
59
|
+
const stack = router.stack;
|
|
60
|
+
if (!stack || stack.length === 0)
|
|
61
|
+
return [];
|
|
62
|
+
const entries = [];
|
|
63
|
+
for (const layer of stack) {
|
|
64
|
+
if (layer.route) {
|
|
65
|
+
const route = layer.route;
|
|
66
|
+
// Skip RegExp/array routes so they stay on Express lane (res.render, etc.)
|
|
67
|
+
if (typeof route.path !== 'string')
|
|
68
|
+
continue;
|
|
69
|
+
// Skip routes whose handler(s) are marked with expressLane() or @ExpressLane()
|
|
70
|
+
const hasExpressLaneHandler = route.stack.some((l) => (0, expressLane_1.isExpressLaneHandler)(l.handle));
|
|
71
|
+
if (hasExpressLaneHandler)
|
|
72
|
+
continue;
|
|
73
|
+
const fullPath = (0, path_1.joinPath)(mountPath, route.path);
|
|
74
|
+
for (const method of Object.keys(route.methods)) {
|
|
75
|
+
const m = method === '_all' ? 'all' : method.toLowerCase();
|
|
76
|
+
const handlers = route.stack
|
|
77
|
+
.filter((l) => l.method === undefined || l.method === m)
|
|
78
|
+
.map((l) => neutralizeJsonParser(l.name, l.handle));
|
|
79
|
+
if (handlers.length === 0)
|
|
80
|
+
continue;
|
|
81
|
+
const validMethod = m === 'all' || HTTP_METHODS.includes(m) ? m : null;
|
|
82
|
+
if (!validMethod)
|
|
83
|
+
continue;
|
|
84
|
+
entries.push({
|
|
85
|
+
type: 'route',
|
|
86
|
+
method: validMethod,
|
|
87
|
+
path: fullPath,
|
|
88
|
+
handlers,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
const handle = layer.handle;
|
|
94
|
+
// Express 4 injects `query` and `expressInit` middleware into the app router stack
|
|
95
|
+
// (Express 5 does not). They must NOT run on the Fastify lane: `expressInit` reassigns
|
|
96
|
+
// req/res __proto__ to Express's own objects (which breaks our adapter — e.g. res.setHeader
|
|
97
|
+
// then hits a non-real response and helmet/etc. throw), and Fastify already parses the query
|
|
98
|
+
// string. Identify them by `layer.name` — Express preserves it even when an instrumentation
|
|
99
|
+
// library (OpenTelemetry/Sentry) wraps the handler (then handle.name is the wrapper, e.g.
|
|
100
|
+
// "patched"). Fall back to handle.name for safety.
|
|
101
|
+
const builtinName = layer.name || (typeof handle === 'function' ? handle.name : '');
|
|
102
|
+
if (builtinName === 'query' || builtinName === 'expressInit')
|
|
103
|
+
continue;
|
|
104
|
+
const middlewarePath = getMiddlewareLayerPath(layer);
|
|
105
|
+
if (middlewarePath === null)
|
|
106
|
+
return null;
|
|
107
|
+
if ((0, expressLane_1.isExpressLaneHandler)(handle))
|
|
108
|
+
continue;
|
|
109
|
+
const fullPath = (0, path_1.joinPath)(mountPath, middlewarePath);
|
|
110
|
+
if (isExpressRouter(handle)) {
|
|
111
|
+
const nested = flattenRouter(handle, fullPath);
|
|
112
|
+
if (nested === null)
|
|
113
|
+
return null;
|
|
114
|
+
entries.push(...nested);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
entries.push({
|
|
118
|
+
type: 'middleware',
|
|
119
|
+
path: fullPath,
|
|
120
|
+
handlers: [neutralizeJsonParser(builtinName, handle)],
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return entries;
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=flattenRouter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flattenRouter.js","sourceRoot":"","sources":["../../src/app/flattenRouter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Introspect an existing Express app's router stack to produce RouteEntry[].
|
|
3
|
+
* Used by fast(app, ops) to compile an already-built Express app onto Fastify.
|
|
4
|
+
*
|
|
5
|
+
* Requires that express-fastify-runtime was loaded before the app was created,
|
|
6
|
+
* so that router Layer has _path set for middleware (see patchRouterLayer.ts).
|
|
7
|
+
* If the app cannot be flattened (e.g. unpatched middleware), returns null.
|
|
8
|
+
*/
|
|
9
|
+
import type { RouteEntry } from '../types/internal';
|
|
10
|
+
import type { ExpressRouterLike } from './flattenRouter';
|
|
11
|
+
/** Express app shape: Express 5 exposes `app.router`; Express 4 uses the private `app._router`. */
|
|
12
|
+
export interface ExpressAppLike {
|
|
13
|
+
router?: ExpressRouterLike;
|
|
14
|
+
_router?: ExpressRouterLike;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Walk the app's router stack and convert to RouteEntry[] with mount path '/'.
|
|
18
|
+
* Returns null if the app has middleware layers we can't flatten (e.g. no _path).
|
|
19
|
+
*/
|
|
20
|
+
export declare function introspectExpressApp(app: ExpressAppLike): RouteEntry[] | null;
|
|
21
|
+
/** Express 4-arg error middleware type. */
|
|
22
|
+
export type ExpressErrorMiddleware = (err: Error, req: import('../types/express').ExpressRequest, res: import('../types/express').ExpressResponse, next: import('../types/express').NextFunction) => void | Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Return the first Express error middleware (4-arg handler) from the app's router stack, if any.
|
|
25
|
+
* Only considers middleware layers (no route), so we don't pick a route's handler by mistake.
|
|
26
|
+
* Used by fast() to wire setErrorHandler so next(err) in the Fastify lane reaches Express error handlers.
|
|
27
|
+
*/
|
|
28
|
+
export declare function getExpressErrorMiddleware(app: ExpressAppLike): ExpressErrorMiddleware | null;
|
|
29
|
+
//# sourceMappingURL=introspectExpress.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"introspectExpress.d.ts","sourceRoot":"","sources":["../../src/app/introspectExpress.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAoB,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAG3E,mGAAmG;AACnG,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,OAAO,CAAC,EAAE,iBAAiB,CAAC;CAC7B;AAiBD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,cAAc,GAAG,UAAU,EAAE,GAAG,IAAI,CAM7E;AAED,2CAA2C;AAC3C,MAAM,MAAM,sBAAsB,GAAG,CACnC,GAAG,EAAE,KAAK,EACV,GAAG,EAAE,OAAO,kBAAkB,EAAE,cAAc,EAC9C,GAAG,EAAE,OAAO,kBAAkB,EAAE,eAAe,EAC/C,IAAI,EAAE,OAAO,kBAAkB,EAAE,YAAY,KAC1C,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE1B;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,cAAc,GAAG,sBAAsB,GAAG,IAAI,CAW5F"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Introspect an existing Express app's router stack to produce RouteEntry[].
|
|
4
|
+
* Used by fast(app, ops) to compile an already-built Express app onto Fastify.
|
|
5
|
+
*
|
|
6
|
+
* Requires that express-fastify-runtime was loaded before the app was created,
|
|
7
|
+
* so that router Layer has _path set for middleware (see patchRouterLayer.ts).
|
|
8
|
+
* If the app cannot be flattened (e.g. unpatched middleware), returns null.
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.introspectExpressApp = introspectExpressApp;
|
|
12
|
+
exports.getExpressErrorMiddleware = getExpressErrorMiddleware;
|
|
13
|
+
const flattenRouter_1 = require("./flattenRouter");
|
|
14
|
+
/**
|
|
15
|
+
* Get the app's router stack across Express majors.
|
|
16
|
+
* Express 4: `app._router` (present after the first route/middleware); `app.router` getter THROWS.
|
|
17
|
+
* Express 5: `app.router` is a lazy getter; `app._router` is undefined.
|
|
18
|
+
* Check `_router` first so we never touch Express 4's throwing getter; guard `app.router` anyway.
|
|
19
|
+
*/
|
|
20
|
+
function getAppRouter(app) {
|
|
21
|
+
if (app._router)
|
|
22
|
+
return app._router;
|
|
23
|
+
try {
|
|
24
|
+
return app.router;
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Walk the app's router stack and convert to RouteEntry[] with mount path '/'.
|
|
32
|
+
* Returns null if the app has middleware layers we can't flatten (e.g. no _path).
|
|
33
|
+
*/
|
|
34
|
+
function introspectExpressApp(app) {
|
|
35
|
+
const router = getAppRouter(app);
|
|
36
|
+
if (!router || !Array.isArray(router.stack) || router.stack.length === 0) {
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
return (0, flattenRouter_1.flattenRouter)(router, '/');
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Return the first Express error middleware (4-arg handler) from the app's router stack, if any.
|
|
43
|
+
* Only considers middleware layers (no route), so we don't pick a route's handler by mistake.
|
|
44
|
+
* Used by fast() to wire setErrorHandler so next(err) in the Fastify lane reaches Express error handlers.
|
|
45
|
+
*/
|
|
46
|
+
function getExpressErrorMiddleware(app) {
|
|
47
|
+
const router = getAppRouter(app);
|
|
48
|
+
if (!router || !Array.isArray(router.stack))
|
|
49
|
+
return null;
|
|
50
|
+
for (const layer of router.stack) {
|
|
51
|
+
if (layer.route)
|
|
52
|
+
continue; // skip route layers; only use app-level middleware
|
|
53
|
+
const handle = layer.handle;
|
|
54
|
+
if (typeof handle === 'function' && handle.length === 4) {
|
|
55
|
+
return handle;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=introspectExpress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"introspectExpress.js","sourceRoot":"","sources":["../../src/app/introspectExpress.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;AA+BH,oDAMC;AAeD,8DAWC;AA3DD,mDAAgD;AAQhD;;;;;GAKG;AACH,SAAS,YAAY,CAAC,GAAmB;IACvC,IAAI,GAAG,CAAC,OAAO;QAAE,OAAO,GAAG,CAAC,OAAO,CAAC;IACpC,IAAI,CAAC;QACH,OAAO,GAAG,CAAC,MAAM,CAAC;IACpB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAgB,oBAAoB,CAAC,GAAmB;IACtD,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzE,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,IAAA,6BAAa,EAAC,MAA2B,EAAE,GAAG,CAAC,CAAC;AACzD,CAAC;AAUD;;;;GAIG;AACH,SAAgB,yBAAyB,CAAC,GAAmB;IAC3D,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACzD,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,KAAoD,EAAE,CAAC;QAChF,IAAI,KAAK,CAAC,KAAK;YAAE,SAAS,CAAC,mDAAmD;QAC9E,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;QAC5B,IAAI,OAAO,MAAM,KAAK,UAAU,IAAK,MAAmB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtE,OAAO,MAAgC,CAAC;QAC1C,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/examples/auth.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|