@powerhousedao/reactor-api 6.2.3-dev.2 → 6.2.3-dev.4

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.
Files changed (26) hide show
  1. package/dist/{adapter-gateway-apollo-DdamNLPT.mjs → adapter-gateway-apollo-CxJNBVyD.mjs} +7 -8
  2. package/dist/adapter-gateway-apollo-CxJNBVyD.mjs.map +1 -0
  3. package/dist/adapter-gateway-apollo-DowrX6E_.mjs +4 -0
  4. package/dist/{adapter-gateway-mercurius-CLmTtNJC.mjs → adapter-gateway-mercurius-CZVy88Za.mjs} +6 -5
  5. package/dist/adapter-gateway-mercurius-CZVy88Za.mjs.map +1 -0
  6. package/dist/adapter-gateway-stitching-CaZjvRzx.mjs +316 -0
  7. package/dist/adapter-gateway-stitching-CaZjvRzx.mjs.map +1 -0
  8. package/dist/{adapter-http-express-54gdI9bu.mjs → adapter-http-express-B39rPhqH.mjs} +4 -4
  9. package/dist/{adapter-http-express-54gdI9bu.mjs.map → adapter-http-express-B39rPhqH.mjs.map} +1 -1
  10. package/dist/{adapter-http-fastify-DmccBVOe.mjs → adapter-http-fastify-BwXO6rqE.mjs} +4 -4
  11. package/dist/{adapter-http-fastify-DmccBVOe.mjs.map → adapter-http-fastify-BwXO6rqE.mjs.map} +1 -1
  12. package/dist/index.d.mts +46 -13
  13. package/dist/index.d.mts.map +1 -1
  14. package/dist/index.mjs +114 -38
  15. package/dist/index.mjs.map +1 -1
  16. package/dist/{path-normalize-DWWFLiy6.mjs → path-normalize-BOQwY9wR.mjs} +3 -3
  17. package/dist/{path-normalize-DWWFLiy6.mjs.map → path-normalize-BOQwY9wR.mjs.map} +1 -1
  18. package/dist/src/packages/vite-loader.d.mts +1 -1
  19. package/dist/src/packages/vite-loader.d.mts.map +1 -1
  20. package/dist/src/packages/vite-loader.mjs +5 -5
  21. package/dist/src/packages/vite-loader.mjs.map +1 -1
  22. package/dist/{types-Bz2niABC.d.mts → types-DcYyNcHJ.d.mts} +1 -1
  23. package/dist/{types-Bz2niABC.d.mts.map → types-DcYyNcHJ.d.mts.map} +1 -1
  24. package/package.json +17 -14
  25. package/dist/adapter-gateway-apollo-DdamNLPT.mjs.map +0 -1
  26. package/dist/adapter-gateway-mercurius-CLmTtNJC.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"adapter-http-express-54gdI9bu.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 { Readable } from \"node:stream\";\nimport type { ReadableStream as WebReadableStream } from \"node:stream/web\";\nimport { match, type MatchFunction, type ParamData } from \"path-to-regexp\";\nimport type {\n FetchHandler,\n HttpMethod,\n IHttpAdapter,\n NodeRouteOptions,\n AdapterRouteHandle,\n TlsOptions,\n} from \"./types.js\";\nimport { normalizePath } from \"./path-normalize.js\";\n\ntype GetHandler = (r: Request) => Response | Promise<Response>;\n\ntype NodeHandler = (\n req: http.IncomingMessage,\n res: http.ServerResponse,\n body?: unknown,\n) => void | Promise<void>;\n\ntype RouteEntry =\n | {\n kind: \"fetch\";\n path: string;\n matcher: MatchFunction<ParamData>;\n prefix: boolean;\n handler: FetchHandler;\n }\n | {\n kind: \"get\";\n path: string;\n matcher: MatchFunction<ParamData>;\n handler: GetHandler;\n }\n | {\n kind: \"node\";\n method: string;\n path: string;\n matcher: MatchFunction<ParamData>;\n handler: NodeHandler;\n /** Dispatched ahead of the body parsers, with the stream unread. */\n rawBody: boolean;\n };\n\nexport class ExpressHttpAdapter implements IHttpAdapter {\n readonly #app: Express;\n readonly #router: IRouter;\n\n /**\n * Every route lives in this registry and is served by one\n * permanently-registered dispatcher (installed by setupMiddleware), because\n * Express 4 has no route-removal API: routes registered directly on the\n * app or router can never be taken back. Entries iterate in registration\n * order; mounting a path that already holds a route of the same kind (and\n * method, for node routes) replaces the old entry, so re-mounting is\n * last-write-wins without accumulating.\n */\n readonly #routes = new Map<number, RouteEntry>();\n #nextHandle = 0;\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 // Connect/Express middleware shape; the caller owns its typing.\n this.#app.use(middleware as express.RequestHandler);\n }\n\n mountNodeRoute(\n method: HttpMethod,\n path: string,\n handler: (\n req: http.IncomingMessage,\n res: http.ServerResponse,\n body?: unknown,\n ) => void | Promise<void>,\n { rawBody = false, prefix = false }: NodeRouteOptions = {},\n ): AdapterRouteHandle {\n this.#replaceDuplicates(\"node\", path, method.toUpperCase());\n const handle = this.#nextHandle++;\n this.#routes.set(handle, {\n kind: \"node\",\n method: method.toUpperCase(),\n path,\n matcher: match(normalizePath(path), { end: !prefix }),\n rawBody,\n handler,\n });\n return { dispose: () => this.#routes.delete(handle) };\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\n // Ahead of the parsers: a raw route's whole point is that nothing has read\n // the stream. Behind them, `req` is a consumed stream and only a\n // re-encoded `req.body` survives — which cannot carry a signature over the\n // octets the client actually sent.\n this.#router.use((req, res, next) => {\n this.#dispatchNodeRoute(req, res, next, true);\n });\n\n this.#router.use(bodyParser.json({ limit: bodyLimit }));\n this.#router.use(\n bodyParser.urlencoded({ extended: true, limit: bodyLimit }),\n );\n\n // The single dispatch point for every registered route, registered\n // AFTER the body parsers so node routes receive a parsed req.body.\n // A request matching no route falls through to app-level middleware\n // (mountRawMiddleware) and then Express's default 404.\n this.#router.use((req, res, next) => {\n const pathname = req.path;\n\n // Node routes first, then GET routes, then Fetch mounts — the same\n // order the Fastify adapter uses. A node route is the most specific\n // registration there is (method plus exact path), while a Fetch mount is\n // often a prefix; letting the prefix win would silently shadow an exact\n // route, and would do it in only one of the two adapters.\n if (this.#dispatchNodeRoute(req, res, () => undefined, false)) return;\n\n if (req.method === \"GET\" || req.method === \"HEAD\") {\n for (const entry of this.#routes.values()) {\n if (entry.kind !== \"get\" || !entry.matcher(pathname)) continue;\n this.#serveGetEntry(entry, req, res);\n return;\n }\n }\n\n for (const entry of this.#routes.values()) {\n if (entry.kind !== \"fetch\" || !entry.matcher(pathname)) continue;\n this.#serveFetchHandler(entry.handler, req, res, next);\n return;\n }\n\n next();\n });\n }\n\n /**\n * Serves the first node route matching this request, or calls `next()`.\n * `raw` selects which half of the registry to consider, so the two passes —\n * one before the body parsers, one after — never serve the same route twice.\n */\n #dispatchNodeRoute(\n req: express.Request,\n res: express.Response,\n next: express.NextFunction,\n raw: boolean,\n ): boolean {\n const pathname = req.path;\n for (const entry of this.#routes.values()) {\n if (entry.kind !== \"node\") continue;\n if (entry.rawBody !== raw) continue;\n if (entry.method !== req.method) continue;\n const matched = entry.matcher(pathname);\n if (!matched) continue;\n req.params = matched.params as Record<string, string>;\n // Fire-and-forget, as before: the node handler manages its own response\n // and the adapter does not await its promise.\n void entry.handler(req, res, entry.rawBody ? undefined : req.body);\n return true;\n }\n next();\n return false;\n }\n\n mount(\n path: string,\n handler: FetchHandler,\n { prefix, exact }: { prefix?: boolean; exact?: boolean } = {},\n ): AdapterRouteHandle {\n // `exact` never meant exact: it selected prefix matching. Kept as an alias\n // so existing callers keep working while the name is retired.\n const asPrefix = prefix ?? exact ?? false;\n this.#replaceDuplicates(\"fetch\", path);\n const handle = this.#nextHandle++;\n this.#routes.set(handle, {\n kind: \"fetch\",\n path,\n matcher: match(normalizePath(path), { end: !asPrefix }),\n prefix: asPrefix,\n handler,\n });\n return { dispose: () => this.#routes.delete(handle) };\n }\n\n getRoute(\n path: string,\n handler: (request: Request) => Response | Promise<Response>,\n ): AdapterRouteHandle {\n this.#replaceDuplicates(\"get\", path);\n const handle = this.#nextHandle++;\n this.#routes.set(handle, {\n kind: \"get\",\n path,\n matcher: match(normalizePath(path)),\n handler,\n });\n return { dispose: () => this.#routes.delete(handle) };\n }\n\n /**\n * Drop any existing entry the new registration would duplicate (same kind\n * and path, plus method for node routes) so a re-mount replaces instead of\n * shadowing. Map iteration tolerates concurrent deletion.\n */\n #replaceDuplicates(\n kind: RouteEntry[\"kind\"],\n path: string,\n method?: string,\n ): void {\n for (const [handle, entry] of this.#routes) {\n if (entry.kind !== kind || entry.path !== path) continue;\n if (kind === \"node\" && entry.kind === \"node\" && entry.method !== method) {\n continue;\n }\n this.#routes.delete(handle);\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 if (response.body === null) {\n res.send(await response.text());\n return;\n }\n // Stream the body to the socket instead of awaiting .text(): a\n // stream-backed body (e.g. graphql-sse) only closes when the\n // subscription completes, so awaiting would hang the request.\n // `response.body` is typed against the global (lib) ReadableStream\n // declaration, while Readable.fromWeb wants node:stream/web's; at\n // runtime they are the same stream, so the cast is safe.\n const bodyStream = response.body as WebReadableStream;\n const nodeStream = Readable.fromWeb(bodyStream);\n req.on(\"close\", () => {\n // The client went away mid-stream; stop pulling from the source.\n nodeStream.destroy();\n });\n nodeStream.on(\"error\", (err) => {\n if (res.headersSent) {\n // The response has already started; nothing left to say.\n res.destroy();\n } else {\n next(err);\n }\n });\n nodeStream.pipe(res);\n })\n .catch(next);\n }\n\n #serveGetEntry(\n entry: Extract<RouteEntry, { kind: \"get\" }>,\n req: express.Request,\n res: express.Response,\n ): void {\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 // GET is forced (matching the pre-refactor behavior, which also\n // normalized HEAD requests through the GET route handler).\n const fetchRequest = new Request(url, { method: \"GET\", headers });\n Promise.resolve(entry.handler(fetchRequest))\n .then(async (response) => {\n res.status(response.status);\n response.headers.forEach((value, key) => {\n res.setHeader(key, value);\n });\n if (response.body === null) {\n res.send(await response.text());\n return;\n }\n // Stream the body to the socket instead of awaiting .text(): a\n // stream-backed body (e.g. graphql-sse) only closes when the\n // subscription completes, so awaiting would hang the request.\n // `response.body` is typed against the global (lib) ReadableStream\n // declaration, while Readable.fromWeb wants node:stream/web's; at\n // runtime they are the same stream, so the cast is safe.\n const bodyStream = response.body as WebReadableStream;\n const nodeStream = Readable.fromWeb(bodyStream);\n req.on(\"close\", () => {\n // The client went away mid-stream; stop pulling from the source.\n nodeStream.destroy();\n });\n nodeStream.on(\"error\", (err) => {\n if (res.headersSent) {\n // The response has already started; nothing left to say.\n res.destroy();\n } else {\n res.status(500).send(String(err));\n }\n });\n nodeStream.pipe(res);\n })\n .catch((err: unknown) => {\n res.status(500).send(String(err));\n });\n }\n}\n\nexport function createExpressHttpAdapter(existingApp?: Express): {\n adapter: IHttpAdapter;\n} {\n return { adapter: new ExpressHttpAdapter(existingApp) };\n}\n"],"names":["#app","#router","#routes","#replaceDuplicates","#nextHandle","#dispatchNodeRoute","#serveGetEntry","#serveFetchHandler"],"mappings":"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","debug_id":"90361ed3-8d11-5317-8905-e79cd3599c85"}
