import { ForgeInstrumentationSink, RequestTraceEvent } from "@ministryofjustice/hmpps-forge/core"; import { Server } from "node:http"; //#region forge-devtools/src/server/trace/RedisTraceChannel.d.ts /** * Minimal structural view of a node-redis v4 client. The package takes no * dependency on `redis`; any client with this shape (the HMPPS template's) * satisfies it, so local-only users never pull `redis` in. */ interface DevToolsRedisClient { duplicate(): DevToolsRedisClient; connect(): Promise; publish(channel: string, message: string | Buffer): Promise; subscribe(channel: string, listener: (message: Buffer) => void, bufferMode: true): Promise; quit(): Promise; } interface RedisChannelLogger { warn(message: string): void; } /** * Carries request traces between app replicas over Redis pub/sub, so whichever * pod holds the panel's websocket sees every pod's traces rather than only the * slice that lands on it. Redis being down just means missing traces, so every * operation logs and swallows its failure instead of crashing the app. */ declare class RedisTraceChannel { private readonly logger; private readonly publisher; private readonly subscriber; constructor(client: DevToolsRedisClient, logger: RedisChannelLogger); connect(): Promise; publish(event: RequestTraceEvent): Promise; subscribe(onEvent: (event: RequestTraceEvent) => void): Promise; close(): Promise; private deliver; private describe; } //#endregion //#region forge-devtools/src/server/DevToolsServer.d.ts interface DevToolsServerOptions { readonly path: string; readonly logger: { info(message: string): void; }; readonly noAuth?: boolean; readonly redisChannel?: RedisTraceChannel; } /** * WebSocket server that authenticates devtools clients via a one-time code * and delegates trace delivery to a {@link TraceDispatcher}. */ declare class DevToolsServer implements ForgeInstrumentationSink { private readonly wss; private readonly dispatcher; private readonly logger; private readonly webSocketPath; private readonly noAuth; private readonly redisChannel?; private attachedServer?; private redisStarted; constructor(options: DevToolsServerOptions); attach(server: Server): void; detach(): void; close(): void; onRequestTrace(event: RequestTraceEvent): void; shouldTrace(snapshot: RequestTraceEvent['snapshot']): boolean; private startRedisChannel; private readonly handleUpgrade; private isDevToolsUpgrade; private handleConnection; private logCodeIssued; } //#endregion //#region forge-devtools/src/server/setUpForgeDevTools.d.ts interface ForgeDevToolsOptions { readonly path?: string; readonly logger?: { info(message: string): void; warn(message: string): void; }; readonly noAuth?: boolean; readonly redis?: DevToolsRedisClient; } /** * Creates the Forge DevTools bridge. Call once at app startup, attach it to * the app's HTTP server, and pass it into Forge's instrumentation sinks. * * Pass a `redis` client to run in multi-instance mode: traces are published to * the app's Redis so whichever replica holds the panel's websocket sees every * replica's traces. Omit it for today's in-process, single-instance behaviour. */ declare function setUpForgeDevTools(options?: ForgeDevToolsOptions): DevToolsServer; //#endregion export { type DevToolsRedisClient, type DevToolsServerOptions, type ForgeDevToolsOptions, setUpForgeDevTools };