@powerhousedao/reactor-api 6.2.2-dev.83 → 6.2.2-dev.84
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapter-http-express-Cf918YME.mjs +225 -0
- package/dist/adapter-http-express-Cf918YME.mjs.map +1 -0
- package/dist/{adapter-http-fastify-B248RJtm.mjs → adapter-http-fastify-DVBSR7C6.mjs} +38 -26
- package/dist/adapter-http-fastify-DVBSR7C6.mjs.map +1 -0
- package/dist/index.d.mts +84 -14
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +188 -32
- package/dist/index.mjs.map +1 -1
- package/dist/path-normalize-Cucs71I2.mjs +19 -0
- package/dist/path-normalize-Cucs71I2.mjs.map +1 -0
- package/dist/src/packages/vite-loader.d.mts +1 -1
- package/dist/src/packages/vite-loader.d.mts.map +1 -1
- package/dist/src/packages/vite-loader.mjs +14 -2
- package/dist/src/packages/vite-loader.mjs.map +1 -1
- package/dist/{types-D2ZrjmCk.d.mts → types-Bz2niABC.d.mts} +6 -1
- package/dist/{types-D2ZrjmCk.d.mts.map → types-Bz2niABC.d.mts.map} +1 -1
- package/dist/utils-lHoPB-ft.mjs +2 -2
- package/dist/utils-lHoPB-ft.mjs.map +1 -1
- package/package.json +14 -14
- package/dist/adapter-http-express-D5OpUIbV.mjs +0 -137
- package/dist/adapter-http-express-D5OpUIbV.mjs.map +0 -1
- package/dist/adapter-http-fastify-B248RJtm.mjs.map +0 -1
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="45603953-04e5-5972-a877-8620773dcfbd")}catch(e){}}();
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import { match } from "path-to-regexp";
|
|
5
|
-
import fs from "node:fs";
|
|
6
|
-
import http from "node:http";
|
|
7
|
-
import https from "node:https";
|
|
8
|
-
import bodyParser from "body-parser";
|
|
9
|
-
import cors from "cors";
|
|
10
|
-
import devcert from "devcert";
|
|
11
|
-
import expressLib, { Router } from "express";
|
|
12
|
-
//#region src/graphql/gateway/adapter-http-express.ts
|
|
13
|
-
var ExpressHttpAdapter = class {
|
|
14
|
-
#app;
|
|
15
|
-
#router;
|
|
16
|
-
#handlers = /* @__PURE__ */ new Map();
|
|
17
|
-
constructor(existingApp) {
|
|
18
|
-
this.#app = existingApp ?? expressLib();
|
|
19
|
-
this.#router = Router();
|
|
20
|
-
this.#app.use(this.#router);
|
|
21
|
-
}
|
|
22
|
-
setupSentryErrorHandler(sentry) {
|
|
23
|
-
sentry.setupExpressErrorHandler(this.#app);
|
|
24
|
-
}
|
|
25
|
-
get handle() {
|
|
26
|
-
return this.#app;
|
|
27
|
-
}
|
|
28
|
-
mountRawMiddleware(middleware) {
|
|
29
|
-
this.#app.use(middleware);
|
|
30
|
-
}
|
|
31
|
-
mountNodeRoute(method, path, handler) {
|
|
32
|
-
const m = method.toLowerCase();
|
|
33
|
-
this.#app[m](path, (req, res) => {
|
|
34
|
-
handler(req, res, req.body);
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
setupMiddleware({ corsOptions, bodyLimit = "50mb" }) {
|
|
38
|
-
this.#router.use(cors(corsOptions));
|
|
39
|
-
this.#router.use(bodyParser.json({ limit: bodyLimit }));
|
|
40
|
-
this.#router.use(bodyParser.urlencoded({
|
|
41
|
-
extended: true,
|
|
42
|
-
limit: bodyLimit
|
|
43
|
-
}));
|
|
44
|
-
this.#router.use((req, res, next) => {
|
|
45
|
-
for (const { handler, matcher } of this.#handlers.values()) if (matcher(req.path)) {
|
|
46
|
-
this.#serveFetchHandler(handler, req, res, next);
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
next();
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
mount(path, handler, { exact = false } = {}) {
|
|
53
|
-
if (exact) this.#router.use(path, (req, res, next) => this.#serveFetchHandler(handler, req, res, next));
|
|
54
|
-
else this.#handlers.set(path, {
|
|
55
|
-
handler,
|
|
56
|
-
matcher: match(path)
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
getRoute(routePath, handler) {
|
|
60
|
-
this.#app.get(routePath, (req, res) => {
|
|
61
|
-
const url = `${req.protocol}://${req.get("host") ?? "localhost"}${req.originalUrl}`;
|
|
62
|
-
const headers = new Headers();
|
|
63
|
-
for (const [key, value] of Object.entries(req.headers)) if (typeof value === "string") headers.set(key, value);
|
|
64
|
-
else if (Array.isArray(value)) headers.set(key, value.join(", "));
|
|
65
|
-
const fetchRequest = new Request(url, {
|
|
66
|
-
method: "GET",
|
|
67
|
-
headers
|
|
68
|
-
});
|
|
69
|
-
Promise.resolve(handler(fetchRequest)).then(async (response) => {
|
|
70
|
-
res.status(response.status);
|
|
71
|
-
response.headers.forEach((value, key) => {
|
|
72
|
-
res.setHeader(key, value);
|
|
73
|
-
});
|
|
74
|
-
res.send(await response.text());
|
|
75
|
-
}).catch((err) => {
|
|
76
|
-
res.status(500).send(String(err));
|
|
77
|
-
});
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
async listen(port, tls) {
|
|
81
|
-
let server;
|
|
82
|
-
if (tls === true) {
|
|
83
|
-
const { cert, key } = await devcert.certificateFor("localhost");
|
|
84
|
-
if (!cert || !key) throw new Error("Invalid certificate generated");
|
|
85
|
-
server = https.createServer({
|
|
86
|
-
cert,
|
|
87
|
-
key
|
|
88
|
-
}, this.#app);
|
|
89
|
-
} else if (tls && "keyPath" in tls) {
|
|
90
|
-
const currentDir = process.cwd();
|
|
91
|
-
server = https.createServer({
|
|
92
|
-
key: fs.readFileSync(path.join(currentDir, tls.keyPath)),
|
|
93
|
-
cert: fs.readFileSync(path.join(currentDir, tls.certPath))
|
|
94
|
-
}, this.#app);
|
|
95
|
-
} else if (tls && "cert" in tls) server = https.createServer({
|
|
96
|
-
cert: tls.cert,
|
|
97
|
-
key: tls.key
|
|
98
|
-
}, this.#app);
|
|
99
|
-
else server = http.createServer(this.#app);
|
|
100
|
-
return new Promise((resolve, reject) => {
|
|
101
|
-
server.once("error", reject);
|
|
102
|
-
server.listen(port, () => {
|
|
103
|
-
server.off("error", reject);
|
|
104
|
-
resolve(server);
|
|
105
|
-
});
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
#serveFetchHandler(handler, req, res, next) {
|
|
109
|
-
const url = `${req.protocol}://${req.get("host") ?? "localhost"}${req.originalUrl}`;
|
|
110
|
-
const headers = new Headers();
|
|
111
|
-
for (const [key, value] of Object.entries(req.headers)) if (typeof value === "string") headers.set(key, value);
|
|
112
|
-
else if (Array.isArray(value)) headers.set(key, value.join(", "));
|
|
113
|
-
let body;
|
|
114
|
-
if (req.method !== "GET" && req.method !== "HEAD" && req.body !== void 0) body = JSON.stringify(req.body);
|
|
115
|
-
const fetchRequest = new Request(url, {
|
|
116
|
-
method: req.method,
|
|
117
|
-
headers,
|
|
118
|
-
body
|
|
119
|
-
});
|
|
120
|
-
Promise.resolve(handler(fetchRequest)).then(async (response) => {
|
|
121
|
-
res.status(response.status);
|
|
122
|
-
response.headers.forEach((value, key) => {
|
|
123
|
-
res.setHeader(key, value);
|
|
124
|
-
});
|
|
125
|
-
const responseBody = await response.text();
|
|
126
|
-
res.send(responseBody);
|
|
127
|
-
}).catch(next);
|
|
128
|
-
}
|
|
129
|
-
};
|
|
130
|
-
function createExpressHttpAdapter(existingApp) {
|
|
131
|
-
return { adapter: new ExpressHttpAdapter(existingApp) };
|
|
132
|
-
}
|
|
133
|
-
//#endregion
|
|
134
|
-
export { createExpressHttpAdapter };
|
|
135
|
-
|
|
136
|
-
//# sourceMappingURL=adapter-http-express-D5OpUIbV.mjs.map
|
|
137
|
-
//# debugId=45603953-04e5-5972-a877-8620773dcfbd
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"adapter-http-express-D5OpUIbV.mjs","sources":["../src/graphql/gateway/adapter-http-express.ts"],"sourcesContent":["import bodyParser from \"body-parser\";\nimport cors from \"cors\";\nimport type { CorsOptions } from \"cors\";\nimport devcert from \"devcert\";\nimport type express from \"express\";\nimport type { Express } from \"express\";\nimport { Router } from \"express\";\nimport expressLib from \"express\";\nimport type { IRouter } from \"express\";\nimport fs from \"node:fs\";\nimport http from \"node:http\";\nimport https from \"node:https\";\nimport path from \"node:path\";\nimport { match, type MatchFunction, type ParamData } from \"path-to-regexp\";\nimport type { FetchHandler, IHttpAdapter, TlsOptions } from \"./types.js\";\n\nexport class ExpressHttpAdapter implements IHttpAdapter {\n readonly #app: Express;\n readonly #router: IRouter;\n readonly #handlers = new Map<\n string,\n { handler: FetchHandler; matcher: MatchFunction<ParamData> }\n >();\n\n constructor(existingApp?: Express) {\n this.#app = existingApp ?? expressLib();\n this.#router = Router();\n this.#app.use(this.#router);\n }\n\n setupSentryErrorHandler(sentry: object): void {\n const s = sentry as {\n setupExpressErrorHandler(app: Express): void;\n };\n s.setupExpressErrorHandler(this.#app);\n }\n\n get handle(): unknown {\n return this.#app;\n }\n\n mountRawMiddleware(middleware: unknown): void {\n this.#app.use(middleware as any);\n }\n\n mountNodeRoute(\n method: \"DELETE\" | \"GET\" | \"HEAD\" | \"POST\" | \"PUT\",\n path: string,\n handler: (\n req: http.IncomingMessage,\n res: http.ServerResponse,\n body?: unknown,\n ) => void | Promise<void>,\n ): void {\n const m = method.toLowerCase() as\n | \"delete\"\n | \"get\"\n | \"head\"\n | \"post\"\n | \"put\";\n this.#app[m](path, (req: express.Request, res: express.Response) => {\n void handler(req, res, req.body as unknown);\n });\n }\n\n setupMiddleware({\n corsOptions,\n bodyLimit = \"50mb\",\n }: {\n corsOptions?: CorsOptions;\n bodyLimit?: string;\n }): void {\n this.#router.use(cors(corsOptions));\n this.#router.use(bodyParser.json({ limit: bodyLimit }));\n this.#router.use(\n bodyParser.urlencoded({ extended: true, limit: bodyLimit }),\n );\n\n // Dispatcher registered AFTER bodyParser so req.body is populated when it fires.\n this.#router.use((req, res, next) => {\n for (const { handler, matcher } of this.#handlers.values()) {\n if (matcher(req.path)) {\n this.#serveFetchHandler(handler, req, res, next);\n return;\n }\n }\n next();\n });\n }\n\n mount(\n path: string,\n handler: FetchHandler,\n { exact = false }: { exact?: boolean } = {},\n ): void {\n if (exact) {\n this.#router.use(path, (req, res, next) =>\n this.#serveFetchHandler(handler, req, res, next),\n );\n } else {\n // Exact match - stored in the internal dispatch map\n this.#handlers.set(path, {\n handler,\n matcher: match(path),\n });\n }\n }\n\n getRoute(\n routePath: string,\n handler: (request: Request) => Response | Promise<Response>,\n ): void {\n this.#app.get(routePath, (req, res) => {\n const protocol = req.protocol;\n const host = req.get(\"host\") ?? \"localhost\";\n const url = `${protocol}://${host}${req.originalUrl}`;\n const headers = new Headers();\n for (const [key, value] of Object.entries(req.headers)) {\n if (typeof value === \"string\") {\n headers.set(key, value);\n } else if (Array.isArray(value)) {\n headers.set(key, value.join(\", \"));\n }\n }\n const fetchRequest = new Request(url, { method: \"GET\", headers });\n Promise.resolve(handler(fetchRequest))\n .then(async (response) => {\n res.status(response.status);\n response.headers.forEach((value, key) => {\n res.setHeader(key, value);\n });\n res.send(await response.text());\n })\n .catch((err: unknown) => {\n res.status(500).send(String(err));\n });\n });\n }\n\n async listen(port: number, tls?: TlsOptions): Promise<http.Server> {\n let server: http.Server;\n\n if (tls === true) {\n const { cert, key } = (await devcert.certificateFor(\"localhost\")) as {\n cert: Buffer;\n key: Buffer;\n };\n if (!cert || !key) {\n throw new Error(\"Invalid certificate generated\");\n }\n server = https.createServer({ cert, key }, this.#app);\n } else if (tls && \"keyPath\" in tls) {\n const currentDir = process.cwd();\n server = https.createServer(\n {\n key: fs.readFileSync(path.join(currentDir, tls.keyPath)),\n cert: fs.readFileSync(path.join(currentDir, tls.certPath)),\n },\n this.#app,\n );\n } else if (tls && \"cert\" in tls) {\n server = https.createServer({ cert: tls.cert, key: tls.key }, this.#app);\n } else {\n server = http.createServer(this.#app);\n }\n\n return new Promise<http.Server>((resolve, reject) => {\n server.once(\"error\", reject);\n server.listen(port, () => {\n server.off(\"error\", reject);\n resolve(server);\n });\n });\n }\n\n #serveFetchHandler(\n handler: FetchHandler,\n req: express.Request,\n res: express.Response,\n next: express.NextFunction,\n ): void {\n // Build the full URL for the Fetch Request\n const protocol = req.protocol;\n const host = req.get(\"host\") ?? \"localhost\";\n const url = `${protocol}://${host}${req.originalUrl}`;\n\n // Convert Node.js incoming headers to Fetch Headers\n const headers = new Headers();\n for (const [key, value] of Object.entries(req.headers)) {\n if (typeof value === \"string\") {\n headers.set(key, value);\n } else if (Array.isArray(value)) {\n headers.set(key, value.join(\", \"));\n }\n }\n\n // bodyParser has already run, so req.body is a parsed JS value.\n // Re-serialize it so the Fetch Request body stream is readable.\n let body: string | undefined;\n if (\n req.method !== \"GET\" &&\n req.method !== \"HEAD\" &&\n req.body !== undefined\n ) {\n body = JSON.stringify(req.body);\n }\n\n const fetchRequest = new Request(url, {\n method: req.method,\n headers,\n body,\n });\n\n Promise.resolve(handler(fetchRequest))\n .then(async (response) => {\n res.status(response.status);\n response.headers.forEach((value, key) => {\n res.setHeader(key, value);\n });\n const responseBody = await response.text();\n res.send(responseBody);\n })\n .catch(next);\n }\n}\n\nexport function createExpressHttpAdapter(existingApp?: Express): {\n adapter: IHttpAdapter;\n} {\n return { adapter: new ExpressHttpAdapter(existingApp) };\n}\n"],"names":["#app","#router","#handlers","#serveFetchHandler"],"mappings":"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","debug_id":"45603953-04e5-5972-a877-8620773dcfbd"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"adapter-http-fastify-B248RJtm.mjs","sources":["../src/graphql/gateway/adapter-http-fastify.ts"],"sourcesContent":["import fastifyCors from \"@fastify/cors\";\nimport fastifyFormbody from \"@fastify/formbody\";\nimport fastifyMiddie from \"@fastify/middie\";\nimport devcert from \"devcert\";\nimport Fastify from \"fastify\";\nimport type { FastifyInstance, FastifyReply, FastifyRequest } from \"fastify\";\nimport type { CorsOptions } from \"cors\";\nimport fs from \"node:fs\";\nimport http from \"node:http\";\nimport https from \"node:https\";\nimport nodePath from \"node:path\";\nimport { match, type MatchFunction, type ParamData } from \"path-to-regexp\";\nimport type { FetchHandler, IHttpAdapter, TlsOptions } from \"./types.js\";\n\n/**\n * Normalises a route path for path-to-regexp v8:\n * - Collapses duplicate slashes (e.g. \"//explorer\" → \"/explorer\")\n * - Converts legacy optional-param syntax \":param?\" → \"{/:param}?\"\n */\nfunction normalizePath(path: string): string {\n return path.replace(/\\/+/g, \"/\").replace(/:(\\w+)\\?/g, \"{/:$1}\");\n}\n\n/** Parses body-limit strings like \"50mb\" to bytes. */\nfunction parseBodyLimit(limit: string): number {\n const m = /^(\\d+(?:\\.\\d+)?)\\s*(b|kb|mb|gb)?$/i.exec(limit.trim());\n if (!m) return 52_428_800; // 50 MB fallback\n const n = parseFloat(m[1]);\n const units: Record<string, number> = {\n b: 1,\n kb: 1_024,\n mb: 1_048_576,\n gb: 1_073_741_824,\n };\n return Math.round(n * (units[(m[2] ?? \"b\").toLowerCase()] ?? 1));\n}\n\ntype FetchEntry = {\n handler: FetchHandler;\n matcher: MatchFunction<ParamData>;\n prefix: boolean;\n};\n\ntype GetEntry = {\n handler: (r: Request) => Response | Promise<Response>;\n matcher: MatchFunction<ParamData>;\n};\n\ntype NodeHandler = (\n req: http.IncomingMessage,\n res: http.ServerResponse,\n body?: unknown,\n) => void;\n\ntype NodeEntry = {\n method: \"DELETE\" | \"GET\" | \"HEAD\" | \"POST\" | \"PUT\";\n matcher: MatchFunction<ParamData>;\n handler: NodeHandler;\n};\n\n// Pre-listen configuration ops (need the Fastify instance to apply).\ntype SetupOp =\n | { kind: \"cors\"; options?: CorsOptions; bodyLimit: number }\n | { kind: \"middie\"; middleware: unknown };\n\nexport class FastifyHttpAdapter implements IHttpAdapter {\n // Dispatch maps — populated at any time (before or after listen).\n readonly #fetchRoutes: FetchEntry[] = [];\n readonly #getRoutes: Map<string, GetEntry> = new Map();\n // Iterated in registration order on dispatch; entries carry their own\n // path-to-regexp matcher so parameterised paths (e.g. \"/attachments/:hash\")\n // resolve correctly and populate `req.params`.\n readonly #nodeRoutes: NodeEntry[] = [];\n\n // Ops that need the Fastify instance (CORS config, Connect middleware).\n readonly #setupOps: SetupOp[] = [];\n\n #instance: FastifyInstance | undefined;\n\n get handle(): unknown {\n return this.#instance;\n }\n\n setupMiddleware({\n corsOptions,\n bodyLimit = \"50mb\",\n }: {\n corsOptions?: CorsOptions;\n bodyLimit?: string;\n }): void {\n this.#setupOps.push({\n kind: \"cors\",\n options: corsOptions,\n bodyLimit: parseBodyLimit(bodyLimit),\n });\n }\n\n mount(\n path: string,\n handler: FetchHandler,\n { exact = false }: { exact?: boolean } = {},\n ): void {\n this.#fetchRoutes.push({\n handler,\n // exact=false → exact path match; exact=true → prefix match.\n matcher: match(normalizePath(path), { end: !exact }),\n prefix: exact,\n });\n }\n\n getRoute(\n path: string,\n handler: (request: Request) => Response | Promise<Response>,\n ): void {\n this.#getRoutes.set(path, { handler, matcher: match(normalizePath(path)) });\n }\n\n mountNodeRoute(\n method: \"DELETE\" | \"GET\" | \"HEAD\" | \"POST\" | \"PUT\",\n path: string,\n handler: NodeHandler,\n ): void {\n this.#nodeRoutes.push({\n method,\n matcher: match(normalizePath(path)),\n handler,\n });\n }\n\n mountRawMiddleware(middleware: unknown): void {\n if (this.#instance) {\n // @fastify/middie is always registered, so .use() is available post-listen.\n (\n this.#instance as FastifyInstance & {\n use(middleware: unknown): FastifyInstance;\n }\n ).use(middleware);\n } else {\n this.#setupOps.push({ kind: \"middie\", middleware });\n }\n }\n\n setupSentryErrorHandler(sentry: object): void {\n if (!this.#instance) return;\n const s = sentry as {\n setupFastifyErrorHandler(app: FastifyInstance): void;\n };\n s.setupFastifyErrorHandler(this.#instance);\n }\n\n async listen(port: number, tls?: TlsOptions): Promise<http.Server> {\n let httpServer: http.Server;\n\n if (tls === true) {\n const { cert, key } = (await devcert.certificateFor(\"localhost\")) as {\n cert: Buffer;\n key: Buffer;\n };\n if (!cert || !key) throw new Error(\"Invalid certificate generated\");\n httpServer = https.createServer({ cert, key });\n } else if (tls && \"keyPath\" in tls) {\n const cwd = process.cwd();\n httpServer = https.createServer({\n key: fs.readFileSync(nodePath.join(cwd, tls.keyPath)),\n cert: fs.readFileSync(nodePath.join(cwd, tls.certPath)),\n });\n } else if (tls && \"cert\" in tls) {\n httpServer = https.createServer({ cert: tls.cert, key: tls.key });\n } else {\n httpServer = http.createServer();\n }\n\n const corsOp = this.#setupOps.find(\n (op): op is Extract<SetupOp, { kind: \"cors\" }> => op.kind === \"cors\",\n );\n const bodyLimit = corsOp?.bodyLimit ?? 52_428_800;\n\n const instance = Fastify({\n serverFactory: (handler) => {\n httpServer.on(\"request\", handler);\n return httpServer;\n },\n bodyLimit,\n logger: false,\n });\n\n this.#instance = instance;\n\n // Always register middie first so .use() is available post-listen.\n await instance.register(fastifyMiddie);\n await instance.register(fastifyFormbody);\n\n for (const op of this.#setupOps) {\n if (op.kind === \"cors\") {\n await instance.register(\n fastifyCors,\n op.options as Parameters<typeof fastifyCors>[1],\n );\n } else {\n (\n instance as FastifyInstance & {\n use(middleware: unknown): FastifyInstance;\n }\n ).use(op.middleware);\n }\n }\n\n // Single catch-all route — all dispatching is done via the Maps above so\n // that routes registered after listen() are picked up automatically.\n // OPTIONS is excluded because @fastify/cors registers its own OPTIONS /*\n // handler for preflight; including it here would cause a duplicate-route\n // conflict at startup.\n instance.route({\n method: [\"DELETE\", \"GET\", \"HEAD\", \"PATCH\", \"POST\", \"PUT\"],\n url: \"/*\",\n handler: (req, reply) => this.#dispatch(req, reply),\n });\n\n await instance.ready();\n\n return new Promise<http.Server>((resolve, reject) => {\n httpServer.once(\"error\", reject);\n httpServer.listen(port, () => {\n httpServer.off(\"error\", reject);\n resolve(httpServer);\n });\n });\n }\n\n #dispatch(req: FastifyRequest, reply: FastifyReply): void | Promise<void> {\n const pathname = new URL(req.url, \"http://localhost\").pathname;\n const method = req.method.toUpperCase() as\n | \"DELETE\"\n | \"GET\"\n | \"HEAD\"\n | \"POST\"\n | \"PUT\";\n\n // 1. Node routes — path-to-regexp match + method, handler manages raw\n // response. Attach decoded params onto `req.raw` so downstream handlers\n // can read them via the same `req.params` API the Express adapter exposes.\n for (const entry of this.#nodeRoutes) {\n if (entry.method !== method) continue;\n const result = entry.matcher(pathname);\n if (!result) continue;\n (req.raw as http.IncomingMessage & { params?: ParamData }).params =\n result.params;\n reply.hijack();\n entry.handler(req.raw, reply.raw, req.body);\n return;\n }\n\n // 2. GET-specific routes (health, explorer, etc.).\n if (method === \"GET\") {\n for (const entry of this.#getRoutes.values()) {\n if (entry.matcher(pathname)) {\n return this.#serveGetEntry(entry, req, reply);\n }\n }\n }\n\n // 3. Fetch routes (GraphQL handlers, SSE, etc.).\n // Iterate in reverse so that the last-mounted handler wins when the same\n // path is mounted more than once (e.g. supergraph remount after reload).\n for (let i = this.#fetchRoutes.length - 1; i >= 0; i--) {\n const entry = this.#fetchRoutes[i]!;\n if (entry.matcher(pathname)) {\n return serveFetchHandler(entry.handler, req, reply);\n }\n }\n\n void reply.status(404).send({\n message: `Route ${req.method}:${pathname} not found`,\n error: \"Not Found\",\n statusCode: 404,\n });\n }\n\n async #serveGetEntry(\n entry: GetEntry,\n req: FastifyRequest,\n reply: FastifyReply,\n ): Promise<void> {\n const url = buildUrl(req);\n const headers = buildHeaders(req);\n const fetchReq = new Request(url, { method: \"GET\", headers });\n const response = await entry.handler(fetchReq);\n writeResponse(reply, response);\n return reply.send(await response.text());\n }\n}\n\nasync function serveFetchHandler(\n handler: FetchHandler,\n req: FastifyRequest,\n reply: FastifyReply,\n): Promise<void> {\n const url = buildUrl(req);\n const headers = buildHeaders(req);\n\n let body: string | undefined;\n if (req.method !== \"GET\" && req.method !== \"HEAD\" && req.body !== undefined) {\n body = JSON.stringify(req.body);\n }\n\n const fetchRequest = new Request(url, { method: req.method, headers, body });\n const response = await handler(fetchRequest);\n writeResponse(reply, response);\n return reply.send(await response.text());\n}\n\nfunction buildUrl(req: FastifyRequest): string {\n const host = req.headers.host ?? \"localhost\";\n return `${req.protocol}://${host}${req.url}`;\n}\n\nfunction buildHeaders(req: FastifyRequest): Headers {\n const headers = new Headers();\n for (const [key, value] of Object.entries(req.headers)) {\n if (typeof value === \"string\") {\n headers.set(key, value);\n } else if (Array.isArray(value)) {\n headers.set(key, value.join(\", \"));\n }\n }\n return headers;\n}\n\nfunction writeResponse(reply: FastifyReply, response: Response): void {\n void reply.status(response.status);\n response.headers.forEach((value, key) => {\n void reply.header(key, value);\n });\n}\n\nexport function createFastifyHttpAdapter(): { adapter: IHttpAdapter } {\n return { adapter: new FastifyHttpAdapter() };\n}\n"],"names":["#fetchRoutes","#getRoutes","#nodeRoutes","#setupOps","#instance","nodePath","#dispatch","#serveGetEntry"],"mappings":"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","debug_id":"4fb1d468-f1ff-54b7-91b9-0b7da8b78c2d"}
|