1
+ {"version":3,"file":"adapter-http-express-B39rPhqH.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 { Readable } from \"node:stream\";\nimport type { ReadableStream as WebReadableStream } from \"node:stream/web\";\nimport { match, type MatchFunction, type ParamData } from \"path-to-regexp\";\nimport type {\n FetchHandler,\n HttpMethod,\n IHttpAdapter,\n NodeRouteOptions,\n AdapterRouteHandle,\n TlsOptions,\n} from \"./types.js\";\nimport { normalizePath } from \"./path-normalize.js\";\n\ntype GetHandler = (r: Request) => Response | Promise<Response>;\n\ntype NodeHandler = (\n req: http.IncomingMessage,\n res: http.ServerResponse,\n body?: unknown,\n) => void | Promise<void>;\n\ntype RouteEntry =\n | {\n kind: \"fetch\";\n path: string;\n matcher: MatchFunction<ParamData>;\n prefix: boolean;\n handler: FetchHandler;\n }\n | {\n kind: \"get\";\n path: string;\n matcher: MatchFunction<ParamData>;\n handler: GetHandler;\n }\n | {\n kind: \"node\";\n method: string;\n path: string;\n matcher: MatchFunction<ParamData>;\n handler: NodeHandler;\n /** Dispatched ahead of the body parsers, with the stream unread. */\n rawBody: boolean;\n };\n\nexport class ExpressHttpAdapter implements IHttpAdapter {\n readonly #app: Express;\n readonly #router: IRouter;\n\n /**\n * Every route lives in this registry and is served by one\n * permanently-registered dispatcher (installed by setupMiddleware), because\n * Express 4 has no route-removal API: routes registered directly on the\n * app or router can never be taken back. Entries iterate in registration\n * order; mounting a path that already holds a route of the same kind (and\n * method, for node routes) replaces the old entry, so re-mounting is\n * last-write-wins without accumulating.\n */\n readonly #routes = new Map<number, RouteEntry>();\n #nextHandle = 0;\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 // Connect/Express middleware shape; the caller owns its typing.\n this.#app.use(middleware as express.RequestHandler);\n }\n\n mountNodeRoute(\n method: HttpMethod,\n path: string,\n handler: (\n req: http.IncomingMessage,\n res: http.ServerResponse,\n body?: unknown,\n ) => void | Promise<void>,\n { rawBody = false, prefix = false }: NodeRouteOptions = {},\n ): AdapterRouteHandle {\n this.#replaceDuplicates(\"node\", path, method.toUpperCase());\n const handle = this.#nextHandle++;\n this.#routes.set(handle, {\n kind: \"node\",\n method: method.toUpperCase(),\n path,\n matcher: match(normalizePath(path), { end: !prefix }),\n rawBody,\n handler,\n });\n return { dispose: () => this.#routes.delete(handle) };\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\n // Ahead of the parsers: a raw route's whole point is that nothing has read\n // the stream. Behind them, `req` is a consumed stream and only a\n // re-encoded `req.body` survives — which cannot carry a signature over the\n // octets the client actually sent.\n this.#router.use((req, res, next) => {\n this.#dispatchNodeRoute(req, res, next, true);\n });\n\n this.#router.use(bodyParser.json({ limit: bodyLimit }));\n this.#router.use(\n bodyParser.urlencoded({ extended: true, limit: bodyLimit }),\n );\n\n // The single dispatch point for every registered route, registered\n // AFTER the body parsers so node routes receive a parsed req.body.\n // A request matching no route falls through to app-level middleware\n // (mountRawMiddleware) and then Express's default 404.\n this.#router.use((req, res, next) => {\n const pathname = req.path;\n\n // Node routes first, then GET routes, then Fetch mounts — the same\n // order the Fastify adapter uses. A node route is the most specific\n // registration there is (method plus exact path), while a Fetch mount is\n // often a prefix; letting the prefix win would silently shadow an exact\n // route, and would do it in only one of the two adapters.\n if (this.#dispatchNodeRoute(req, res, () => undefined, false)) return;\n\n if (req.method === \"GET\" || req.method === \"HEAD\") {\n for (const entry of this.#routes.values()) {\n if (entry.kind !== \"get\" || !entry.matcher(pathname)) continue;\n this.#serveGetEntry(entry, req, res);\n return;\n }\n }\n\n for (const entry of this.#routes.values()) {\n if (entry.kind !== \"fetch\" || !entry.matcher(pathname)) continue;\n this.#serveFetchHandler(entry.handler, req, res, next);\n return;\n }\n\n next();\n });\n }\n\n /**\n * Serves the first node route matching this request, or calls `next()`.\n * `raw` selects which half of the registry to consider, so the two passes —\n * one before the body parsers, one after — never serve the same route twice.\n */\n #dispatchNodeRoute(\n req: express.Request,\n res: express.Response,\n next: express.NextFunction,\n raw: boolean,\n ): boolean {\n const pathname = req.path;\n for (const entry of this.#routes.values()) {\n if (entry.kind !== \"node\") continue;\n if (entry.rawBody !== raw) continue;\n if (entry.method !== req.method) continue;\n const matched = entry.matcher(pathname);\n if (!matched) continue;\n req.params = matched.params as Record<string, string>;\n // Fire-and-forget, as before: the node handler manages its own response\n // and the adapter does not await its promise.\n void entry.handler(req, res, entry.rawBody ? undefined : req.body);\n return true;\n }\n next();\n return false;\n }\n\n mount(\n path: string,\n handler: FetchHandler,\n { prefix, exact }: { prefix?: boolean; exact?: boolean } = {},\n ): AdapterRouteHandle {\n // `exact` never meant exact: it selected prefix matching. Kept as an alias\n // so existing callers keep working while the name is retired.\n const asPrefix = prefix ?? exact ?? false;\n this.#replaceDuplicates(\"fetch\", path);\n const handle = this.#nextHandle++;\n this.#routes.set(handle, {\n kind: \"fetch\",\n path,\n matcher: match(normalizePath(path), { end: !asPrefix }),\n prefix: asPrefix,\n handler,\n });\n return { dispose: () => this.#routes.delete(handle) };\n }\n\n getRoute(\n path: string,\n handler: (request: Request) => Response | Promise<Response>,\n ): AdapterRouteHandle {\n this.#replaceDuplicates(\"get\", path);\n const handle = this.#nextHandle++;\n this.#routes.set(handle, {\n kind: \"get\",\n path,\n matcher: match(normalizePath(path)),\n handler,\n });\n return { dispose: () => this.#routes.delete(handle) };\n }\n\n /**\n * Drop any existing entry the new registration would duplicate (same kind\n * and path, plus method for node routes) so a re-mount replaces instead of\n * shadowing. Map iteration tolerates concurrent deletion.\n */\n #replaceDuplicates(\n kind: RouteEntry[\"kind\"],\n path: string,\n method?: string,\n ): void {\n for (const [handle, entry] of this.#routes) {\n if (entry.kind !== kind || entry.path !== path) continue;\n if (kind === \"node\" && entry.kind === \"node\" && entry.method !== method) {\n continue;\n }\n this.#routes.delete(handle);\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 if (response.body === null) {\n res.send(await response.text());\n return;\n }\n // Stream the body to the socket instead of awaiting .text(): a\n // stream-backed body (e.g. graphql-sse) only closes when the\n // subscription completes, so awaiting would hang the request.\n // `response.body` is typed against the global (lib) ReadableStream\n // declaration, while Readable.fromWeb wants node:stream/web's; at\n // runtime they are the same stream, so the cast is safe.\n const bodyStream = response.body as WebReadableStream;\n const nodeStream = Readable.fromWeb(bodyStream);\n req.on(\"close\", () => {\n // The client went away mid-stream; stop pulling from the source.\n nodeStream.destroy();\n });\n nodeStream.on(\"error\", (err) => {\n if (res.headersSent) {\n // The response has already started; nothing left to say.\n res.destroy();\n } else {\n next(err);\n }\n });\n nodeStream.pipe(res);\n })\n .catch(next);\n }\n\n #serveGetEntry(\n entry: Extract<RouteEntry, { kind: \"get\" }>,\n req: express.Request,\n res: express.Response,\n ): void {\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 // GET is forced (matching the pre-refactor behavior, which also\n // normalized HEAD requests through the GET route handler).\n const fetchRequest = new Request(url, { method: \"GET\", headers });\n Promise.resolve(entry.handler(fetchRequest))\n .then(async (response) => {\n res.status(response.status);\n response.headers.forEach((value, key) => {\n res.setHeader(key, value);\n });\n if (response.body === null) {\n res.send(await response.text());\n return;\n }\n // Stream the body to the socket instead of awaiting .text(): a\n // stream-backed body (e.g. graphql-sse) only closes when the\n // subscription completes, so awaiting would hang the request.\n // `response.body` is typed against the global (lib) ReadableStream\n // declaration, while Readable.fromWeb wants node:stream/web's; at\n // runtime they are the same stream, so the cast is safe.\n const bodyStream = response.body as WebReadableStream;\n const nodeStream = Readable.fromWeb(bodyStream);\n req.on(\"close\", () => {\n // The client went away mid-stream; stop pulling from the source.\n nodeStream.destroy();\n });\n nodeStream.on(\"error\", (err) => {\n if (res.headersSent) {\n // The response has already started; nothing left to say.\n res.destroy();\n } else {\n res.status(500).send(String(err));\n }\n });\n nodeStream.pipe(res);\n })\n .catch((err: unknown) => {\n res.status(500).send(String(err));\n });\n }\n}\n\nexport function createExpressHttpAdapter(existingApp?: Express): {\n adapter: IHttpAdapter;\n} {\n return { adapter: new ExpressHttpAdapter(existingApp) };\n}\n"],"names":["#app","#router","#routes","#replaceDuplicates","#nextHandle","#dispatchNodeRoute","#serveGetEntry","#serveFetchHandler"],"mappings":"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","debug_id":"af482776-5e68-5345-a965-0937af984537"}
@@ -1,6 +1,6 @@
1
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]="a9dc57df-8ede-54a4-8a09-14b3ff82f44d")}catch(e){}}();
3
- import { t as normalizePath } from "./path-normalize-DWWFLiy6.mjs";
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]="07c62958-83d2-55bc-b138-149275988013")}catch(e){}}();
3
+ import { t as normalizePath } from "./path-normalize-BOQwY9wR.mjs";
4
4
  import path from "node:path";
5
5
  import { match } from "path-to-regexp";
6
6
  import { Readable } from "node:stream";
@@ -239,5 +239,5 @@ function createFastifyHttpAdapter() {
239
239
  //#endregion
240
240
  export { createFastifyHttpAdapter };
241
241
 
242
- //# sourceMappingURL=adapter-http-fastify-DmccBVOe.mjs.map
243
- //# debugId=a9dc57df-8ede-54a4-8a09-14b3ff82f44d
242
+ //# sourceMappingURL=adapter-http-fastify-BwXO6rqE.mjs.map
243
+ //# debugId=07c62958-83d2-55bc-b138-149275988013
@@ -1 +1 @@
1
- {"version":3,"file":"adapter-http-fastify-DmccBVOe.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 type { CorsOptions } from \"cors\";\nimport devcert from \"devcert\";\nimport Fastify from \"fastify\";\nimport type { FastifyInstance, FastifyReply, FastifyRequest } from \"fastify\";\nimport fs from \"node:fs\";\nimport http from \"node:http\";\nimport https from \"node:https\";\nimport nodePath from \"node:path\";\nimport { Readable } from \"node:stream\";\nimport type { ReadableStream as WebReadableStream } from \"node:stream/web\";\nimport { match, type MatchFunction, type ParamData } from \"path-to-regexp\";\nimport type {\n FetchHandler,\n HttpMethod,\n IHttpAdapter,\n NodeRouteOptions,\n AdapterRouteHandle,\n TlsOptions,\n} from \"./types.js\";\nimport { normalizePath } from \"./path-normalize.js\";\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 path: string;\n handler: FetchHandler;\n matcher: MatchFunction<ParamData>;\n prefix: boolean;\n};\n\ntype GetEntry = {\n path: string;\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 path: string;\n method: HttpMethod;\n matcher: MatchFunction<ParamData>;\n handler: NodeHandler;\n /** Claimed in the onRequest hook, before any body parsing. */\n rawBody: boolean;\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, keyed by route handle and iterated in registration\n // order — populated at any time (before or after listen). Mounting a\n // path that already holds a route of the same kind (and method, for\n // node routes) replaces the old entry, so re-mounting is last-write-\n // wins without accumulating; a handle's dispose() removes its own entry.\n readonly #fetchRoutes = new Map<number, FetchEntry>();\n readonly #getRoutes = new Map<number, GetEntry>();\n readonly #nodeRoutes = new Map<number, NodeEntry>();\n #nextHandle = 0;\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 { prefix, exact }: { prefix?: boolean; exact?: boolean } = {},\n ): AdapterRouteHandle {\n // `exact` never meant exact: it selected prefix matching. Kept as an alias\n // so existing callers keep working while the name is retired.\n const asPrefix = prefix ?? exact ?? false;\n for (const [handle, entry] of this.#fetchRoutes) {\n if (entry.path === path) this.#fetchRoutes.delete(handle);\n }\n const handle = this.#nextHandle++;\n this.#fetchRoutes.set(handle, {\n path,\n handler,\n matcher: match(normalizePath(path), { end: !asPrefix }),\n prefix: asPrefix,\n });\n return { dispose: () => this.#fetchRoutes.delete(handle) };\n }\n\n getRoute(\n path: string,\n handler: (r: Request) => Response | Promise<Response>,\n ): AdapterRouteHandle {\n for (const [handle, entry] of this.#getRoutes) {\n if (entry.path === path) this.#getRoutes.delete(handle);\n }\n const handle = this.#nextHandle++;\n this.#getRoutes.set(handle, {\n path,\n handler,\n matcher: match(normalizePath(path)),\n });\n return { dispose: () => this.#getRoutes.delete(handle) };\n }\n\n mountNodeRoute(\n method: HttpMethod,\n path: string,\n handler: NodeHandler,\n { rawBody = false, prefix = false }: NodeRouteOptions = {},\n ): AdapterRouteHandle {\n for (const [handle, entry] of this.#nodeRoutes) {\n if (entry.path === path && entry.method === method) {\n this.#nodeRoutes.delete(handle);\n }\n }\n const handle = this.#nextHandle++;\n this.#nodeRoutes.set(handle, {\n path,\n method,\n matcher: match(normalizePath(path), { end: !prefix }),\n handler,\n rawBody,\n });\n return { dispose: () => this.#nodeRoutes.delete(handle) };\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 // Raw routes are claimed here, in the earliest hook there is: Fastify\n // parses the body before the handler runs, and it 415s an unknown content\n // type outright, so a route that needs the octets as sent cannot wait for\n // dispatch. `hijack()` takes the reply out of Fastify's lifecycle and the\n // handler owns the socket from here.\n instance.addHook(\"onRequest\", (req, reply, done) => {\n const claimed = this.#matchNodeRoute(req, true);\n if (!claimed) {\n done();\n return;\n }\n (req.raw as http.IncomingMessage & { params?: ParamData }).params =\n claimed.params;\n reply.hijack();\n claimed.route.handler(req.raw, reply.raw, undefined);\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 /**\n * Finds a node route for this request. `raw` selects which half of the\n * registry to consider: raw routes are claimed in the onRequest hook, the\n * rest in the catch-all handler once the body is parsed.\n */\n #matchNodeRoute(\n req: FastifyRequest,\n raw: boolean,\n ): { route: NodeEntry; params: ParamData } | undefined {\n const pathname = new URL(req.url, \"http://localhost\").pathname;\n const method = req.method.toUpperCase();\n for (const entry of this.#nodeRoutes.values()) {\n if (entry.rawBody !== raw) continue;\n if (entry.method !== method) continue;\n const result = entry.matcher(pathname);\n if (result) return { route: entry, params: result.params };\n }\n return undefined;\n }\n\n #dispatch(\n req: FastifyRequest,\n reply: FastifyReply,\n ): void | Promise<FastifyReply> {\n const pathname = new URL(req.url, \"http://localhost\").pathname;\n const method = req.method.toUpperCase() as\n | \"DELETE\"\n | \"GET\"\n | \"HEAD\"\n | \"PATCH\"\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 const node = this.#matchNodeRoute(req, false);\n if (node) {\n (req.raw as http.IncomingMessage & { params?: ParamData }).params =\n node.params;\n reply.hijack();\n node.route.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 (const entry of [...this.#fetchRoutes.values()].reverse()) {\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<FastifyReply> {\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 if (response.body === null) {\n return reply.send(await response.text());\n }\n // Stream the body instead of awaiting .text(): a stream-backed body\n // (e.g. graphql-sse) only closes when the subscription completes, so\n // awaiting would hang the request. Fastify tears the source down on\n // client disconnect and routes pre-header stream errors to the\n // error handler.\n // `response.body` is typed against the global (lib) ReadableStream\n // declaration, while Readable.fromWeb wants node:stream/web's; at\n // runtime they are the same stream, so the cast is safe.\n const bodyStream = response.body as WebReadableStream;\n return reply.send(Readable.fromWeb(bodyStream));\n }\n}\n\nasync function serveFetchHandler(\n handler: FetchHandler,\n req: FastifyRequest,\n reply: FastifyReply,\n): Promise<FastifyReply> {\n const url = buildUrl(req);\n const headers = buildHeaders(req);\n let body: string | undefined;\n if (req.method !== \"GET\" && req.method !== \"HEAD\" && req.body !== undefined) {\n body = JSON.stringify(req.body);\n }\n const response = await handler(\n new Request(url, { method: req.method, headers, body }),\n );\n writeResponse(reply, response);\n if (response.body === null) {\n return reply.send(await response.text());\n }\n // Stream the body instead of awaiting .text(): a stream-backed body\n // (e.g. graphql-sse) only closes when the subscription completes, so\n // awaiting would hang the request. Fastify tears the source down on\n // client disconnect and routes pre-header stream errors to the\n // error handler.\n // `response.body` is typed against the global (lib) ReadableStream\n // declaration, while Readable.fromWeb wants node:stream/web's; at\n // runtime they are the same stream, so the cast is safe.\n const bodyStream = response.body as WebReadableStream;\n return reply.send(Readable.fromWeb(bodyStream));\n}\n\nfunction buildUrl(req: FastifyRequest): string {\n const protocol = req.protocol;\n const host = req.headers.host ?? \"localhost\";\n return `${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 reply.statusCode = response.status;\n response.headers.forEach((value, key) => {\n 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","#nextHandle","nodePath","#matchNodeRoute","#dispatch","#serveGetEntry"],"mappings":"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","debug_id":"a9dc57df-8ede-54a4-8a09-14b3ff82f44d"}
1
+ {"version":3,"file":"adapter-http-fastify-BwXO6rqE.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 type { CorsOptions } from \"cors\";\nimport devcert from \"devcert\";\nimport Fastify from \"fastify\";\nimport type { FastifyInstance, FastifyReply, FastifyRequest } from \"fastify\";\nimport fs from \"node:fs\";\nimport http from \"node:http\";\nimport https from \"node:https\";\nimport nodePath from \"node:path\";\nimport { Readable } from \"node:stream\";\nimport type { ReadableStream as WebReadableStream } from \"node:stream/web\";\nimport { match, type MatchFunction, type ParamData } from \"path-to-regexp\";\nimport type {\n FetchHandler,\n HttpMethod,\n IHttpAdapter,\n NodeRouteOptions,\n AdapterRouteHandle,\n TlsOptions,\n} from \"./types.js\";\nimport { normalizePath } from \"./path-normalize.js\";\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 path: string;\n handler: FetchHandler;\n matcher: MatchFunction<ParamData>;\n prefix: boolean;\n};\n\ntype GetEntry = {\n path: string;\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 path: string;\n method: HttpMethod;\n matcher: MatchFunction<ParamData>;\n handler: NodeHandler;\n /** Claimed in the onRequest hook, before any body parsing. */\n rawBody: boolean;\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, keyed by route handle and iterated in registration\n // order — populated at any time (before or after listen). Mounting a\n // path that already holds a route of the same kind (and method, for\n // node routes) replaces the old entry, so re-mounting is last-write-\n // wins without accumulating; a handle's dispose() removes its own entry.\n readonly #fetchRoutes = new Map<number, FetchEntry>();\n readonly #getRoutes = new Map<number, GetEntry>();\n readonly #nodeRoutes = new Map<number, NodeEntry>();\n #nextHandle = 0;\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 { prefix, exact }: { prefix?: boolean; exact?: boolean } = {},\n ): AdapterRouteHandle {\n // `exact` never meant exact: it selected prefix matching. Kept as an alias\n // so existing callers keep working while the name is retired.\n const asPrefix = prefix ?? exact ?? false;\n for (const [handle, entry] of this.#fetchRoutes) {\n if (entry.path === path) this.#fetchRoutes.delete(handle);\n }\n const handle = this.#nextHandle++;\n this.#fetchRoutes.set(handle, {\n path,\n handler,\n matcher: match(normalizePath(path), { end: !asPrefix }),\n prefix: asPrefix,\n });\n return { dispose: () => this.#fetchRoutes.delete(handle) };\n }\n\n getRoute(\n path: string,\n handler: (r: Request) => Response | Promise<Response>,\n ): AdapterRouteHandle {\n for (const [handle, entry] of this.#getRoutes) {\n if (entry.path === path) this.#getRoutes.delete(handle);\n }\n const handle = this.#nextHandle++;\n this.#getRoutes.set(handle, {\n path,\n handler,\n matcher: match(normalizePath(path)),\n });\n return { dispose: () => this.#getRoutes.delete(handle) };\n }\n\n mountNodeRoute(\n method: HttpMethod,\n path: string,\n handler: NodeHandler,\n { rawBody = false, prefix = false }: NodeRouteOptions = {},\n ): AdapterRouteHandle {\n for (const [handle, entry] of this.#nodeRoutes) {\n if (entry.path === path && entry.method === method) {\n this.#nodeRoutes.delete(handle);\n }\n }\n const handle = this.#nextHandle++;\n this.#nodeRoutes.set(handle, {\n path,\n method,\n matcher: match(normalizePath(path), { end: !prefix }),\n handler,\n rawBody,\n });\n return { dispose: () => this.#nodeRoutes.delete(handle) };\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 // Raw routes are claimed here, in the earliest hook there is: Fastify\n // parses the body before the handler runs, and it 415s an unknown content\n // type outright, so a route that needs the octets as sent cannot wait for\n // dispatch. `hijack()` takes the reply out of Fastify's lifecycle and the\n // handler owns the socket from here.\n instance.addHook(\"onRequest\", (req, reply, done) => {\n const claimed = this.#matchNodeRoute(req, true);\n if (!claimed) {\n done();\n return;\n }\n (req.raw as http.IncomingMessage & { params?: ParamData }).params =\n claimed.params;\n reply.hijack();\n claimed.route.handler(req.raw, reply.raw, undefined);\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 /**\n * Finds a node route for this request. `raw` selects which half of the\n * registry to consider: raw routes are claimed in the onRequest hook, the\n * rest in the catch-all handler once the body is parsed.\n */\n #matchNodeRoute(\n req: FastifyRequest,\n raw: boolean,\n ): { route: NodeEntry; params: ParamData } | undefined {\n const pathname = new URL(req.url, \"http://localhost\").pathname;\n const method = req.method.toUpperCase();\n for (const entry of this.#nodeRoutes.values()) {\n if (entry.rawBody !== raw) continue;\n if (entry.method !== method) continue;\n const result = entry.matcher(pathname);\n if (result) return { route: entry, params: result.params };\n }\n return undefined;\n }\n\n #dispatch(\n req: FastifyRequest,\n reply: FastifyReply,\n ): void | Promise<FastifyReply> {\n const pathname = new URL(req.url, \"http://localhost\").pathname;\n const method = req.method.toUpperCase() as\n | \"DELETE\"\n | \"GET\"\n | \"HEAD\"\n | \"PATCH\"\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 const node = this.#matchNodeRoute(req, false);\n if (node) {\n (req.raw as http.IncomingMessage & { params?: ParamData }).params =\n node.params;\n reply.hijack();\n node.route.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 (const entry of [...this.#fetchRoutes.values()].reverse()) {\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<FastifyReply> {\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 if (response.body === null) {\n return reply.send(await response.text());\n }\n // Stream the body instead of awaiting .text(): a stream-backed body\n // (e.g. graphql-sse) only closes when the subscription completes, so\n // awaiting would hang the request. Fastify tears the source down on\n // client disconnect and routes pre-header stream errors to the\n // error handler.\n // `response.body` is typed against the global (lib) ReadableStream\n // declaration, while Readable.fromWeb wants node:stream/web's; at\n // runtime they are the same stream, so the cast is safe.\n const bodyStream = response.body as WebReadableStream;\n return reply.send(Readable.fromWeb(bodyStream));\n }\n}\n\nasync function serveFetchHandler(\n handler: FetchHandler,\n req: FastifyRequest,\n reply: FastifyReply,\n): Promise<FastifyReply> {\n const url = buildUrl(req);\n const headers = buildHeaders(req);\n let body: string | undefined;\n if (req.method !== \"GET\" && req.method !== \"HEAD\" && req.body !== undefined) {\n body = JSON.stringify(req.body);\n }\n const response = await handler(\n new Request(url, { method: req.method, headers, body }),\n );\n writeResponse(reply, response);\n if (response.body === null) {\n return reply.send(await response.text());\n }\n // Stream the body instead of awaiting .text(): a stream-backed body\n // (e.g. graphql-sse) only closes when the subscription completes, so\n // awaiting would hang the request. Fastify tears the source down on\n // client disconnect and routes pre-header stream errors to the\n // error handler.\n // `response.body` is typed against the global (lib) ReadableStream\n // declaration, while Readable.fromWeb wants node:stream/web's; at\n // runtime they are the same stream, so the cast is safe.\n const bodyStream = response.body as WebReadableStream;\n return reply.send(Readable.fromWeb(bodyStream));\n}\n\nfunction buildUrl(req: FastifyRequest): string {\n const protocol = req.protocol;\n const host = req.headers.host ?? \"localhost\";\n return `${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 reply.statusCode = response.status;\n response.headers.forEach((value, key) => {\n 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","#nextHandle","nodePath","#matchNodeRoute","#dispatch","#serveGetEntry"],"mappings":"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","debug_id":"07c62958-83d2-55bc-b138-149275988013"}
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { i as IPackageManagerOptions, n as IPackageLoaderOptions, r as IPackageManager, s as PackageManagerResult, t as IPackageLoader } from "./types-Bz2niABC.mjs";
1
+ import { i as IPackageManagerOptions, n as IPackageLoaderOptions, r as IPackageManager, s as PackageManagerResult, t as IPackageLoader } from "./types-DcYyNcHJ.mjs";
2
2
  import { IAnalyticsStore } from "@powerhousedao/analytics-engine-core";
3
3
  import { AnalyticsModel } from "@powerhousedao/analytics-engine-graphql";
4
4
  import * as graphql from "graphql";
@@ -296,7 +296,20 @@ type TlsOptions = {
296
296
  key: Buffer | string;
297
297
  } | true;
298
298
  type GatewayContextFactory<TContext = unknown> = (request: Request) => Promise<TContext>;
299
- type WsContextFactory<TContext = unknown> = (connectionParams: Record<string, unknown>) => Promise<TContext>;
299
+ /** Under graphql-ws this is `ctx.extra`, created once per socket. */
300
+ type WsConnection = object;
301
+ type WsContextFactory<TContext = unknown> = (connectionParams: Record<string, unknown>, connection: WsConnection) => Promise<TContext>;
302
+ type WsConnectHandler = (connectionParams: Record<string, unknown>, connection: WsConnection) => Promise<boolean>;
303
+ type WsHandlers<TContext = unknown> = {
304
+ onConnect: WsConnectHandler;
305
+ context: WsContextFactory<TContext>;
306
+ };
307
+ /** No authenticated caller resolved, and REQUIRE_AUTHENTICATED_CALLER wants one. */
308
+ declare const WS_CLOSE_REASON_AUTHENTICATION_REQUIRED = "authentication-required";
309
+ /** A bearer was sent and could not be verified. */
310
+ declare const WS_CLOSE_REASON_BEARER_REJECTED = "bearer-rejected";
311
+ /** Every reason a refusal closes with, for a client matching on the set. */
312
+ declare const WS_AUTH_CLOSE_REASONS: readonly ["authentication-required", "bearer-rejected"];
300
313
  type WsDisposer = {
301
314
  dispose: () => void | Promise<void>;
302
315
  };
@@ -320,13 +333,23 @@ interface AdapterRouteHandle {
320
333
  dispose(): void;
321
334
  }
322
335
  /**
323
- * A framework-agnostic description of a federated subgraph service.
324
- * Used by IGatewayAdapter.createSupergraphHandler() to compose the supergraph SDL.
336
+ * A framework-agnostic description of one subgraph.
337
+ * Used by IGatewayAdapter.createSupergraphHandler() to compose the supergraph:
338
+ * federation adapters treat it as a service to call over HTTP, while the
339
+ * stitching adapter merges its typeDefs and resolvers in-process.
325
340
  */
326
341
  type SubgraphDefinition = {
327
342
  name: string;
328
343
  typeDefs: DocumentNode;
329
344
  url: string;
345
+ /**
346
+ * The subgraph's resolver map, in-process form. Optional: federation
347
+ * adapters (Apollo, Mercurius) execute subgraphs over HTTP and ignore this,
348
+ * while stitching-style adapters merge these resolvers directly into the
349
+ * supergraph schema. Subgraph authors never see this field - it is filled
350
+ * in by the gateway manager from the subgraph's own resolvers.
351
+ */
352
+ resolvers?: Record<string, unknown>;
330
353
  };
331
354
  interface IGatewayAdapter<TContext = unknown> {
332
355
  /** One-time startup. */
@@ -337,18 +360,21 @@ interface IGatewayAdapter<TContext = unknown> {
337
360
  */
338
361
  createHandler(schema: GraphQLSchema, contextFactory: GatewayContextFactory<TContext>): Promise<FetchHandler>;
339
362
  /**
340
- * Create a federation gateway handler that composes all subgraphs into a supergraph.
341
- * getSubgraphs is called eagerly (during setup) and again on every updateSupergraph() call.
363
+ * Create a handler that composes all subgraphs into a supergraph (a
364
+ * federation gateway, or a merged in-process schema under the stitching
365
+ * adapter). getSubgraphs is called eagerly (during setup) and again on every
366
+ * updateSupergraph() call.
342
367
  */
343
368
  createSupergraphHandler(getSubgraphs: () => SubgraphDefinition[], httpServer: http.Server, contextFactory: GatewayContextFactory<TContext>): Promise<FetchHandler>;
344
369
  /**
345
- * Recompose the supergraph SDL from the current subgraph list and push the update
346
- * to the running federation gateway. No-op if createSupergraphHandler() has not
347
- * been called yet.
370
+ * Recompose the supergraph from the current subgraph list and push the update
371
+ * to the running gateway (a federation gateway, or a merged in-process schema
372
+ * under the stitching adapter). No-op if createSupergraphHandler() has not
373
+ * been called yet, or after stop().
348
374
  */
349
375
  updateSupergraph(): Promise<void>;
350
- /** Attach WebSocket subscriptions. Returns a disposer. */
351
- attachWebSocket(wsServer: WebSocketServer, schema: GraphQLSchema, contextFactory: WsContextFactory<TContext>): WsDisposer;
376
+ /** Without `onConnect`, refusing would mean throwing: an unretryable 4500. */
377
+ attachWebSocket(wsServer: WebSocketServer, schema: GraphQLSchema, handlers: WsHandlers<TContext>): WsDisposer;
352
378
  stop(): Promise<void>;
353
379
  }
354
380
  /**
@@ -489,6 +515,7 @@ declare class AuthService {
489
515
  * middleware that must enforce authentication on every request.
490
516
  */
491
517
  verifyBearer(authorization: string | undefined): Promise<AuthContext | globalThis.Response>;
518
+ /** Throws only for a bearer that is present and unusable, as HTTP 401s it. */
492
519
  authenticateWebSocketConnection(connectionParams: Record<string, unknown>): Promise<User | null>;
493
520
  /**
494
521
  * Verify the auth bearer token
@@ -1075,7 +1102,7 @@ declare function getAuthContext(request: globalThis.Request): AuthContext | unde
1075
1102
  declare function createAuthFetchMiddleware(authService: AuthService): AuthFetchMiddleware;
1076
1103
  //#endregion
1077
1104
  //#region src/graphql/gateway/factory.d.ts
1078
- type GatewayAdapterType = "apollo" | "mercurius";
1105
+ type GatewayAdapterType = "apollo" | "mercurius" | "stitching";
1079
1106
  type HttpAdapterType = "express" | "fastify";
1080
1107
  declare function createGatewayAdapter(type: GatewayAdapterType, logger: ILogger): Promise<IGatewayAdapter<Context>>;
1081
1108
  type HttpAdapterSetup = {
@@ -1112,6 +1139,12 @@ type RequireAuthFetchMiddleware = (handler: FetchHandler) => FetchHandler;
1112
1139
  type GraphqlManagerFeatureFlags = {
1113
1140
  enableDocumentModelSubgraphs?: boolean;
1114
1141
  };
1142
+ declare function createWsAuthHandlers(opts: {
1143
+ authService?: AuthService; /** Whether anonymous callers are refused; read at call time, not at build time. */
1144
+ requireAuthenticatedCaller: () => boolean;
1145
+ logger: ILogger;
1146
+ buildContext: (connectionParams: Record<string, unknown>, user?: User) => Context$1;
1147
+ }): WsHandlers<Context$1>;
1115
1148
  declare class GraphQLManager {
1116
1149
  #private;
1117
1150
  private readonly path;
@@ -3629,5 +3662,5 @@ interface DocumentModelSchemaOptions {
3629
3662
  */
3630
3663
  declare function generateDocumentModelSchema(documentModel: DocumentModelGlobalState$1, options?: DocumentModelSchemaOptions): DocumentNode;
3631
3664
  //#endregion
3632
- export { ADMIN_USERS, API, Action, ActionCandidateInput, ActionCandidateInputSchema, ActionContext, ActionContextInput, ActionContextInputSchema, ActionContextResolvers, ActionEvaluation, ActionEvaluationResolvers, ActionEvaluations, ActionEvaluationsResolvers, ActionInput, ActionInputSchema, ActionResolvers, AdapterRouteHandle, AddRelationshipDocument, AddRelationshipMutation, AddRelationshipMutationVariables, AnalyticsSubgraph, AttachmentAccessRequest, AttachmentAccessResult, AttachmentAccessService, type AttachmentReferenceProjectionCapability, AuthConfig, AuthContext, AuthDecision, AuthDecisionSchema, AuthFetchMiddleware, AuthService, AuthSubgraph, type AuthorizationConfig, AuthorizationPolicy, AuthorizedDocumentHandle, type AuthorizerResult, BaseSubgraph, CORE_PACKAGE_NAME, type CanonicalDocumentId, CanonicalDocumentIdResolutionError, CanonicalDocumentIdResolver, ChannelMeta, ChannelMetaInput, ChannelMetaInputSchema, ChannelMetaResolvers, ClientInitializerDependencies, ClientInitializerResult, Context, CreateDocumentDocument, CreateDocumentMutation, CreateDocumentMutationVariables, CreateEmptyDocumentDocument, CreateEmptyDocumentMutation, CreateEmptyDocumentMutationVariables, CredentialVerifier, DateTimeScalarConfig, DbClient, DeadLetterInfo, DeadLetterInfoResolvers, DeleteDocumentDocument, DeleteDocumentMutation, DeleteDocumentMutationVariables, DeleteDocumentsDocument, DeleteDocumentsMutation, DeleteDocumentsMutationVariables, DirectiveResolverFn, DocumentChangeContext, DocumentChangeContextResolvers, DocumentChangeEvent, DocumentChangeEventResolvers, DocumentChangeType, DocumentChangeTypeSchema, DocumentChangesDocument, DocumentChangesSubscription, DocumentChangesSubscriptionVariables, DocumentModelGlobalState, DocumentModelGlobalStateResolvers, DocumentModelResultPage, DocumentModelResultPageResolvers, DocumentModelSchemaOptions, DocumentOperationsFilterInput, DocumentOperationsFilterInputSchema, DocumentPermissionConfig, DocumentPermissionDatabase, DocumentPermissionEntry, DocumentPermissionLevel, DocumentPermissionService, DocumentPermissionTable, DocumentProtectionTable, DocumentWithChildren, DocumentWithChildrenResolvers, EvaluateActionsDocument, EvaluateActionsQuery, EvaluateActionsQueryVariables, Exact, ExplorerUrlState, FetchHandler, FindDocumentsDocument, FindDocumentsQuery, FindDocumentsQueryVariables, GatewayAdapterType, GatewayContextFactory, GetDocumentDocument, GetDocumentIncomingRelationshipsDocument, GetDocumentIncomingRelationshipsQuery, GetDocumentIncomingRelationshipsQueryVariables, GetDocumentModelsDocument, GetDocumentModelsQuery, GetDocumentModelsQueryVariables, GetDocumentOperationsDocument, GetDocumentOperationsQuery, GetDocumentOperationsQueryVariables, GetDocumentOutgoingRelationshipsDocument, GetDocumentOutgoingRelationshipsQuery, GetDocumentOutgoingRelationshipsQueryVariables, GetDocumentQuery, GetDocumentQueryVariables, GetDocumentWithOperationsDocument, GetDocumentWithOperationsQuery, GetDocumentWithOperationsQueryVariables, GetJobStatusDocument, GetJobStatusQuery, GetJobStatusQueryVariables, GetParentIdsFn, GqlDocument, GqlDriveDocument, GqlOperation, GqlOperationContext, GqlSigner, GqlSignerApp, GqlSignerUser, GraphQLManager, GraphqlManagerFeatureFlags, HttpAdapterSetup, HttpAdapterType, HttpDocumentModelLoader, HttpMethod, HttpPackageLoader, HttpPackageLoaderLogger, HttpPackageLoaderOptions, HttpRouteService, type HttpRouteServiceOptions, IAttachmentAccessService, type IAuthorizationService, IGatewayAdapter, IHttpAdapter, type IHttpScope, type IPackageLoader, type IPackageLoaderOptions, IPackageStorage, IProcessorHostModule, IReactorProcessorHostModule, ISubgraph, type IWebhookEndpoints, type IWebhookScope, type IWebhookStore, ImportPackageLoader, InMemoryPackageStorage, Incremental, InputMaybe, InstallPackageResult, InstalledPackageInfo, InvalidNamespaceError, IsTypeOfResolverFn, JobChangeEvent, JobChangeEventResolvers, JobChangesDocument, JobChangesSubscription, JobChangesSubscriptionVariables, JobInfo, JobInfoResolvers, JsonObjectScalarConfig, MakeEmpty, MakeMaybe, MakeOptional, Maybe, MemoryWebhookStore, MoveRelationshipDocument, MoveRelationshipMutation, MoveRelationshipMutationVariables, MoveRelationshipResult, MoveRelationshipResultResolvers, MutateDocumentAsyncDocument, MutateDocumentAsyncMutation, MutateDocumentAsyncMutationVariables, MutateDocumentDocument, MutateDocumentMutation, MutateDocumentMutationVariables, Mutation, MutationAddRelationshipArgs, MutationCreateDocumentArgs, MutationCreateEmptyDocumentArgs, MutationDeleteDocumentArgs, MutationDeleteDocumentsArgs, MutationExecuteArgs, MutationExecuteAsyncArgs, MutationMoveRelationshipArgs, MutationMutateDocumentArgs, MutationMutateDocumentAsyncArgs, MutationPushSyncEnvelopesArgs, MutationRemoveRelationshipArgs, MutationRenameDocumentArgs, MutationResolvers, MutationSetPreferredEditorArgs, MutationTouchChannelArgs, NextResolverFn, NodeRouteOptions, type NodeRouteSpec, OperationContext, OperationContextInput, OperationContextInputSchema, OperationContextResolvers, OperationInput, OperationInputSchema, OperationUserPermissionEntry, OperationUserPermissionTable, OperationWithContext, OperationWithContextInput, OperationWithContextInputSchema, OperationWithContextResolvers, OperationsFilterInput, OperationsFilterInputSchema, PACKAGE_ROUTE_SEGMENT, PGLITE_UTC_PARSERS, PackageManagementService, PackageManagementServiceOptions, PackageManager, PackagesSubgraph, type PackagesSubgraphArgs, PagingInput, PagingInputSchema, type ParsedDriveUrl, PgliteFactory, PhDocument, PhDocumentFieldsFragment, PhDocumentFieldsFragmentDoc, PhDocumentOperationsArgs, PhDocumentResolvers, PhDocumentResultPage, PhDocumentResultPageResolvers, PollSyncEnvelopesDocument, PollSyncEnvelopesQuery, PollSyncEnvelopesQueryVariables, PollSyncEnvelopesResult, PollSyncEnvelopesResultResolvers, Processor, ProcessorDriveFactory, ProcessorFactoryBuilder, PropagationMode, PropagationModeSchema, PushSyncEnvelopesDocument, PushSyncEnvelopesMutation, PushSyncEnvelopesMutationVariables, Query, QueryDocumentArgs, QueryDocumentIncomingRelationshipsArgs, QueryDocumentModelsArgs, QueryDocumentOperationsArgs, QueryDocumentOutgoingRelationshipsArgs, QueryEvaluateActionsArgs, QueryFindDocumentsArgs, QueryJobStatusArgs, QueryPollSyncEnvelopesArgs, QueryResolvers, ReactorModule, ReactorOperation, ReactorOperationResolvers, ReactorOperationResultPage, ReactorOperationResultPageResolvers, ReactorSigner, ReactorSignerApp, ReactorSignerAppInput, ReactorSignerAppInputSchema, ReactorSignerAppResolvers, ReactorSignerInput, ReactorSignerInputSchema, ReactorSignerResolvers, ReactorSignerUser, ReactorSignerUserInput, ReactorSignerUserInputSchema, ReactorSignerUserResolvers, ReactorSubgraph, ReadinessGate, RelationalWebhookStore, RemoteCursor, RemoteCursorInput, RemoteCursorInputSchema, RemoteCursorResolvers, RemoteFilterInput, RemoteFilterInputSchema, RemoveRelationshipDocument, RemoveRelationshipMutation, RemoveRelationshipMutationVariables, RenameDocumentDocument, RenameDocumentMutation, RenameDocumentMutationVariables, RenownConfig, RenownCredentialVerifierConfig, RenownSource, Requester, RequireFields, ResolvedRenownConfig, Resolver, ResolverFn, ResolverTypeWrapper, ResolverWithResolve, Resolvers, ResolversObject, ResolversParentTypes, ResolversTypes, Revision, RevisionResolvers, type RouteActor, type RouteAuth, type RouteAuthorizer, type RouteBody, type RouteContext, type RouteHandler, type RouteMethod, type RouteOptions, type RouteSpec, type RouteTransport, type RouteUser, Scalars, type ScopedRouteHandle, Sdk, SearchFilterInput, SearchFilterInputSchema, SetPreferredEditorDocument, SetPreferredEditorMutation, SetPreferredEditorMutationVariables, SubgraphArgs, SubgraphClass, SubgraphDefinition, Subscription, SubscriptionDocumentChangesArgs, SubscriptionJobChangesArgs, SubscriptionObject, SubscriptionResolveFn, SubscriptionResolver, SubscriptionResolverObject, SubscriptionResolvers, SubscriptionSubscribeFn, SubscriptionSubscriberObject, SyncEnvelope, SyncEnvelopeInput, SyncEnvelopeInputSchema, SyncEnvelopeResolvers, SyncEnvelopeType, SyncEnvelopeTypeSchema, SystemSubgraph, TlsOptions, TouchChannelDocument, TouchChannelInput, TouchChannelInputSchema, TouchChannelMutation, TouchChannelMutationVariables, TouchChannelResult, TouchChannelResultResolvers, TypeResolveFn, User, ViewFilterInput, ViewFilterInputSchema, WEBHOOK_SEGMENT, type WebhookEndpointInfo, type WebhookEndpointRow, type WebhookField, type WebhookHashAlgorithm, type WebhookPolicy, type WebhookReply, type WebhookRequest, type WebhookScheme, WebhookService, type WebhookSignatureEncoding, type WebhookSpec, type WebhookVerification, WithIndex, WsContextFactory, WsDisposer, assertAuthRequiredForDocumentPermissions, assertCredentialVerifierForSource, assertHostMountPath, assertRequireAuthenticatedCallerAllowed, assertSkipCredentialVerificationAllowed, buildGraphQlDocument, buildGraphQlDriveDocument, buildGraphqlOperation, buildGraphqlOperations, buildSubgraphSchemaModule, createAuthFetchMiddleware, createCanonicalDocumentIdResolver, createGatewayAdapter, createHttpAdapter, createMergedSchema, createReactorGraphQLClient, createRenownCredentialVerifier, createSchema, decodeExplorerUrlState, definedNonNullAnySchema, driveIdFromUrl, extractSubgraphsFromModule, generateDocumentModelSchema, getAuthContext, getDbClient, getDocumentModelSchemaName, getDocumentModelTypeDefs, getExplorerPrefix, getGitHash, getGitUrl, getSdk, getUniqueDocumentModels, getUniqueUpgradeManifests, getVersion, initAnalyticsStoreSql, initializeAndStartAPI, isDefinedNonNullAny, isExpectedLoaderMiss, isSubgraphClass, namespacePath, namespaceSegments, newWebhookToken, parseDriveUrl, parseWebhookBody, redactHeaders, renderGraphqlPlayground, resolvePackageName, resolveRenownConfig, verifyWebhook };
3665
+ export { ADMIN_USERS, API, Action, ActionCandidateInput, ActionCandidateInputSchema, ActionContext, ActionContextInput, ActionContextInputSchema, ActionContextResolvers, ActionEvaluation, ActionEvaluationResolvers, ActionEvaluations, ActionEvaluationsResolvers, ActionInput, ActionInputSchema, ActionResolvers, AdapterRouteHandle, AddRelationshipDocument, AddRelationshipMutation, AddRelationshipMutationVariables, AnalyticsSubgraph, AttachmentAccessRequest, AttachmentAccessResult, AttachmentAccessService, type AttachmentReferenceProjectionCapability, AuthConfig, AuthContext, AuthDecision, AuthDecisionSchema, AuthFetchMiddleware, AuthService, AuthSubgraph, type AuthorizationConfig, AuthorizationPolicy, AuthorizedDocumentHandle, type AuthorizerResult, BaseSubgraph, CORE_PACKAGE_NAME, type CanonicalDocumentId, CanonicalDocumentIdResolutionError, CanonicalDocumentIdResolver, ChannelMeta, ChannelMetaInput, ChannelMetaInputSchema, ChannelMetaResolvers, ClientInitializerDependencies, ClientInitializerResult, Context, CreateDocumentDocument, CreateDocumentMutation, CreateDocumentMutationVariables, CreateEmptyDocumentDocument, CreateEmptyDocumentMutation, CreateEmptyDocumentMutationVariables, CredentialVerifier, DateTimeScalarConfig, DbClient, DeadLetterInfo, DeadLetterInfoResolvers, DeleteDocumentDocument, DeleteDocumentMutation, DeleteDocumentMutationVariables, DeleteDocumentsDocument, DeleteDocumentsMutation, DeleteDocumentsMutationVariables, DirectiveResolverFn, DocumentChangeContext, DocumentChangeContextResolvers, DocumentChangeEvent, DocumentChangeEventResolvers, DocumentChangeType, DocumentChangeTypeSchema, DocumentChangesDocument, DocumentChangesSubscription, DocumentChangesSubscriptionVariables, DocumentModelGlobalState, DocumentModelGlobalStateResolvers, DocumentModelResultPage, DocumentModelResultPageResolvers, DocumentModelSchemaOptions, DocumentOperationsFilterInput, DocumentOperationsFilterInputSchema, DocumentPermissionConfig, DocumentPermissionDatabase, DocumentPermissionEntry, DocumentPermissionLevel, DocumentPermissionService, DocumentPermissionTable, DocumentProtectionTable, DocumentWithChildren, DocumentWithChildrenResolvers, EvaluateActionsDocument, EvaluateActionsQuery, EvaluateActionsQueryVariables, Exact, ExplorerUrlState, FetchHandler, FindDocumentsDocument, FindDocumentsQuery, FindDocumentsQueryVariables, GatewayAdapterType, GatewayContextFactory, GetDocumentDocument, GetDocumentIncomingRelationshipsDocument, GetDocumentIncomingRelationshipsQuery, GetDocumentIncomingRelationshipsQueryVariables, GetDocumentModelsDocument, GetDocumentModelsQuery, GetDocumentModelsQueryVariables, GetDocumentOperationsDocument, GetDocumentOperationsQuery, GetDocumentOperationsQueryVariables, GetDocumentOutgoingRelationshipsDocument, GetDocumentOutgoingRelationshipsQuery, GetDocumentOutgoingRelationshipsQueryVariables, GetDocumentQuery, GetDocumentQueryVariables, GetDocumentWithOperationsDocument, GetDocumentWithOperationsQuery, GetDocumentWithOperationsQueryVariables, GetJobStatusDocument, GetJobStatusQuery, GetJobStatusQueryVariables, GetParentIdsFn, GqlDocument, GqlDriveDocument, GqlOperation, GqlOperationContext, GqlSigner, GqlSignerApp, GqlSignerUser, GraphQLManager, GraphqlManagerFeatureFlags, HttpAdapterSetup, HttpAdapterType, HttpDocumentModelLoader, HttpMethod, HttpPackageLoader, HttpPackageLoaderLogger, HttpPackageLoaderOptions, HttpRouteService, type HttpRouteServiceOptions, IAttachmentAccessService, type IAuthorizationService, IGatewayAdapter, IHttpAdapter, type IHttpScope, type IPackageLoader, type IPackageLoaderOptions, IPackageStorage, IProcessorHostModule, IReactorProcessorHostModule, ISubgraph, type IWebhookEndpoints, type IWebhookScope, type IWebhookStore, ImportPackageLoader, InMemoryPackageStorage, Incremental, InputMaybe, InstallPackageResult, InstalledPackageInfo, InvalidNamespaceError, IsTypeOfResolverFn, JobChangeEvent, JobChangeEventResolvers, JobChangesDocument, JobChangesSubscription, JobChangesSubscriptionVariables, JobInfo, JobInfoResolvers, JsonObjectScalarConfig, MakeEmpty, MakeMaybe, MakeOptional, Maybe, MemoryWebhookStore, MoveRelationshipDocument, MoveRelationshipMutation, MoveRelationshipMutationVariables, MoveRelationshipResult, MoveRelationshipResultResolvers, MutateDocumentAsyncDocument, MutateDocumentAsyncMutation, MutateDocumentAsyncMutationVariables, MutateDocumentDocument, MutateDocumentMutation, MutateDocumentMutationVariables, Mutation, MutationAddRelationshipArgs, MutationCreateDocumentArgs, MutationCreateEmptyDocumentArgs, MutationDeleteDocumentArgs, MutationDeleteDocumentsArgs, MutationExecuteArgs, MutationExecuteAsyncArgs, MutationMoveRelationshipArgs, MutationMutateDocumentArgs, MutationMutateDocumentAsyncArgs, MutationPushSyncEnvelopesArgs, MutationRemoveRelationshipArgs, MutationRenameDocumentArgs, MutationResolvers, MutationSetPreferredEditorArgs, MutationTouchChannelArgs, NextResolverFn, NodeRouteOptions, type NodeRouteSpec, OperationContext, OperationContextInput, OperationContextInputSchema, OperationContextResolvers, OperationInput, OperationInputSchema, OperationUserPermissionEntry, OperationUserPermissionTable, OperationWithContext, OperationWithContextInput, OperationWithContextInputSchema, OperationWithContextResolvers, OperationsFilterInput, OperationsFilterInputSchema, PACKAGE_ROUTE_SEGMENT, PGLITE_UTC_PARSERS, PackageManagementService, PackageManagementServiceOptions, PackageManager, PackagesSubgraph, type PackagesSubgraphArgs, PagingInput, PagingInputSchema, type ParsedDriveUrl, PgliteFactory, PhDocument, PhDocumentFieldsFragment, PhDocumentFieldsFragmentDoc, PhDocumentOperationsArgs, PhDocumentResolvers, PhDocumentResultPage, PhDocumentResultPageResolvers, PollSyncEnvelopesDocument, PollSyncEnvelopesQuery, PollSyncEnvelopesQueryVariables, PollSyncEnvelopesResult, PollSyncEnvelopesResultResolvers, Processor, ProcessorDriveFactory, ProcessorFactoryBuilder, PropagationMode, PropagationModeSchema, PushSyncEnvelopesDocument, PushSyncEnvelopesMutation, PushSyncEnvelopesMutationVariables, Query, QueryDocumentArgs, QueryDocumentIncomingRelationshipsArgs, QueryDocumentModelsArgs, QueryDocumentOperationsArgs, QueryDocumentOutgoingRelationshipsArgs, QueryEvaluateActionsArgs, QueryFindDocumentsArgs, QueryJobStatusArgs, QueryPollSyncEnvelopesArgs, QueryResolvers, ReactorModule, ReactorOperation, ReactorOperationResolvers, ReactorOperationResultPage, ReactorOperationResultPageResolvers, ReactorSigner, ReactorSignerApp, ReactorSignerAppInput, ReactorSignerAppInputSchema, ReactorSignerAppResolvers, ReactorSignerInput, ReactorSignerInputSchema, ReactorSignerResolvers, ReactorSignerUser, ReactorSignerUserInput, ReactorSignerUserInputSchema, ReactorSignerUserResolvers, ReactorSubgraph, ReadinessGate, RelationalWebhookStore, RemoteCursor, RemoteCursorInput, RemoteCursorInputSchema, RemoteCursorResolvers, RemoteFilterInput, RemoteFilterInputSchema, RemoveRelationshipDocument, RemoveRelationshipMutation, RemoveRelationshipMutationVariables, RenameDocumentDocument, RenameDocumentMutation, RenameDocumentMutationVariables, RenownConfig, RenownCredentialVerifierConfig, RenownSource, Requester, RequireFields, ResolvedRenownConfig, Resolver, ResolverFn, ResolverTypeWrapper, ResolverWithResolve, Resolvers, ResolversObject, ResolversParentTypes, ResolversTypes, Revision, RevisionResolvers, type RouteActor, type RouteAuth, type RouteAuthorizer, type RouteBody, type RouteContext, type RouteHandler, type RouteMethod, type RouteOptions, type RouteSpec, type RouteTransport, type RouteUser, Scalars, type ScopedRouteHandle, Sdk, SearchFilterInput, SearchFilterInputSchema, SetPreferredEditorDocument, SetPreferredEditorMutation, SetPreferredEditorMutationVariables, SubgraphArgs, SubgraphClass, SubgraphDefinition, Subscription, SubscriptionDocumentChangesArgs, SubscriptionJobChangesArgs, SubscriptionObject, SubscriptionResolveFn, SubscriptionResolver, SubscriptionResolverObject, SubscriptionResolvers, SubscriptionSubscribeFn, SubscriptionSubscriberObject, SyncEnvelope, SyncEnvelopeInput, SyncEnvelopeInputSchema, SyncEnvelopeResolvers, SyncEnvelopeType, SyncEnvelopeTypeSchema, SystemSubgraph, TlsOptions, TouchChannelDocument, TouchChannelInput, TouchChannelInputSchema, TouchChannelMutation, TouchChannelMutationVariables, TouchChannelResult, TouchChannelResultResolvers, TypeResolveFn, User, ViewFilterInput, ViewFilterInputSchema, WEBHOOK_SEGMENT, WS_AUTH_CLOSE_REASONS, WS_CLOSE_REASON_AUTHENTICATION_REQUIRED, WS_CLOSE_REASON_BEARER_REJECTED, type WebhookEndpointInfo, type WebhookEndpointRow, type WebhookField, type WebhookHashAlgorithm, type WebhookPolicy, type WebhookReply, type WebhookRequest, type WebhookScheme, WebhookService, type WebhookSignatureEncoding, type WebhookSpec, type WebhookVerification, WithIndex, WsConnectHandler, WsConnection, WsContextFactory, WsDisposer, WsHandlers, assertAuthRequiredForDocumentPermissions, assertCredentialVerifierForSource, assertHostMountPath, assertRequireAuthenticatedCallerAllowed, assertSkipCredentialVerificationAllowed, buildGraphQlDocument, buildGraphQlDriveDocument, buildGraphqlOperation, buildGraphqlOperations, buildSubgraphSchemaModule, createAuthFetchMiddleware, createCanonicalDocumentIdResolver, createGatewayAdapter, createHttpAdapter, createMergedSchema, createReactorGraphQLClient, createRenownCredentialVerifier, createSchema, createWsAuthHandlers, decodeExplorerUrlState, definedNonNullAnySchema, driveIdFromUrl, extractSubgraphsFromModule, generateDocumentModelSchema, getAuthContext, getDbClient, getDocumentModelSchemaName, getDocumentModelTypeDefs, getExplorerPrefix, getGitHash, getGitUrl, getSdk, getUniqueDocumentModels, getUniqueUpgradeManifests, getVersion, initAnalyticsStoreSql, initializeAndStartAPI, isDefinedNonNullAny, isExpectedLoaderMiss, isSubgraphClass, namespacePath, namespaceSegments, newWebhookToken, parseDriveUrl, parseWebhookBody, redactHeaders, renderGraphqlPlayground, resolvePackageName, resolveRenownConfig, verifyWebhook };
3633
3666
  //# sourceMappingURL=index.d.mts.map