@emeryld/rrroutes-server 2.1.0 → 2.1.2

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/index.cjs CHANGED
@@ -496,12 +496,6 @@ function createBuiltInConnectionHandlers(opts) {
496
496
  snapshot: snapshotSocketConfig(socket)
497
497
  });
498
498
  const defaultConnect = () => {
499
- dbg("sys:connect", {
500
- type: "handler",
501
- phase: "handler_success",
502
- event: "sys:connect",
503
- socketId: socket.id
504
- });
505
499
  const includeRaw = debugVerbose === true;
506
500
  const joinHandler = async (msg) => {
507
501
  dbg(roomJoinEvent, {
@@ -509,7 +503,7 @@ function createBuiltInConnectionHandlers(opts) {
509
503
  phase: "receive",
510
504
  action: "join",
511
505
  socketId: socket.id,
512
- payload: includeRaw ? msg : void 0
506
+ payload: msg
513
507
  });
514
508
  const parsed = joinPayloadSchema.safeParse(msg);
515
509
  if (!parsed.success) {
@@ -523,7 +517,7 @@ function createBuiltInConnectionHandlers(opts) {
523
517
  phase: "validation_error",
524
518
  socketId: socket.id,
525
519
  issues: parsed.error.issues,
526
- payload: includeRaw ? msg : void 0
520
+ payload: msg
527
521
  });
528
522
  return;
529
523
  }
@@ -561,7 +555,7 @@ function createBuiltInConnectionHandlers(opts) {
561
555
  phase: "receive",
562
556
  action: "leave",
563
557
  socketId: socket.id,
564
- payload: includeRaw ? msg : void 0
558
+ payload: msg
565
559
  });
566
560
  const parsed = leavePayloadSchema.safeParse(msg);
567
561
  if (!parsed.success) {
@@ -575,14 +569,14 @@ function createBuiltInConnectionHandlers(opts) {
575
569
  phase: "validation_error",
576
570
  socketId: socket.id,
577
571
  issues: parsed.error.issues,
578
- payload: includeRaw ? msg : void 0
572
+ payload: msg
579
573
  });
580
574
  return;
581
575
  }
582
576
  const list = toArray(parsed.data.rooms);
583
577
  const leave = async (room) => {
584
- dbg(null, { type: "rooms", action: "leave", rooms: room, socketId: socket.id });
585
578
  await socket.leave(room);
579
+ dbg(null, { type: "rooms", action: "leave", rooms: room, socketId: socket.id });
586
580
  };
587
581
  const run = async () => {
588
582
  await getSysEvent("sys:room_leave")({
@@ -600,7 +594,7 @@ function createBuiltInConnectionHandlers(opts) {
600
594
  dbg(roomJoinEvent, {
601
595
  type: "rooms",
602
596
  phase: "handler_error",
603
- payload: includeRaw ? { rooms: list, meta: parsed.data.meta } : void 0,
597
+ payload: { rooms: list, meta: parsed.data.meta },
604
598
  socketId: socket.id,
605
599
  issues: [error],
606
600
  action: "join"
@@ -689,13 +683,13 @@ function createBuiltInConnectionHandlers(opts) {
689
683
  if (heartbeatEnabled) {
690
684
  socket.on(pingEvent, pingHandler);
691
685
  }
692
- const cleanup = () => {
686
+ const cleanup = (reason) => {
693
687
  dbg(null, {
694
688
  type: "lifecycle",
695
689
  stage: "connection_cleanup",
696
690
  socketId: socket.id,
697
691
  nsp: socket.nsp.name,
698
- details: { reason: "teardown" }
692
+ details: { reason }
699
693
  });
700
694
  socket.off(roomJoinEvent, joinHandler);
701
695
  socket.off(roomLeaveEvent, leaveHandler);
@@ -722,10 +716,10 @@ function createBuiltInConnectionHandlers(opts) {
722
716
  stage: "connection_cleanup",
723
717
  nsp: socket.nsp.name,
724
718
  socketId: socket.id,
725
- details: { reason: String(reason) }
719
+ details: { reason }
726
720
  });
727
721
  const defaultDisconnect = () => {
728
- cleanup();
722
+ cleanup(reason);
729
723
  socketTeardowns.delete(socket);
730
724
  };
731
725
  getSysEvent("sys:disconnect")({
@@ -784,7 +778,7 @@ function createSocketConnections(io, events, opts) {
784
778
  type: "lifecycle",
785
779
  stage: "server_init",
786
780
  details: {
787
- eventCount: eventNames,
781
+ prefinedEvents: eventNames,
788
782
  heartbeatEnabled,
789
783
  path: io?.path(),
790
784
  namespaces: Array.from(io._nsps.keys()),
@@ -1013,7 +1007,7 @@ function createSocketConnections(io, events, opts) {
1013
1007
  for (const socket of io.sockets.sockets.values()) {
1014
1008
  const cleanup = socketTeardowns.get(socket);
1015
1009
  if (cleanup) {
1016
- cleanup();
1010
+ cleanup("destroy");
1017
1011
  socketTeardowns.delete(socket);
1018
1012
  } else {
1019
1013
  dbg(null, {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/routesV3.server.ts","../src/sockets/socket.server.debug.ts","../src/sockets/socket.server.sys.ts","../src/sockets/socket.server.index.ts","../src/sockets/socket.server.middleware.ts"],"sourcesContent":["export * from './routesV3.server';\nexport * from './sockets/socket.server.index';\nexport * from './sockets/socket.server.middleware';\n","/**\n * routesV3.server.ts\n * -----------------------------------------------------------------------------\n * Bind an Express router/app to a `finalize(...)` registry of AnyLeafs.\n * - Fully typed handlers (params/query/body/output)\n * - Zod parsing + optional output validation\n * - buildCtx runs as a middleware *first*, before all other middlewares\n * - Global, per-route, and cfg-derived middlewares (auth, uploads)\n * - Helper to warn about unimplemented routes\n * - DX helpers to use `ctx` in any middleware with proper types\n */\n\nimport { AnyLeaf, FileField, HttpMethod, InferBody, InferOutput, InferParams, InferQuery, MethodCfg } from '@emeryld/rrroutes-contract';\nimport type * as express from 'express';\nimport type { RequestHandler, Router } from 'express';\nimport type { ZodType } from 'zod';\n\n\n\n/** Shape expected from optional logger implementations. */\nexport type LoggerLike = {\n info?: (...args: any[]) => void;\n warn?: (...args: any[]) => void;\n error?: (...args: any[]) => void;\n debug?: (...args: any[]) => void;\n verbose?: (...args: any[]) => void;\n system?: (...args: any[]) => void;\n log?: (...args: any[]) => void;\n};\n\ntype RoutesLoggerCarrier = {\n routesLogger?: LoggerLike;\n};\n\ntype CtxWithRoutesLogger<Ctx> = Ctx & RoutesLoggerCarrier;\n\n// Debug logging --------------------------------------------------------------\nexport type RouteServerDebugMode = 'minimal' | 'complete';\n\ntype RouteServerDebugEventBase = {\n /** Optional logical name assigned via `RouteDef.debug?.debugName` (or `RouteDef.debugName`). */\n name?: string;\n};\n\nexport type RouteServerDebugEvent =\n | (RouteServerDebugEventBase & {\n type: 'request';\n stage: 'start' | 'success' | 'error';\n method: Uppercase<HttpMethod>;\n path: string;\n url: string;\n durationMs?: number;\n params?: unknown;\n query?: unknown;\n body?: unknown;\n output?: unknown;\n error?: unknown;\n })\n | (RouteServerDebugEventBase & {\n type: 'register';\n method: Uppercase<HttpMethod>;\n path: string;\n })\n | (RouteServerDebugEventBase & {\n type: 'buildCtx';\n stage: 'start' | 'success' | 'error';\n method: Uppercase<HttpMethod>;\n path: string;\n url: string;\n durationMs?: number;\n error?: unknown;\n })\n | (RouteServerDebugEventBase & {\n type: 'handler';\n stage: 'start' | 'success' | 'error';\n method: Uppercase<HttpMethod>;\n path: string;\n durationMs?: number;\n params?: unknown;\n query?: unknown;\n body?: unknown;\n output?: unknown;\n error?: unknown;\n });\n\nexport type RouteServerDebugLogger = (event: RouteServerDebugEvent) => void;\n\n/**\n * Configure server-side debug logging.\n * - Use booleans or `'minimal'/'complete'` for quick toggles.\n * - Pass a custom logger function to redirect structured events.\n * - Provide a map to enable specific event types, opt into verbose payload logging, or restrict logs via `only`.\n */\nexport type RouteServerDebugOptions<Names extends string = string> = RouteServerDebugToggleOptions<Names>;\n\n/**\n * Fine-grained toggle map for server debug logging.\n * Enable individual event types, opt into verbose payload logging, override the logger, or restrict to named routes.\n * Use `RouteDef.debug?.debugName` (or the deprecated `RouteDef.debugName`) to set the name that `only` will match against.\n */\nexport type RouteServerDebugToggleOptions<Names extends string = string> = Partial<\n Record<RouteServerDebugEvent['type'], boolean>\n> & {\n verbose?: boolean;\n logger?: RouteServerDebugLogger;\n only?: Names[];\n};\n\n/**\n * Per-route debug overrides. Same toggles as `RouteServerDebugOptions`, but limited to a single route\n * and therefore replaces the `only` filter with a local `debugName`.\n */\nexport type RouteDefDebugOptions<Names extends string = string> = Omit<\n RouteServerDebugToggleOptions<Names>,\n 'only'\n> & {\n debugName?: Names;\n};\n\nconst serverDebugEventTypes: RouteServerDebugEvent['type'][] = [\n 'register',\n 'request',\n 'buildCtx',\n 'handler',\n];\n\ntype ServerDebugEmitter<Names extends string> = {\n emit: (event: RouteServerDebugEvent, name?: Names) => void;\n mode: RouteServerDebugMode;\n};\n\nconst noopServerEmit = () => {};\n\nfunction createServerDebugEmitter<Names extends string>(\n option?: RouteServerDebugOptions<Names>,\n): ServerDebugEmitter<Names> {\n const disabled: ServerDebugEmitter<Names> = { emit: noopServerEmit, mode: 'minimal' };\n if (!option) return disabled;\n\n if (typeof option === 'object') {\n const toggles = option as RouteServerDebugToggleOptions<Names>;\n const verbose = Boolean(toggles.verbose);\n const enabledTypes = serverDebugEventTypes.filter((type) => toggles[type]);\n if (enabledTypes.length === 0) {\n return { emit: noopServerEmit, mode: verbose ? 'complete' : 'minimal' };\n }\n const whitelist = new Set<RouteServerDebugEvent['type']>(enabledTypes);\n const onlySet =\n toggles.only && toggles.only.length > 0 ? new Set<Names>(toggles.only) : undefined;\n const logger = toggles.logger;\n const emit: ServerDebugEmitter<Names>['emit'] = (event, name) => {\n if (!whitelist.has(event.type) || !logger) return;\n if (onlySet && (!name || !onlySet.has(name))) return;\n logger(name ? { ...event, name } : event);\n };\n return { emit, mode: verbose ? 'complete' : 'minimal' };\n }\n\n return disabled;\n}\n\n// ──────────────────────────────────────────────────────────────────────────────\n// Keys + leaf helpers (derive keys from byKey to avoid template-literal pitfalls)\n// ──────────────────────────────────────────────────────────────────────────────\n\n/** Keys like \"GET /v1/foo\" that *actually* exist in the registry */\nexport type KeysOfRegistry<R extends { byKey: Record<string, AnyLeaf> }> = keyof R['byKey'] &\n string;\n\ntype MethodFromKey<K extends string> = K extends `${infer M} ${string}` ? Lowercase<M> : never;\ntype PathFromKey<K extends string> = K extends `${string} ${infer P}` ? P : never;\n\n/** Given a registry and a key, pick the exact leaf for that method+path */\nexport type LeafFromKey<R extends { all: readonly AnyLeaf[] }, K extends string> = Extract<\n R['all'][number],\n { method: MethodFromKey<K> & HttpMethod; path: PathFromKey<K> }\n>;\n\n/** Optional-ify types if your core returns `never` when a schema isn't defined */\ntype Maybe<T> = [T] extends [never] ? undefined : T;\n\n/** Typed params argument exposed to handlers. */\nexport type ArgParams<L extends AnyLeaf> = Maybe<InferParams<L>>;\n/** Typed query argument exposed to handlers. */\nexport type ArgQuery<L extends AnyLeaf> = Maybe<InferQuery<L>>;\n/** Typed body argument exposed to handlers. */\nexport type ArgBody<L extends AnyLeaf> = Maybe<InferBody<L>>;\n\n/**\n * Convenience to compute a `\"METHOD /path\"` key from a leaf.\n * @param leaf Leaf describing the route.\n * @returns Uppercase method + path key.\n */\nexport const keyOf = (leaf: AnyLeaf) => `${leaf.method.toUpperCase()} ${leaf.path}` as const;\n\n// ──────────────────────────────────────────────────────────────────────────────\n// Context typing & DX helpers (so ctx is usable in *any* middleware)\n// ──────────────────────────────────────────────────────────────────────────────\n\n/**\n * Unique symbol used to stash ctx on res.locals.\n * (Symbols are safer than string keys against collisions.)\n */\nexport const CTX_SYMBOL: unique symbol = Symbol.for('typedLeaves.ctx');\n\nconst AFTER_HANDLER_NEXT_SYMBOL: unique symbol = Symbol.for('typedLeaves.afterHandlerNext');\n\nfunction setAfterHandlerNext(res: express.Response, value: boolean) {\n (res.locals as any)[AFTER_HANDLER_NEXT_SYMBOL] = value;\n}\n\nfunction handlerInvokedNext(res: express.Response): boolean {\n return Boolean((res.locals as any)[AFTER_HANDLER_NEXT_SYMBOL]);\n}\n\n/** Response type that *has* a ctx on locals for DX in middlewares */\nexport type ResponseWithCtx<Ctx> =\n // Replace locals with an intersection that guarantees CTX_SYMBOL exists\n Omit<express.Response, 'locals'> & {\n locals: express.Response['locals'] & { [CTX_SYMBOL]: CtxWithRoutesLogger<Ctx> };\n };\n\n/** A middleware signature that can *use* ctx via `res.locals[CTX_SYMBOL]` */\nexport type CtxRequestHandler<Ctx> = (args: {\n req: express.Request;\n res: express.Response;\n next: express.NextFunction;\n ctx: CtxWithRoutesLogger<Ctx>;\n}) => any;\n\n/**\n * Safely read ctx from any Response.\n * @param res Express response whose locals contain the ctx symbol.\n * @returns Strongly typed context object.\n */\nexport function getCtx<Ctx = unknown>(res: express.Response): CtxWithRoutesLogger<Ctx> {\n return (res.locals as any)[CTX_SYMBOL] as CtxWithRoutesLogger<Ctx>;\n}\n\n/**\n * Wrap a ctx-typed middleware to a plain RequestHandler (for arrays, etc.).\n * @param mw Middleware that expects a typed response with ctx available.\n * @returns Standard Express request handler.\n */\nfunction adaptCtxMw<Ctx>(mw: CtxRequestHandler<Ctx>): RequestHandler {\n return (req, res, next) => {\n try {\n const result = mw({ req, res, next, ctx: getCtx<Ctx>(res) });\n if (result && typeof (result as Promise<unknown>).then === 'function') {\n return (result as Promise<unknown>).catch((err) => next(err));\n }\n return result as any;\n } catch (err) {\n next(err as any);\n return undefined;\n }\n };\n}\n\nfunction adaptAfterMw<Ctx>(mw: CtxRequestHandler<Ctx>): RequestHandler {\n const adapted = adaptCtxMw<Ctx>(mw);\n return (req: express.Request, res: express.Response, next: express.NextFunction) => {\n if (!handlerInvokedNext(res)) {\n next();\n return;\n }\n adapted(req, res, next);\n };\n}\n\nfunction mapAfterMiddleware<Ctx>(mws?: Array<CtxRequestHandler<Ctx>>): RequestHandler[] {\n return (mws ?? []).map((mw) => adaptAfterMw<Ctx>(mw));\n}\n\nfunction logHandlerDebugWithRoutesLogger(\n logger: LoggerLike | undefined,\n event: RouteServerDebugEvent,\n) {\n if (!logger || event.type !== 'handler') return;\n const payload: [string, RouteServerDebugEvent] = [\n `[rrroutes-server][handler:${event.stage}] ${event.method} ${event.path}`,\n event,\n ];\n if (event.stage === 'error') {\n (\n logger.error ??\n logger.warn ??\n logger.debug ??\n logger.info ??\n logger.log ??\n logger.system\n )?.call(logger, ...payload);\n return;\n }\n (\n logger.debug ??\n logger.verbose ??\n logger.info ??\n logger.log ??\n logger.system\n )?.call(logger, ...payload);\n}\n\n// ──────────────────────────────────────────────────────────────────────────────\n// Controller types — object form only (simpler, clearer typings)\n// ──────────────────────────────────────────────────────────────────────────────\n\n/** Typed route handler for a specific leaf */\nexport type Handler<L extends AnyLeaf, Ctx = unknown> = (args: {\n req: express.Request;\n res: express.Response;\n next: express.NextFunction;\n ctx: CtxWithRoutesLogger<Ctx>;\n params: ArgParams<L>;\n query: ArgQuery<L>;\n body: ArgBody<L>;\n}) => Promise<InferOutput<L>> | InferOutput<L>;\n\n/** Route definition for one key */\nexport type RouteDef<L extends AnyLeaf, Ctx = unknown, Names extends string = string> = {\n /** Middlewares before the handler (run after buildCtx/global/derived) */\n use?: Array<CtxRequestHandler<Ctx>>;\n /** Middlewares after the handler *if* it calls next() */\n after?: Array<CtxRequestHandler<Ctx>>;\n /** Your business logic */\n handler: Handler<L, Ctx>;\n /**\n * Optional per-route debug overrides. When provided, these replace the global debug options.\n */\n debug?: RouteDefDebugOptions<Names>;\n /**\n * Optional logical name used for debug filtering. Prefer `debug.debugName`; this field remains for backwards compatibility.\n */\n debugName?: Names;\n};\n\n/** Map of registry keys -> route defs */\nexport type ControllerMap<\n R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> },\n Ctx = unknown,\n Names extends string = string,\n> = {\n [P in KeysOfRegistry<R>]: RouteDef<LeafFromKey<R, P>, Ctx, Names>;\n};\n\nexport type PartialControllerMap<\n R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> },\n Ctx = unknown,\n Names extends string = string,\n> = Partial<ControllerMap<R, Ctx, Names>>;\n\n// ──────────────────────────────────────────────────────────────────────────────\n/** Options + derivation helpers */\n// ──────────────────────────────────────────────────────────────────────────────\n\nexport type RouteServerConfig<Ctx = unknown, Names extends string = string> = {\n /**\n * Build a request-scoped context. We wrap this in a middleware that runs\n * *first* (before global/derived/route middlewares), and stash it on\n * `res.locals[CTX_SYMBOL]` so *all* later middlewares can use it.\n * You can optionally include `routesLogger` to override handler debug logging per request.\n */\n buildCtx: (\n req: express.Request,\n res: express.Response,\n ) => CtxWithRoutesLogger<Ctx> | Promise<CtxWithRoutesLogger<Ctx>>;\n\n /**\n * Grouped global middlewares that run *before* or *after* the handler for every route.\n */\n globalMiddleware?: {\n before?: Array<CtxRequestHandler<Ctx>>;\n after?: Array<CtxRequestHandler<Ctx>>;\n };\n\n /**\n * Derive middleware from MethodCfg.\n * - `upload` runs when cfg.bodyFiles has entries\n */\n fromCfg?: {\n upload?: (files: FileField[] | undefined, leaf: AnyLeaf) => RequestHandler[];\n };\n\n /** Validate handler return values with outputSchema (default: true) */\n validateOutput?: boolean;\n\n /** Custom responder (default: res.json(data)) */\n send?: (res: express.Response, data: unknown) => void;\n\n /** Optional logger hooks */\n logger?: LoggerLike;\n\n /**\n * Optional debug logging for the request lifecycle.\n * Supports booleans/modes/loggers, or a toggle map with per-event enabling, verbose payload logging,\n * and `only` filters tied to `RouteDef.debug?.debugName` (or the deprecated `RouteDef.debugName`).\n */\n debug?: RouteServerDebugOptions<Names>;\n};\n\n/** Default JSON responder (typed to avoid implicit-any diagnostics) */\nconst defaultSend: (res: express.Response, data: unknown) => void = (res, data) => {\n res.json(data as any);\n};\n\n// ──────────────────────────────────────────────────────────────────────────────\n// Core builder\n// ──────────────────────────────────────────────────────────────────────────────\n\nconst REGISTERED_ROUTES_SYMBOL = Symbol.for('routesV3.registeredRoutes');\n\ntype RegisteredRouteStore = Set<string>;\n\n/**\n * Retrieve or initialize the shared store of registered route keys.\n * @param router Express router/application that carries previously registered keys.\n * @returns Set of string keys describing registered routes.\n */\nfunction getRegisteredRouteStore(router: Router): RegisteredRouteStore {\n const existing = (router as any)[REGISTERED_ROUTES_SYMBOL] as RegisteredRouteStore | undefined;\n if (existing) return existing;\n const store: RegisteredRouteStore = new Set();\n (router as any)[REGISTERED_ROUTES_SYMBOL] = store;\n return store;\n}\n\n/**\n * Inspect the Express layer stack to discover already-registered routes.\n * @param appOrRouter Express application or router to inspect.\n * @returns All keys in the form `\"METHOD /path\"` found on the stack.\n */\nfunction collectRoutesFromStack(appOrRouter: Router): string[] {\n const result: string[] = [];\n const stack: any[] =\n (appOrRouter as any).stack ??\n ((appOrRouter as any)._router ? (appOrRouter as any)._router.stack : undefined) ??\n [];\n\n if (!Array.isArray(stack)) return result;\n\n for (const layer of stack) {\n const route = layer && layer.route;\n if (!route) continue;\n\n const paths = Array.isArray(route.path) ? route.path : [route.path];\n const methodEntries = Object.entries(route.methods ?? {}).filter(([, enabled]) => enabled);\n\n for (const path of paths) {\n for (const [method] of methodEntries) {\n result.push(`${method.toUpperCase()} ${path}`);\n }\n }\n }\n\n return result;\n}\n\n/** Runtime helpers returned by `createRRRoute`. */\nexport type RouteServer<Ctx = unknown, Names extends string = string> = {\n router: Router;\n register<L extends AnyLeaf>(leaf: L, def: RouteDef<L, Ctx, Names>): void;\n registerControllers<R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> }>(\n registry: R,\n controllers: PartialControllerMap<R, Ctx, Names>,\n ): void;\n warnMissingControllers<R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> }>(\n registry: R,\n logger: { warn: (...args: any[]) => void },\n ): void;\n getRegisteredKeys(): string[];\n};\n\n/**\n * Create an Express binding helper that keeps routes and controllers in sync.\n * @param router Express router or app to register handlers on.\n * @param config Optional configuration controlling ctx building, auth, uploads, etc.\n * @returns Object with helpers to register controllers and inspect registered keys.\n */\nexport function createRRRoute<Ctx = unknown, Names extends string = string>(\n router: Router,\n config: RouteServerConfig<Ctx, Names>,\n): RouteServer<Ctx, Names> {\n const validateOutput = config.validateOutput ?? true;\n const send = config.send ?? defaultSend;\n const logger = config.logger;\n const { emit: defaultEmitDebug, mode: defaultDebugMode } =\n createServerDebugEmitter<Names>(config.debug);\n const decorateDebugEvent = <T extends RouteServerDebugEvent>(\n isVerbose: boolean,\n event: T,\n details?: Partial<RouteServerDebugEvent>,\n ): RouteServerDebugEvent => {\n if (!isVerbose || !details) return event;\n return { ...event, ...details } as RouteServerDebugEvent;\n };\n\n const globalBeforeMws = [ ...(config.globalMiddleware?.before ?? [])].map(\n (mw) => adaptCtxMw<Ctx>(mw),\n );\n const globalAfterMws = mapAfterMiddleware<Ctx>(config.globalMiddleware?.after);\n const registered = getRegisteredRouteStore(router);\n\n const buildDerived = (leaf: AnyLeaf): RequestHandler[] => {\n const derived: RequestHandler[] = [];\n if (\n config.fromCfg?.upload &&\n Array.isArray(leaf.cfg.bodyFiles) &&\n leaf.cfg.bodyFiles.length > 0\n ) {\n derived.push(...config.fromCfg.upload(leaf.cfg.bodyFiles, leaf));\n }\n\n return derived;\n };\n\n /** Register a single leaf/controller pair on the underlying router. */\n function register<L extends AnyLeaf>(leaf: L, def: RouteDef<L, Ctx, Names>) {\n const method = leaf.method as HttpMethod;\n const methodUpper = method.toUpperCase() as Uppercase<HttpMethod>;\n const path = leaf.path as string;\n const key = keyOf(leaf);\n const defDebug = def.debug;\n let debugName = def.debugName as Names | undefined;\n let routeDebugEmitter: ServerDebugEmitter<Names> | undefined;\n if (defDebug) {\n const { debugName: overrideName, ...rest } = defDebug;\n const hasOverrides = Object.values(rest).some((value) => value !== undefined);\n if (hasOverrides) {\n routeDebugEmitter = createServerDebugEmitter<Names>(\n rest as RouteServerDebugOptions<Names>,\n );\n }\n debugName = (overrideName ?? debugName) as Names | undefined;\n }\n const activeEmit = routeDebugEmitter?.emit ?? defaultEmitDebug;\n const activeDebugMode = routeDebugEmitter?.mode ?? defaultDebugMode;\n const emit = (event: RouteServerDebugEvent) => activeEmit(event, debugName);\n const isVerboseDebug = activeDebugMode === 'complete';\n emit({ type: 'register', method: methodUpper, path });\n\n const routeSpecific = (def?.use ?? []).map((mw) => adaptCtxMw<Ctx>(mw));\n const derived = buildDerived(leaf);\n const ctxMw: RequestHandler = async (req, res, next) => {\n const requestUrl = req.originalUrl ?? path;\n const startedAt = Date.now();\n emit({ type: 'buildCtx', stage: 'start', method: methodUpper, path, url: requestUrl });\n try {\n const ctx = await config.buildCtx(req, res);\n (res.locals as any)[CTX_SYMBOL] = ctx;\n emit({\n type: 'buildCtx',\n stage: 'success',\n method: methodUpper,\n path,\n url: requestUrl,\n durationMs: Date.now() - startedAt,\n });\n next();\n } catch (err) {\n emit({\n type: 'buildCtx',\n stage: 'error',\n method: methodUpper,\n path,\n url: requestUrl,\n durationMs: Date.now() - startedAt,\n error: err,\n });\n logger?.error?.('buildCtx error', err);\n next(err as any);\n }\n };\n const before: RequestHandler[] = [ctxMw, ...globalBeforeMws, ...derived, ...routeSpecific];\n\n const wrapped: RequestHandler = async (req, res, next) => {\n const requestUrl = req.originalUrl.split('?')[0] ?? path;\n const startedAt = Date.now();\n emit({ type: 'request', stage: 'start', method: methodUpper, path, url: requestUrl });\n let params: ArgParams<L> | undefined;\n let query: ArgQuery<L> | undefined;\n let body: ArgBody<L> | undefined;\n let responsePayload: InferOutput<L> | undefined;\n let hasResponsePayload = false;\n setAfterHandlerNext(res, false);\n let handlerCalledNext = false;\n const downstreamNext: express.NextFunction = (err?: any) => {\n handlerCalledNext = true;\n setAfterHandlerNext(res, true);\n next(err);\n };\n\n logger?.info?.(`${methodUpper}@${path} (${requestUrl})`);\n const ctx = (res.locals as any)[CTX_SYMBOL] as CtxWithRoutesLogger<Ctx>;\n const ctxRoutesLogger = ctx?.routesLogger;\n const emitWithCtx = (\n event: RouteServerDebugEvent,\n details?: Partial<RouteServerDebugEvent>,\n ) => {\n const decorated = decorateDebugEvent(isVerboseDebug, event, details);\n if (decorated.type === 'handler' && ctxRoutesLogger) {\n logHandlerDebugWithRoutesLogger(ctxRoutesLogger, decorated);\n }else{\n emit(decorated);\n }\n };\n try {\n params = (\n leaf.cfg.paramsSchema\n ? (leaf.cfg.paramsSchema as ZodType).parse(req.params)\n : Object.keys(req.params || {}).length\n ? (req.params as any)\n : undefined\n ) as ArgParams<L>;\n\n try {\n query = leaf.cfg.querySchema\n ? (leaf.cfg.querySchema as ZodType).parse(req.query)\n : Object.keys(req.query || {}).length\n ? (req.query as any)\n : undefined;\n } catch (e) {\n logger?.error?.('Query parsing error', {\n path,\n method: methodUpper,\n error: e,\n raw: JSON.stringify(req.query),\n });\n throw e;\n }\n\n body = (\n leaf.cfg.bodySchema\n ? (leaf.cfg.bodySchema as ZodType).parse(req.body)\n : req.body !== undefined\n ? (req.body as any)\n : undefined\n ) as ArgBody<L>;\n\n logger?.verbose?.(`${methodUpper}@${path} (${requestUrl})`, {\n params,\n query,\n body,\n });\n\n const handlerStartedAt = Date.now();\n emitWithCtx(\n {\n type: 'handler',\n stage: 'start',\n method: methodUpper,\n path,\n },\n isVerboseDebug ? { params, query, body } : undefined,\n );\n\n let result;\n try {\n result = await def.handler({\n req,\n res,\n next: downstreamNext,\n ctx,\n params: params as ArgParams<L>,\n query: query as ArgQuery<L>,\n body: body as ArgBody<L>,\n });\n emitWithCtx(\n {\n type: 'handler',\n stage: 'success',\n method: methodUpper,\n path,\n durationMs: Date.now() - handlerStartedAt,\n },\n isVerboseDebug\n ? {\n params,\n query,\n body,\n ...(result !== undefined ? { output: result } : {}),\n }\n : undefined,\n );\n } catch (e) {\n emitWithCtx(\n {\n type: 'handler',\n stage: 'error',\n method: methodUpper,\n path,\n durationMs: Date.now() - handlerStartedAt,\n error: e,\n },\n isVerboseDebug ? { params, query, body } : undefined,\n );\n logger?.error?.('Handler error', e);\n throw e;\n }\n\n if (!res.headersSent) {\n if (result !== undefined) {\n const out =\n validateOutput && leaf.cfg.outputSchema\n ? (leaf.cfg.outputSchema as ZodType).parse(result)\n : result;\n responsePayload = out as InferOutput<L>;\n hasResponsePayload = true;\n logger?.verbose?.(`${methodUpper}@${path} result`, out);\n send(res, out);\n } else if (!handlerCalledNext) {\n next();\n }\n }\n\n emitWithCtx(\n {\n type: 'request',\n stage: 'success',\n method: methodUpper,\n path,\n url: requestUrl,\n durationMs: Date.now() - startedAt,\n },\n isVerboseDebug\n ? {\n params,\n query,\n body,\n ...(hasResponsePayload ? { output: responsePayload } : {}),\n }\n : undefined,\n );\n } catch (err) {\n emitWithCtx(\n {\n type: 'request',\n stage: 'error',\n method: methodUpper,\n path,\n url: requestUrl,\n durationMs: Date.now() - startedAt,\n error: err,\n },\n isVerboseDebug ? { params, query, body } : undefined,\n );\n logger?.error?.('Route error', err);\n next(err as any);\n }\n };\n\n const after = [...mapAfterMiddleware<Ctx>(def?.after), ...globalAfterMws];\n (router as any)[method](path, ...before, wrapped, ...after);\n registered.add(key);\n }\n\n /**\n * Register controller definitions for the provided keys.\n * @param registry Finalized registry of leaves.\n * @param controllers Partial controller map keyed by `\"METHOD /path\"`.\n */\n function registerControllers<\n R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> },\n >(registry: R, controllers: PartialControllerMap<R, Ctx, Names>) {\n (Object.keys(controllers) as Array<KeysOfRegistry<R>>).forEach((key) => {\n const leaf = registry.byKey[key] as unknown as LeafFromKey<R, typeof key> | undefined;\n if (!leaf) {\n logger?.warn?.(`No leaf found for controller key: ${key}. Not registering route.`);\n return;\n }\n const def = controllers[key];\n if (!def) return;\n register(leaf as LeafFromKey<R, typeof key>, def);\n });\n }\n\n /**\n * Warn about leaves that do not have a registered controller.\n * @param registry Finalized registry of leaves.\n * @param warnLogger Logger used for warning output.\n */\n function warnMissing<R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> }>(\n registry: R,\n warnLogger: { warn: (...args: any[]) => void },\n ) {\n const registeredFromStore = new Set<string>(Array.from(registered));\n if (registeredFromStore.size === 0) {\n collectRoutesFromStack(router).forEach((key) => registeredFromStore.add(key));\n }\n for (const leaf of registry.all) {\n const key = keyOf(leaf);\n if (!registeredFromStore.has(key)) {\n warnLogger.warn(`No controller registered for route: ${key}`);\n }\n }\n }\n\n return {\n router,\n register,\n registerControllers,\n warnMissingControllers: warnMissing,\n getRegisteredKeys: () => Array.from(registered),\n };\n}\n\n/**\n * Bind only the controllers that are present in the provided map.\n * @param router Express router or app.\n * @param registry Finalized registry produced by `finalize(...)`.\n * @param controllers Partial map of controllers keyed by `\"METHOD /path\"`.\n * @param config Optional route server configuration.\n * @returns The same router instance for chaining.\n */\nexport function bindExpressRoutes<\n R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> },\n Ctx = unknown,\n Names extends string = string,\n>(\n router: Router,\n registry: R,\n controllers: PartialControllerMap<R, Ctx, Names>,\n config: RouteServerConfig<Ctx, Names>,\n) {\n const server = createRRRoute<Ctx, Names>(router, config);\n server.registerControllers(registry, controllers);\n return router;\n}\n\n/**\n * Bind controllers for every leaf. Missing entries fail at compile time.\n * @param router Express router or app.\n * @param registry Finalized registry produced by `finalize(...)`.\n * @param controllers Complete map of controllers keyed by `\"METHOD /path\"`.\n * @param config Optional route server configuration.\n * @returns The same router instance for chaining.\n */\nexport function bindAll<\n R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> },\n Ctx = unknown,\n Names extends string = string,\n>(\n router: Router,\n registry: R,\n controllers: { [K in KeysOfRegistry<R>]: RouteDef<LeafFromKey<R, K>, Ctx, Names> },\n config: RouteServerConfig<Ctx, Names>,\n) {\n const server = createRRRoute<Ctx, Names>(router, config);\n server.registerControllers(registry, controllers);\n return router;\n}\n\n// ──────────────────────────────────────────────────────────────────────────────\n// DX helpers\n// ──────────────────────────────────────────────────────────────────────────────\n\n/**\n * Helper for great IntelliSense when authoring controller maps.\n * @returns Function that enforces key names while preserving partial flexibility.\n */\nexport const defineControllers =\n <\n R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> },\n Ctx = unknown,\n Names extends string = string,\n >() =>\n <M extends PartialControllerMap<R, Ctx, Names>>(m: M) =>\n m;\n\n/**\n * Warn about leaves that don't have controllers.\n * Call this during startup to surface missing routes.\n * @param router Express router or app to inspect.\n * @param registry Finalized registry produced by `finalize(...)`.\n * @param logger Logger where warnings are emitted.\n */\nexport function warnMissingControllers<\n R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> },\n>(router: Router, registry: R, logger: { warn: (...args: any[]) => void }) {\n const registeredStore = (router as any)[REGISTERED_ROUTES_SYMBOL] as Set<string> | undefined;\n const initial = registeredStore ? Array.from(registeredStore) : collectRoutesFromStack(router);\n const registeredKeys = new Set<string>(initial);\n\n for (const leaf of registry.all) {\n const k = keyOf(leaf);\n if (!registeredKeys.has(k)) {\n logger.warn(`No controller registered for route: ${k}`);\n }\n }\n}\n","// socket.server.debug.ts\nimport type { IncomingHttpHeaders } from 'http';\n\nexport type SocketServerConfigSnapshot = {\n url?: string;\n transport?: string;\n protocol?: string;\n address?: string;\n issued?: number;\n time?: string;\n query?: Record<string, unknown>;\n auth?: Record<string, unknown>;\n headers?: IncomingHttpHeaders;\n};\n\nexport type SocketServerLifecycleStage =\n | 'server_init'\n | 'connection_listener_installed'\n | 'connection_init'\n | 'connection_handlers_attached'\n | 'connection_cleanup'\n | 'destroy_start'\n | 'destroy_complete'\n | 'connection_cleanup_fallback';\n\nexport type SocketServerHeartbeatPhase = 'ping' | 'pong' | 'skip';\n\nexport type SocketServerDebugEvent =\n | {\n type: 'register';\n action: 'register' | 'unregister';\n event: string;\n msg?:string;\n }\n | {\n type: 'handler';\n phase: 'receive' | 'validation_error' | 'handler_success' | 'handler_error';\n event: string;\n socketId?: string;\n nsp?: string;\n rooms?: string[];\n raw?: unknown;\n issues?: any[];\n error?: unknown;\n details?: Record<string, unknown>;\n }\n | {\n type: 'emit';\n event: string;\n rooms: string[];\n envelope?: unknown;\n error?: {\n reason: string;\n message?: string;\n issues?: unknown;\n };\n metadata?:unknown;\n }\n | {\n type: 'rooms';\n action: 'join' | 'leave';\n rooms?: string|string[];\n socketId: string;\n phase?:string;\n payload?: unknown;\n issues?: any[];\n }\n | {\n type: 'heartbeat';\n phase: SocketServerHeartbeatPhase;\n socketId: string;\n payload?: unknown;\n issues?: any[];\n error?: boolean;\n details?: Record<string, unknown>;\n }\n | {\n type: 'config';\n socketId: string;\n nsp: string;\n snapshot: SocketServerConfigSnapshot;\n }\n | {\n type: 'lifecycle';\n stage: SocketServerLifecycleStage;\n socketId?: string;\n nsp?: string;\n details?: Record<string, unknown>;\n };\n\nexport type SocketDebugOptions = {\n verbose?: boolean;\n /** filters event-based logs (register/handler/emit) by event name */\n only?: string[];\n logger?: (e: SocketServerDebugEvent) => void;\n} & {\n [P in SocketServerDebugEvent['type']]?: boolean;\n};\n\nexport function createDebugger(options?: SocketDebugOptions) {\n const debug = options ?? {};\n\n return (maybeEvent: string | null, e: SocketServerDebugEvent) => {\n if (!debug.logger) return;\n if (!debug[e.type]) return;\n\n // only filter applies to event-shaped logs\n if (\n debug.only &&\n maybeEvent &&\n (e.type === 'register' || e.type === 'handler' || e.type === 'emit') &&\n !debug.only.includes(maybeEvent)\n ) {\n return;\n }\n\n debug.logger(e);\n };\n}\n","// socket.server.sys.ts\nimport type { Socket } from 'socket.io';\nimport { z } from 'zod';\nimport type { EventMap, SocketConnectionConfig, SysEventName } from '@emeryld/rrroutes-contract';\nimport type {\n SocketServerConfigSnapshot,\n SocketServerDebugEvent,\n} from './socket.server.debug';\nimport type { HandlerCtxNoAck } from './socket.server.types';\n\n// Helper: payload for event map\ntype EventPayload<Events extends EventMap, K extends keyof Events & string> =\n z.infer<Events[K]['message']>;\n\nexport type SocketConnectionHelper<Events extends EventMap> = {\n emit<K extends keyof Events & string>(\n event: K,\n payload: EventPayload<Events, K>,\n metadata?: Record<string, unknown>,\n onAck?: (ack: unknown) => void\n ): void;\n};\n\n\n/** Heartbeat configuration that is not tied to payload shapes (which live in sys event schemas). */\nexport type HeartbeatServerOptions = {\n /** Enable/disable built-in heartbeat handling. Defaults to true. */\n enabled?: boolean;\n};\n\nexport type SysServerEventMap<\n Config extends SocketConnectionConfig = SocketConnectionConfig,\n Events extends EventMap = EventMap,\n> = {\n 'sys:connect': (args: {\n socket: Socket;\n helper: SocketConnectionHelper<Events>;\n /**\n * Call to proceed with the default connection initialization\n * (attaches heartbeat, join, leave and disconnect handlers).\n */\n complete: () => void;\n }) => void | Promise<void>;\n\n 'sys:disconnect': (args: {\n socket: Socket;\n helper: SocketConnectionHelper<Events>;\n /** cleans up all handlers */\n cleanup: () => void;\n reason: string;\n }) => void | Promise<void>;\n\n 'sys:ping': (\n args:{\n socket: Socket;\n helper: SocketConnectionHelper<Events>;\n ping: z.output<Config['pingPayload']>,\n ctx: HandlerCtxNoAck}\n ) => z.output<Config['pongPayload']> | Promise<z.output<Config['pongPayload']>>;\n\n 'sys:room_join': (args: {\n socket: Socket;\n helper: SocketConnectionHelper<Events>;\n rooms: string[];\n meta: z.output<Config['joinMetaMessage']>;\n join: (room: string) => Promise<void>;\n }) => void | Promise<void>;\n\n 'sys:room_leave': (args: {\n socket: Socket;\n helper: SocketConnectionHelper<Events>;\n rooms: string[];\n meta: z.output<Config['leaveMetaMessage']>;\n leave: (room: string) => Promise<void>;\n }) => void | Promise<void>;\n};\n\n\nconst normalizeError = (error: unknown) => {\n if (error instanceof Error) {\n return { name: error.name, message: error.message };\n }\n if (typeof error === 'string') return { message: error };\n return { message: 'Unknown error' };\n};\n\nconst roomValueSchema = z.union([z.string(), z.array(z.string())]);\n\nconst buildRoomPayloadSchema = <Meta extends z.ZodTypeAny>(metaSchema: Meta) =>\n z.object({\n rooms: roomValueSchema,\n meta: metaSchema,\n });\n\ntype DebugFn = (maybeEvent: string | null, e: SocketServerDebugEvent) => void;\n\nconst toArray = (rooms?: string[] | string): string[] =>\n rooms == null ? [] : Array.isArray(rooms) ? rooms : [rooms];\n\nconst snapshotSocketConfig = (socket: Socket): SocketServerConfigSnapshot => {\n const conn = socket.conn as { transport?: { name?: string }; protocol?: string | number; remoteAddress?: string } | undefined;\n const protocol = conn?.protocol;\n return {\n url: socket.handshake.url,\n transport: conn?.transport?.name,\n protocol: protocol != null ? String(protocol) : undefined,\n address: conn?.remoteAddress ?? socket.handshake.address,\n issued: socket.handshake.issued,\n time: socket.handshake.time,\n query: socket.handshake.query as Record<string, unknown>,\n auth: socket.handshake.auth as Record<string, unknown>,\n headers: socket.handshake.headers,\n };\n};\n\nexport function createBuiltInConnectionHandlers<\n C extends SocketConnectionConfig,\n Events extends EventMap,\n>(opts: {\n heartbeat?: HeartbeatServerOptions;\n sys: SysServerEventMap<C, Events>;\n dbg: DebugFn;\n config: C;\n createCtx: (socket: Socket) => HandlerCtxNoAck;\n debugVerbose?: boolean;\n createHelper: (socket: Socket) => SocketConnectionHelper<Events>;\n}) {\n const { heartbeat, sys, dbg, config, createCtx, debugVerbose, createHelper } = opts;\n\n const roomJoinEvent: SysEventName = 'sys:room_join';\n const roomLeaveEvent: SysEventName = 'sys:room_leave';\n const pingEvent: SysEventName = 'sys:ping';\n const pongEvent: SysEventName = 'sys:pong';\n const heartbeatEnabled = heartbeat?.enabled !== false;\n\n const joinPayloadSchema = buildRoomPayloadSchema(config.joinMetaMessage);\n const leavePayloadSchema = buildRoomPayloadSchema(config.leaveMetaMessage);\n const pingPayloadSchema = config.pingPayload as C['pingPayload'];\n const pongPayloadSchema = config.pongPayload as C['pongPayload'];\n\n const sysEvents = sys;\n const getSysEvent = <K extends keyof SysServerEventMap<C, Events> & SysEventName>(name: K) =>\n sysEvents[name];\n\n /** Track per-socket teardown for built-in handlers to ensure explicit cleanup on destroy(). */\n const socketTeardowns = new WeakMap<Socket, () => void>();\n\n const builtInConnectionListener = (socket: Socket) => {\n const helper = createHelper(socket);\n dbg(null, {\n type: 'lifecycle',\n stage: 'connection_init',\n socketId: socket.id,\n nsp: socket.nsp.name,\n details: {\n rooms: Array.from(socket.rooms),\n handshakeIssued: socket.handshake.issued,\n },\n });\n dbg(null, {\n type: 'config',\n socketId: socket.id,\n nsp: socket.nsp.name,\n snapshot: snapshotSocketConfig(socket),\n });\n\n const defaultConnect = () => {\n dbg('sys:connect', {\n type: 'handler',\n phase: 'handler_success',\n event: 'sys:connect',\n socketId: socket.id,\n });\n\n const includeRaw = debugVerbose === true;\n\n // built-in room handlers (wrapped with sys:room_join / sys:room_leave)\n const joinHandler = async (msg: unknown) => {\n dbg(roomJoinEvent, {\n type: 'rooms',\n phase: 'receive',\n action:'join',\n socketId: socket.id,\n payload: includeRaw ? msg : undefined,\n });\n const parsed = joinPayloadSchema.safeParse(msg);\n\n if (!parsed.success) {\n socket.emit(`${roomJoinEvent}:error`, {\n eventName: roomJoinEvent,\n issues: parsed.error.issues,\n });\n dbg(roomJoinEvent, {\n type: 'rooms',\n action:'join',\n phase:'validation_error',\n socketId: socket.id,\n issues: parsed.error.issues,\n payload: includeRaw ? msg : undefined,\n });\n return;\n }\n const list = toArray(parsed.data.rooms);\n\n const join = async (room: string) => {\n await socket.join(room);\n dbg(null, { type: 'rooms', action: 'join', rooms:room, socketId: socket.id });\n };\n\n const run = async () => {\n await getSysEvent('sys:room_join')({\n socket,\n helper,\n rooms: list,\n meta: parsed.data.meta as z.output<C['joinMetaMessage']>,\n join,\n });\n };\n\n try {\n await run();\n } catch (error) {\n socket.emit(`${roomJoinEvent}:error`, { error: normalizeError(error) });\n dbg(roomJoinEvent, {\n type: 'rooms',\n action:'join',\n phase: 'handler_error',\n payload: includeRaw ? { rooms: list, meta: parsed.data.meta } : undefined,\n socketId: socket.id,\n issues:[error],\n });\n }\n };\n\n const leaveHandler = async (msg: unknown) => {\n dbg(roomLeaveEvent, {\n type: 'rooms',\n phase: 'receive',\n action:'leave',\n socketId: socket.id,\n payload: includeRaw ? msg : undefined,\n });\n const parsed = leavePayloadSchema.safeParse(msg);\n if (!parsed.success) {\n socket.emit(`${roomLeaveEvent}:error`, {\n eventName: roomLeaveEvent,\n issues: parsed.error.issues,\n });\n dbg(roomJoinEvent, {\n type: 'rooms',\n action:'leave',\n phase:'validation_error',\n socketId: socket.id,\n issues: parsed.error.issues,\n payload: includeRaw ? msg : undefined,\n });\n return;\n }\n\n const list = toArray(parsed.data.rooms);\n\n const leave = async (room: string) => {\n dbg(null, { type: 'rooms', action: 'leave', rooms:room, socketId: socket.id });\n await socket.leave(room);\n };\n\n const run = async () => {\n await getSysEvent('sys:room_leave')({\n socket,\n helper,\n rooms: list,\n meta: parsed.data.meta as z.output<C['leaveMetaMessage']>,\n leave,\n });\n };\n\n try {\n await run();\n } catch (error) {\n socket.emit(`${roomLeaveEvent}:error`, { error: normalizeError(error) });\n dbg(roomJoinEvent, {\n type: 'rooms',\n phase: 'handler_error',\n payload: includeRaw ? { rooms: list, meta: parsed.data.meta } : undefined,\n socketId: socket.id,\n issues:[error],\n action:'join'\n });\n }\n };\n\n // heartbeat, wrapped with sys:ping/sys:pong\n const pingHandler = async (msg: unknown) => {\n if (!heartbeatEnabled) {\n dbg(null, {\n type: 'heartbeat',\n phase: 'skip',\n socketId: socket.id,\n details: { reason: 'heartbeat_disabled' },\n error: false,\n });\n return;\n }\n\n const parsedPing = pingPayloadSchema.safeParse(msg);\n if (!parsedPing.success) {\n socket.emit(`${pingEvent}:error`, {\n eventName: pingEvent,\n issues: parsedPing.error.issues,\n });\n dbg(null, {\n type: 'heartbeat',\n phase: 'ping',\n socketId: socket.id,\n payload: includeRaw ? msg : undefined,\n issues: parsedPing.error.issues,\n error: true,\n details: { step: 'parse' },\n });\n return;\n }\n const ctx = createCtx(socket);\n\n dbg(null, {\n type: 'heartbeat',\n phase: 'ping',\n socketId: socket.id,\n payload: parsedPing.data,\n error: false,\n });\n\n let pongPayload: z.output<C['pongPayload']>;\n try {\n pongPayload = await getSysEvent('sys:ping')({ping:parsedPing.data, ctx, socket, helper});\n } catch (error) {\n socket.emit(`${pingEvent}:error`, { error: normalizeError(error) });\n dbg(null, {\n type: 'heartbeat',\n phase: 'ping',\n socketId: socket.id,\n payload: parsedPing.data,\n error: true,\n details: { step: 'sys_handler_error' },\n });\n return;\n }\n\n const parsedPong = pongPayloadSchema.safeParse(pongPayload);\n if (!parsedPong.success) {\n socket.emit(`${pongEvent}:error`, {\n eventName: pongEvent,\n issues: parsedPong.error.issues,\n });\n dbg(null, {\n type: 'heartbeat',\n phase: 'pong',\n socketId: socket.id,\n payload: includeRaw ? pongPayload : undefined,\n issues: parsedPong.error.issues,\n error: true,\n details: { step: 'parse' },\n });\n return;\n }\n socket.emit(pongEvent, parsedPong.data);\n dbg(null, {\n type: 'heartbeat',\n phase: 'pong',\n socketId: socket.id,\n payload: parsedPong.data,\n error: false,\n });\n };\n\n // attach built-in handlers\n socket.on(roomJoinEvent, joinHandler);\n socket.on(roomLeaveEvent, leaveHandler);\n if (heartbeatEnabled) {\n socket.on(pingEvent, pingHandler);\n }\n\n const cleanup = () => {\n dbg(null, {\n type: 'lifecycle',\n stage: 'connection_cleanup',\n socketId: socket.id,\n nsp: socket.nsp.name,\n details: { reason: 'teardown' },\n });\n socket.off(roomJoinEvent, joinHandler);\n socket.off(roomLeaveEvent, leaveHandler);\n if (heartbeatEnabled) {\n socket.off(pingEvent, pingHandler);\n }\n };\n\n socketTeardowns.set(socket, cleanup);\n dbg(null, {\n type: 'lifecycle',\n stage: 'connection_handlers_attached',\n socketId: socket.id,\n nsp: socket.nsp.name,\n details: {\n heartbeatEnabled,\n joinEvent: roomJoinEvent,\n leaveEvent: roomLeaveEvent,\n pingEvent: heartbeatEnabled ? pingEvent : undefined,\n },\n });\n\n socket.once('disconnect', (reason) => {\n dbg('sys:disconnect', {\n type: 'lifecycle',\n stage:'connection_cleanup',\n nsp: socket.nsp.name,\n socketId: socket.id,\n details: { reason: String(reason) },\n });\n const defaultDisconnect = () => {\n cleanup();\n socketTeardowns.delete(socket);\n };\n getSysEvent('sys:disconnect')({\n socket,\n helper,\n reason: String(reason),\n cleanup: defaultDisconnect,\n });\n });\n };\n getSysEvent('sys:connect')({\n socket,\n helper,\n complete: defaultConnect,\n });\n };\n\n return {\n builtInConnectionListener,\n socketTeardowns,\n roomJoinEvent,\n roomLeaveEvent,\n pingEvent,\n };\n}\n","// socket.server.index.ts\nimport { Server, Socket } from 'socket.io';\nimport { z } from 'zod';\nimport type { EventMap, SocketConnectionConfig } from '@emeryld/rrroutes-contract';\nimport { createDebugger } from './socket.server.debug';\nimport type { SocketServerDebugEvent, SocketDebugOptions } from './socket.server.debug';\nimport { createBuiltInConnectionHandlers } from './socket.server.sys';\nimport type {\n HeartbeatServerOptions,\n SocketConnectionHelper,\n SysServerEventMap,\n} from './socket.server.sys';\nimport type { HandlerCtx, HandlerCtxNoAck } from './socket.server.types';\n\ntype Payload<T extends EventMap, K extends keyof T> = z.infer<T[K]['message']>;\n\nconst createBaseHandlerCtx = (socket: Socket): HandlerCtxNoAck => ({\n sentAt: new Date(),\n socket,\n socketId: socket.id,\n nsp: socket.nsp.name,\n rooms: Array.from(socket.rooms),\n user: socket.data?.user,\n scopes: socket.data?.scopes,\n});\n\nconst normalizeError = (error: unknown, verbose?: boolean) => {\n if (error instanceof Error) {\n return {\n name: error.name,\n message: error.message,\n stack: verbose ? error.stack : undefined,\n };\n }\n if (typeof error === 'string') return { message: error };\n if (typeof error === 'object' && error !== null) {\n return verbose ? error : { message: 'Unknown error' };\n }\n return { message: String(error) };\n};\n\nexport interface SocketConnection<T extends EventMap> {\n on<K extends keyof T & string>(\n eventName: K,\n handler: (payload: Payload<T, K>, ctx: HandlerCtx) => void | Promise<void>\n ): () => void;\n\n off<K extends keyof T & string>(eventName: K): void;\n\n emit<K extends keyof T & string>(\n eventName: K,\n payload: Payload<T, K>,\n toRooms?: string[] | string,\n metadata?: Record<string, unknown>,\n onAck?: (ack: unknown) => void\n ): void;\n\n /** Dispose all listeners, timers, and room memberships created by this instance. */\n destroy(): void;\n}\n\nexport function createSocketConnections<\n T extends EventMap,\n TConfig extends SocketConnectionConfig = SocketConnectionConfig,\n>(\n io: Server,\n events: T,\n opts: {\n debug?: SocketDebugOptions;\n heartbeat?: HeartbeatServerOptions;\n /** System event customization (connect / disconnect / ping / pong / room join/leave) */\n sys: SysServerEventMap<TConfig, T>;\n config: TConfig;\n }\n): SocketConnection<T> {\n const dbg = createDebugger(opts?.debug);\n const socketConfig = opts.config;\n const heartbeatEnabled = opts?.heartbeat?.enabled !== false;\n const eventNames = Object.keys(events);\n dbg(null, {\n type: 'lifecycle',\n stage: 'server_init',\n details: {\n eventCount: eventNames,\n heartbeatEnabled,\n path: io?.path(),\n namespaces: Array.from(io._nsps.keys()),\n transport: io?._opts.transports,\n sysEvents: Object.keys(opts.sys ?? {}),\n },\n });\n\n const getSchema = <K extends keyof T & string>(k: K) => events[k].message;\n const toArray = (rooms?: string[] | string): string[] =>\n rooms == null ? [] : Array.isArray(rooms) ? rooms : [rooms];\n const emitToTargets = <K extends keyof T & string>(\n eventName: K,\n payload: Payload<T, K>,\n targets: string[],\n metadata?: Record<string, unknown>,\n ) => {\n const schema = getSchema(eventName);\n const check = schema.safeParse(payload);\n if (!check.success) {\n dbg(String(eventName), {\n type: 'emit',\n event: String(eventName),\n rooms: targets,\n ...(opts?.debug?.verbose ? { attemptedPayload: payload } : {}),\n error: {\n reason: 'invalid_payload',\n message: check.error.message,\n issues: check.error.issues\n },\n metadata\n });\n throw new Error(`Invalid payload for \"${String(eventName)}\": ${check.error.message}`);\n }\n\n const envelope = {\n eventName,\n sentAt: new Date(),\n sentTo: targets,\n data: check.data as Payload<T, K>,\n metadata: metadata ?? {},\n };\n\n if (targets.length === 0) io.emit(String(eventName), envelope);\n else if (targets.length === 1) {\n const sid = targets[0]!;\n const sock = io.sockets.sockets.get(sid as any);\n if (sock) {\n sock.emit(String(eventName), envelope);\n }else{\n io.to(targets).emit(String(eventName), envelope);\n }\n } else{\n io.to(targets).emit(String(eventName), envelope);\n }\n\n dbg(String(eventName), {\n type: 'emit',\n event: String(eventName),\n rooms: targets,\n envelope: opts?.debug?.verbose ? envelope : undefined,\n });\n };\n const createSocketHelper = (socket: Socket): SocketConnectionHelper<T> => ({\n emit<K extends keyof T & string>(\n eventName: K,\n payload: Payload<T, K>,\n metadata?: Record<string, unknown>,\n ) {\n emitToTargets(eventName, payload, [socket.id], metadata);\n },\n });\n\n // registrations\n const registrations = new Map<\n string,\n Set<{\n connectionListener: (socket: Socket) => void;\n socketListeners: WeakMap<Socket, (raw: unknown) => void>;\n }>\n >();\n\n const addRegistration = (\n eventName: string,\n reg: {\n connectionListener: (socket: Socket) => void;\n socketListeners: WeakMap<Socket, (raw: unknown) => void>;\n }\n ) => {\n let set = registrations.get(eventName);\n if (!set) {\n set = new Set();\n registrations.set(eventName, set);\n }\n set.add(reg);\n };\n\n const removeAllForEvent = (eventName: string) => {\n const set = registrations.get(eventName);\n if (!set) {\n dbg(null, {\n type: 'register',\n event: eventName,\n action: 'unregister',\nmsg:'no handlers registered'\n });\n return;\n }\n for (const reg of set) {\n io.off('connection', reg.connectionListener);\n for (const socket of io.sockets.sockets.values()) {\n const wrapped = reg.socketListeners.get(socket);\n if (wrapped) socket.off(String(eventName), wrapped);\n }\n }\n registrations.delete(eventName);\n dbg(eventName, { type: 'register', action: 'unregister', event: eventName, msg:'unregistered' });\n };\n\n const {\n builtInConnectionListener,\n socketTeardowns,\n roomJoinEvent,\n roomLeaveEvent,\n pingEvent,\n } = createBuiltInConnectionHandlers<TConfig, T>({\n heartbeat: opts?.heartbeat,\n sys: opts.sys,\n dbg,\n config: socketConfig,\n createCtx: createBaseHandlerCtx,\n debugVerbose: opts?.debug?.verbose === true,\n createHelper: createSocketHelper,\n });\n\n // install built-in connection listener\n io.on('connection', builtInConnectionListener);\n\n const conn = {\n on<K extends keyof T & string>(\n eventName: K,\n handler: (payload: Payload<T, K>, ctx: HandlerCtx) => void | Promise<void>\n ): () => void {\n const socketListeners = new WeakMap<Socket, (raw: unknown) => void>();\n\n const connectionListener = (socket: Socket) => {\n const wrapped = async (raw: unknown) => {\n const schema = getSchema(eventName);\n const parsed = schema.safeParse(raw);\n\n const ctx = createBaseHandlerCtx(socket);\n\n dbg(String(eventName), {\n type: 'handler',\n phase: 'receive',\n event: String(eventName),\n socketId: ctx.socketId,\n nsp: ctx.nsp,\n rooms: ctx.rooms,\n raw: opts?.debug?.verbose ? raw : undefined,\n });\n\n if (!parsed.success) {\n socket.emit(`${String(eventName)}:error`, {\n eventName,\n sentAt: ctx.sentAt,\n issues: parsed.error.issues,\n });\n dbg(String(eventName), {\n type: 'handler',\n phase: 'validation_error',\n event: String(eventName),\n socketId: ctx.socketId,\n nsp: ctx.nsp,\n issues: parsed.error.issues,\n });\n return;\n }\n\n try {\n await handler(parsed.data as Payload<T, K>, ctx);\n dbg(String(eventName), {\n type: 'handler',\n phase: 'handler_success',\n event: String(eventName),\n socketId: ctx.socketId,\n nsp: ctx.nsp,\n rooms: ctx.rooms,\n });\n } catch (error) {\n dbg(String(eventName), {\n type: 'handler',\n phase: 'handler_error',\n event: String(eventName),\n socketId: ctx.socketId,\n nsp: ctx.nsp,\n rooms: ctx.rooms,\n error,\n });\n socket.emit(`${String(eventName)}:error`, {\n eventName,\n sentAt: ctx.sentAt,\n error: normalizeError(error, opts?.debug?.verbose),\n });\n }\n };\n\n socketListeners.set(socket, wrapped);\n socket.on(String(eventName), wrapped);\n socket.once('disconnect', () => {\n const w = socketListeners.get(socket);\n if (w) socket.off(String(eventName), w);\n });\n };\n\n io.on('connection', connectionListener);\n addRegistration(String(eventName), { connectionListener, socketListeners });\n dbg(String(eventName), {\n type: 'register',\n action: 'register',\n event: String(eventName),\n });\n\n return () => {\n const set = registrations.get(String(eventName));\n if (!set) {\n dbg(null, {\n type: 'register',\n action:'unregister',\n event: String(eventName),msg:`No registration under ${eventName}`\n });\n return;\n }\n for (const reg of Array.from(set)) {\n if (reg.connectionListener === connectionListener) {\n io.off('connection', reg.connectionListener);\n for (const socket of io.sockets.sockets.values()) {\n const wrapped = reg.socketListeners.get(socket);\n if (wrapped) socket.off(String(eventName), wrapped);\n }\n set.delete(reg);\n break;\n }\n }\n if (set.size === 0) registrations.delete(String(eventName));\n dbg(String(eventName), {\n type: 'register',\n action: 'unregister',\n event: String(eventName),\n });\n };\n },\n\n off<K extends keyof T & string>(eventName: K): void {\n removeAllForEvent(String(eventName));\n },\n\n emit<K extends keyof T & string>(\n eventName: K,\n payload: Payload<T, K>,\n rooms?: string[] | string,\n metadata?: Record<string, unknown>,\n ): void {\n const targets = toArray(rooms);\n emitToTargets(eventName, payload, targets, metadata);\n },\n\n destroy(): void {\n dbg(null, {\n type: 'lifecycle',\n stage: 'destroy_start',\n details: {\n socketCount: io.sockets.sockets.size,\n registrationCount: registrations.size,\n },\n });\n // 1) Remove built-in connection listener so no new sockets get handlers\n io.off('connection', builtInConnectionListener);\n\n // 2) Cleanup built-in handlers for all current sockets and leave rooms\n for (const socket of io.sockets.sockets.values()) {\n const cleanup = socketTeardowns.get(socket);\n if (cleanup) {\n cleanup();\n socketTeardowns.delete(socket);\n } else {\n dbg(null, {\n type: 'lifecycle',\n stage: 'connection_cleanup_fallback',\n socketId: socket.id,\n nsp: socket.nsp.name,\n details: { reason: 'teardown_missing' },\n });\n // Fallback if socket was attached before map population\n try {\n socket.removeAllListeners(roomJoinEvent);\n socket.removeAllListeners(roomLeaveEvent);\n socket.removeAllListeners(pingEvent);\n } catch {\n // noop\n }\n }\n }\n\n // 3) Remove all user-registered event listeners and their connection hooks\n for (const eventName of Array.from(registrations.keys())) {\n removeAllForEvent(eventName);\n }\n\n // 4) Defensive: clear any residual maps\n registrations.clear();\n dbg(null, {\n type: 'lifecycle',\n stage: 'destroy_complete',\n details: {\n socketCount: io.sockets.sockets.size,\n registrationCount: registrations.size,\n },\n });\n },\n } as const satisfies SocketConnection<T>;\n\n return conn;\n}\n\nexport type { EventMap, Payload };\nexport type { HandlerCtx } from './socket.server.types';\nexport type {\n SocketServerDebugEvent,\n SocketDebugOptions,\n SocketServerConfigSnapshot,\n SocketServerLifecycleStage,\n SocketServerHeartbeatPhase,\n} from './socket.server.debug';\nexport type {\n HeartbeatServerOptions,\n SocketConnectionHelper,\n SysServerEventMap,\n} from './socket.server.sys';\n","import type { IncomingHttpHeaders } from 'http';\nimport type { Socket } from 'socket.io';\n\nexport type ConnectionMiddlewareStage = 'incoming';\n\nexport type ConnectionMiddlewareContext = {\n socketId?: string;\n nsp?: string;\n rooms: string[];\n user?: unknown;\n scopes?: string[];\n address?: string;\n transport?: string;\n protocol?: string;\n handshake: {\n url?: string;\n issued?: number;\n time?: string;\n query?: Record<string, unknown>;\n auth?: Record<string, unknown>;\n headers?: IncomingHttpHeaders;\n };\n};\n\nexport type ConnectionMiddlewareEvent = {\n type: 'connection';\n stage: ConnectionMiddlewareStage;\n timestamp: Date;\n context: ConnectionMiddlewareContext;\n};\n\nexport type ConnectionLoggingMiddlewareOptions = {\n /**\n * Custom logger invoked with the structured event.\n * Defaults to console.info.\n */\n logger?: (event: ConnectionMiddlewareEvent) => void;\n /**\n * Include raw headers from the handshake. Defaults to false to avoid leaking PII.\n */\n includeHeaders?: boolean;\n /**\n * List of auth keys that should be redacted (case-insensitive). Defaults to ['authorization'].\n */\n redactAuthKeys?: string[];\n};\n\nconst defaultRedactedValue = '[REDACTED]';\n\nconst defaultLogger = (event: ConnectionMiddlewareEvent) => {\n const {\n stage,\n context: { socketId, nsp, address, transport, handshake },\n } = event;\n // eslint-disable-next-line no-console\n console.info('[socket-connection]', {\n stage,\n socketId,\n nsp,\n address,\n transport,\n url: handshake.url,\n query: handshake.query,\n auth: handshake.auth,\n });\n};\n\nconst redactAuth = (\n auth: Record<string, unknown> | undefined,\n redactKeys: Set<string>\n): Record<string, unknown> | undefined => {\n if (!auth) return undefined;\n if (redactKeys.size === 0) return auth;\n\n const clone: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(auth)) {\n const normalizedKey = key.toLowerCase();\n clone[key] = redactKeys.has(normalizedKey) ? defaultRedactedValue : value;\n }\n return clone;\n};\n\nconst buildContext = (\n socket: Socket,\n includeHeaders: boolean,\n redactKeys: Set<string>\n): ConnectionMiddlewareContext => {\n const conn = socket.conn as\n | {\n remoteAddress?: string;\n transport?: { name?: string };\n protocol?: string | number;\n }\n | undefined;\n\n const handshake = socket.handshake ?? {};\n\n const protocolValue = conn?.protocol;\n\n return {\n socketId: socket.id,\n nsp: socket.nsp?.name,\n rooms: Array.from(socket.rooms ?? []),\n user: (socket.data as any)?.user,\n scopes: (socket.data as any)?.scopes,\n address: conn?.remoteAddress ?? (handshake as any).address,\n transport: conn?.transport?.name,\n protocol: protocolValue != null ? String(protocolValue) : undefined,\n handshake: {\n url: handshake.url,\n issued: handshake.issued,\n time: handshake.time,\n query: handshake.query as Record<string, unknown>,\n auth: redactAuth(handshake.auth as Record<string, unknown>, redactKeys),\n headers: includeHeaders ? (handshake.headers as IncomingHttpHeaders) : undefined,\n },\n };\n};\n\nexport const createConnectionLoggingMiddleware = (\n options: ConnectionLoggingMiddlewareOptions = {}\n) => {\n const logger = options.logger ?? defaultLogger;\n const includeHeaders = options.includeHeaders ?? false;\n const redactKeys = new Set(\n (options.redactAuthKeys ?? ['authorization', 'token']).map((key) => key.toLowerCase())\n );\n\n return (socket: Socket, next: (err?: Error) => void) => {\n const context = buildContext(socket, includeHeaders, redactKeys);\n logger({\n type: 'connection',\n stage: 'incoming',\n timestamp: new Date(),\n context,\n });\n next();\n };\n};\n\nexport type ConnectionLoggingMiddleware = ReturnType<typeof createConnectionLoggingMiddleware>;\n"],"mappings":"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","names":["normalizeError","toArray"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/routesV3.server.ts","../src/sockets/socket.server.debug.ts","../src/sockets/socket.server.sys.ts","../src/sockets/socket.server.index.ts","../src/sockets/socket.server.middleware.ts"],"sourcesContent":["export * from './routesV3.server';\nexport * from './sockets/socket.server.index';\nexport * from './sockets/socket.server.middleware';\n","/**\n * routesV3.server.ts\n * -----------------------------------------------------------------------------\n * Bind an Express router/app to a `finalize(...)` registry of AnyLeafs.\n * - Fully typed handlers (params/query/body/output)\n * - Zod parsing + optional output validation\n * - buildCtx runs as a middleware *first*, before all other middlewares\n * - Global, per-route, and cfg-derived middlewares (auth, uploads)\n * - Helper to warn about unimplemented routes\n * - DX helpers to use `ctx` in any middleware with proper types\n */\n\nimport { AnyLeaf, FileField, HttpMethod, InferBody, InferOutput, InferParams, InferQuery, MethodCfg } from '@emeryld/rrroutes-contract';\nimport type * as express from 'express';\nimport type { RequestHandler, Router } from 'express';\nimport type { ZodType } from 'zod';\n\n\n\n/** Shape expected from optional logger implementations. */\nexport type LoggerLike = {\n info?: (...args: any[]) => void;\n warn?: (...args: any[]) => void;\n error?: (...args: any[]) => void;\n debug?: (...args: any[]) => void;\n verbose?: (...args: any[]) => void;\n system?: (...args: any[]) => void;\n log?: (...args: any[]) => void;\n};\n\ntype RoutesLoggerCarrier = {\n routesLogger?: LoggerLike;\n};\n\ntype CtxWithRoutesLogger<Ctx> = Ctx & RoutesLoggerCarrier;\n\n// Debug logging --------------------------------------------------------------\nexport type RouteServerDebugMode = 'minimal' | 'complete';\n\ntype RouteServerDebugEventBase = {\n /** Optional logical name assigned via `RouteDef.debug?.debugName` (or `RouteDef.debugName`). */\n name?: string;\n};\n\nexport type RouteServerDebugEvent =\n | (RouteServerDebugEventBase & {\n type: 'request';\n stage: 'start' | 'success' | 'error';\n method: Uppercase<HttpMethod>;\n path: string;\n url: string;\n durationMs?: number;\n params?: unknown;\n query?: unknown;\n body?: unknown;\n output?: unknown;\n error?: unknown;\n })\n | (RouteServerDebugEventBase & {\n type: 'register';\n method: Uppercase<HttpMethod>;\n path: string;\n })\n | (RouteServerDebugEventBase & {\n type: 'buildCtx';\n stage: 'start' | 'success' | 'error';\n method: Uppercase<HttpMethod>;\n path: string;\n url: string;\n durationMs?: number;\n error?: unknown;\n })\n | (RouteServerDebugEventBase & {\n type: 'handler';\n stage: 'start' | 'success' | 'error';\n method: Uppercase<HttpMethod>;\n path: string;\n durationMs?: number;\n params?: unknown;\n query?: unknown;\n body?: unknown;\n output?: unknown;\n error?: unknown;\n });\n\nexport type RouteServerDebugLogger = (event: RouteServerDebugEvent) => void;\n\n/**\n * Configure server-side debug logging.\n * - Use booleans or `'minimal'/'complete'` for quick toggles.\n * - Pass a custom logger function to redirect structured events.\n * - Provide a map to enable specific event types, opt into verbose payload logging, or restrict logs via `only`.\n */\nexport type RouteServerDebugOptions<Names extends string = string> = RouteServerDebugToggleOptions<Names>;\n\n/**\n * Fine-grained toggle map for server debug logging.\n * Enable individual event types, opt into verbose payload logging, override the logger, or restrict to named routes.\n * Use `RouteDef.debug?.debugName` (or the deprecated `RouteDef.debugName`) to set the name that `only` will match against.\n */\nexport type RouteServerDebugToggleOptions<Names extends string = string> = Partial<\n Record<RouteServerDebugEvent['type'], boolean>\n> & {\n verbose?: boolean;\n logger?: RouteServerDebugLogger;\n only?: Names[];\n};\n\n/**\n * Per-route debug overrides. Same toggles as `RouteServerDebugOptions`, but limited to a single route\n * and therefore replaces the `only` filter with a local `debugName`.\n */\nexport type RouteDefDebugOptions<Names extends string = string> = Omit<\n RouteServerDebugToggleOptions<Names>,\n 'only'\n> & {\n debugName?: Names;\n};\n\nconst serverDebugEventTypes: RouteServerDebugEvent['type'][] = [\n 'register',\n 'request',\n 'buildCtx',\n 'handler',\n];\n\ntype ServerDebugEmitter<Names extends string> = {\n emit: (event: RouteServerDebugEvent, name?: Names) => void;\n mode: RouteServerDebugMode;\n};\n\nconst noopServerEmit = () => {};\n\nfunction createServerDebugEmitter<Names extends string>(\n option?: RouteServerDebugOptions<Names>,\n): ServerDebugEmitter<Names> {\n const disabled: ServerDebugEmitter<Names> = { emit: noopServerEmit, mode: 'minimal' };\n if (!option) return disabled;\n\n if (typeof option === 'object') {\n const toggles = option as RouteServerDebugToggleOptions<Names>;\n const verbose = Boolean(toggles.verbose);\n const enabledTypes = serverDebugEventTypes.filter((type) => toggles[type]);\n if (enabledTypes.length === 0) {\n return { emit: noopServerEmit, mode: verbose ? 'complete' : 'minimal' };\n }\n const whitelist = new Set<RouteServerDebugEvent['type']>(enabledTypes);\n const onlySet =\n toggles.only && toggles.only.length > 0 ? new Set<Names>(toggles.only) : undefined;\n const logger = toggles.logger;\n const emit: ServerDebugEmitter<Names>['emit'] = (event, name) => {\n if (!whitelist.has(event.type) || !logger) return;\n if (onlySet && (!name || !onlySet.has(name))) return;\n logger(name ? { ...event, name } : event);\n };\n return { emit, mode: verbose ? 'complete' : 'minimal' };\n }\n\n return disabled;\n}\n\n// ──────────────────────────────────────────────────────────────────────────────\n// Keys + leaf helpers (derive keys from byKey to avoid template-literal pitfalls)\n// ──────────────────────────────────────────────────────────────────────────────\n\n/** Keys like \"GET /v1/foo\" that *actually* exist in the registry */\nexport type KeysOfRegistry<R extends { byKey: Record<string, AnyLeaf> }> = keyof R['byKey'] &\n string;\n\ntype MethodFromKey<K extends string> = K extends `${infer M} ${string}` ? Lowercase<M> : never;\ntype PathFromKey<K extends string> = K extends `${string} ${infer P}` ? P : never;\n\n/** Given a registry and a key, pick the exact leaf for that method+path */\nexport type LeafFromKey<R extends { all: readonly AnyLeaf[] }, K extends string> = Extract<\n R['all'][number],\n { method: MethodFromKey<K> & HttpMethod; path: PathFromKey<K> }\n>;\n\n/** Optional-ify types if your core returns `never` when a schema isn't defined */\ntype Maybe<T> = [T] extends [never] ? undefined : T;\n\n/** Typed params argument exposed to handlers. */\nexport type ArgParams<L extends AnyLeaf> = Maybe<InferParams<L>>;\n/** Typed query argument exposed to handlers. */\nexport type ArgQuery<L extends AnyLeaf> = Maybe<InferQuery<L>>;\n/** Typed body argument exposed to handlers. */\nexport type ArgBody<L extends AnyLeaf> = Maybe<InferBody<L>>;\n\n/**\n * Convenience to compute a `\"METHOD /path\"` key from a leaf.\n * @param leaf Leaf describing the route.\n * @returns Uppercase method + path key.\n */\nexport const keyOf = (leaf: AnyLeaf) => `${leaf.method.toUpperCase()} ${leaf.path}` as const;\n\n// ──────────────────────────────────────────────────────────────────────────────\n// Context typing & DX helpers (so ctx is usable in *any* middleware)\n// ──────────────────────────────────────────────────────────────────────────────\n\n/**\n * Unique symbol used to stash ctx on res.locals.\n * (Symbols are safer than string keys against collisions.)\n */\nexport const CTX_SYMBOL: unique symbol = Symbol.for('typedLeaves.ctx');\n\nconst AFTER_HANDLER_NEXT_SYMBOL: unique symbol = Symbol.for('typedLeaves.afterHandlerNext');\n\nfunction setAfterHandlerNext(res: express.Response, value: boolean) {\n (res.locals as any)[AFTER_HANDLER_NEXT_SYMBOL] = value;\n}\n\nfunction handlerInvokedNext(res: express.Response): boolean {\n return Boolean((res.locals as any)[AFTER_HANDLER_NEXT_SYMBOL]);\n}\n\n/** Response type that *has* a ctx on locals for DX in middlewares */\nexport type ResponseWithCtx<Ctx> =\n // Replace locals with an intersection that guarantees CTX_SYMBOL exists\n Omit<express.Response, 'locals'> & {\n locals: express.Response['locals'] & { [CTX_SYMBOL]: CtxWithRoutesLogger<Ctx> };\n };\n\n/** A middleware signature that can *use* ctx via `res.locals[CTX_SYMBOL]` */\nexport type CtxRequestHandler<Ctx> = (args: {\n req: express.Request;\n res: express.Response;\n next: express.NextFunction;\n ctx: CtxWithRoutesLogger<Ctx>;\n}) => any;\n\n/**\n * Safely read ctx from any Response.\n * @param res Express response whose locals contain the ctx symbol.\n * @returns Strongly typed context object.\n */\nexport function getCtx<Ctx = unknown>(res: express.Response): CtxWithRoutesLogger<Ctx> {\n return (res.locals as any)[CTX_SYMBOL] as CtxWithRoutesLogger<Ctx>;\n}\n\n/**\n * Wrap a ctx-typed middleware to a plain RequestHandler (for arrays, etc.).\n * @param mw Middleware that expects a typed response with ctx available.\n * @returns Standard Express request handler.\n */\nfunction adaptCtxMw<Ctx>(mw: CtxRequestHandler<Ctx>): RequestHandler {\n return (req, res, next) => {\n try {\n const result = mw({ req, res, next, ctx: getCtx<Ctx>(res) });\n if (result && typeof (result as Promise<unknown>).then === 'function') {\n return (result as Promise<unknown>).catch((err) => next(err));\n }\n return result as any;\n } catch (err) {\n next(err as any);\n return undefined;\n }\n };\n}\n\nfunction adaptAfterMw<Ctx>(mw: CtxRequestHandler<Ctx>): RequestHandler {\n const adapted = adaptCtxMw<Ctx>(mw);\n return (req: express.Request, res: express.Response, next: express.NextFunction) => {\n if (!handlerInvokedNext(res)) {\n next();\n return;\n }\n adapted(req, res, next);\n };\n}\n\nfunction mapAfterMiddleware<Ctx>(mws?: Array<CtxRequestHandler<Ctx>>): RequestHandler[] {\n return (mws ?? []).map((mw) => adaptAfterMw<Ctx>(mw));\n}\n\nfunction logHandlerDebugWithRoutesLogger(\n logger: LoggerLike | undefined,\n event: RouteServerDebugEvent,\n) {\n if (!logger || event.type !== 'handler') return;\n const payload: [string, RouteServerDebugEvent] = [\n `[rrroutes-server][handler:${event.stage}] ${event.method} ${event.path}`,\n event,\n ];\n if (event.stage === 'error') {\n (\n logger.error ??\n logger.warn ??\n logger.debug ??\n logger.info ??\n logger.log ??\n logger.system\n )?.call(logger, ...payload);\n return;\n }\n (\n logger.debug ??\n logger.verbose ??\n logger.info ??\n logger.log ??\n logger.system\n )?.call(logger, ...payload);\n}\n\n// ──────────────────────────────────────────────────────────────────────────────\n// Controller types — object form only (simpler, clearer typings)\n// ──────────────────────────────────────────────────────────────────────────────\n\n/** Typed route handler for a specific leaf */\nexport type Handler<L extends AnyLeaf, Ctx = unknown> = (args: {\n req: express.Request;\n res: express.Response;\n next: express.NextFunction;\n ctx: CtxWithRoutesLogger<Ctx>;\n params: ArgParams<L>;\n query: ArgQuery<L>;\n body: ArgBody<L>;\n}) => Promise<InferOutput<L>> | InferOutput<L>;\n\n/** Route definition for one key */\nexport type RouteDef<L extends AnyLeaf, Ctx = unknown, Names extends string = string> = {\n /** Middlewares before the handler (run after buildCtx/global/derived) */\n use?: Array<CtxRequestHandler<Ctx>>;\n /** Middlewares after the handler *if* it calls next() */\n after?: Array<CtxRequestHandler<Ctx>>;\n /** Your business logic */\n handler: Handler<L, Ctx>;\n /**\n * Optional per-route debug overrides. When provided, these replace the global debug options.\n */\n debug?: RouteDefDebugOptions<Names>;\n /**\n * Optional logical name used for debug filtering. Prefer `debug.debugName`; this field remains for backwards compatibility.\n */\n debugName?: Names;\n};\n\n/** Map of registry keys -> route defs */\nexport type ControllerMap<\n R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> },\n Ctx = unknown,\n Names extends string = string,\n> = {\n [P in KeysOfRegistry<R>]: RouteDef<LeafFromKey<R, P>, Ctx, Names>;\n};\n\nexport type PartialControllerMap<\n R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> },\n Ctx = unknown,\n Names extends string = string,\n> = Partial<ControllerMap<R, Ctx, Names>>;\n\n// ──────────────────────────────────────────────────────────────────────────────\n/** Options + derivation helpers */\n// ──────────────────────────────────────────────────────────────────────────────\n\nexport type RouteServerConfig<Ctx = unknown, Names extends string = string> = {\n /**\n * Build a request-scoped context. We wrap this in a middleware that runs\n * *first* (before global/derived/route middlewares), and stash it on\n * `res.locals[CTX_SYMBOL]` so *all* later middlewares can use it.\n * You can optionally include `routesLogger` to override handler debug logging per request.\n */\n buildCtx: (\n req: express.Request,\n res: express.Response,\n ) => CtxWithRoutesLogger<Ctx> | Promise<CtxWithRoutesLogger<Ctx>>;\n\n /**\n * Grouped global middlewares that run *before* or *after* the handler for every route.\n */\n globalMiddleware?: {\n before?: Array<CtxRequestHandler<Ctx>>;\n after?: Array<CtxRequestHandler<Ctx>>;\n };\n\n /**\n * Derive middleware from MethodCfg.\n * - `upload` runs when cfg.bodyFiles has entries\n */\n fromCfg?: {\n upload?: (files: FileField[] | undefined, leaf: AnyLeaf) => RequestHandler[];\n };\n\n /** Validate handler return values with outputSchema (default: true) */\n validateOutput?: boolean;\n\n /** Custom responder (default: res.json(data)) */\n send?: (res: express.Response, data: unknown) => void;\n\n /** Optional logger hooks */\n logger?: LoggerLike;\n\n /**\n * Optional debug logging for the request lifecycle.\n * Supports booleans/modes/loggers, or a toggle map with per-event enabling, verbose payload logging,\n * and `only` filters tied to `RouteDef.debug?.debugName` (or the deprecated `RouteDef.debugName`).\n */\n debug?: RouteServerDebugOptions<Names>;\n};\n\n/** Default JSON responder (typed to avoid implicit-any diagnostics) */\nconst defaultSend: (res: express.Response, data: unknown) => void = (res, data) => {\n res.json(data as any);\n};\n\n// ──────────────────────────────────────────────────────────────────────────────\n// Core builder\n// ──────────────────────────────────────────────────────────────────────────────\n\nconst REGISTERED_ROUTES_SYMBOL = Symbol.for('routesV3.registeredRoutes');\n\ntype RegisteredRouteStore = Set<string>;\n\n/**\n * Retrieve or initialize the shared store of registered route keys.\n * @param router Express router/application that carries previously registered keys.\n * @returns Set of string keys describing registered routes.\n */\nfunction getRegisteredRouteStore(router: Router): RegisteredRouteStore {\n const existing = (router as any)[REGISTERED_ROUTES_SYMBOL] as RegisteredRouteStore | undefined;\n if (existing) return existing;\n const store: RegisteredRouteStore = new Set();\n (router as any)[REGISTERED_ROUTES_SYMBOL] = store;\n return store;\n}\n\n/**\n * Inspect the Express layer stack to discover already-registered routes.\n * @param appOrRouter Express application or router to inspect.\n * @returns All keys in the form `\"METHOD /path\"` found on the stack.\n */\nfunction collectRoutesFromStack(appOrRouter: Router): string[] {\n const result: string[] = [];\n const stack: any[] =\n (appOrRouter as any).stack ??\n ((appOrRouter as any)._router ? (appOrRouter as any)._router.stack : undefined) ??\n [];\n\n if (!Array.isArray(stack)) return result;\n\n for (const layer of stack) {\n const route = layer && layer.route;\n if (!route) continue;\n\n const paths = Array.isArray(route.path) ? route.path : [route.path];\n const methodEntries = Object.entries(route.methods ?? {}).filter(([, enabled]) => enabled);\n\n for (const path of paths) {\n for (const [method] of methodEntries) {\n result.push(`${method.toUpperCase()} ${path}`);\n }\n }\n }\n\n return result;\n}\n\n/** Runtime helpers returned by `createRRRoute`. */\nexport type RouteServer<Ctx = unknown, Names extends string = string> = {\n router: Router;\n register<L extends AnyLeaf>(leaf: L, def: RouteDef<L, Ctx, Names>): void;\n registerControllers<R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> }>(\n registry: R,\n controllers: PartialControllerMap<R, Ctx, Names>,\n ): void;\n warnMissingControllers<R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> }>(\n registry: R,\n logger: { warn: (...args: any[]) => void },\n ): void;\n getRegisteredKeys(): string[];\n};\n\n/**\n * Create an Express binding helper that keeps routes and controllers in sync.\n * @param router Express router or app to register handlers on.\n * @param config Optional configuration controlling ctx building, auth, uploads, etc.\n * @returns Object with helpers to register controllers and inspect registered keys.\n */\nexport function createRRRoute<Ctx = unknown, Names extends string = string>(\n router: Router,\n config: RouteServerConfig<Ctx, Names>,\n): RouteServer<Ctx, Names> {\n const validateOutput = config.validateOutput ?? true;\n const send = config.send ?? defaultSend;\n const logger = config.logger;\n const { emit: defaultEmitDebug, mode: defaultDebugMode } =\n createServerDebugEmitter<Names>(config.debug);\n const decorateDebugEvent = <T extends RouteServerDebugEvent>(\n isVerbose: boolean,\n event: T,\n details?: Partial<RouteServerDebugEvent>,\n ): RouteServerDebugEvent => {\n if (!isVerbose || !details) return event;\n return { ...event, ...details } as RouteServerDebugEvent;\n };\n\n const globalBeforeMws = [ ...(config.globalMiddleware?.before ?? [])].map(\n (mw) => adaptCtxMw<Ctx>(mw),\n );\n const globalAfterMws = mapAfterMiddleware<Ctx>(config.globalMiddleware?.after);\n const registered = getRegisteredRouteStore(router);\n\n const buildDerived = (leaf: AnyLeaf): RequestHandler[] => {\n const derived: RequestHandler[] = [];\n if (\n config.fromCfg?.upload &&\n Array.isArray(leaf.cfg.bodyFiles) &&\n leaf.cfg.bodyFiles.length > 0\n ) {\n derived.push(...config.fromCfg.upload(leaf.cfg.bodyFiles, leaf));\n }\n\n return derived;\n };\n\n /** Register a single leaf/controller pair on the underlying router. */\n function register<L extends AnyLeaf>(leaf: L, def: RouteDef<L, Ctx, Names>) {\n const method = leaf.method as HttpMethod;\n const methodUpper = method.toUpperCase() as Uppercase<HttpMethod>;\n const path = leaf.path as string;\n const key = keyOf(leaf);\n const defDebug = def.debug;\n let debugName = def.debugName as Names | undefined;\n let routeDebugEmitter: ServerDebugEmitter<Names> | undefined;\n if (defDebug) {\n const { debugName: overrideName, ...rest } = defDebug;\n const hasOverrides = Object.values(rest).some((value) => value !== undefined);\n if (hasOverrides) {\n routeDebugEmitter = createServerDebugEmitter<Names>(\n rest as RouteServerDebugOptions<Names>,\n );\n }\n debugName = (overrideName ?? debugName) as Names | undefined;\n }\n const activeEmit = routeDebugEmitter?.emit ?? defaultEmitDebug;\n const activeDebugMode = routeDebugEmitter?.mode ?? defaultDebugMode;\n const emit = (event: RouteServerDebugEvent) => activeEmit(event, debugName);\n const isVerboseDebug = activeDebugMode === 'complete';\n emit({ type: 'register', method: methodUpper, path });\n\n const routeSpecific = (def?.use ?? []).map((mw) => adaptCtxMw<Ctx>(mw));\n const derived = buildDerived(leaf);\n const ctxMw: RequestHandler = async (req, res, next) => {\n const requestUrl = req.originalUrl ?? path;\n const startedAt = Date.now();\n emit({ type: 'buildCtx', stage: 'start', method: methodUpper, path, url: requestUrl });\n try {\n const ctx = await config.buildCtx(req, res);\n (res.locals as any)[CTX_SYMBOL] = ctx;\n emit({\n type: 'buildCtx',\n stage: 'success',\n method: methodUpper,\n path,\n url: requestUrl,\n durationMs: Date.now() - startedAt,\n });\n next();\n } catch (err) {\n emit({\n type: 'buildCtx',\n stage: 'error',\n method: methodUpper,\n path,\n url: requestUrl,\n durationMs: Date.now() - startedAt,\n error: err,\n });\n logger?.error?.('buildCtx error', err);\n next(err as any);\n }\n };\n const before: RequestHandler[] = [ctxMw, ...globalBeforeMws, ...derived, ...routeSpecific];\n\n const wrapped: RequestHandler = async (req, res, next) => {\n const requestUrl = req.originalUrl.split('?')[0] ?? path;\n const startedAt = Date.now();\n emit({ type: 'request', stage: 'start', method: methodUpper, path, url: requestUrl });\n let params: ArgParams<L> | undefined;\n let query: ArgQuery<L> | undefined;\n let body: ArgBody<L> | undefined;\n let responsePayload: InferOutput<L> | undefined;\n let hasResponsePayload = false;\n setAfterHandlerNext(res, false);\n let handlerCalledNext = false;\n const downstreamNext: express.NextFunction = (err?: any) => {\n handlerCalledNext = true;\n setAfterHandlerNext(res, true);\n next(err);\n };\n\n logger?.info?.(`${methodUpper}@${path} (${requestUrl})`);\n const ctx = (res.locals as any)[CTX_SYMBOL] as CtxWithRoutesLogger<Ctx>;\n const ctxRoutesLogger = ctx?.routesLogger;\n const emitWithCtx = (\n event: RouteServerDebugEvent,\n details?: Partial<RouteServerDebugEvent>,\n ) => {\n const decorated = decorateDebugEvent(isVerboseDebug, event, details);\n if (decorated.type === 'handler' && ctxRoutesLogger) {\n logHandlerDebugWithRoutesLogger(ctxRoutesLogger, decorated);\n }else{\n emit(decorated);\n }\n };\n try {\n params = (\n leaf.cfg.paramsSchema\n ? (leaf.cfg.paramsSchema as ZodType).parse(req.params)\n : Object.keys(req.params || {}).length\n ? (req.params as any)\n : undefined\n ) as ArgParams<L>;\n\n try {\n query = leaf.cfg.querySchema\n ? (leaf.cfg.querySchema as ZodType).parse(req.query)\n : Object.keys(req.query || {}).length\n ? (req.query as any)\n : undefined;\n } catch (e) {\n logger?.error?.('Query parsing error', {\n path,\n method: methodUpper,\n error: e,\n raw: JSON.stringify(req.query),\n });\n throw e;\n }\n\n body = (\n leaf.cfg.bodySchema\n ? (leaf.cfg.bodySchema as ZodType).parse(req.body)\n : req.body !== undefined\n ? (req.body as any)\n : undefined\n ) as ArgBody<L>;\n\n logger?.verbose?.(`${methodUpper}@${path} (${requestUrl})`, {\n params,\n query,\n body,\n });\n\n const handlerStartedAt = Date.now();\n emitWithCtx(\n {\n type: 'handler',\n stage: 'start',\n method: methodUpper,\n path,\n },\n isVerboseDebug ? { params, query, body } : undefined,\n );\n\n let result;\n try {\n result = await def.handler({\n req,\n res,\n next: downstreamNext,\n ctx,\n params: params as ArgParams<L>,\n query: query as ArgQuery<L>,\n body: body as ArgBody<L>,\n });\n emitWithCtx(\n {\n type: 'handler',\n stage: 'success',\n method: methodUpper,\n path,\n durationMs: Date.now() - handlerStartedAt,\n },\n isVerboseDebug\n ? {\n params,\n query,\n body,\n ...(result !== undefined ? { output: result } : {}),\n }\n : undefined,\n );\n } catch (e) {\n emitWithCtx(\n {\n type: 'handler',\n stage: 'error',\n method: methodUpper,\n path,\n durationMs: Date.now() - handlerStartedAt,\n error: e,\n },\n isVerboseDebug ? { params, query, body } : undefined,\n );\n logger?.error?.('Handler error', e);\n throw e;\n }\n\n if (!res.headersSent) {\n if (result !== undefined) {\n const out =\n validateOutput && leaf.cfg.outputSchema\n ? (leaf.cfg.outputSchema as ZodType).parse(result)\n : result;\n responsePayload = out as InferOutput<L>;\n hasResponsePayload = true;\n logger?.verbose?.(`${methodUpper}@${path} result`, out);\n send(res, out);\n } else if (!handlerCalledNext) {\n next();\n }\n }\n\n emitWithCtx(\n {\n type: 'request',\n stage: 'success',\n method: methodUpper,\n path,\n url: requestUrl,\n durationMs: Date.now() - startedAt,\n },\n isVerboseDebug\n ? {\n params,\n query,\n body,\n ...(hasResponsePayload ? { output: responsePayload } : {}),\n }\n : undefined,\n );\n } catch (err) {\n emitWithCtx(\n {\n type: 'request',\n stage: 'error',\n method: methodUpper,\n path,\n url: requestUrl,\n durationMs: Date.now() - startedAt,\n error: err,\n },\n isVerboseDebug ? { params, query, body } : undefined,\n );\n logger?.error?.('Route error', err);\n next(err as any);\n }\n };\n\n const after = [...mapAfterMiddleware<Ctx>(def?.after), ...globalAfterMws];\n (router as any)[method](path, ...before, wrapped, ...after);\n registered.add(key);\n }\n\n /**\n * Register controller definitions for the provided keys.\n * @param registry Finalized registry of leaves.\n * @param controllers Partial controller map keyed by `\"METHOD /path\"`.\n */\n function registerControllers<\n R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> },\n >(registry: R, controllers: PartialControllerMap<R, Ctx, Names>) {\n (Object.keys(controllers) as Array<KeysOfRegistry<R>>).forEach((key) => {\n const leaf = registry.byKey[key] as unknown as LeafFromKey<R, typeof key> | undefined;\n if (!leaf) {\n logger?.warn?.(`No leaf found for controller key: ${key}. Not registering route.`);\n return;\n }\n const def = controllers[key];\n if (!def) return;\n register(leaf as LeafFromKey<R, typeof key>, def);\n });\n }\n\n /**\n * Warn about leaves that do not have a registered controller.\n * @param registry Finalized registry of leaves.\n * @param warnLogger Logger used for warning output.\n */\n function warnMissing<R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> }>(\n registry: R,\n warnLogger: { warn: (...args: any[]) => void },\n ) {\n const registeredFromStore = new Set<string>(Array.from(registered));\n if (registeredFromStore.size === 0) {\n collectRoutesFromStack(router).forEach((key) => registeredFromStore.add(key));\n }\n for (const leaf of registry.all) {\n const key = keyOf(leaf);\n if (!registeredFromStore.has(key)) {\n warnLogger.warn(`No controller registered for route: ${key}`);\n }\n }\n }\n\n return {\n router,\n register,\n registerControllers,\n warnMissingControllers: warnMissing,\n getRegisteredKeys: () => Array.from(registered),\n };\n}\n\n/**\n * Bind only the controllers that are present in the provided map.\n * @param router Express router or app.\n * @param registry Finalized registry produced by `finalize(...)`.\n * @param controllers Partial map of controllers keyed by `\"METHOD /path\"`.\n * @param config Optional route server configuration.\n * @returns The same router instance for chaining.\n */\nexport function bindExpressRoutes<\n R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> },\n Ctx = unknown,\n Names extends string = string,\n>(\n router: Router,\n registry: R,\n controllers: PartialControllerMap<R, Ctx, Names>,\n config: RouteServerConfig<Ctx, Names>,\n) {\n const server = createRRRoute<Ctx, Names>(router, config);\n server.registerControllers(registry, controllers);\n return router;\n}\n\n/**\n * Bind controllers for every leaf. Missing entries fail at compile time.\n * @param router Express router or app.\n * @param registry Finalized registry produced by `finalize(...)`.\n * @param controllers Complete map of controllers keyed by `\"METHOD /path\"`.\n * @param config Optional route server configuration.\n * @returns The same router instance for chaining.\n */\nexport function bindAll<\n R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> },\n Ctx = unknown,\n Names extends string = string,\n>(\n router: Router,\n registry: R,\n controllers: { [K in KeysOfRegistry<R>]: RouteDef<LeafFromKey<R, K>, Ctx, Names> },\n config: RouteServerConfig<Ctx, Names>,\n) {\n const server = createRRRoute<Ctx, Names>(router, config);\n server.registerControllers(registry, controllers);\n return router;\n}\n\n// ──────────────────────────────────────────────────────────────────────────────\n// DX helpers\n// ──────────────────────────────────────────────────────────────────────────────\n\n/**\n * Helper for great IntelliSense when authoring controller maps.\n * @returns Function that enforces key names while preserving partial flexibility.\n */\nexport const defineControllers =\n <\n R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> },\n Ctx = unknown,\n Names extends string = string,\n >() =>\n <M extends PartialControllerMap<R, Ctx, Names>>(m: M) =>\n m;\n\n/**\n * Warn about leaves that don't have controllers.\n * Call this during startup to surface missing routes.\n * @param router Express router or app to inspect.\n * @param registry Finalized registry produced by `finalize(...)`.\n * @param logger Logger where warnings are emitted.\n */\nexport function warnMissingControllers<\n R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> },\n>(router: Router, registry: R, logger: { warn: (...args: any[]) => void }) {\n const registeredStore = (router as any)[REGISTERED_ROUTES_SYMBOL] as Set<string> | undefined;\n const initial = registeredStore ? Array.from(registeredStore) : collectRoutesFromStack(router);\n const registeredKeys = new Set<string>(initial);\n\n for (const leaf of registry.all) {\n const k = keyOf(leaf);\n if (!registeredKeys.has(k)) {\n logger.warn(`No controller registered for route: ${k}`);\n }\n }\n}\n","// socket.server.debug.ts\nimport type { IncomingHttpHeaders } from 'http';\n\nexport type SocketServerConfigSnapshot = {\n url?: string;\n transport?: string;\n protocol?: string;\n address?: string;\n issued?: number;\n time?: string;\n query?: Record<string, unknown>;\n auth?: Record<string, unknown>;\n headers?: IncomingHttpHeaders;\n};\n\nexport type SocketServerLifecycleStage =\n | 'server_init'\n | 'connection_listener_installed'\n | 'connection_init'\n | 'connection_handlers_attached'\n | 'connection_cleanup'\n | 'destroy_start'\n | 'destroy_complete'\n | 'connection_cleanup_fallback';\n\nexport type SocketServerHeartbeatPhase = 'ping' | 'pong' | 'skip';\n\nexport type SocketServerDebugEvent =\n | {\n type: 'register';\n action: 'register' | 'unregister';\n event: string;\n msg?:string;\n }\n | {\n type: 'handler';\n phase: 'receive' | 'validation_error' | 'handler_success' | 'handler_error';\n event: string;\n socketId?: string;\n nsp?: string;\n rooms?: string[];\n raw?: unknown;\n issues?: any[];\n error?: unknown;\n details?: Record<string, unknown>;\n }\n | {\n type: 'emit';\n event: string;\n rooms: string[];\n envelope?: unknown;\n error?: {\n reason: string;\n message?: string;\n issues?: unknown;\n };\n metadata?:unknown;\n }\n | {\n type: 'rooms';\n action: 'join' | 'leave';\n rooms?: string|string[];\n socketId: string;\n phase?:string;\n payload?: unknown;\n issues?: any[];\n }\n | {\n type: 'heartbeat';\n phase: SocketServerHeartbeatPhase;\n socketId: string;\n payload?: unknown;\n issues?: any[];\n error?: boolean;\n details?: Record<string, unknown>;\n }\n | {\n type: 'config';\n socketId: string;\n nsp: string;\n snapshot: SocketServerConfigSnapshot;\n }\n | {\n type: 'lifecycle';\n stage: SocketServerLifecycleStage;\n socketId?: string;\n nsp?: string;\n details?: Record<string, unknown>;\n };\n\nexport type SocketDebugOptions = {\n verbose?: boolean;\n /** filters event-based logs (register/handler/emit) by event name */\n only?: string[];\n logger?: (e: SocketServerDebugEvent) => void;\n} & {\n [P in SocketServerDebugEvent['type']]?: boolean;\n};\n\nexport function createDebugger(options?: SocketDebugOptions) {\n const debug = options ?? {};\n\n return (maybeEvent: string | null, e: SocketServerDebugEvent) => {\n if (!debug.logger) return;\n if (!debug[e.type]) return;\n\n // only filter applies to event-shaped logs\n if (\n debug.only &&\n maybeEvent &&\n (e.type === 'register' || e.type === 'handler' || e.type === 'emit') &&\n !debug.only.includes(maybeEvent)\n ) {\n return;\n }\n\n debug.logger(e);\n };\n}\n","// socket.server.sys.ts\nimport type { Socket } from 'socket.io';\nimport { z } from 'zod';\nimport type { EventMap, Payload, SocketConnectionConfig, SysEventName } from '@emeryld/rrroutes-contract';\nimport type {\n SocketServerConfigSnapshot,\n SocketServerDebugEvent,\n} from './socket.server.debug';\nimport type { HandlerCtxNoAck } from './socket.server.types';\n\nexport type SocketConnectionHelper<Events extends EventMap> = {\n emit<K extends keyof Events & string>(\n event: K,\n payload: Payload<Events, K>,\n metadata?: Record<string, unknown>,\n onAck?: (ack: unknown) => void\n ): void;\n};\n\n\n/** Heartbeat configuration that is not tied to payload shapes (which live in sys event schemas). */\nexport type HeartbeatServerOptions = {\n /** Enable/disable built-in heartbeat handling. Defaults to true. */\n enabled?: boolean;\n};\n\nexport type SysServerEventMap<\n Config extends SocketConnectionConfig = SocketConnectionConfig,\n Events extends EventMap = EventMap,\n> = {\n 'sys:connect': (args: {\n socket: Socket;\n helper: SocketConnectionHelper<Events>;\n /**\n * Call to proceed with the default connection initialization\n * (attaches heartbeat, join, leave and disconnect handlers).\n */\n complete: () => void;\n }) => void | Promise<void>;\n\n 'sys:disconnect': (args: {\n socket: Socket;\n helper: SocketConnectionHelper<Events>;\n /** cleans up all handlers */\n cleanup: () => void;\n reason: string;\n }) => void | Promise<void>;\n\n 'sys:ping': (\n args:{\n socket: Socket;\n helper: SocketConnectionHelper<Events>;\n ping: z.output<Config['pingPayload']>,\n ctx: HandlerCtxNoAck}\n ) => z.output<Config['pongPayload']> | Promise<z.output<Config['pongPayload']>>;\n\n 'sys:room_join': (args: {\n socket: Socket;\n helper: SocketConnectionHelper<Events>;\n rooms: string[];\n meta: z.output<Config['joinMetaMessage']>;\n join: (room: string) => Promise<void>;\n }) => void | Promise<void>;\n\n 'sys:room_leave': (args: {\n socket: Socket;\n helper: SocketConnectionHelper<Events>;\n rooms: string[];\n meta: z.output<Config['leaveMetaMessage']>;\n leave: (room: string) => Promise<void>;\n }) => void | Promise<void>;\n};\n\n\nconst normalizeError = (error: unknown) => {\n if (error instanceof Error) {\n return { name: error.name, message: error.message };\n }\n if (typeof error === 'string') return { message: error };\n return { message: 'Unknown error' };\n};\n\nconst roomValueSchema = z.union([z.string(), z.array(z.string())]);\n\nconst buildRoomPayloadSchema = <Meta extends z.ZodTypeAny>(metaSchema: Meta) =>\n z.object({\n rooms: roomValueSchema,\n meta: metaSchema,\n });\n\ntype DebugFn = (maybeEvent: string | null, e: SocketServerDebugEvent) => void;\n\nconst toArray = (rooms?: string[] | string): string[] =>\n rooms == null ? [] : Array.isArray(rooms) ? rooms : [rooms];\n\nconst snapshotSocketConfig = (socket: Socket): SocketServerConfigSnapshot => {\n const conn = socket.conn as { transport?: { name?: string }; protocol?: string | number; remoteAddress?: string } | undefined;\n const protocol = conn?.protocol;\n return {\n url: socket.handshake.url,\n transport: conn?.transport?.name,\n protocol: protocol != null ? String(protocol) : undefined,\n address: conn?.remoteAddress ?? socket.handshake.address,\n issued: socket.handshake.issued,\n time: socket.handshake.time,\n query: socket.handshake.query as Record<string, unknown>,\n auth: socket.handshake.auth as Record<string, unknown>,\n headers: socket.handshake.headers,\n };\n};\n\nexport function createBuiltInConnectionHandlers<\n C extends SocketConnectionConfig,\n Events extends EventMap,\n>(opts: {\n heartbeat?: HeartbeatServerOptions;\n sys: SysServerEventMap<C, Events>;\n dbg: DebugFn;\n config: C;\n createCtx: (socket: Socket) => HandlerCtxNoAck;\n debugVerbose?: boolean;\n createHelper: (socket: Socket) => SocketConnectionHelper<Events>;\n}) {\n const { heartbeat, sys, dbg, config, createCtx, debugVerbose, createHelper } = opts;\n\n const roomJoinEvent: SysEventName = 'sys:room_join';\n const roomLeaveEvent: SysEventName = 'sys:room_leave';\n const pingEvent: SysEventName = 'sys:ping';\n const pongEvent: SysEventName = 'sys:pong';\n const heartbeatEnabled = heartbeat?.enabled !== false;\n\n const joinPayloadSchema = buildRoomPayloadSchema(config.joinMetaMessage);\n const leavePayloadSchema = buildRoomPayloadSchema(config.leaveMetaMessage);\n const pingPayloadSchema = config.pingPayload as C['pingPayload'];\n const pongPayloadSchema = config.pongPayload as C['pongPayload'];\n\n const sysEvents = sys;\n const getSysEvent = <K extends keyof SysServerEventMap<C, Events> & SysEventName>(name: K) =>\n sysEvents[name];\n\n /** Track per-socket teardown for built-in handlers to ensure explicit cleanup on destroy(). */\n const socketTeardowns = new WeakMap<Socket, (reason:string) => void>();\n\n const builtInConnectionListener = (socket: Socket) => {\n const helper = createHelper(socket);\n dbg(null, {\n type: 'lifecycle',\n stage: 'connection_init',\n socketId: socket.id,\n nsp: socket.nsp.name,\n details: {\n rooms: Array.from(socket.rooms),\n handshakeIssued: socket.handshake.issued,\n },\n });\n dbg(null, {\n type: 'config',\n socketId: socket.id,\n nsp: socket.nsp.name,\n snapshot: snapshotSocketConfig(socket),\n });\n\n const defaultConnect = () => {\n const includeRaw = debugVerbose === true;\n\n // built-in room handlers (wrapped with sys:room_join / sys:room_leave)\n const joinHandler = async (msg: unknown) => {\n dbg(roomJoinEvent, {\n type: 'rooms',\n phase: 'receive',\n action:'join',\n socketId: socket.id,\n payload: msg,\n });\n const parsed = joinPayloadSchema.safeParse(msg);\n\n if (!parsed.success) {\n socket.emit(`${roomJoinEvent}:error`, {\n eventName: roomJoinEvent,\n issues: parsed.error.issues,\n });\n dbg(roomJoinEvent, {\n type: 'rooms',\n action:'join',\n phase:'validation_error',\n socketId: socket.id,\n issues: parsed.error.issues,\n payload: msg,\n });\n return;\n }\n const list = toArray(parsed.data.rooms);\n\n const join = async (room: string) => {\n await socket.join(room);\n dbg(null, { type: 'rooms', action: 'join', rooms:room, socketId: socket.id });\n };\n\n const run = async () => {\n await getSysEvent('sys:room_join')({\n socket,\n helper,\n rooms: list,\n meta: parsed.data.meta as z.output<C['joinMetaMessage']>,\n join,\n });\n };\n\n try {\n await run();\n } catch (error) {\n socket.emit(`${roomJoinEvent}:error`, { error: normalizeError(error) });\n dbg(roomJoinEvent, {\n type: 'rooms',\n action:'join',\n phase: 'handler_error',\n payload: includeRaw ? { rooms: list, meta: parsed.data.meta } : undefined,\n socketId: socket.id,\n issues:[error],\n });\n }\n };\n\n const leaveHandler = async (msg: unknown) => {\n dbg(roomLeaveEvent, {\n type: 'rooms',\n phase: 'receive',\n action:'leave',\n socketId: socket.id,\n payload: msg ,\n });\n const parsed = leavePayloadSchema.safeParse(msg);\n if (!parsed.success) {\n socket.emit(`${roomLeaveEvent}:error`, {\n eventName: roomLeaveEvent,\n issues: parsed.error.issues,\n });\n dbg(roomJoinEvent, {\n type: 'rooms',\n action:'leave',\n phase:'validation_error',\n socketId: socket.id,\n issues: parsed.error.issues,\n payload: msg ,\n });\n return;\n }\n\n const list = toArray(parsed.data.rooms);\n\n const leave = async (room: string) => {\n await socket.leave(room);\n dbg(null, { type: 'rooms', action: 'leave', rooms:room, socketId: socket.id });\n };\n\n const run = async () => {\n await getSysEvent('sys:room_leave')({\n socket,\n helper,\n rooms: list,\n meta: parsed.data.meta as z.output<C['leaveMetaMessage']>,\n leave,\n });\n };\n\n try {\n await run();\n } catch (error) {\n socket.emit(`${roomLeaveEvent}:error`, { error: normalizeError(error) });\n dbg(roomJoinEvent, {\n type: 'rooms',\n phase: 'handler_error',\n payload: { rooms: list, meta: parsed.data.meta } ,\n socketId: socket.id,\n issues:[error],\n action:'join'\n });\n }\n };\n\n // heartbeat, wrapped with sys:ping/sys:pong\n const pingHandler = async (msg: unknown) => {\n if (!heartbeatEnabled) {\n dbg(null, {\n type: 'heartbeat',\n phase: 'skip',\n socketId: socket.id,\n details: { reason: 'heartbeat_disabled' },\n error: false,\n });\n return;\n }\n\n const parsedPing = pingPayloadSchema.safeParse(msg);\n if (!parsedPing.success) {\n socket.emit(`${pingEvent}:error`, {\n eventName: pingEvent,\n issues: parsedPing.error.issues,\n });\n dbg(null, {\n type: 'heartbeat',\n phase: 'ping',\n socketId: socket.id,\n payload: includeRaw ? msg : undefined,\n issues: parsedPing.error.issues,\n error: true,\n details: { step: 'parse' },\n });\n return;\n }\n const ctx = createCtx(socket);\n\n dbg(null, {\n type: 'heartbeat',\n phase: 'ping',\n socketId: socket.id,\n payload: parsedPing.data,\n error: false,\n });\n\n let pongPayload: z.output<C['pongPayload']>;\n try {\n pongPayload = await getSysEvent('sys:ping')({ping:parsedPing.data, ctx, socket, helper});\n } catch (error) {\n socket.emit(`${pingEvent}:error`, { error: normalizeError(error) });\n dbg(null, {\n type: 'heartbeat',\n phase: 'ping',\n socketId: socket.id,\n payload: parsedPing.data,\n error: true,\n details: { step: 'sys_handler_error' },\n });\n return;\n }\n\n const parsedPong = pongPayloadSchema.safeParse(pongPayload);\n if (!parsedPong.success) {\n socket.emit(`${pongEvent}:error`, {\n eventName: pongEvent,\n issues: parsedPong.error.issues,\n });\n dbg(null, {\n type: 'heartbeat',\n phase: 'pong',\n socketId: socket.id,\n payload: includeRaw ? pongPayload : undefined,\n issues: parsedPong.error.issues,\n error: true,\n details: { step: 'parse' },\n });\n return;\n }\n socket.emit(pongEvent, parsedPong.data);\n dbg(null, {\n type: 'heartbeat',\n phase: 'pong',\n socketId: socket.id,\n payload: parsedPong.data,\n error: false,\n });\n };\n\n // attach built-in handlers\n socket.on(roomJoinEvent, joinHandler);\n socket.on(roomLeaveEvent, leaveHandler);\n if (heartbeatEnabled) {\n socket.on(pingEvent, pingHandler);\n }\n\n const cleanup = (reason:string) => {\n dbg(null, {\n type: 'lifecycle',\n stage: 'connection_cleanup',\n socketId: socket.id,\n nsp: socket.nsp.name,\n details: { reason },\n });\n socket.off(roomJoinEvent, joinHandler);\n socket.off(roomLeaveEvent, leaveHandler);\n if (heartbeatEnabled) {\n socket.off(pingEvent, pingHandler);\n }\n };\n\n socketTeardowns.set(socket, cleanup);\n dbg(null, {\n type: 'lifecycle',\n stage: 'connection_handlers_attached',\n socketId: socket.id,\n nsp: socket.nsp.name,\n details: {\n heartbeatEnabled,\n joinEvent: roomJoinEvent,\n leaveEvent: roomLeaveEvent,\n pingEvent: heartbeatEnabled ? pingEvent : undefined,\n },\n });\n\n socket.once('disconnect', (reason) => {\n dbg('sys:disconnect', {\n type: 'lifecycle',\n stage:'connection_cleanup',\n nsp: socket.nsp.name,\n socketId: socket.id,\n details: { reason },\n });\n const defaultDisconnect = () => {\n cleanup(reason);\n socketTeardowns.delete(socket);\n };\n getSysEvent('sys:disconnect')({\n socket,\n helper,\n reason: String(reason),\n cleanup: defaultDisconnect,\n });\n });\n };\n getSysEvent('sys:connect')({\n socket,\n helper,\n complete: defaultConnect,\n });\n };\n\n return {\n builtInConnectionListener,\n socketTeardowns,\n roomJoinEvent,\n roomLeaveEvent,\n pingEvent,\n };\n}\n","// socket.server.index.ts\nimport { Server, Socket } from 'socket.io';\nimport { z } from 'zod';\nimport type { EventMap, SocketConnectionConfig, Payload } from '@emeryld/rrroutes-contract';\nimport { createDebugger } from './socket.server.debug';\nimport type { SocketServerDebugEvent, SocketDebugOptions } from './socket.server.debug';\nimport { createBuiltInConnectionHandlers } from './socket.server.sys';\nimport type {\n HeartbeatServerOptions,\n SocketConnectionHelper,\n SysServerEventMap,\n} from './socket.server.sys';\nimport type { HandlerCtx, HandlerCtxNoAck } from './socket.server.types';\n\nconst createBaseHandlerCtx = (socket: Socket): HandlerCtxNoAck => ({\n sentAt: new Date(),\n socket,\n socketId: socket.id,\n nsp: socket.nsp.name,\n rooms: Array.from(socket.rooms),\n user: socket.data?.user,\n scopes: socket.data?.scopes,\n});\n\nconst normalizeError = (error: unknown, verbose?: boolean) => {\n if (error instanceof Error) {\n return {\n name: error.name,\n message: error.message,\n stack: verbose ? error.stack : undefined,\n };\n }\n if (typeof error === 'string') return { message: error };\n if (typeof error === 'object' && error !== null) {\n return verbose ? error : { message: 'Unknown error' };\n }\n return { message: String(error) };\n};\n\nexport interface SocketConnection<T extends EventMap> {\n on<K extends keyof T & string>(\n eventName: K,\n handler: (payload: Payload<T, K>, ctx: HandlerCtx) => void | Promise<void>\n ): () => void;\n\n off<K extends keyof T & string>(eventName: K): void;\n\n emit<K extends keyof T & string>(\n eventName: K,\n payload: Payload<T, K>,\n toRooms?: string[] | string,\n metadata?: Record<string, unknown>,\n onAck?: (ack: unknown) => void\n ): void;\n\n /** Dispose all listeners, timers, and room memberships created by this instance. */\n destroy(): void;\n}\n\nexport function createSocketConnections<\n T extends EventMap,\n TConfig extends SocketConnectionConfig = SocketConnectionConfig,\n>(\n io: Server,\n events: T,\n opts: {\n debug?: SocketDebugOptions;\n heartbeat?: HeartbeatServerOptions;\n /** System event customization (connect / disconnect / ping / pong / room join/leave) */\n sys: SysServerEventMap<TConfig, T>;\n config: TConfig;\n }\n): SocketConnection<T> {\n const dbg = createDebugger(opts?.debug);\n const socketConfig = opts.config;\n const heartbeatEnabled = opts?.heartbeat?.enabled !== false;\n const eventNames = Object.keys(events);\n dbg(null, {\n type: 'lifecycle',\n stage: 'server_init',\n details: {\n prefinedEvents: eventNames,\n heartbeatEnabled,\n path: io?.path(),\n namespaces: Array.from(io._nsps.keys()),\n transport: io?._opts.transports,\n sysEvents: Object.keys(opts.sys ?? {}),\n },\n });\n\n const getSchema = <K extends keyof T & string>(k: K) => events[k].message;\n const toArray = (rooms?: string[] | string): string[] =>\n rooms == null ? [] : Array.isArray(rooms) ? rooms : [rooms];\n const emitToTargets = <K extends keyof T & string>(\n eventName: K,\n payload: Payload<T, K>,\n targets: string[],\n metadata?: Record<string, unknown>,\n ) => {\n const schema = getSchema(eventName);\n const check = schema.safeParse(payload);\n if (!check.success) {\n dbg(String(eventName), {\n type: 'emit',\n event: String(eventName),\n rooms: targets,\n ...(opts?.debug?.verbose ? { attemptedPayload: payload } : {}),\n error: {\n reason: 'invalid_payload',\n message: check.error.message,\n issues: check.error.issues\n },\n metadata\n });\n throw new Error(`Invalid payload for \"${String(eventName)}\": ${check.error.message}`);\n }\n\n const envelope = {\n eventName,\n sentAt: new Date(),\n sentTo: targets,\n data: check.data as Payload<T, K>,\n metadata: metadata ?? {},\n };\n\n if (targets.length === 0) io.emit(String(eventName), envelope);\n else if (targets.length === 1) {\n const sid = targets[0]!;\n const sock = io.sockets.sockets.get(sid as any);\n if (sock) {\n sock.emit(String(eventName), envelope);\n }else{\n io.to(targets).emit(String(eventName), envelope);\n }\n } else{\n io.to(targets).emit(String(eventName), envelope);\n }\n\n dbg(String(eventName), {\n type: 'emit',\n event: String(eventName),\n rooms: targets,\n envelope: opts?.debug?.verbose ? envelope : undefined,\n });\n };\n const createSocketHelper = (socket: Socket): SocketConnectionHelper<T> => ({\n emit<K extends keyof T & string>(\n eventName: K,\n payload: Payload<T, K>,\n metadata?: Record<string, unknown>,\n ) {\n emitToTargets(eventName, payload, [socket.id], metadata);\n },\n });\n\n // registrations\n const registrations = new Map<\n string,\n Set<{\n connectionListener: (socket: Socket) => void;\n socketListeners: WeakMap<Socket, (raw: unknown) => void>;\n }>\n >();\n\n const addRegistration = (\n eventName: string,\n reg: {\n connectionListener: (socket: Socket) => void;\n socketListeners: WeakMap<Socket, (raw: unknown) => void>;\n }\n ) => {\n let set = registrations.get(eventName);\n if (!set) {\n set = new Set();\n registrations.set(eventName, set);\n }\n set.add(reg);\n };\n\n const removeAllForEvent = (eventName: string) => {\n const set = registrations.get(eventName);\n if (!set) {\n dbg(null, {\n type: 'register',\n event: eventName,\n action: 'unregister',\nmsg:'no handlers registered'\n });\n return;\n }\n for (const reg of set) {\n io.off('connection', reg.connectionListener);\n for (const socket of io.sockets.sockets.values()) {\n const wrapped = reg.socketListeners.get(socket);\n if (wrapped) socket.off(String(eventName), wrapped);\n }\n }\n registrations.delete(eventName);\n dbg(eventName, { type: 'register', action: 'unregister', event: eventName, msg:'unregistered' });\n };\n\n const {\n builtInConnectionListener,\n socketTeardowns,\n roomJoinEvent,\n roomLeaveEvent,\n pingEvent,\n } = createBuiltInConnectionHandlers<TConfig, T>({\n heartbeat: opts?.heartbeat,\n sys: opts.sys,\n dbg,\n config: socketConfig,\n createCtx: createBaseHandlerCtx,\n debugVerbose: opts?.debug?.verbose === true,\n createHelper: createSocketHelper,\n });\n\n // install built-in connection listener\n io.on('connection', builtInConnectionListener);\n\n const conn = {\n on<K extends keyof T & string>(\n eventName: K,\n handler: (payload: Payload<T, K>, ctx: HandlerCtx) => void | Promise<void>\n ): () => void {\n const socketListeners = new WeakMap<Socket, (raw: unknown) => void>();\n\n const connectionListener = (socket: Socket) => {\n const wrapped = async (raw: unknown) => {\n const schema = getSchema(eventName);\n const parsed = schema.safeParse(raw);\n\n const ctx = createBaseHandlerCtx(socket);\n\n dbg(String(eventName), {\n type: 'handler',\n phase: 'receive',\n event: String(eventName),\n socketId: ctx.socketId,\n nsp: ctx.nsp,\n rooms: ctx.rooms,\n raw: opts?.debug?.verbose ? raw : undefined,\n });\n\n if (!parsed.success) {\n socket.emit(`${String(eventName)}:error`, {\n eventName,\n sentAt: ctx.sentAt,\n issues: parsed.error.issues,\n });\n dbg(String(eventName), {\n type: 'handler',\n phase: 'validation_error',\n event: String(eventName),\n socketId: ctx.socketId,\n nsp: ctx.nsp,\n issues: parsed.error.issues,\n });\n return;\n }\n\n try {\n await handler(parsed.data as Payload<T, K>, ctx);\n dbg(String(eventName), {\n type: 'handler',\n phase: 'handler_success',\n event: String(eventName),\n socketId: ctx.socketId,\n nsp: ctx.nsp,\n rooms: ctx.rooms,\n });\n } catch (error) {\n dbg(String(eventName), {\n type: 'handler',\n phase: 'handler_error',\n event: String(eventName),\n socketId: ctx.socketId,\n nsp: ctx.nsp,\n rooms: ctx.rooms,\n error,\n });\n socket.emit(`${String(eventName)}:error`, {\n eventName,\n sentAt: ctx.sentAt,\n error: normalizeError(error, opts?.debug?.verbose),\n });\n }\n };\n\n socketListeners.set(socket, wrapped);\n socket.on(String(eventName), wrapped);\n socket.once('disconnect', () => {\n const w = socketListeners.get(socket);\n if (w) socket.off(String(eventName), w);\n });\n };\n\n io.on('connection', connectionListener);\n addRegistration(String(eventName), { connectionListener, socketListeners });\n dbg(String(eventName), {\n type: 'register',\n action: 'register',\n event: String(eventName),\n });\n\n return () => {\n const set = registrations.get(String(eventName));\n if (!set) {\n dbg(null, {\n type: 'register',\n action:'unregister',\n event: String(eventName),msg:`No registration under ${eventName}`\n });\n return;\n }\n for (const reg of Array.from(set)) {\n if (reg.connectionListener === connectionListener) {\n io.off('connection', reg.connectionListener);\n for (const socket of io.sockets.sockets.values()) {\n const wrapped = reg.socketListeners.get(socket);\n if (wrapped) socket.off(String(eventName), wrapped);\n }\n set.delete(reg);\n break;\n }\n }\n if (set.size === 0) registrations.delete(String(eventName));\n dbg(String(eventName), {\n type: 'register',\n action: 'unregister',\n event: String(eventName),\n });\n };\n },\n\n off<K extends keyof T & string>(eventName: K): void {\n removeAllForEvent(String(eventName));\n },\n\n emit<K extends keyof T & string>(\n eventName: K,\n payload: Payload<T, K>,\n rooms?: string[] | string,\n metadata?: Record<string, unknown>,\n ): void {\n const targets = toArray(rooms);\n emitToTargets(eventName, payload, targets, metadata);\n },\n\n destroy(): void {\n dbg(null, {\n type: 'lifecycle',\n stage: 'destroy_start',\n details: {\n socketCount: io.sockets.sockets.size,\n registrationCount: registrations.size,\n },\n });\n // 1) Remove built-in connection listener so no new sockets get handlers\n io.off('connection', builtInConnectionListener);\n\n // 2) Cleanup built-in handlers for all current sockets and leave rooms\n for (const socket of io.sockets.sockets.values()) {\n const cleanup = socketTeardowns.get(socket);\n if (cleanup) {\n cleanup('destroy');\n socketTeardowns.delete(socket);\n } else {\n dbg(null, {\n type: 'lifecycle',\n stage: 'connection_cleanup_fallback',\n socketId: socket.id,\n nsp: socket.nsp.name,\n details: { reason: 'teardown_missing' },\n });\n // Fallback if socket was attached before map population\n try {\n socket.removeAllListeners(roomJoinEvent);\n socket.removeAllListeners(roomLeaveEvent);\n socket.removeAllListeners(pingEvent);\n } catch {\n // noop\n }\n }\n }\n\n // 3) Remove all user-registered event listeners and their connection hooks\n for (const eventName of Array.from(registrations.keys())) {\n removeAllForEvent(eventName);\n }\n\n // 4) Defensive: clear any residual maps\n registrations.clear();\n dbg(null, {\n type: 'lifecycle',\n stage: 'destroy_complete',\n details: {\n socketCount: io.sockets.sockets.size,\n registrationCount: registrations.size,\n },\n });\n },\n } as const satisfies SocketConnection<T>;\n\n return conn;\n}\n\nexport type { EventMap, Payload };\nexport type { HandlerCtx } from './socket.server.types';\nexport type {\n SocketServerDebugEvent,\n SocketDebugOptions,\n SocketServerConfigSnapshot,\n SocketServerLifecycleStage,\n SocketServerHeartbeatPhase,\n} from './socket.server.debug';\nexport type {\n HeartbeatServerOptions,\n SocketConnectionHelper,\n SysServerEventMap,\n} from './socket.server.sys';\n","import type { IncomingHttpHeaders } from 'http';\nimport type { Socket } from 'socket.io';\n\nexport type ConnectionMiddlewareStage = 'incoming';\n\nexport type ConnectionMiddlewareContext = {\n socketId?: string;\n nsp?: string;\n rooms: string[];\n user?: unknown;\n scopes?: string[];\n address?: string;\n transport?: string;\n protocol?: string;\n handshake: {\n url?: string;\n issued?: number;\n time?: string;\n query?: Record<string, unknown>;\n auth?: Record<string, unknown>;\n headers?: IncomingHttpHeaders;\n };\n};\n\nexport type ConnectionMiddlewareEvent = {\n type: 'connection';\n stage: ConnectionMiddlewareStage;\n timestamp: Date;\n context: ConnectionMiddlewareContext;\n};\n\nexport type ConnectionLoggingMiddlewareOptions = {\n /**\n * Custom logger invoked with the structured event.\n * Defaults to console.info.\n */\n logger?: (event: ConnectionMiddlewareEvent) => void;\n /**\n * Include raw headers from the handshake. Defaults to false to avoid leaking PII.\n */\n includeHeaders?: boolean;\n /**\n * List of auth keys that should be redacted (case-insensitive). Defaults to ['authorization'].\n */\n redactAuthKeys?: string[];\n};\n\nconst defaultRedactedValue = '[REDACTED]';\n\nconst defaultLogger = (event: ConnectionMiddlewareEvent) => {\n const {\n stage,\n context: { socketId, nsp, address, transport, handshake },\n } = event;\n // eslint-disable-next-line no-console\n console.info('[socket-connection]', {\n stage,\n socketId,\n nsp,\n address,\n transport,\n url: handshake.url,\n query: handshake.query,\n auth: handshake.auth,\n });\n};\n\nconst redactAuth = (\n auth: Record<string, unknown> | undefined,\n redactKeys: Set<string>\n): Record<string, unknown> | undefined => {\n if (!auth) return undefined;\n if (redactKeys.size === 0) return auth;\n\n const clone: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(auth)) {\n const normalizedKey = key.toLowerCase();\n clone[key] = redactKeys.has(normalizedKey) ? defaultRedactedValue : value;\n }\n return clone;\n};\n\nconst buildContext = (\n socket: Socket,\n includeHeaders: boolean,\n redactKeys: Set<string>\n): ConnectionMiddlewareContext => {\n const conn = socket.conn as\n | {\n remoteAddress?: string;\n transport?: { name?: string };\n protocol?: string | number;\n }\n | undefined;\n\n const handshake = socket.handshake ?? {};\n\n const protocolValue = conn?.protocol;\n\n return {\n socketId: socket.id,\n nsp: socket.nsp?.name,\n rooms: Array.from(socket.rooms ?? []),\n user: (socket.data as any)?.user,\n scopes: (socket.data as any)?.scopes,\n address: conn?.remoteAddress ?? (handshake as any).address,\n transport: conn?.transport?.name,\n protocol: protocolValue != null ? String(protocolValue) : undefined,\n handshake: {\n url: handshake.url,\n issued: handshake.issued,\n time: handshake.time,\n query: handshake.query as Record<string, unknown>,\n auth: redactAuth(handshake.auth as Record<string, unknown>, redactKeys),\n headers: includeHeaders ? (handshake.headers as IncomingHttpHeaders) : undefined,\n },\n };\n};\n\nexport const createConnectionLoggingMiddleware = (\n options: ConnectionLoggingMiddlewareOptions = {}\n) => {\n const logger = options.logger ?? defaultLogger;\n const includeHeaders = options.includeHeaders ?? false;\n const redactKeys = new Set(\n (options.redactAuthKeys ?? ['authorization', 'token']).map((key) => key.toLowerCase())\n );\n\n return (socket: Socket, next: (err?: Error) => void) => {\n const context = buildContext(socket, includeHeaders, redactKeys);\n logger({\n type: 'connection',\n stage: 'incoming',\n timestamp: new Date(),\n context,\n });\n next();\n };\n};\n\nexport type ConnectionLoggingMiddleware = ReturnType<typeof createConnectionLoggingMiddleware>;\n"],"mappings":"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","names":["normalizeError","toArray"]}
package/dist/index.js CHANGED
@@ -461,12 +461,6 @@ function createBuiltInConnectionHandlers(opts) {
461
461
  snapshot: snapshotSocketConfig(socket)
462
462
  });
463
463
  const defaultConnect = () => {
464
- dbg("sys:connect", {
465
- type: "handler",
466
- phase: "handler_success",
467
- event: "sys:connect",
468
- socketId: socket.id
469
- });
470
464
  const includeRaw = debugVerbose === true;
471
465
  const joinHandler = async (msg) => {
472
466
  dbg(roomJoinEvent, {
@@ -474,7 +468,7 @@ function createBuiltInConnectionHandlers(opts) {
474
468
  phase: "receive",
475
469
  action: "join",
476
470
  socketId: socket.id,
477
- payload: includeRaw ? msg : void 0
471
+ payload: msg
478
472
  });
479
473
  const parsed = joinPayloadSchema.safeParse(msg);
480
474
  if (!parsed.success) {
@@ -488,7 +482,7 @@ function createBuiltInConnectionHandlers(opts) {
488
482
  phase: "validation_error",
489
483
  socketId: socket.id,
490
484
  issues: parsed.error.issues,
491
- payload: includeRaw ? msg : void 0
485
+ payload: msg
492
486
  });
493
487
  return;
494
488
  }
@@ -526,7 +520,7 @@ function createBuiltInConnectionHandlers(opts) {
526
520
  phase: "receive",
527
521
  action: "leave",
528
522
  socketId: socket.id,
529
- payload: includeRaw ? msg : void 0
523
+ payload: msg
530
524
  });
531
525
  const parsed = leavePayloadSchema.safeParse(msg);
532
526
  if (!parsed.success) {
@@ -540,14 +534,14 @@ function createBuiltInConnectionHandlers(opts) {
540
534
  phase: "validation_error",
541
535
  socketId: socket.id,
542
536
  issues: parsed.error.issues,
543
- payload: includeRaw ? msg : void 0
537
+ payload: msg
544
538
  });
545
539
  return;
546
540
  }
547
541
  const list = toArray(parsed.data.rooms);
548
542
  const leave = async (room) => {
549
- dbg(null, { type: "rooms", action: "leave", rooms: room, socketId: socket.id });
550
543
  await socket.leave(room);
544
+ dbg(null, { type: "rooms", action: "leave", rooms: room, socketId: socket.id });
551
545
  };
552
546
  const run = async () => {
553
547
  await getSysEvent("sys:room_leave")({
@@ -565,7 +559,7 @@ function createBuiltInConnectionHandlers(opts) {
565
559
  dbg(roomJoinEvent, {
566
560
  type: "rooms",
567
561
  phase: "handler_error",
568
- payload: includeRaw ? { rooms: list, meta: parsed.data.meta } : void 0,
562
+ payload: { rooms: list, meta: parsed.data.meta },
569
563
  socketId: socket.id,
570
564
  issues: [error],
571
565
  action: "join"
@@ -654,13 +648,13 @@ function createBuiltInConnectionHandlers(opts) {
654
648
  if (heartbeatEnabled) {
655
649
  socket.on(pingEvent, pingHandler);
656
650
  }
657
- const cleanup = () => {
651
+ const cleanup = (reason) => {
658
652
  dbg(null, {
659
653
  type: "lifecycle",
660
654
  stage: "connection_cleanup",
661
655
  socketId: socket.id,
662
656
  nsp: socket.nsp.name,
663
- details: { reason: "teardown" }
657
+ details: { reason }
664
658
  });
665
659
  socket.off(roomJoinEvent, joinHandler);
666
660
  socket.off(roomLeaveEvent, leaveHandler);
@@ -687,10 +681,10 @@ function createBuiltInConnectionHandlers(opts) {
687
681
  stage: "connection_cleanup",
688
682
  nsp: socket.nsp.name,
689
683
  socketId: socket.id,
690
- details: { reason: String(reason) }
684
+ details: { reason }
691
685
  });
692
686
  const defaultDisconnect = () => {
693
- cleanup();
687
+ cleanup(reason);
694
688
  socketTeardowns.delete(socket);
695
689
  };
696
690
  getSysEvent("sys:disconnect")({
@@ -749,7 +743,7 @@ function createSocketConnections(io, events, opts) {
749
743
  type: "lifecycle",
750
744
  stage: "server_init",
751
745
  details: {
752
- eventCount: eventNames,
746
+ prefinedEvents: eventNames,
753
747
  heartbeatEnabled,
754
748
  path: io?.path(),
755
749
  namespaces: Array.from(io._nsps.keys()),
@@ -978,7 +972,7 @@ function createSocketConnections(io, events, opts) {
978
972
  for (const socket of io.sockets.sockets.values()) {
979
973
  const cleanup = socketTeardowns.get(socket);
980
974
  if (cleanup) {
981
- cleanup();
975
+ cleanup("destroy");
982
976
  socketTeardowns.delete(socket);
983
977
  } else {
984
978
  dbg(null, {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/routesV3.server.ts","../src/sockets/socket.server.debug.ts","../src/sockets/socket.server.sys.ts","../src/sockets/socket.server.index.ts","../src/sockets/socket.server.middleware.ts"],"sourcesContent":["/**\n * routesV3.server.ts\n * -----------------------------------------------------------------------------\n * Bind an Express router/app to a `finalize(...)` registry of AnyLeafs.\n * - Fully typed handlers (params/query/body/output)\n * - Zod parsing + optional output validation\n * - buildCtx runs as a middleware *first*, before all other middlewares\n * - Global, per-route, and cfg-derived middlewares (auth, uploads)\n * - Helper to warn about unimplemented routes\n * - DX helpers to use `ctx` in any middleware with proper types\n */\n\nimport { AnyLeaf, FileField, HttpMethod, InferBody, InferOutput, InferParams, InferQuery, MethodCfg } from '@emeryld/rrroutes-contract';\nimport type * as express from 'express';\nimport type { RequestHandler, Router } from 'express';\nimport type { ZodType } from 'zod';\n\n\n\n/** Shape expected from optional logger implementations. */\nexport type LoggerLike = {\n info?: (...args: any[]) => void;\n warn?: (...args: any[]) => void;\n error?: (...args: any[]) => void;\n debug?: (...args: any[]) => void;\n verbose?: (...args: any[]) => void;\n system?: (...args: any[]) => void;\n log?: (...args: any[]) => void;\n};\n\ntype RoutesLoggerCarrier = {\n routesLogger?: LoggerLike;\n};\n\ntype CtxWithRoutesLogger<Ctx> = Ctx & RoutesLoggerCarrier;\n\n// Debug logging --------------------------------------------------------------\nexport type RouteServerDebugMode = 'minimal' | 'complete';\n\ntype RouteServerDebugEventBase = {\n /** Optional logical name assigned via `RouteDef.debug?.debugName` (or `RouteDef.debugName`). */\n name?: string;\n};\n\nexport type RouteServerDebugEvent =\n | (RouteServerDebugEventBase & {\n type: 'request';\n stage: 'start' | 'success' | 'error';\n method: Uppercase<HttpMethod>;\n path: string;\n url: string;\n durationMs?: number;\n params?: unknown;\n query?: unknown;\n body?: unknown;\n output?: unknown;\n error?: unknown;\n })\n | (RouteServerDebugEventBase & {\n type: 'register';\n method: Uppercase<HttpMethod>;\n path: string;\n })\n | (RouteServerDebugEventBase & {\n type: 'buildCtx';\n stage: 'start' | 'success' | 'error';\n method: Uppercase<HttpMethod>;\n path: string;\n url: string;\n durationMs?: number;\n error?: unknown;\n })\n | (RouteServerDebugEventBase & {\n type: 'handler';\n stage: 'start' | 'success' | 'error';\n method: Uppercase<HttpMethod>;\n path: string;\n durationMs?: number;\n params?: unknown;\n query?: unknown;\n body?: unknown;\n output?: unknown;\n error?: unknown;\n });\n\nexport type RouteServerDebugLogger = (event: RouteServerDebugEvent) => void;\n\n/**\n * Configure server-side debug logging.\n * - Use booleans or `'minimal'/'complete'` for quick toggles.\n * - Pass a custom logger function to redirect structured events.\n * - Provide a map to enable specific event types, opt into verbose payload logging, or restrict logs via `only`.\n */\nexport type RouteServerDebugOptions<Names extends string = string> = RouteServerDebugToggleOptions<Names>;\n\n/**\n * Fine-grained toggle map for server debug logging.\n * Enable individual event types, opt into verbose payload logging, override the logger, or restrict to named routes.\n * Use `RouteDef.debug?.debugName` (or the deprecated `RouteDef.debugName`) to set the name that `only` will match against.\n */\nexport type RouteServerDebugToggleOptions<Names extends string = string> = Partial<\n Record<RouteServerDebugEvent['type'], boolean>\n> & {\n verbose?: boolean;\n logger?: RouteServerDebugLogger;\n only?: Names[];\n};\n\n/**\n * Per-route debug overrides. Same toggles as `RouteServerDebugOptions`, but limited to a single route\n * and therefore replaces the `only` filter with a local `debugName`.\n */\nexport type RouteDefDebugOptions<Names extends string = string> = Omit<\n RouteServerDebugToggleOptions<Names>,\n 'only'\n> & {\n debugName?: Names;\n};\n\nconst serverDebugEventTypes: RouteServerDebugEvent['type'][] = [\n 'register',\n 'request',\n 'buildCtx',\n 'handler',\n];\n\ntype ServerDebugEmitter<Names extends string> = {\n emit: (event: RouteServerDebugEvent, name?: Names) => void;\n mode: RouteServerDebugMode;\n};\n\nconst noopServerEmit = () => {};\n\nfunction createServerDebugEmitter<Names extends string>(\n option?: RouteServerDebugOptions<Names>,\n): ServerDebugEmitter<Names> {\n const disabled: ServerDebugEmitter<Names> = { emit: noopServerEmit, mode: 'minimal' };\n if (!option) return disabled;\n\n if (typeof option === 'object') {\n const toggles = option as RouteServerDebugToggleOptions<Names>;\n const verbose = Boolean(toggles.verbose);\n const enabledTypes = serverDebugEventTypes.filter((type) => toggles[type]);\n if (enabledTypes.length === 0) {\n return { emit: noopServerEmit, mode: verbose ? 'complete' : 'minimal' };\n }\n const whitelist = new Set<RouteServerDebugEvent['type']>(enabledTypes);\n const onlySet =\n toggles.only && toggles.only.length > 0 ? new Set<Names>(toggles.only) : undefined;\n const logger = toggles.logger;\n const emit: ServerDebugEmitter<Names>['emit'] = (event, name) => {\n if (!whitelist.has(event.type) || !logger) return;\n if (onlySet && (!name || !onlySet.has(name))) return;\n logger(name ? { ...event, name } : event);\n };\n return { emit, mode: verbose ? 'complete' : 'minimal' };\n }\n\n return disabled;\n}\n\n// ──────────────────────────────────────────────────────────────────────────────\n// Keys + leaf helpers (derive keys from byKey to avoid template-literal pitfalls)\n// ──────────────────────────────────────────────────────────────────────────────\n\n/** Keys like \"GET /v1/foo\" that *actually* exist in the registry */\nexport type KeysOfRegistry<R extends { byKey: Record<string, AnyLeaf> }> = keyof R['byKey'] &\n string;\n\ntype MethodFromKey<K extends string> = K extends `${infer M} ${string}` ? Lowercase<M> : never;\ntype PathFromKey<K extends string> = K extends `${string} ${infer P}` ? P : never;\n\n/** Given a registry and a key, pick the exact leaf for that method+path */\nexport type LeafFromKey<R extends { all: readonly AnyLeaf[] }, K extends string> = Extract<\n R['all'][number],\n { method: MethodFromKey<K> & HttpMethod; path: PathFromKey<K> }\n>;\n\n/** Optional-ify types if your core returns `never` when a schema isn't defined */\ntype Maybe<T> = [T] extends [never] ? undefined : T;\n\n/** Typed params argument exposed to handlers. */\nexport type ArgParams<L extends AnyLeaf> = Maybe<InferParams<L>>;\n/** Typed query argument exposed to handlers. */\nexport type ArgQuery<L extends AnyLeaf> = Maybe<InferQuery<L>>;\n/** Typed body argument exposed to handlers. */\nexport type ArgBody<L extends AnyLeaf> = Maybe<InferBody<L>>;\n\n/**\n * Convenience to compute a `\"METHOD /path\"` key from a leaf.\n * @param leaf Leaf describing the route.\n * @returns Uppercase method + path key.\n */\nexport const keyOf = (leaf: AnyLeaf) => `${leaf.method.toUpperCase()} ${leaf.path}` as const;\n\n// ──────────────────────────────────────────────────────────────────────────────\n// Context typing & DX helpers (so ctx is usable in *any* middleware)\n// ──────────────────────────────────────────────────────────────────────────────\n\n/**\n * Unique symbol used to stash ctx on res.locals.\n * (Symbols are safer than string keys against collisions.)\n */\nexport const CTX_SYMBOL: unique symbol = Symbol.for('typedLeaves.ctx');\n\nconst AFTER_HANDLER_NEXT_SYMBOL: unique symbol = Symbol.for('typedLeaves.afterHandlerNext');\n\nfunction setAfterHandlerNext(res: express.Response, value: boolean) {\n (res.locals as any)[AFTER_HANDLER_NEXT_SYMBOL] = value;\n}\n\nfunction handlerInvokedNext(res: express.Response): boolean {\n return Boolean((res.locals as any)[AFTER_HANDLER_NEXT_SYMBOL]);\n}\n\n/** Response type that *has* a ctx on locals for DX in middlewares */\nexport type ResponseWithCtx<Ctx> =\n // Replace locals with an intersection that guarantees CTX_SYMBOL exists\n Omit<express.Response, 'locals'> & {\n locals: express.Response['locals'] & { [CTX_SYMBOL]: CtxWithRoutesLogger<Ctx> };\n };\n\n/** A middleware signature that can *use* ctx via `res.locals[CTX_SYMBOL]` */\nexport type CtxRequestHandler<Ctx> = (args: {\n req: express.Request;\n res: express.Response;\n next: express.NextFunction;\n ctx: CtxWithRoutesLogger<Ctx>;\n}) => any;\n\n/**\n * Safely read ctx from any Response.\n * @param res Express response whose locals contain the ctx symbol.\n * @returns Strongly typed context object.\n */\nexport function getCtx<Ctx = unknown>(res: express.Response): CtxWithRoutesLogger<Ctx> {\n return (res.locals as any)[CTX_SYMBOL] as CtxWithRoutesLogger<Ctx>;\n}\n\n/**\n * Wrap a ctx-typed middleware to a plain RequestHandler (for arrays, etc.).\n * @param mw Middleware that expects a typed response with ctx available.\n * @returns Standard Express request handler.\n */\nfunction adaptCtxMw<Ctx>(mw: CtxRequestHandler<Ctx>): RequestHandler {\n return (req, res, next) => {\n try {\n const result = mw({ req, res, next, ctx: getCtx<Ctx>(res) });\n if (result && typeof (result as Promise<unknown>).then === 'function') {\n return (result as Promise<unknown>).catch((err) => next(err));\n }\n return result as any;\n } catch (err) {\n next(err as any);\n return undefined;\n }\n };\n}\n\nfunction adaptAfterMw<Ctx>(mw: CtxRequestHandler<Ctx>): RequestHandler {\n const adapted = adaptCtxMw<Ctx>(mw);\n return (req: express.Request, res: express.Response, next: express.NextFunction) => {\n if (!handlerInvokedNext(res)) {\n next();\n return;\n }\n adapted(req, res, next);\n };\n}\n\nfunction mapAfterMiddleware<Ctx>(mws?: Array<CtxRequestHandler<Ctx>>): RequestHandler[] {\n return (mws ?? []).map((mw) => adaptAfterMw<Ctx>(mw));\n}\n\nfunction logHandlerDebugWithRoutesLogger(\n logger: LoggerLike | undefined,\n event: RouteServerDebugEvent,\n) {\n if (!logger || event.type !== 'handler') return;\n const payload: [string, RouteServerDebugEvent] = [\n `[rrroutes-server][handler:${event.stage}] ${event.method} ${event.path}`,\n event,\n ];\n if (event.stage === 'error') {\n (\n logger.error ??\n logger.warn ??\n logger.debug ??\n logger.info ??\n logger.log ??\n logger.system\n )?.call(logger, ...payload);\n return;\n }\n (\n logger.debug ??\n logger.verbose ??\n logger.info ??\n logger.log ??\n logger.system\n )?.call(logger, ...payload);\n}\n\n// ──────────────────────────────────────────────────────────────────────────────\n// Controller types — object form only (simpler, clearer typings)\n// ──────────────────────────────────────────────────────────────────────────────\n\n/** Typed route handler for a specific leaf */\nexport type Handler<L extends AnyLeaf, Ctx = unknown> = (args: {\n req: express.Request;\n res: express.Response;\n next: express.NextFunction;\n ctx: CtxWithRoutesLogger<Ctx>;\n params: ArgParams<L>;\n query: ArgQuery<L>;\n body: ArgBody<L>;\n}) => Promise<InferOutput<L>> | InferOutput<L>;\n\n/** Route definition for one key */\nexport type RouteDef<L extends AnyLeaf, Ctx = unknown, Names extends string = string> = {\n /** Middlewares before the handler (run after buildCtx/global/derived) */\n use?: Array<CtxRequestHandler<Ctx>>;\n /** Middlewares after the handler *if* it calls next() */\n after?: Array<CtxRequestHandler<Ctx>>;\n /** Your business logic */\n handler: Handler<L, Ctx>;\n /**\n * Optional per-route debug overrides. When provided, these replace the global debug options.\n */\n debug?: RouteDefDebugOptions<Names>;\n /**\n * Optional logical name used for debug filtering. Prefer `debug.debugName`; this field remains for backwards compatibility.\n */\n debugName?: Names;\n};\n\n/** Map of registry keys -> route defs */\nexport type ControllerMap<\n R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> },\n Ctx = unknown,\n Names extends string = string,\n> = {\n [P in KeysOfRegistry<R>]: RouteDef<LeafFromKey<R, P>, Ctx, Names>;\n};\n\nexport type PartialControllerMap<\n R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> },\n Ctx = unknown,\n Names extends string = string,\n> = Partial<ControllerMap<R, Ctx, Names>>;\n\n// ──────────────────────────────────────────────────────────────────────────────\n/** Options + derivation helpers */\n// ──────────────────────────────────────────────────────────────────────────────\n\nexport type RouteServerConfig<Ctx = unknown, Names extends string = string> = {\n /**\n * Build a request-scoped context. We wrap this in a middleware that runs\n * *first* (before global/derived/route middlewares), and stash it on\n * `res.locals[CTX_SYMBOL]` so *all* later middlewares can use it.\n * You can optionally include `routesLogger` to override handler debug logging per request.\n */\n buildCtx: (\n req: express.Request,\n res: express.Response,\n ) => CtxWithRoutesLogger<Ctx> | Promise<CtxWithRoutesLogger<Ctx>>;\n\n /**\n * Grouped global middlewares that run *before* or *after* the handler for every route.\n */\n globalMiddleware?: {\n before?: Array<CtxRequestHandler<Ctx>>;\n after?: Array<CtxRequestHandler<Ctx>>;\n };\n\n /**\n * Derive middleware from MethodCfg.\n * - `upload` runs when cfg.bodyFiles has entries\n */\n fromCfg?: {\n upload?: (files: FileField[] | undefined, leaf: AnyLeaf) => RequestHandler[];\n };\n\n /** Validate handler return values with outputSchema (default: true) */\n validateOutput?: boolean;\n\n /** Custom responder (default: res.json(data)) */\n send?: (res: express.Response, data: unknown) => void;\n\n /** Optional logger hooks */\n logger?: LoggerLike;\n\n /**\n * Optional debug logging for the request lifecycle.\n * Supports booleans/modes/loggers, or a toggle map with per-event enabling, verbose payload logging,\n * and `only` filters tied to `RouteDef.debug?.debugName` (or the deprecated `RouteDef.debugName`).\n */\n debug?: RouteServerDebugOptions<Names>;\n};\n\n/** Default JSON responder (typed to avoid implicit-any diagnostics) */\nconst defaultSend: (res: express.Response, data: unknown) => void = (res, data) => {\n res.json(data as any);\n};\n\n// ──────────────────────────────────────────────────────────────────────────────\n// Core builder\n// ──────────────────────────────────────────────────────────────────────────────\n\nconst REGISTERED_ROUTES_SYMBOL = Symbol.for('routesV3.registeredRoutes');\n\ntype RegisteredRouteStore = Set<string>;\n\n/**\n * Retrieve or initialize the shared store of registered route keys.\n * @param router Express router/application that carries previously registered keys.\n * @returns Set of string keys describing registered routes.\n */\nfunction getRegisteredRouteStore(router: Router): RegisteredRouteStore {\n const existing = (router as any)[REGISTERED_ROUTES_SYMBOL] as RegisteredRouteStore | undefined;\n if (existing) return existing;\n const store: RegisteredRouteStore = new Set();\n (router as any)[REGISTERED_ROUTES_SYMBOL] = store;\n return store;\n}\n\n/**\n * Inspect the Express layer stack to discover already-registered routes.\n * @param appOrRouter Express application or router to inspect.\n * @returns All keys in the form `\"METHOD /path\"` found on the stack.\n */\nfunction collectRoutesFromStack(appOrRouter: Router): string[] {\n const result: string[] = [];\n const stack: any[] =\n (appOrRouter as any).stack ??\n ((appOrRouter as any)._router ? (appOrRouter as any)._router.stack : undefined) ??\n [];\n\n if (!Array.isArray(stack)) return result;\n\n for (const layer of stack) {\n const route = layer && layer.route;\n if (!route) continue;\n\n const paths = Array.isArray(route.path) ? route.path : [route.path];\n const methodEntries = Object.entries(route.methods ?? {}).filter(([, enabled]) => enabled);\n\n for (const path of paths) {\n for (const [method] of methodEntries) {\n result.push(`${method.toUpperCase()} ${path}`);\n }\n }\n }\n\n return result;\n}\n\n/** Runtime helpers returned by `createRRRoute`. */\nexport type RouteServer<Ctx = unknown, Names extends string = string> = {\n router: Router;\n register<L extends AnyLeaf>(leaf: L, def: RouteDef<L, Ctx, Names>): void;\n registerControllers<R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> }>(\n registry: R,\n controllers: PartialControllerMap<R, Ctx, Names>,\n ): void;\n warnMissingControllers<R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> }>(\n registry: R,\n logger: { warn: (...args: any[]) => void },\n ): void;\n getRegisteredKeys(): string[];\n};\n\n/**\n * Create an Express binding helper that keeps routes and controllers in sync.\n * @param router Express router or app to register handlers on.\n * @param config Optional configuration controlling ctx building, auth, uploads, etc.\n * @returns Object with helpers to register controllers and inspect registered keys.\n */\nexport function createRRRoute<Ctx = unknown, Names extends string = string>(\n router: Router,\n config: RouteServerConfig<Ctx, Names>,\n): RouteServer<Ctx, Names> {\n const validateOutput = config.validateOutput ?? true;\n const send = config.send ?? defaultSend;\n const logger = config.logger;\n const { emit: defaultEmitDebug, mode: defaultDebugMode } =\n createServerDebugEmitter<Names>(config.debug);\n const decorateDebugEvent = <T extends RouteServerDebugEvent>(\n isVerbose: boolean,\n event: T,\n details?: Partial<RouteServerDebugEvent>,\n ): RouteServerDebugEvent => {\n if (!isVerbose || !details) return event;\n return { ...event, ...details } as RouteServerDebugEvent;\n };\n\n const globalBeforeMws = [ ...(config.globalMiddleware?.before ?? [])].map(\n (mw) => adaptCtxMw<Ctx>(mw),\n );\n const globalAfterMws = mapAfterMiddleware<Ctx>(config.globalMiddleware?.after);\n const registered = getRegisteredRouteStore(router);\n\n const buildDerived = (leaf: AnyLeaf): RequestHandler[] => {\n const derived: RequestHandler[] = [];\n if (\n config.fromCfg?.upload &&\n Array.isArray(leaf.cfg.bodyFiles) &&\n leaf.cfg.bodyFiles.length > 0\n ) {\n derived.push(...config.fromCfg.upload(leaf.cfg.bodyFiles, leaf));\n }\n\n return derived;\n };\n\n /** Register a single leaf/controller pair on the underlying router. */\n function register<L extends AnyLeaf>(leaf: L, def: RouteDef<L, Ctx, Names>) {\n const method = leaf.method as HttpMethod;\n const methodUpper = method.toUpperCase() as Uppercase<HttpMethod>;\n const path = leaf.path as string;\n const key = keyOf(leaf);\n const defDebug = def.debug;\n let debugName = def.debugName as Names | undefined;\n let routeDebugEmitter: ServerDebugEmitter<Names> | undefined;\n if (defDebug) {\n const { debugName: overrideName, ...rest } = defDebug;\n const hasOverrides = Object.values(rest).some((value) => value !== undefined);\n if (hasOverrides) {\n routeDebugEmitter = createServerDebugEmitter<Names>(\n rest as RouteServerDebugOptions<Names>,\n );\n }\n debugName = (overrideName ?? debugName) as Names | undefined;\n }\n const activeEmit = routeDebugEmitter?.emit ?? defaultEmitDebug;\n const activeDebugMode = routeDebugEmitter?.mode ?? defaultDebugMode;\n const emit = (event: RouteServerDebugEvent) => activeEmit(event, debugName);\n const isVerboseDebug = activeDebugMode === 'complete';\n emit({ type: 'register', method: methodUpper, path });\n\n const routeSpecific = (def?.use ?? []).map((mw) => adaptCtxMw<Ctx>(mw));\n const derived = buildDerived(leaf);\n const ctxMw: RequestHandler = async (req, res, next) => {\n const requestUrl = req.originalUrl ?? path;\n const startedAt = Date.now();\n emit({ type: 'buildCtx', stage: 'start', method: methodUpper, path, url: requestUrl });\n try {\n const ctx = await config.buildCtx(req, res);\n (res.locals as any)[CTX_SYMBOL] = ctx;\n emit({\n type: 'buildCtx',\n stage: 'success',\n method: methodUpper,\n path,\n url: requestUrl,\n durationMs: Date.now() - startedAt,\n });\n next();\n } catch (err) {\n emit({\n type: 'buildCtx',\n stage: 'error',\n method: methodUpper,\n path,\n url: requestUrl,\n durationMs: Date.now() - startedAt,\n error: err,\n });\n logger?.error?.('buildCtx error', err);\n next(err as any);\n }\n };\n const before: RequestHandler[] = [ctxMw, ...globalBeforeMws, ...derived, ...routeSpecific];\n\n const wrapped: RequestHandler = async (req, res, next) => {\n const requestUrl = req.originalUrl.split('?')[0] ?? path;\n const startedAt = Date.now();\n emit({ type: 'request', stage: 'start', method: methodUpper, path, url: requestUrl });\n let params: ArgParams<L> | undefined;\n let query: ArgQuery<L> | undefined;\n let body: ArgBody<L> | undefined;\n let responsePayload: InferOutput<L> | undefined;\n let hasResponsePayload = false;\n setAfterHandlerNext(res, false);\n let handlerCalledNext = false;\n const downstreamNext: express.NextFunction = (err?: any) => {\n handlerCalledNext = true;\n setAfterHandlerNext(res, true);\n next(err);\n };\n\n logger?.info?.(`${methodUpper}@${path} (${requestUrl})`);\n const ctx = (res.locals as any)[CTX_SYMBOL] as CtxWithRoutesLogger<Ctx>;\n const ctxRoutesLogger = ctx?.routesLogger;\n const emitWithCtx = (\n event: RouteServerDebugEvent,\n details?: Partial<RouteServerDebugEvent>,\n ) => {\n const decorated = decorateDebugEvent(isVerboseDebug, event, details);\n if (decorated.type === 'handler' && ctxRoutesLogger) {\n logHandlerDebugWithRoutesLogger(ctxRoutesLogger, decorated);\n }else{\n emit(decorated);\n }\n };\n try {\n params = (\n leaf.cfg.paramsSchema\n ? (leaf.cfg.paramsSchema as ZodType).parse(req.params)\n : Object.keys(req.params || {}).length\n ? (req.params as any)\n : undefined\n ) as ArgParams<L>;\n\n try {\n query = leaf.cfg.querySchema\n ? (leaf.cfg.querySchema as ZodType).parse(req.query)\n : Object.keys(req.query || {}).length\n ? (req.query as any)\n : undefined;\n } catch (e) {\n logger?.error?.('Query parsing error', {\n path,\n method: methodUpper,\n error: e,\n raw: JSON.stringify(req.query),\n });\n throw e;\n }\n\n body = (\n leaf.cfg.bodySchema\n ? (leaf.cfg.bodySchema as ZodType).parse(req.body)\n : req.body !== undefined\n ? (req.body as any)\n : undefined\n ) as ArgBody<L>;\n\n logger?.verbose?.(`${methodUpper}@${path} (${requestUrl})`, {\n params,\n query,\n body,\n });\n\n const handlerStartedAt = Date.now();\n emitWithCtx(\n {\n type: 'handler',\n stage: 'start',\n method: methodUpper,\n path,\n },\n isVerboseDebug ? { params, query, body } : undefined,\n );\n\n let result;\n try {\n result = await def.handler({\n req,\n res,\n next: downstreamNext,\n ctx,\n params: params as ArgParams<L>,\n query: query as ArgQuery<L>,\n body: body as ArgBody<L>,\n });\n emitWithCtx(\n {\n type: 'handler',\n stage: 'success',\n method: methodUpper,\n path,\n durationMs: Date.now() - handlerStartedAt,\n },\n isVerboseDebug\n ? {\n params,\n query,\n body,\n ...(result !== undefined ? { output: result } : {}),\n }\n : undefined,\n );\n } catch (e) {\n emitWithCtx(\n {\n type: 'handler',\n stage: 'error',\n method: methodUpper,\n path,\n durationMs: Date.now() - handlerStartedAt,\n error: e,\n },\n isVerboseDebug ? { params, query, body } : undefined,\n );\n logger?.error?.('Handler error', e);\n throw e;\n }\n\n if (!res.headersSent) {\n if (result !== undefined) {\n const out =\n validateOutput && leaf.cfg.outputSchema\n ? (leaf.cfg.outputSchema as ZodType).parse(result)\n : result;\n responsePayload = out as InferOutput<L>;\n hasResponsePayload = true;\n logger?.verbose?.(`${methodUpper}@${path} result`, out);\n send(res, out);\n } else if (!handlerCalledNext) {\n next();\n }\n }\n\n emitWithCtx(\n {\n type: 'request',\n stage: 'success',\n method: methodUpper,\n path,\n url: requestUrl,\n durationMs: Date.now() - startedAt,\n },\n isVerboseDebug\n ? {\n params,\n query,\n body,\n ...(hasResponsePayload ? { output: responsePayload } : {}),\n }\n : undefined,\n );\n } catch (err) {\n emitWithCtx(\n {\n type: 'request',\n stage: 'error',\n method: methodUpper,\n path,\n url: requestUrl,\n durationMs: Date.now() - startedAt,\n error: err,\n },\n isVerboseDebug ? { params, query, body } : undefined,\n );\n logger?.error?.('Route error', err);\n next(err as any);\n }\n };\n\n const after = [...mapAfterMiddleware<Ctx>(def?.after), ...globalAfterMws];\n (router as any)[method](path, ...before, wrapped, ...after);\n registered.add(key);\n }\n\n /**\n * Register controller definitions for the provided keys.\n * @param registry Finalized registry of leaves.\n * @param controllers Partial controller map keyed by `\"METHOD /path\"`.\n */\n function registerControllers<\n R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> },\n >(registry: R, controllers: PartialControllerMap<R, Ctx, Names>) {\n (Object.keys(controllers) as Array<KeysOfRegistry<R>>).forEach((key) => {\n const leaf = registry.byKey[key] as unknown as LeafFromKey<R, typeof key> | undefined;\n if (!leaf) {\n logger?.warn?.(`No leaf found for controller key: ${key}. Not registering route.`);\n return;\n }\n const def = controllers[key];\n if (!def) return;\n register(leaf as LeafFromKey<R, typeof key>, def);\n });\n }\n\n /**\n * Warn about leaves that do not have a registered controller.\n * @param registry Finalized registry of leaves.\n * @param warnLogger Logger used for warning output.\n */\n function warnMissing<R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> }>(\n registry: R,\n warnLogger: { warn: (...args: any[]) => void },\n ) {\n const registeredFromStore = new Set<string>(Array.from(registered));\n if (registeredFromStore.size === 0) {\n collectRoutesFromStack(router).forEach((key) => registeredFromStore.add(key));\n }\n for (const leaf of registry.all) {\n const key = keyOf(leaf);\n if (!registeredFromStore.has(key)) {\n warnLogger.warn(`No controller registered for route: ${key}`);\n }\n }\n }\n\n return {\n router,\n register,\n registerControllers,\n warnMissingControllers: warnMissing,\n getRegisteredKeys: () => Array.from(registered),\n };\n}\n\n/**\n * Bind only the controllers that are present in the provided map.\n * @param router Express router or app.\n * @param registry Finalized registry produced by `finalize(...)`.\n * @param controllers Partial map of controllers keyed by `\"METHOD /path\"`.\n * @param config Optional route server configuration.\n * @returns The same router instance for chaining.\n */\nexport function bindExpressRoutes<\n R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> },\n Ctx = unknown,\n Names extends string = string,\n>(\n router: Router,\n registry: R,\n controllers: PartialControllerMap<R, Ctx, Names>,\n config: RouteServerConfig<Ctx, Names>,\n) {\n const server = createRRRoute<Ctx, Names>(router, config);\n server.registerControllers(registry, controllers);\n return router;\n}\n\n/**\n * Bind controllers for every leaf. Missing entries fail at compile time.\n * @param router Express router or app.\n * @param registry Finalized registry produced by `finalize(...)`.\n * @param controllers Complete map of controllers keyed by `\"METHOD /path\"`.\n * @param config Optional route server configuration.\n * @returns The same router instance for chaining.\n */\nexport function bindAll<\n R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> },\n Ctx = unknown,\n Names extends string = string,\n>(\n router: Router,\n registry: R,\n controllers: { [K in KeysOfRegistry<R>]: RouteDef<LeafFromKey<R, K>, Ctx, Names> },\n config: RouteServerConfig<Ctx, Names>,\n) {\n const server = createRRRoute<Ctx, Names>(router, config);\n server.registerControllers(registry, controllers);\n return router;\n}\n\n// ──────────────────────────────────────────────────────────────────────────────\n// DX helpers\n// ──────────────────────────────────────────────────────────────────────────────\n\n/**\n * Helper for great IntelliSense when authoring controller maps.\n * @returns Function that enforces key names while preserving partial flexibility.\n */\nexport const defineControllers =\n <\n R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> },\n Ctx = unknown,\n Names extends string = string,\n >() =>\n <M extends PartialControllerMap<R, Ctx, Names>>(m: M) =>\n m;\n\n/**\n * Warn about leaves that don't have controllers.\n * Call this during startup to surface missing routes.\n * @param router Express router or app to inspect.\n * @param registry Finalized registry produced by `finalize(...)`.\n * @param logger Logger where warnings are emitted.\n */\nexport function warnMissingControllers<\n R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> },\n>(router: Router, registry: R, logger: { warn: (...args: any[]) => void }) {\n const registeredStore = (router as any)[REGISTERED_ROUTES_SYMBOL] as Set<string> | undefined;\n const initial = registeredStore ? Array.from(registeredStore) : collectRoutesFromStack(router);\n const registeredKeys = new Set<string>(initial);\n\n for (const leaf of registry.all) {\n const k = keyOf(leaf);\n if (!registeredKeys.has(k)) {\n logger.warn(`No controller registered for route: ${k}`);\n }\n }\n}\n","// socket.server.debug.ts\nimport type { IncomingHttpHeaders } from 'http';\n\nexport type SocketServerConfigSnapshot = {\n url?: string;\n transport?: string;\n protocol?: string;\n address?: string;\n issued?: number;\n time?: string;\n query?: Record<string, unknown>;\n auth?: Record<string, unknown>;\n headers?: IncomingHttpHeaders;\n};\n\nexport type SocketServerLifecycleStage =\n | 'server_init'\n | 'connection_listener_installed'\n | 'connection_init'\n | 'connection_handlers_attached'\n | 'connection_cleanup'\n | 'destroy_start'\n | 'destroy_complete'\n | 'connection_cleanup_fallback';\n\nexport type SocketServerHeartbeatPhase = 'ping' | 'pong' | 'skip';\n\nexport type SocketServerDebugEvent =\n | {\n type: 'register';\n action: 'register' | 'unregister';\n event: string;\n msg?:string;\n }\n | {\n type: 'handler';\n phase: 'receive' | 'validation_error' | 'handler_success' | 'handler_error';\n event: string;\n socketId?: string;\n nsp?: string;\n rooms?: string[];\n raw?: unknown;\n issues?: any[];\n error?: unknown;\n details?: Record<string, unknown>;\n }\n | {\n type: 'emit';\n event: string;\n rooms: string[];\n envelope?: unknown;\n error?: {\n reason: string;\n message?: string;\n issues?: unknown;\n };\n metadata?:unknown;\n }\n | {\n type: 'rooms';\n action: 'join' | 'leave';\n rooms?: string|string[];\n socketId: string;\n phase?:string;\n payload?: unknown;\n issues?: any[];\n }\n | {\n type: 'heartbeat';\n phase: SocketServerHeartbeatPhase;\n socketId: string;\n payload?: unknown;\n issues?: any[];\n error?: boolean;\n details?: Record<string, unknown>;\n }\n | {\n type: 'config';\n socketId: string;\n nsp: string;\n snapshot: SocketServerConfigSnapshot;\n }\n | {\n type: 'lifecycle';\n stage: SocketServerLifecycleStage;\n socketId?: string;\n nsp?: string;\n details?: Record<string, unknown>;\n };\n\nexport type SocketDebugOptions = {\n verbose?: boolean;\n /** filters event-based logs (register/handler/emit) by event name */\n only?: string[];\n logger?: (e: SocketServerDebugEvent) => void;\n} & {\n [P in SocketServerDebugEvent['type']]?: boolean;\n};\n\nexport function createDebugger(options?: SocketDebugOptions) {\n const debug = options ?? {};\n\n return (maybeEvent: string | null, e: SocketServerDebugEvent) => {\n if (!debug.logger) return;\n if (!debug[e.type]) return;\n\n // only filter applies to event-shaped logs\n if (\n debug.only &&\n maybeEvent &&\n (e.type === 'register' || e.type === 'handler' || e.type === 'emit') &&\n !debug.only.includes(maybeEvent)\n ) {\n return;\n }\n\n debug.logger(e);\n };\n}\n","// socket.server.sys.ts\nimport type { Socket } from 'socket.io';\nimport { z } from 'zod';\nimport type { EventMap, SocketConnectionConfig, SysEventName } from '@emeryld/rrroutes-contract';\nimport type {\n SocketServerConfigSnapshot,\n SocketServerDebugEvent,\n} from './socket.server.debug';\nimport type { HandlerCtxNoAck } from './socket.server.types';\n\n// Helper: payload for event map\ntype EventPayload<Events extends EventMap, K extends keyof Events & string> =\n z.infer<Events[K]['message']>;\n\nexport type SocketConnectionHelper<Events extends EventMap> = {\n emit<K extends keyof Events & string>(\n event: K,\n payload: EventPayload<Events, K>,\n metadata?: Record<string, unknown>,\n onAck?: (ack: unknown) => void\n ): void;\n};\n\n\n/** Heartbeat configuration that is not tied to payload shapes (which live in sys event schemas). */\nexport type HeartbeatServerOptions = {\n /** Enable/disable built-in heartbeat handling. Defaults to true. */\n enabled?: boolean;\n};\n\nexport type SysServerEventMap<\n Config extends SocketConnectionConfig = SocketConnectionConfig,\n Events extends EventMap = EventMap,\n> = {\n 'sys:connect': (args: {\n socket: Socket;\n helper: SocketConnectionHelper<Events>;\n /**\n * Call to proceed with the default connection initialization\n * (attaches heartbeat, join, leave and disconnect handlers).\n */\n complete: () => void;\n }) => void | Promise<void>;\n\n 'sys:disconnect': (args: {\n socket: Socket;\n helper: SocketConnectionHelper<Events>;\n /** cleans up all handlers */\n cleanup: () => void;\n reason: string;\n }) => void | Promise<void>;\n\n 'sys:ping': (\n args:{\n socket: Socket;\n helper: SocketConnectionHelper<Events>;\n ping: z.output<Config['pingPayload']>,\n ctx: HandlerCtxNoAck}\n ) => z.output<Config['pongPayload']> | Promise<z.output<Config['pongPayload']>>;\n\n 'sys:room_join': (args: {\n socket: Socket;\n helper: SocketConnectionHelper<Events>;\n rooms: string[];\n meta: z.output<Config['joinMetaMessage']>;\n join: (room: string) => Promise<void>;\n }) => void | Promise<void>;\n\n 'sys:room_leave': (args: {\n socket: Socket;\n helper: SocketConnectionHelper<Events>;\n rooms: string[];\n meta: z.output<Config['leaveMetaMessage']>;\n leave: (room: string) => Promise<void>;\n }) => void | Promise<void>;\n};\n\n\nconst normalizeError = (error: unknown) => {\n if (error instanceof Error) {\n return { name: error.name, message: error.message };\n }\n if (typeof error === 'string') return { message: error };\n return { message: 'Unknown error' };\n};\n\nconst roomValueSchema = z.union([z.string(), z.array(z.string())]);\n\nconst buildRoomPayloadSchema = <Meta extends z.ZodTypeAny>(metaSchema: Meta) =>\n z.object({\n rooms: roomValueSchema,\n meta: metaSchema,\n });\n\ntype DebugFn = (maybeEvent: string | null, e: SocketServerDebugEvent) => void;\n\nconst toArray = (rooms?: string[] | string): string[] =>\n rooms == null ? [] : Array.isArray(rooms) ? rooms : [rooms];\n\nconst snapshotSocketConfig = (socket: Socket): SocketServerConfigSnapshot => {\n const conn = socket.conn as { transport?: { name?: string }; protocol?: string | number; remoteAddress?: string } | undefined;\n const protocol = conn?.protocol;\n return {\n url: socket.handshake.url,\n transport: conn?.transport?.name,\n protocol: protocol != null ? String(protocol) : undefined,\n address: conn?.remoteAddress ?? socket.handshake.address,\n issued: socket.handshake.issued,\n time: socket.handshake.time,\n query: socket.handshake.query as Record<string, unknown>,\n auth: socket.handshake.auth as Record<string, unknown>,\n headers: socket.handshake.headers,\n };\n};\n\nexport function createBuiltInConnectionHandlers<\n C extends SocketConnectionConfig,\n Events extends EventMap,\n>(opts: {\n heartbeat?: HeartbeatServerOptions;\n sys: SysServerEventMap<C, Events>;\n dbg: DebugFn;\n config: C;\n createCtx: (socket: Socket) => HandlerCtxNoAck;\n debugVerbose?: boolean;\n createHelper: (socket: Socket) => SocketConnectionHelper<Events>;\n}) {\n const { heartbeat, sys, dbg, config, createCtx, debugVerbose, createHelper } = opts;\n\n const roomJoinEvent: SysEventName = 'sys:room_join';\n const roomLeaveEvent: SysEventName = 'sys:room_leave';\n const pingEvent: SysEventName = 'sys:ping';\n const pongEvent: SysEventName = 'sys:pong';\n const heartbeatEnabled = heartbeat?.enabled !== false;\n\n const joinPayloadSchema = buildRoomPayloadSchema(config.joinMetaMessage);\n const leavePayloadSchema = buildRoomPayloadSchema(config.leaveMetaMessage);\n const pingPayloadSchema = config.pingPayload as C['pingPayload'];\n const pongPayloadSchema = config.pongPayload as C['pongPayload'];\n\n const sysEvents = sys;\n const getSysEvent = <K extends keyof SysServerEventMap<C, Events> & SysEventName>(name: K) =>\n sysEvents[name];\n\n /** Track per-socket teardown for built-in handlers to ensure explicit cleanup on destroy(). */\n const socketTeardowns = new WeakMap<Socket, () => void>();\n\n const builtInConnectionListener = (socket: Socket) => {\n const helper = createHelper(socket);\n dbg(null, {\n type: 'lifecycle',\n stage: 'connection_init',\n socketId: socket.id,\n nsp: socket.nsp.name,\n details: {\n rooms: Array.from(socket.rooms),\n handshakeIssued: socket.handshake.issued,\n },\n });\n dbg(null, {\n type: 'config',\n socketId: socket.id,\n nsp: socket.nsp.name,\n snapshot: snapshotSocketConfig(socket),\n });\n\n const defaultConnect = () => {\n dbg('sys:connect', {\n type: 'handler',\n phase: 'handler_success',\n event: 'sys:connect',\n socketId: socket.id,\n });\n\n const includeRaw = debugVerbose === true;\n\n // built-in room handlers (wrapped with sys:room_join / sys:room_leave)\n const joinHandler = async (msg: unknown) => {\n dbg(roomJoinEvent, {\n type: 'rooms',\n phase: 'receive',\n action:'join',\n socketId: socket.id,\n payload: includeRaw ? msg : undefined,\n });\n const parsed = joinPayloadSchema.safeParse(msg);\n\n if (!parsed.success) {\n socket.emit(`${roomJoinEvent}:error`, {\n eventName: roomJoinEvent,\n issues: parsed.error.issues,\n });\n dbg(roomJoinEvent, {\n type: 'rooms',\n action:'join',\n phase:'validation_error',\n socketId: socket.id,\n issues: parsed.error.issues,\n payload: includeRaw ? msg : undefined,\n });\n return;\n }\n const list = toArray(parsed.data.rooms);\n\n const join = async (room: string) => {\n await socket.join(room);\n dbg(null, { type: 'rooms', action: 'join', rooms:room, socketId: socket.id });\n };\n\n const run = async () => {\n await getSysEvent('sys:room_join')({\n socket,\n helper,\n rooms: list,\n meta: parsed.data.meta as z.output<C['joinMetaMessage']>,\n join,\n });\n };\n\n try {\n await run();\n } catch (error) {\n socket.emit(`${roomJoinEvent}:error`, { error: normalizeError(error) });\n dbg(roomJoinEvent, {\n type: 'rooms',\n action:'join',\n phase: 'handler_error',\n payload: includeRaw ? { rooms: list, meta: parsed.data.meta } : undefined,\n socketId: socket.id,\n issues:[error],\n });\n }\n };\n\n const leaveHandler = async (msg: unknown) => {\n dbg(roomLeaveEvent, {\n type: 'rooms',\n phase: 'receive',\n action:'leave',\n socketId: socket.id,\n payload: includeRaw ? msg : undefined,\n });\n const parsed = leavePayloadSchema.safeParse(msg);\n if (!parsed.success) {\n socket.emit(`${roomLeaveEvent}:error`, {\n eventName: roomLeaveEvent,\n issues: parsed.error.issues,\n });\n dbg(roomJoinEvent, {\n type: 'rooms',\n action:'leave',\n phase:'validation_error',\n socketId: socket.id,\n issues: parsed.error.issues,\n payload: includeRaw ? msg : undefined,\n });\n return;\n }\n\n const list = toArray(parsed.data.rooms);\n\n const leave = async (room: string) => {\n dbg(null, { type: 'rooms', action: 'leave', rooms:room, socketId: socket.id });\n await socket.leave(room);\n };\n\n const run = async () => {\n await getSysEvent('sys:room_leave')({\n socket,\n helper,\n rooms: list,\n meta: parsed.data.meta as z.output<C['leaveMetaMessage']>,\n leave,\n });\n };\n\n try {\n await run();\n } catch (error) {\n socket.emit(`${roomLeaveEvent}:error`, { error: normalizeError(error) });\n dbg(roomJoinEvent, {\n type: 'rooms',\n phase: 'handler_error',\n payload: includeRaw ? { rooms: list, meta: parsed.data.meta } : undefined,\n socketId: socket.id,\n issues:[error],\n action:'join'\n });\n }\n };\n\n // heartbeat, wrapped with sys:ping/sys:pong\n const pingHandler = async (msg: unknown) => {\n if (!heartbeatEnabled) {\n dbg(null, {\n type: 'heartbeat',\n phase: 'skip',\n socketId: socket.id,\n details: { reason: 'heartbeat_disabled' },\n error: false,\n });\n return;\n }\n\n const parsedPing = pingPayloadSchema.safeParse(msg);\n if (!parsedPing.success) {\n socket.emit(`${pingEvent}:error`, {\n eventName: pingEvent,\n issues: parsedPing.error.issues,\n });\n dbg(null, {\n type: 'heartbeat',\n phase: 'ping',\n socketId: socket.id,\n payload: includeRaw ? msg : undefined,\n issues: parsedPing.error.issues,\n error: true,\n details: { step: 'parse' },\n });\n return;\n }\n const ctx = createCtx(socket);\n\n dbg(null, {\n type: 'heartbeat',\n phase: 'ping',\n socketId: socket.id,\n payload: parsedPing.data,\n error: false,\n });\n\n let pongPayload: z.output<C['pongPayload']>;\n try {\n pongPayload = await getSysEvent('sys:ping')({ping:parsedPing.data, ctx, socket, helper});\n } catch (error) {\n socket.emit(`${pingEvent}:error`, { error: normalizeError(error) });\n dbg(null, {\n type: 'heartbeat',\n phase: 'ping',\n socketId: socket.id,\n payload: parsedPing.data,\n error: true,\n details: { step: 'sys_handler_error' },\n });\n return;\n }\n\n const parsedPong = pongPayloadSchema.safeParse(pongPayload);\n if (!parsedPong.success) {\n socket.emit(`${pongEvent}:error`, {\n eventName: pongEvent,\n issues: parsedPong.error.issues,\n });\n dbg(null, {\n type: 'heartbeat',\n phase: 'pong',\n socketId: socket.id,\n payload: includeRaw ? pongPayload : undefined,\n issues: parsedPong.error.issues,\n error: true,\n details: { step: 'parse' },\n });\n return;\n }\n socket.emit(pongEvent, parsedPong.data);\n dbg(null, {\n type: 'heartbeat',\n phase: 'pong',\n socketId: socket.id,\n payload: parsedPong.data,\n error: false,\n });\n };\n\n // attach built-in handlers\n socket.on(roomJoinEvent, joinHandler);\n socket.on(roomLeaveEvent, leaveHandler);\n if (heartbeatEnabled) {\n socket.on(pingEvent, pingHandler);\n }\n\n const cleanup = () => {\n dbg(null, {\n type: 'lifecycle',\n stage: 'connection_cleanup',\n socketId: socket.id,\n nsp: socket.nsp.name,\n details: { reason: 'teardown' },\n });\n socket.off(roomJoinEvent, joinHandler);\n socket.off(roomLeaveEvent, leaveHandler);\n if (heartbeatEnabled) {\n socket.off(pingEvent, pingHandler);\n }\n };\n\n socketTeardowns.set(socket, cleanup);\n dbg(null, {\n type: 'lifecycle',\n stage: 'connection_handlers_attached',\n socketId: socket.id,\n nsp: socket.nsp.name,\n details: {\n heartbeatEnabled,\n joinEvent: roomJoinEvent,\n leaveEvent: roomLeaveEvent,\n pingEvent: heartbeatEnabled ? pingEvent : undefined,\n },\n });\n\n socket.once('disconnect', (reason) => {\n dbg('sys:disconnect', {\n type: 'lifecycle',\n stage:'connection_cleanup',\n nsp: socket.nsp.name,\n socketId: socket.id,\n details: { reason: String(reason) },\n });\n const defaultDisconnect = () => {\n cleanup();\n socketTeardowns.delete(socket);\n };\n getSysEvent('sys:disconnect')({\n socket,\n helper,\n reason: String(reason),\n cleanup: defaultDisconnect,\n });\n });\n };\n getSysEvent('sys:connect')({\n socket,\n helper,\n complete: defaultConnect,\n });\n };\n\n return {\n builtInConnectionListener,\n socketTeardowns,\n roomJoinEvent,\n roomLeaveEvent,\n pingEvent,\n };\n}\n","// socket.server.index.ts\nimport { Server, Socket } from 'socket.io';\nimport { z } from 'zod';\nimport type { EventMap, SocketConnectionConfig } from '@emeryld/rrroutes-contract';\nimport { createDebugger } from './socket.server.debug';\nimport type { SocketServerDebugEvent, SocketDebugOptions } from './socket.server.debug';\nimport { createBuiltInConnectionHandlers } from './socket.server.sys';\nimport type {\n HeartbeatServerOptions,\n SocketConnectionHelper,\n SysServerEventMap,\n} from './socket.server.sys';\nimport type { HandlerCtx, HandlerCtxNoAck } from './socket.server.types';\n\ntype Payload<T extends EventMap, K extends keyof T> = z.infer<T[K]['message']>;\n\nconst createBaseHandlerCtx = (socket: Socket): HandlerCtxNoAck => ({\n sentAt: new Date(),\n socket,\n socketId: socket.id,\n nsp: socket.nsp.name,\n rooms: Array.from(socket.rooms),\n user: socket.data?.user,\n scopes: socket.data?.scopes,\n});\n\nconst normalizeError = (error: unknown, verbose?: boolean) => {\n if (error instanceof Error) {\n return {\n name: error.name,\n message: error.message,\n stack: verbose ? error.stack : undefined,\n };\n }\n if (typeof error === 'string') return { message: error };\n if (typeof error === 'object' && error !== null) {\n return verbose ? error : { message: 'Unknown error' };\n }\n return { message: String(error) };\n};\n\nexport interface SocketConnection<T extends EventMap> {\n on<K extends keyof T & string>(\n eventName: K,\n handler: (payload: Payload<T, K>, ctx: HandlerCtx) => void | Promise<void>\n ): () => void;\n\n off<K extends keyof T & string>(eventName: K): void;\n\n emit<K extends keyof T & string>(\n eventName: K,\n payload: Payload<T, K>,\n toRooms?: string[] | string,\n metadata?: Record<string, unknown>,\n onAck?: (ack: unknown) => void\n ): void;\n\n /** Dispose all listeners, timers, and room memberships created by this instance. */\n destroy(): void;\n}\n\nexport function createSocketConnections<\n T extends EventMap,\n TConfig extends SocketConnectionConfig = SocketConnectionConfig,\n>(\n io: Server,\n events: T,\n opts: {\n debug?: SocketDebugOptions;\n heartbeat?: HeartbeatServerOptions;\n /** System event customization (connect / disconnect / ping / pong / room join/leave) */\n sys: SysServerEventMap<TConfig, T>;\n config: TConfig;\n }\n): SocketConnection<T> {\n const dbg = createDebugger(opts?.debug);\n const socketConfig = opts.config;\n const heartbeatEnabled = opts?.heartbeat?.enabled !== false;\n const eventNames = Object.keys(events);\n dbg(null, {\n type: 'lifecycle',\n stage: 'server_init',\n details: {\n eventCount: eventNames,\n heartbeatEnabled,\n path: io?.path(),\n namespaces: Array.from(io._nsps.keys()),\n transport: io?._opts.transports,\n sysEvents: Object.keys(opts.sys ?? {}),\n },\n });\n\n const getSchema = <K extends keyof T & string>(k: K) => events[k].message;\n const toArray = (rooms?: string[] | string): string[] =>\n rooms == null ? [] : Array.isArray(rooms) ? rooms : [rooms];\n const emitToTargets = <K extends keyof T & string>(\n eventName: K,\n payload: Payload<T, K>,\n targets: string[],\n metadata?: Record<string, unknown>,\n ) => {\n const schema = getSchema(eventName);\n const check = schema.safeParse(payload);\n if (!check.success) {\n dbg(String(eventName), {\n type: 'emit',\n event: String(eventName),\n rooms: targets,\n ...(opts?.debug?.verbose ? { attemptedPayload: payload } : {}),\n error: {\n reason: 'invalid_payload',\n message: check.error.message,\n issues: check.error.issues\n },\n metadata\n });\n throw new Error(`Invalid payload for \"${String(eventName)}\": ${check.error.message}`);\n }\n\n const envelope = {\n eventName,\n sentAt: new Date(),\n sentTo: targets,\n data: check.data as Payload<T, K>,\n metadata: metadata ?? {},\n };\n\n if (targets.length === 0) io.emit(String(eventName), envelope);\n else if (targets.length === 1) {\n const sid = targets[0]!;\n const sock = io.sockets.sockets.get(sid as any);\n if (sock) {\n sock.emit(String(eventName), envelope);\n }else{\n io.to(targets).emit(String(eventName), envelope);\n }\n } else{\n io.to(targets).emit(String(eventName), envelope);\n }\n\n dbg(String(eventName), {\n type: 'emit',\n event: String(eventName),\n rooms: targets,\n envelope: opts?.debug?.verbose ? envelope : undefined,\n });\n };\n const createSocketHelper = (socket: Socket): SocketConnectionHelper<T> => ({\n emit<K extends keyof T & string>(\n eventName: K,\n payload: Payload<T, K>,\n metadata?: Record<string, unknown>,\n ) {\n emitToTargets(eventName, payload, [socket.id], metadata);\n },\n });\n\n // registrations\n const registrations = new Map<\n string,\n Set<{\n connectionListener: (socket: Socket) => void;\n socketListeners: WeakMap<Socket, (raw: unknown) => void>;\n }>\n >();\n\n const addRegistration = (\n eventName: string,\n reg: {\n connectionListener: (socket: Socket) => void;\n socketListeners: WeakMap<Socket, (raw: unknown) => void>;\n }\n ) => {\n let set = registrations.get(eventName);\n if (!set) {\n set = new Set();\n registrations.set(eventName, set);\n }\n set.add(reg);\n };\n\n const removeAllForEvent = (eventName: string) => {\n const set = registrations.get(eventName);\n if (!set) {\n dbg(null, {\n type: 'register',\n event: eventName,\n action: 'unregister',\nmsg:'no handlers registered'\n });\n return;\n }\n for (const reg of set) {\n io.off('connection', reg.connectionListener);\n for (const socket of io.sockets.sockets.values()) {\n const wrapped = reg.socketListeners.get(socket);\n if (wrapped) socket.off(String(eventName), wrapped);\n }\n }\n registrations.delete(eventName);\n dbg(eventName, { type: 'register', action: 'unregister', event: eventName, msg:'unregistered' });\n };\n\n const {\n builtInConnectionListener,\n socketTeardowns,\n roomJoinEvent,\n roomLeaveEvent,\n pingEvent,\n } = createBuiltInConnectionHandlers<TConfig, T>({\n heartbeat: opts?.heartbeat,\n sys: opts.sys,\n dbg,\n config: socketConfig,\n createCtx: createBaseHandlerCtx,\n debugVerbose: opts?.debug?.verbose === true,\n createHelper: createSocketHelper,\n });\n\n // install built-in connection listener\n io.on('connection', builtInConnectionListener);\n\n const conn = {\n on<K extends keyof T & string>(\n eventName: K,\n handler: (payload: Payload<T, K>, ctx: HandlerCtx) => void | Promise<void>\n ): () => void {\n const socketListeners = new WeakMap<Socket, (raw: unknown) => void>();\n\n const connectionListener = (socket: Socket) => {\n const wrapped = async (raw: unknown) => {\n const schema = getSchema(eventName);\n const parsed = schema.safeParse(raw);\n\n const ctx = createBaseHandlerCtx(socket);\n\n dbg(String(eventName), {\n type: 'handler',\n phase: 'receive',\n event: String(eventName),\n socketId: ctx.socketId,\n nsp: ctx.nsp,\n rooms: ctx.rooms,\n raw: opts?.debug?.verbose ? raw : undefined,\n });\n\n if (!parsed.success) {\n socket.emit(`${String(eventName)}:error`, {\n eventName,\n sentAt: ctx.sentAt,\n issues: parsed.error.issues,\n });\n dbg(String(eventName), {\n type: 'handler',\n phase: 'validation_error',\n event: String(eventName),\n socketId: ctx.socketId,\n nsp: ctx.nsp,\n issues: parsed.error.issues,\n });\n return;\n }\n\n try {\n await handler(parsed.data as Payload<T, K>, ctx);\n dbg(String(eventName), {\n type: 'handler',\n phase: 'handler_success',\n event: String(eventName),\n socketId: ctx.socketId,\n nsp: ctx.nsp,\n rooms: ctx.rooms,\n });\n } catch (error) {\n dbg(String(eventName), {\n type: 'handler',\n phase: 'handler_error',\n event: String(eventName),\n socketId: ctx.socketId,\n nsp: ctx.nsp,\n rooms: ctx.rooms,\n error,\n });\n socket.emit(`${String(eventName)}:error`, {\n eventName,\n sentAt: ctx.sentAt,\n error: normalizeError(error, opts?.debug?.verbose),\n });\n }\n };\n\n socketListeners.set(socket, wrapped);\n socket.on(String(eventName), wrapped);\n socket.once('disconnect', () => {\n const w = socketListeners.get(socket);\n if (w) socket.off(String(eventName), w);\n });\n };\n\n io.on('connection', connectionListener);\n addRegistration(String(eventName), { connectionListener, socketListeners });\n dbg(String(eventName), {\n type: 'register',\n action: 'register',\n event: String(eventName),\n });\n\n return () => {\n const set = registrations.get(String(eventName));\n if (!set) {\n dbg(null, {\n type: 'register',\n action:'unregister',\n event: String(eventName),msg:`No registration under ${eventName}`\n });\n return;\n }\n for (const reg of Array.from(set)) {\n if (reg.connectionListener === connectionListener) {\n io.off('connection', reg.connectionListener);\n for (const socket of io.sockets.sockets.values()) {\n const wrapped = reg.socketListeners.get(socket);\n if (wrapped) socket.off(String(eventName), wrapped);\n }\n set.delete(reg);\n break;\n }\n }\n if (set.size === 0) registrations.delete(String(eventName));\n dbg(String(eventName), {\n type: 'register',\n action: 'unregister',\n event: String(eventName),\n });\n };\n },\n\n off<K extends keyof T & string>(eventName: K): void {\n removeAllForEvent(String(eventName));\n },\n\n emit<K extends keyof T & string>(\n eventName: K,\n payload: Payload<T, K>,\n rooms?: string[] | string,\n metadata?: Record<string, unknown>,\n ): void {\n const targets = toArray(rooms);\n emitToTargets(eventName, payload, targets, metadata);\n },\n\n destroy(): void {\n dbg(null, {\n type: 'lifecycle',\n stage: 'destroy_start',\n details: {\n socketCount: io.sockets.sockets.size,\n registrationCount: registrations.size,\n },\n });\n // 1) Remove built-in connection listener so no new sockets get handlers\n io.off('connection', builtInConnectionListener);\n\n // 2) Cleanup built-in handlers for all current sockets and leave rooms\n for (const socket of io.sockets.sockets.values()) {\n const cleanup = socketTeardowns.get(socket);\n if (cleanup) {\n cleanup();\n socketTeardowns.delete(socket);\n } else {\n dbg(null, {\n type: 'lifecycle',\n stage: 'connection_cleanup_fallback',\n socketId: socket.id,\n nsp: socket.nsp.name,\n details: { reason: 'teardown_missing' },\n });\n // Fallback if socket was attached before map population\n try {\n socket.removeAllListeners(roomJoinEvent);\n socket.removeAllListeners(roomLeaveEvent);\n socket.removeAllListeners(pingEvent);\n } catch {\n // noop\n }\n }\n }\n\n // 3) Remove all user-registered event listeners and their connection hooks\n for (const eventName of Array.from(registrations.keys())) {\n removeAllForEvent(eventName);\n }\n\n // 4) Defensive: clear any residual maps\n registrations.clear();\n dbg(null, {\n type: 'lifecycle',\n stage: 'destroy_complete',\n details: {\n socketCount: io.sockets.sockets.size,\n registrationCount: registrations.size,\n },\n });\n },\n } as const satisfies SocketConnection<T>;\n\n return conn;\n}\n\nexport type { EventMap, Payload };\nexport type { HandlerCtx } from './socket.server.types';\nexport type {\n SocketServerDebugEvent,\n SocketDebugOptions,\n SocketServerConfigSnapshot,\n SocketServerLifecycleStage,\n SocketServerHeartbeatPhase,\n} from './socket.server.debug';\nexport type {\n HeartbeatServerOptions,\n SocketConnectionHelper,\n SysServerEventMap,\n} from './socket.server.sys';\n","import type { IncomingHttpHeaders } from 'http';\nimport type { Socket } from 'socket.io';\n\nexport type ConnectionMiddlewareStage = 'incoming';\n\nexport type ConnectionMiddlewareContext = {\n socketId?: string;\n nsp?: string;\n rooms: string[];\n user?: unknown;\n scopes?: string[];\n address?: string;\n transport?: string;\n protocol?: string;\n handshake: {\n url?: string;\n issued?: number;\n time?: string;\n query?: Record<string, unknown>;\n auth?: Record<string, unknown>;\n headers?: IncomingHttpHeaders;\n };\n};\n\nexport type ConnectionMiddlewareEvent = {\n type: 'connection';\n stage: ConnectionMiddlewareStage;\n timestamp: Date;\n context: ConnectionMiddlewareContext;\n};\n\nexport type ConnectionLoggingMiddlewareOptions = {\n /**\n * Custom logger invoked with the structured event.\n * Defaults to console.info.\n */\n logger?: (event: ConnectionMiddlewareEvent) => void;\n /**\n * Include raw headers from the handshake. Defaults to false to avoid leaking PII.\n */\n includeHeaders?: boolean;\n /**\n * List of auth keys that should be redacted (case-insensitive). Defaults to ['authorization'].\n */\n redactAuthKeys?: string[];\n};\n\nconst defaultRedactedValue = '[REDACTED]';\n\nconst defaultLogger = (event: ConnectionMiddlewareEvent) => {\n const {\n stage,\n context: { socketId, nsp, address, transport, handshake },\n } = event;\n // eslint-disable-next-line no-console\n console.info('[socket-connection]', {\n stage,\n socketId,\n nsp,\n address,\n transport,\n url: handshake.url,\n query: handshake.query,\n auth: handshake.auth,\n });\n};\n\nconst redactAuth = (\n auth: Record<string, unknown> | undefined,\n redactKeys: Set<string>\n): Record<string, unknown> | undefined => {\n if (!auth) return undefined;\n if (redactKeys.size === 0) return auth;\n\n const clone: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(auth)) {\n const normalizedKey = key.toLowerCase();\n clone[key] = redactKeys.has(normalizedKey) ? defaultRedactedValue : value;\n }\n return clone;\n};\n\nconst buildContext = (\n socket: Socket,\n includeHeaders: boolean,\n redactKeys: Set<string>\n): ConnectionMiddlewareContext => {\n const conn = socket.conn as\n | {\n remoteAddress?: string;\n transport?: { name?: string };\n protocol?: string | number;\n }\n | undefined;\n\n const handshake = socket.handshake ?? {};\n\n const protocolValue = conn?.protocol;\n\n return {\n socketId: socket.id,\n nsp: socket.nsp?.name,\n rooms: Array.from(socket.rooms ?? []),\n user: (socket.data as any)?.user,\n scopes: (socket.data as any)?.scopes,\n address: conn?.remoteAddress ?? (handshake as any).address,\n transport: conn?.transport?.name,\n protocol: protocolValue != null ? String(protocolValue) : undefined,\n handshake: {\n url: handshake.url,\n issued: handshake.issued,\n time: handshake.time,\n query: handshake.query as Record<string, unknown>,\n auth: redactAuth(handshake.auth as Record<string, unknown>, redactKeys),\n headers: includeHeaders ? (handshake.headers as IncomingHttpHeaders) : undefined,\n },\n };\n};\n\nexport const createConnectionLoggingMiddleware = (\n options: ConnectionLoggingMiddlewareOptions = {}\n) => {\n const logger = options.logger ?? defaultLogger;\n const includeHeaders = options.includeHeaders ?? false;\n const redactKeys = new Set(\n (options.redactAuthKeys ?? ['authorization', 'token']).map((key) => key.toLowerCase())\n );\n\n return (socket: Socket, next: (err?: Error) => void) => {\n const context = buildContext(socket, includeHeaders, redactKeys);\n logger({\n type: 'connection',\n stage: 'incoming',\n timestamp: new Date(),\n context,\n });\n next();\n };\n};\n\nexport type ConnectionLoggingMiddleware = ReturnType<typeof createConnectionLoggingMiddleware>;\n"],"mappings":"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","names":["normalizeError","toArray"]}
1
+ {"version":3,"sources":["../src/routesV3.server.ts","../src/sockets/socket.server.debug.ts","../src/sockets/socket.server.sys.ts","../src/sockets/socket.server.index.ts","../src/sockets/socket.server.middleware.ts"],"sourcesContent":["/**\n * routesV3.server.ts\n * -----------------------------------------------------------------------------\n * Bind an Express router/app to a `finalize(...)` registry of AnyLeafs.\n * - Fully typed handlers (params/query/body/output)\n * - Zod parsing + optional output validation\n * - buildCtx runs as a middleware *first*, before all other middlewares\n * - Global, per-route, and cfg-derived middlewares (auth, uploads)\n * - Helper to warn about unimplemented routes\n * - DX helpers to use `ctx` in any middleware with proper types\n */\n\nimport { AnyLeaf, FileField, HttpMethod, InferBody, InferOutput, InferParams, InferQuery, MethodCfg } from '@emeryld/rrroutes-contract';\nimport type * as express from 'express';\nimport type { RequestHandler, Router } from 'express';\nimport type { ZodType } from 'zod';\n\n\n\n/** Shape expected from optional logger implementations. */\nexport type LoggerLike = {\n info?: (...args: any[]) => void;\n warn?: (...args: any[]) => void;\n error?: (...args: any[]) => void;\n debug?: (...args: any[]) => void;\n verbose?: (...args: any[]) => void;\n system?: (...args: any[]) => void;\n log?: (...args: any[]) => void;\n};\n\ntype RoutesLoggerCarrier = {\n routesLogger?: LoggerLike;\n};\n\ntype CtxWithRoutesLogger<Ctx> = Ctx & RoutesLoggerCarrier;\n\n// Debug logging --------------------------------------------------------------\nexport type RouteServerDebugMode = 'minimal' | 'complete';\n\ntype RouteServerDebugEventBase = {\n /** Optional logical name assigned via `RouteDef.debug?.debugName` (or `RouteDef.debugName`). */\n name?: string;\n};\n\nexport type RouteServerDebugEvent =\n | (RouteServerDebugEventBase & {\n type: 'request';\n stage: 'start' | 'success' | 'error';\n method: Uppercase<HttpMethod>;\n path: string;\n url: string;\n durationMs?: number;\n params?: unknown;\n query?: unknown;\n body?: unknown;\n output?: unknown;\n error?: unknown;\n })\n | (RouteServerDebugEventBase & {\n type: 'register';\n method: Uppercase<HttpMethod>;\n path: string;\n })\n | (RouteServerDebugEventBase & {\n type: 'buildCtx';\n stage: 'start' | 'success' | 'error';\n method: Uppercase<HttpMethod>;\n path: string;\n url: string;\n durationMs?: number;\n error?: unknown;\n })\n | (RouteServerDebugEventBase & {\n type: 'handler';\n stage: 'start' | 'success' | 'error';\n method: Uppercase<HttpMethod>;\n path: string;\n durationMs?: number;\n params?: unknown;\n query?: unknown;\n body?: unknown;\n output?: unknown;\n error?: unknown;\n });\n\nexport type RouteServerDebugLogger = (event: RouteServerDebugEvent) => void;\n\n/**\n * Configure server-side debug logging.\n * - Use booleans or `'minimal'/'complete'` for quick toggles.\n * - Pass a custom logger function to redirect structured events.\n * - Provide a map to enable specific event types, opt into verbose payload logging, or restrict logs via `only`.\n */\nexport type RouteServerDebugOptions<Names extends string = string> = RouteServerDebugToggleOptions<Names>;\n\n/**\n * Fine-grained toggle map for server debug logging.\n * Enable individual event types, opt into verbose payload logging, override the logger, or restrict to named routes.\n * Use `RouteDef.debug?.debugName` (or the deprecated `RouteDef.debugName`) to set the name that `only` will match against.\n */\nexport type RouteServerDebugToggleOptions<Names extends string = string> = Partial<\n Record<RouteServerDebugEvent['type'], boolean>\n> & {\n verbose?: boolean;\n logger?: RouteServerDebugLogger;\n only?: Names[];\n};\n\n/**\n * Per-route debug overrides. Same toggles as `RouteServerDebugOptions`, but limited to a single route\n * and therefore replaces the `only` filter with a local `debugName`.\n */\nexport type RouteDefDebugOptions<Names extends string = string> = Omit<\n RouteServerDebugToggleOptions<Names>,\n 'only'\n> & {\n debugName?: Names;\n};\n\nconst serverDebugEventTypes: RouteServerDebugEvent['type'][] = [\n 'register',\n 'request',\n 'buildCtx',\n 'handler',\n];\n\ntype ServerDebugEmitter<Names extends string> = {\n emit: (event: RouteServerDebugEvent, name?: Names) => void;\n mode: RouteServerDebugMode;\n};\n\nconst noopServerEmit = () => {};\n\nfunction createServerDebugEmitter<Names extends string>(\n option?: RouteServerDebugOptions<Names>,\n): ServerDebugEmitter<Names> {\n const disabled: ServerDebugEmitter<Names> = { emit: noopServerEmit, mode: 'minimal' };\n if (!option) return disabled;\n\n if (typeof option === 'object') {\n const toggles = option as RouteServerDebugToggleOptions<Names>;\n const verbose = Boolean(toggles.verbose);\n const enabledTypes = serverDebugEventTypes.filter((type) => toggles[type]);\n if (enabledTypes.length === 0) {\n return { emit: noopServerEmit, mode: verbose ? 'complete' : 'minimal' };\n }\n const whitelist = new Set<RouteServerDebugEvent['type']>(enabledTypes);\n const onlySet =\n toggles.only && toggles.only.length > 0 ? new Set<Names>(toggles.only) : undefined;\n const logger = toggles.logger;\n const emit: ServerDebugEmitter<Names>['emit'] = (event, name) => {\n if (!whitelist.has(event.type) || !logger) return;\n if (onlySet && (!name || !onlySet.has(name))) return;\n logger(name ? { ...event, name } : event);\n };\n return { emit, mode: verbose ? 'complete' : 'minimal' };\n }\n\n return disabled;\n}\n\n// ──────────────────────────────────────────────────────────────────────────────\n// Keys + leaf helpers (derive keys from byKey to avoid template-literal pitfalls)\n// ──────────────────────────────────────────────────────────────────────────────\n\n/** Keys like \"GET /v1/foo\" that *actually* exist in the registry */\nexport type KeysOfRegistry<R extends { byKey: Record<string, AnyLeaf> }> = keyof R['byKey'] &\n string;\n\ntype MethodFromKey<K extends string> = K extends `${infer M} ${string}` ? Lowercase<M> : never;\ntype PathFromKey<K extends string> = K extends `${string} ${infer P}` ? P : never;\n\n/** Given a registry and a key, pick the exact leaf for that method+path */\nexport type LeafFromKey<R extends { all: readonly AnyLeaf[] }, K extends string> = Extract<\n R['all'][number],\n { method: MethodFromKey<K> & HttpMethod; path: PathFromKey<K> }\n>;\n\n/** Optional-ify types if your core returns `never` when a schema isn't defined */\ntype Maybe<T> = [T] extends [never] ? undefined : T;\n\n/** Typed params argument exposed to handlers. */\nexport type ArgParams<L extends AnyLeaf> = Maybe<InferParams<L>>;\n/** Typed query argument exposed to handlers. */\nexport type ArgQuery<L extends AnyLeaf> = Maybe<InferQuery<L>>;\n/** Typed body argument exposed to handlers. */\nexport type ArgBody<L extends AnyLeaf> = Maybe<InferBody<L>>;\n\n/**\n * Convenience to compute a `\"METHOD /path\"` key from a leaf.\n * @param leaf Leaf describing the route.\n * @returns Uppercase method + path key.\n */\nexport const keyOf = (leaf: AnyLeaf) => `${leaf.method.toUpperCase()} ${leaf.path}` as const;\n\n// ──────────────────────────────────────────────────────────────────────────────\n// Context typing & DX helpers (so ctx is usable in *any* middleware)\n// ──────────────────────────────────────────────────────────────────────────────\n\n/**\n * Unique symbol used to stash ctx on res.locals.\n * (Symbols are safer than string keys against collisions.)\n */\nexport const CTX_SYMBOL: unique symbol = Symbol.for('typedLeaves.ctx');\n\nconst AFTER_HANDLER_NEXT_SYMBOL: unique symbol = Symbol.for('typedLeaves.afterHandlerNext');\n\nfunction setAfterHandlerNext(res: express.Response, value: boolean) {\n (res.locals as any)[AFTER_HANDLER_NEXT_SYMBOL] = value;\n}\n\nfunction handlerInvokedNext(res: express.Response): boolean {\n return Boolean((res.locals as any)[AFTER_HANDLER_NEXT_SYMBOL]);\n}\n\n/** Response type that *has* a ctx on locals for DX in middlewares */\nexport type ResponseWithCtx<Ctx> =\n // Replace locals with an intersection that guarantees CTX_SYMBOL exists\n Omit<express.Response, 'locals'> & {\n locals: express.Response['locals'] & { [CTX_SYMBOL]: CtxWithRoutesLogger<Ctx> };\n };\n\n/** A middleware signature that can *use* ctx via `res.locals[CTX_SYMBOL]` */\nexport type CtxRequestHandler<Ctx> = (args: {\n req: express.Request;\n res: express.Response;\n next: express.NextFunction;\n ctx: CtxWithRoutesLogger<Ctx>;\n}) => any;\n\n/**\n * Safely read ctx from any Response.\n * @param res Express response whose locals contain the ctx symbol.\n * @returns Strongly typed context object.\n */\nexport function getCtx<Ctx = unknown>(res: express.Response): CtxWithRoutesLogger<Ctx> {\n return (res.locals as any)[CTX_SYMBOL] as CtxWithRoutesLogger<Ctx>;\n}\n\n/**\n * Wrap a ctx-typed middleware to a plain RequestHandler (for arrays, etc.).\n * @param mw Middleware that expects a typed response with ctx available.\n * @returns Standard Express request handler.\n */\nfunction adaptCtxMw<Ctx>(mw: CtxRequestHandler<Ctx>): RequestHandler {\n return (req, res, next) => {\n try {\n const result = mw({ req, res, next, ctx: getCtx<Ctx>(res) });\n if (result && typeof (result as Promise<unknown>).then === 'function') {\n return (result as Promise<unknown>).catch((err) => next(err));\n }\n return result as any;\n } catch (err) {\n next(err as any);\n return undefined;\n }\n };\n}\n\nfunction adaptAfterMw<Ctx>(mw: CtxRequestHandler<Ctx>): RequestHandler {\n const adapted = adaptCtxMw<Ctx>(mw);\n return (req: express.Request, res: express.Response, next: express.NextFunction) => {\n if (!handlerInvokedNext(res)) {\n next();\n return;\n }\n adapted(req, res, next);\n };\n}\n\nfunction mapAfterMiddleware<Ctx>(mws?: Array<CtxRequestHandler<Ctx>>): RequestHandler[] {\n return (mws ?? []).map((mw) => adaptAfterMw<Ctx>(mw));\n}\n\nfunction logHandlerDebugWithRoutesLogger(\n logger: LoggerLike | undefined,\n event: RouteServerDebugEvent,\n) {\n if (!logger || event.type !== 'handler') return;\n const payload: [string, RouteServerDebugEvent] = [\n `[rrroutes-server][handler:${event.stage}] ${event.method} ${event.path}`,\n event,\n ];\n if (event.stage === 'error') {\n (\n logger.error ??\n logger.warn ??\n logger.debug ??\n logger.info ??\n logger.log ??\n logger.system\n )?.call(logger, ...payload);\n return;\n }\n (\n logger.debug ??\n logger.verbose ??\n logger.info ??\n logger.log ??\n logger.system\n )?.call(logger, ...payload);\n}\n\n// ──────────────────────────────────────────────────────────────────────────────\n// Controller types — object form only (simpler, clearer typings)\n// ──────────────────────────────────────────────────────────────────────────────\n\n/** Typed route handler for a specific leaf */\nexport type Handler<L extends AnyLeaf, Ctx = unknown> = (args: {\n req: express.Request;\n res: express.Response;\n next: express.NextFunction;\n ctx: CtxWithRoutesLogger<Ctx>;\n params: ArgParams<L>;\n query: ArgQuery<L>;\n body: ArgBody<L>;\n}) => Promise<InferOutput<L>> | InferOutput<L>;\n\n/** Route definition for one key */\nexport type RouteDef<L extends AnyLeaf, Ctx = unknown, Names extends string = string> = {\n /** Middlewares before the handler (run after buildCtx/global/derived) */\n use?: Array<CtxRequestHandler<Ctx>>;\n /** Middlewares after the handler *if* it calls next() */\n after?: Array<CtxRequestHandler<Ctx>>;\n /** Your business logic */\n handler: Handler<L, Ctx>;\n /**\n * Optional per-route debug overrides. When provided, these replace the global debug options.\n */\n debug?: RouteDefDebugOptions<Names>;\n /**\n * Optional logical name used for debug filtering. Prefer `debug.debugName`; this field remains for backwards compatibility.\n */\n debugName?: Names;\n};\n\n/** Map of registry keys -> route defs */\nexport type ControllerMap<\n R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> },\n Ctx = unknown,\n Names extends string = string,\n> = {\n [P in KeysOfRegistry<R>]: RouteDef<LeafFromKey<R, P>, Ctx, Names>;\n};\n\nexport type PartialControllerMap<\n R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> },\n Ctx = unknown,\n Names extends string = string,\n> = Partial<ControllerMap<R, Ctx, Names>>;\n\n// ──────────────────────────────────────────────────────────────────────────────\n/** Options + derivation helpers */\n// ──────────────────────────────────────────────────────────────────────────────\n\nexport type RouteServerConfig<Ctx = unknown, Names extends string = string> = {\n /**\n * Build a request-scoped context. We wrap this in a middleware that runs\n * *first* (before global/derived/route middlewares), and stash it on\n * `res.locals[CTX_SYMBOL]` so *all* later middlewares can use it.\n * You can optionally include `routesLogger` to override handler debug logging per request.\n */\n buildCtx: (\n req: express.Request,\n res: express.Response,\n ) => CtxWithRoutesLogger<Ctx> | Promise<CtxWithRoutesLogger<Ctx>>;\n\n /**\n * Grouped global middlewares that run *before* or *after* the handler for every route.\n */\n globalMiddleware?: {\n before?: Array<CtxRequestHandler<Ctx>>;\n after?: Array<CtxRequestHandler<Ctx>>;\n };\n\n /**\n * Derive middleware from MethodCfg.\n * - `upload` runs when cfg.bodyFiles has entries\n */\n fromCfg?: {\n upload?: (files: FileField[] | undefined, leaf: AnyLeaf) => RequestHandler[];\n };\n\n /** Validate handler return values with outputSchema (default: true) */\n validateOutput?: boolean;\n\n /** Custom responder (default: res.json(data)) */\n send?: (res: express.Response, data: unknown) => void;\n\n /** Optional logger hooks */\n logger?: LoggerLike;\n\n /**\n * Optional debug logging for the request lifecycle.\n * Supports booleans/modes/loggers, or a toggle map with per-event enabling, verbose payload logging,\n * and `only` filters tied to `RouteDef.debug?.debugName` (or the deprecated `RouteDef.debugName`).\n */\n debug?: RouteServerDebugOptions<Names>;\n};\n\n/** Default JSON responder (typed to avoid implicit-any diagnostics) */\nconst defaultSend: (res: express.Response, data: unknown) => void = (res, data) => {\n res.json(data as any);\n};\n\n// ──────────────────────────────────────────────────────────────────────────────\n// Core builder\n// ──────────────────────────────────────────────────────────────────────────────\n\nconst REGISTERED_ROUTES_SYMBOL = Symbol.for('routesV3.registeredRoutes');\n\ntype RegisteredRouteStore = Set<string>;\n\n/**\n * Retrieve or initialize the shared store of registered route keys.\n * @param router Express router/application that carries previously registered keys.\n * @returns Set of string keys describing registered routes.\n */\nfunction getRegisteredRouteStore(router: Router): RegisteredRouteStore {\n const existing = (router as any)[REGISTERED_ROUTES_SYMBOL] as RegisteredRouteStore | undefined;\n if (existing) return existing;\n const store: RegisteredRouteStore = new Set();\n (router as any)[REGISTERED_ROUTES_SYMBOL] = store;\n return store;\n}\n\n/**\n * Inspect the Express layer stack to discover already-registered routes.\n * @param appOrRouter Express application or router to inspect.\n * @returns All keys in the form `\"METHOD /path\"` found on the stack.\n */\nfunction collectRoutesFromStack(appOrRouter: Router): string[] {\n const result: string[] = [];\n const stack: any[] =\n (appOrRouter as any).stack ??\n ((appOrRouter as any)._router ? (appOrRouter as any)._router.stack : undefined) ??\n [];\n\n if (!Array.isArray(stack)) return result;\n\n for (const layer of stack) {\n const route = layer && layer.route;\n if (!route) continue;\n\n const paths = Array.isArray(route.path) ? route.path : [route.path];\n const methodEntries = Object.entries(route.methods ?? {}).filter(([, enabled]) => enabled);\n\n for (const path of paths) {\n for (const [method] of methodEntries) {\n result.push(`${method.toUpperCase()} ${path}`);\n }\n }\n }\n\n return result;\n}\n\n/** Runtime helpers returned by `createRRRoute`. */\nexport type RouteServer<Ctx = unknown, Names extends string = string> = {\n router: Router;\n register<L extends AnyLeaf>(leaf: L, def: RouteDef<L, Ctx, Names>): void;\n registerControllers<R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> }>(\n registry: R,\n controllers: PartialControllerMap<R, Ctx, Names>,\n ): void;\n warnMissingControllers<R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> }>(\n registry: R,\n logger: { warn: (...args: any[]) => void },\n ): void;\n getRegisteredKeys(): string[];\n};\n\n/**\n * Create an Express binding helper that keeps routes and controllers in sync.\n * @param router Express router or app to register handlers on.\n * @param config Optional configuration controlling ctx building, auth, uploads, etc.\n * @returns Object with helpers to register controllers and inspect registered keys.\n */\nexport function createRRRoute<Ctx = unknown, Names extends string = string>(\n router: Router,\n config: RouteServerConfig<Ctx, Names>,\n): RouteServer<Ctx, Names> {\n const validateOutput = config.validateOutput ?? true;\n const send = config.send ?? defaultSend;\n const logger = config.logger;\n const { emit: defaultEmitDebug, mode: defaultDebugMode } =\n createServerDebugEmitter<Names>(config.debug);\n const decorateDebugEvent = <T extends RouteServerDebugEvent>(\n isVerbose: boolean,\n event: T,\n details?: Partial<RouteServerDebugEvent>,\n ): RouteServerDebugEvent => {\n if (!isVerbose || !details) return event;\n return { ...event, ...details } as RouteServerDebugEvent;\n };\n\n const globalBeforeMws = [ ...(config.globalMiddleware?.before ?? [])].map(\n (mw) => adaptCtxMw<Ctx>(mw),\n );\n const globalAfterMws = mapAfterMiddleware<Ctx>(config.globalMiddleware?.after);\n const registered = getRegisteredRouteStore(router);\n\n const buildDerived = (leaf: AnyLeaf): RequestHandler[] => {\n const derived: RequestHandler[] = [];\n if (\n config.fromCfg?.upload &&\n Array.isArray(leaf.cfg.bodyFiles) &&\n leaf.cfg.bodyFiles.length > 0\n ) {\n derived.push(...config.fromCfg.upload(leaf.cfg.bodyFiles, leaf));\n }\n\n return derived;\n };\n\n /** Register a single leaf/controller pair on the underlying router. */\n function register<L extends AnyLeaf>(leaf: L, def: RouteDef<L, Ctx, Names>) {\n const method = leaf.method as HttpMethod;\n const methodUpper = method.toUpperCase() as Uppercase<HttpMethod>;\n const path = leaf.path as string;\n const key = keyOf(leaf);\n const defDebug = def.debug;\n let debugName = def.debugName as Names | undefined;\n let routeDebugEmitter: ServerDebugEmitter<Names> | undefined;\n if (defDebug) {\n const { debugName: overrideName, ...rest } = defDebug;\n const hasOverrides = Object.values(rest).some((value) => value !== undefined);\n if (hasOverrides) {\n routeDebugEmitter = createServerDebugEmitter<Names>(\n rest as RouteServerDebugOptions<Names>,\n );\n }\n debugName = (overrideName ?? debugName) as Names | undefined;\n }\n const activeEmit = routeDebugEmitter?.emit ?? defaultEmitDebug;\n const activeDebugMode = routeDebugEmitter?.mode ?? defaultDebugMode;\n const emit = (event: RouteServerDebugEvent) => activeEmit(event, debugName);\n const isVerboseDebug = activeDebugMode === 'complete';\n emit({ type: 'register', method: methodUpper, path });\n\n const routeSpecific = (def?.use ?? []).map((mw) => adaptCtxMw<Ctx>(mw));\n const derived = buildDerived(leaf);\n const ctxMw: RequestHandler = async (req, res, next) => {\n const requestUrl = req.originalUrl ?? path;\n const startedAt = Date.now();\n emit({ type: 'buildCtx', stage: 'start', method: methodUpper, path, url: requestUrl });\n try {\n const ctx = await config.buildCtx(req, res);\n (res.locals as any)[CTX_SYMBOL] = ctx;\n emit({\n type: 'buildCtx',\n stage: 'success',\n method: methodUpper,\n path,\n url: requestUrl,\n durationMs: Date.now() - startedAt,\n });\n next();\n } catch (err) {\n emit({\n type: 'buildCtx',\n stage: 'error',\n method: methodUpper,\n path,\n url: requestUrl,\n durationMs: Date.now() - startedAt,\n error: err,\n });\n logger?.error?.('buildCtx error', err);\n next(err as any);\n }\n };\n const before: RequestHandler[] = [ctxMw, ...globalBeforeMws, ...derived, ...routeSpecific];\n\n const wrapped: RequestHandler = async (req, res, next) => {\n const requestUrl = req.originalUrl.split('?')[0] ?? path;\n const startedAt = Date.now();\n emit({ type: 'request', stage: 'start', method: methodUpper, path, url: requestUrl });\n let params: ArgParams<L> | undefined;\n let query: ArgQuery<L> | undefined;\n let body: ArgBody<L> | undefined;\n let responsePayload: InferOutput<L> | undefined;\n let hasResponsePayload = false;\n setAfterHandlerNext(res, false);\n let handlerCalledNext = false;\n const downstreamNext: express.NextFunction = (err?: any) => {\n handlerCalledNext = true;\n setAfterHandlerNext(res, true);\n next(err);\n };\n\n logger?.info?.(`${methodUpper}@${path} (${requestUrl})`);\n const ctx = (res.locals as any)[CTX_SYMBOL] as CtxWithRoutesLogger<Ctx>;\n const ctxRoutesLogger = ctx?.routesLogger;\n const emitWithCtx = (\n event: RouteServerDebugEvent,\n details?: Partial<RouteServerDebugEvent>,\n ) => {\n const decorated = decorateDebugEvent(isVerboseDebug, event, details);\n if (decorated.type === 'handler' && ctxRoutesLogger) {\n logHandlerDebugWithRoutesLogger(ctxRoutesLogger, decorated);\n }else{\n emit(decorated);\n }\n };\n try {\n params = (\n leaf.cfg.paramsSchema\n ? (leaf.cfg.paramsSchema as ZodType).parse(req.params)\n : Object.keys(req.params || {}).length\n ? (req.params as any)\n : undefined\n ) as ArgParams<L>;\n\n try {\n query = leaf.cfg.querySchema\n ? (leaf.cfg.querySchema as ZodType).parse(req.query)\n : Object.keys(req.query || {}).length\n ? (req.query as any)\n : undefined;\n } catch (e) {\n logger?.error?.('Query parsing error', {\n path,\n method: methodUpper,\n error: e,\n raw: JSON.stringify(req.query),\n });\n throw e;\n }\n\n body = (\n leaf.cfg.bodySchema\n ? (leaf.cfg.bodySchema as ZodType).parse(req.body)\n : req.body !== undefined\n ? (req.body as any)\n : undefined\n ) as ArgBody<L>;\n\n logger?.verbose?.(`${methodUpper}@${path} (${requestUrl})`, {\n params,\n query,\n body,\n });\n\n const handlerStartedAt = Date.now();\n emitWithCtx(\n {\n type: 'handler',\n stage: 'start',\n method: methodUpper,\n path,\n },\n isVerboseDebug ? { params, query, body } : undefined,\n );\n\n let result;\n try {\n result = await def.handler({\n req,\n res,\n next: downstreamNext,\n ctx,\n params: params as ArgParams<L>,\n query: query as ArgQuery<L>,\n body: body as ArgBody<L>,\n });\n emitWithCtx(\n {\n type: 'handler',\n stage: 'success',\n method: methodUpper,\n path,\n durationMs: Date.now() - handlerStartedAt,\n },\n isVerboseDebug\n ? {\n params,\n query,\n body,\n ...(result !== undefined ? { output: result } : {}),\n }\n : undefined,\n );\n } catch (e) {\n emitWithCtx(\n {\n type: 'handler',\n stage: 'error',\n method: methodUpper,\n path,\n durationMs: Date.now() - handlerStartedAt,\n error: e,\n },\n isVerboseDebug ? { params, query, body } : undefined,\n );\n logger?.error?.('Handler error', e);\n throw e;\n }\n\n if (!res.headersSent) {\n if (result !== undefined) {\n const out =\n validateOutput && leaf.cfg.outputSchema\n ? (leaf.cfg.outputSchema as ZodType).parse(result)\n : result;\n responsePayload = out as InferOutput<L>;\n hasResponsePayload = true;\n logger?.verbose?.(`${methodUpper}@${path} result`, out);\n send(res, out);\n } else if (!handlerCalledNext) {\n next();\n }\n }\n\n emitWithCtx(\n {\n type: 'request',\n stage: 'success',\n method: methodUpper,\n path,\n url: requestUrl,\n durationMs: Date.now() - startedAt,\n },\n isVerboseDebug\n ? {\n params,\n query,\n body,\n ...(hasResponsePayload ? { output: responsePayload } : {}),\n }\n : undefined,\n );\n } catch (err) {\n emitWithCtx(\n {\n type: 'request',\n stage: 'error',\n method: methodUpper,\n path,\n url: requestUrl,\n durationMs: Date.now() - startedAt,\n error: err,\n },\n isVerboseDebug ? { params, query, body } : undefined,\n );\n logger?.error?.('Route error', err);\n next(err as any);\n }\n };\n\n const after = [...mapAfterMiddleware<Ctx>(def?.after), ...globalAfterMws];\n (router as any)[method](path, ...before, wrapped, ...after);\n registered.add(key);\n }\n\n /**\n * Register controller definitions for the provided keys.\n * @param registry Finalized registry of leaves.\n * @param controllers Partial controller map keyed by `\"METHOD /path\"`.\n */\n function registerControllers<\n R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> },\n >(registry: R, controllers: PartialControllerMap<R, Ctx, Names>) {\n (Object.keys(controllers) as Array<KeysOfRegistry<R>>).forEach((key) => {\n const leaf = registry.byKey[key] as unknown as LeafFromKey<R, typeof key> | undefined;\n if (!leaf) {\n logger?.warn?.(`No leaf found for controller key: ${key}. Not registering route.`);\n return;\n }\n const def = controllers[key];\n if (!def) return;\n register(leaf as LeafFromKey<R, typeof key>, def);\n });\n }\n\n /**\n * Warn about leaves that do not have a registered controller.\n * @param registry Finalized registry of leaves.\n * @param warnLogger Logger used for warning output.\n */\n function warnMissing<R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> }>(\n registry: R,\n warnLogger: { warn: (...args: any[]) => void },\n ) {\n const registeredFromStore = new Set<string>(Array.from(registered));\n if (registeredFromStore.size === 0) {\n collectRoutesFromStack(router).forEach((key) => registeredFromStore.add(key));\n }\n for (const leaf of registry.all) {\n const key = keyOf(leaf);\n if (!registeredFromStore.has(key)) {\n warnLogger.warn(`No controller registered for route: ${key}`);\n }\n }\n }\n\n return {\n router,\n register,\n registerControllers,\n warnMissingControllers: warnMissing,\n getRegisteredKeys: () => Array.from(registered),\n };\n}\n\n/**\n * Bind only the controllers that are present in the provided map.\n * @param router Express router or app.\n * @param registry Finalized registry produced by `finalize(...)`.\n * @param controllers Partial map of controllers keyed by `\"METHOD /path\"`.\n * @param config Optional route server configuration.\n * @returns The same router instance for chaining.\n */\nexport function bindExpressRoutes<\n R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> },\n Ctx = unknown,\n Names extends string = string,\n>(\n router: Router,\n registry: R,\n controllers: PartialControllerMap<R, Ctx, Names>,\n config: RouteServerConfig<Ctx, Names>,\n) {\n const server = createRRRoute<Ctx, Names>(router, config);\n server.registerControllers(registry, controllers);\n return router;\n}\n\n/**\n * Bind controllers for every leaf. Missing entries fail at compile time.\n * @param router Express router or app.\n * @param registry Finalized registry produced by `finalize(...)`.\n * @param controllers Complete map of controllers keyed by `\"METHOD /path\"`.\n * @param config Optional route server configuration.\n * @returns The same router instance for chaining.\n */\nexport function bindAll<\n R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> },\n Ctx = unknown,\n Names extends string = string,\n>(\n router: Router,\n registry: R,\n controllers: { [K in KeysOfRegistry<R>]: RouteDef<LeafFromKey<R, K>, Ctx, Names> },\n config: RouteServerConfig<Ctx, Names>,\n) {\n const server = createRRRoute<Ctx, Names>(router, config);\n server.registerControllers(registry, controllers);\n return router;\n}\n\n// ──────────────────────────────────────────────────────────────────────────────\n// DX helpers\n// ──────────────────────────────────────────────────────────────────────────────\n\n/**\n * Helper for great IntelliSense when authoring controller maps.\n * @returns Function that enforces key names while preserving partial flexibility.\n */\nexport const defineControllers =\n <\n R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> },\n Ctx = unknown,\n Names extends string = string,\n >() =>\n <M extends PartialControllerMap<R, Ctx, Names>>(m: M) =>\n m;\n\n/**\n * Warn about leaves that don't have controllers.\n * Call this during startup to surface missing routes.\n * @param router Express router or app to inspect.\n * @param registry Finalized registry produced by `finalize(...)`.\n * @param logger Logger where warnings are emitted.\n */\nexport function warnMissingControllers<\n R extends { all: readonly AnyLeaf[]; byKey: Record<string, AnyLeaf> },\n>(router: Router, registry: R, logger: { warn: (...args: any[]) => void }) {\n const registeredStore = (router as any)[REGISTERED_ROUTES_SYMBOL] as Set<string> | undefined;\n const initial = registeredStore ? Array.from(registeredStore) : collectRoutesFromStack(router);\n const registeredKeys = new Set<string>(initial);\n\n for (const leaf of registry.all) {\n const k = keyOf(leaf);\n if (!registeredKeys.has(k)) {\n logger.warn(`No controller registered for route: ${k}`);\n }\n }\n}\n","// socket.server.debug.ts\nimport type { IncomingHttpHeaders } from 'http';\n\nexport type SocketServerConfigSnapshot = {\n url?: string;\n transport?: string;\n protocol?: string;\n address?: string;\n issued?: number;\n time?: string;\n query?: Record<string, unknown>;\n auth?: Record<string, unknown>;\n headers?: IncomingHttpHeaders;\n};\n\nexport type SocketServerLifecycleStage =\n | 'server_init'\n | 'connection_listener_installed'\n | 'connection_init'\n | 'connection_handlers_attached'\n | 'connection_cleanup'\n | 'destroy_start'\n | 'destroy_complete'\n | 'connection_cleanup_fallback';\n\nexport type SocketServerHeartbeatPhase = 'ping' | 'pong' | 'skip';\n\nexport type SocketServerDebugEvent =\n | {\n type: 'register';\n action: 'register' | 'unregister';\n event: string;\n msg?:string;\n }\n | {\n type: 'handler';\n phase: 'receive' | 'validation_error' | 'handler_success' | 'handler_error';\n event: string;\n socketId?: string;\n nsp?: string;\n rooms?: string[];\n raw?: unknown;\n issues?: any[];\n error?: unknown;\n details?: Record<string, unknown>;\n }\n | {\n type: 'emit';\n event: string;\n rooms: string[];\n envelope?: unknown;\n error?: {\n reason: string;\n message?: string;\n issues?: unknown;\n };\n metadata?:unknown;\n }\n | {\n type: 'rooms';\n action: 'join' | 'leave';\n rooms?: string|string[];\n socketId: string;\n phase?:string;\n payload?: unknown;\n issues?: any[];\n }\n | {\n type: 'heartbeat';\n phase: SocketServerHeartbeatPhase;\n socketId: string;\n payload?: unknown;\n issues?: any[];\n error?: boolean;\n details?: Record<string, unknown>;\n }\n | {\n type: 'config';\n socketId: string;\n nsp: string;\n snapshot: SocketServerConfigSnapshot;\n }\n | {\n type: 'lifecycle';\n stage: SocketServerLifecycleStage;\n socketId?: string;\n nsp?: string;\n details?: Record<string, unknown>;\n };\n\nexport type SocketDebugOptions = {\n verbose?: boolean;\n /** filters event-based logs (register/handler/emit) by event name */\n only?: string[];\n logger?: (e: SocketServerDebugEvent) => void;\n} & {\n [P in SocketServerDebugEvent['type']]?: boolean;\n};\n\nexport function createDebugger(options?: SocketDebugOptions) {\n const debug = options ?? {};\n\n return (maybeEvent: string | null, e: SocketServerDebugEvent) => {\n if (!debug.logger) return;\n if (!debug[e.type]) return;\n\n // only filter applies to event-shaped logs\n if (\n debug.only &&\n maybeEvent &&\n (e.type === 'register' || e.type === 'handler' || e.type === 'emit') &&\n !debug.only.includes(maybeEvent)\n ) {\n return;\n }\n\n debug.logger(e);\n };\n}\n","// socket.server.sys.ts\nimport type { Socket } from 'socket.io';\nimport { z } from 'zod';\nimport type { EventMap, Payload, SocketConnectionConfig, SysEventName } from '@emeryld/rrroutes-contract';\nimport type {\n SocketServerConfigSnapshot,\n SocketServerDebugEvent,\n} from './socket.server.debug';\nimport type { HandlerCtxNoAck } from './socket.server.types';\n\nexport type SocketConnectionHelper<Events extends EventMap> = {\n emit<K extends keyof Events & string>(\n event: K,\n payload: Payload<Events, K>,\n metadata?: Record<string, unknown>,\n onAck?: (ack: unknown) => void\n ): void;\n};\n\n\n/** Heartbeat configuration that is not tied to payload shapes (which live in sys event schemas). */\nexport type HeartbeatServerOptions = {\n /** Enable/disable built-in heartbeat handling. Defaults to true. */\n enabled?: boolean;\n};\n\nexport type SysServerEventMap<\n Config extends SocketConnectionConfig = SocketConnectionConfig,\n Events extends EventMap = EventMap,\n> = {\n 'sys:connect': (args: {\n socket: Socket;\n helper: SocketConnectionHelper<Events>;\n /**\n * Call to proceed with the default connection initialization\n * (attaches heartbeat, join, leave and disconnect handlers).\n */\n complete: () => void;\n }) => void | Promise<void>;\n\n 'sys:disconnect': (args: {\n socket: Socket;\n helper: SocketConnectionHelper<Events>;\n /** cleans up all handlers */\n cleanup: () => void;\n reason: string;\n }) => void | Promise<void>;\n\n 'sys:ping': (\n args:{\n socket: Socket;\n helper: SocketConnectionHelper<Events>;\n ping: z.output<Config['pingPayload']>,\n ctx: HandlerCtxNoAck}\n ) => z.output<Config['pongPayload']> | Promise<z.output<Config['pongPayload']>>;\n\n 'sys:room_join': (args: {\n socket: Socket;\n helper: SocketConnectionHelper<Events>;\n rooms: string[];\n meta: z.output<Config['joinMetaMessage']>;\n join: (room: string) => Promise<void>;\n }) => void | Promise<void>;\n\n 'sys:room_leave': (args: {\n socket: Socket;\n helper: SocketConnectionHelper<Events>;\n rooms: string[];\n meta: z.output<Config['leaveMetaMessage']>;\n leave: (room: string) => Promise<void>;\n }) => void | Promise<void>;\n};\n\n\nconst normalizeError = (error: unknown) => {\n if (error instanceof Error) {\n return { name: error.name, message: error.message };\n }\n if (typeof error === 'string') return { message: error };\n return { message: 'Unknown error' };\n};\n\nconst roomValueSchema = z.union([z.string(), z.array(z.string())]);\n\nconst buildRoomPayloadSchema = <Meta extends z.ZodTypeAny>(metaSchema: Meta) =>\n z.object({\n rooms: roomValueSchema,\n meta: metaSchema,\n });\n\ntype DebugFn = (maybeEvent: string | null, e: SocketServerDebugEvent) => void;\n\nconst toArray = (rooms?: string[] | string): string[] =>\n rooms == null ? [] : Array.isArray(rooms) ? rooms : [rooms];\n\nconst snapshotSocketConfig = (socket: Socket): SocketServerConfigSnapshot => {\n const conn = socket.conn as { transport?: { name?: string }; protocol?: string | number; remoteAddress?: string } | undefined;\n const protocol = conn?.protocol;\n return {\n url: socket.handshake.url,\n transport: conn?.transport?.name,\n protocol: protocol != null ? String(protocol) : undefined,\n address: conn?.remoteAddress ?? socket.handshake.address,\n issued: socket.handshake.issued,\n time: socket.handshake.time,\n query: socket.handshake.query as Record<string, unknown>,\n auth: socket.handshake.auth as Record<string, unknown>,\n headers: socket.handshake.headers,\n };\n};\n\nexport function createBuiltInConnectionHandlers<\n C extends SocketConnectionConfig,\n Events extends EventMap,\n>(opts: {\n heartbeat?: HeartbeatServerOptions;\n sys: SysServerEventMap<C, Events>;\n dbg: DebugFn;\n config: C;\n createCtx: (socket: Socket) => HandlerCtxNoAck;\n debugVerbose?: boolean;\n createHelper: (socket: Socket) => SocketConnectionHelper<Events>;\n}) {\n const { heartbeat, sys, dbg, config, createCtx, debugVerbose, createHelper } = opts;\n\n const roomJoinEvent: SysEventName = 'sys:room_join';\n const roomLeaveEvent: SysEventName = 'sys:room_leave';\n const pingEvent: SysEventName = 'sys:ping';\n const pongEvent: SysEventName = 'sys:pong';\n const heartbeatEnabled = heartbeat?.enabled !== false;\n\n const joinPayloadSchema = buildRoomPayloadSchema(config.joinMetaMessage);\n const leavePayloadSchema = buildRoomPayloadSchema(config.leaveMetaMessage);\n const pingPayloadSchema = config.pingPayload as C['pingPayload'];\n const pongPayloadSchema = config.pongPayload as C['pongPayload'];\n\n const sysEvents = sys;\n const getSysEvent = <K extends keyof SysServerEventMap<C, Events> & SysEventName>(name: K) =>\n sysEvents[name];\n\n /** Track per-socket teardown for built-in handlers to ensure explicit cleanup on destroy(). */\n const socketTeardowns = new WeakMap<Socket, (reason:string) => void>();\n\n const builtInConnectionListener = (socket: Socket) => {\n const helper = createHelper(socket);\n dbg(null, {\n type: 'lifecycle',\n stage: 'connection_init',\n socketId: socket.id,\n nsp: socket.nsp.name,\n details: {\n rooms: Array.from(socket.rooms),\n handshakeIssued: socket.handshake.issued,\n },\n });\n dbg(null, {\n type: 'config',\n socketId: socket.id,\n nsp: socket.nsp.name,\n snapshot: snapshotSocketConfig(socket),\n });\n\n const defaultConnect = () => {\n const includeRaw = debugVerbose === true;\n\n // built-in room handlers (wrapped with sys:room_join / sys:room_leave)\n const joinHandler = async (msg: unknown) => {\n dbg(roomJoinEvent, {\n type: 'rooms',\n phase: 'receive',\n action:'join',\n socketId: socket.id,\n payload: msg,\n });\n const parsed = joinPayloadSchema.safeParse(msg);\n\n if (!parsed.success) {\n socket.emit(`${roomJoinEvent}:error`, {\n eventName: roomJoinEvent,\n issues: parsed.error.issues,\n });\n dbg(roomJoinEvent, {\n type: 'rooms',\n action:'join',\n phase:'validation_error',\n socketId: socket.id,\n issues: parsed.error.issues,\n payload: msg,\n });\n return;\n }\n const list = toArray(parsed.data.rooms);\n\n const join = async (room: string) => {\n await socket.join(room);\n dbg(null, { type: 'rooms', action: 'join', rooms:room, socketId: socket.id });\n };\n\n const run = async () => {\n await getSysEvent('sys:room_join')({\n socket,\n helper,\n rooms: list,\n meta: parsed.data.meta as z.output<C['joinMetaMessage']>,\n join,\n });\n };\n\n try {\n await run();\n } catch (error) {\n socket.emit(`${roomJoinEvent}:error`, { error: normalizeError(error) });\n dbg(roomJoinEvent, {\n type: 'rooms',\n action:'join',\n phase: 'handler_error',\n payload: includeRaw ? { rooms: list, meta: parsed.data.meta } : undefined,\n socketId: socket.id,\n issues:[error],\n });\n }\n };\n\n const leaveHandler = async (msg: unknown) => {\n dbg(roomLeaveEvent, {\n type: 'rooms',\n phase: 'receive',\n action:'leave',\n socketId: socket.id,\n payload: msg ,\n });\n const parsed = leavePayloadSchema.safeParse(msg);\n if (!parsed.success) {\n socket.emit(`${roomLeaveEvent}:error`, {\n eventName: roomLeaveEvent,\n issues: parsed.error.issues,\n });\n dbg(roomJoinEvent, {\n type: 'rooms',\n action:'leave',\n phase:'validation_error',\n socketId: socket.id,\n issues: parsed.error.issues,\n payload: msg ,\n });\n return;\n }\n\n const list = toArray(parsed.data.rooms);\n\n const leave = async (room: string) => {\n await socket.leave(room);\n dbg(null, { type: 'rooms', action: 'leave', rooms:room, socketId: socket.id });\n };\n\n const run = async () => {\n await getSysEvent('sys:room_leave')({\n socket,\n helper,\n rooms: list,\n meta: parsed.data.meta as z.output<C['leaveMetaMessage']>,\n leave,\n });\n };\n\n try {\n await run();\n } catch (error) {\n socket.emit(`${roomLeaveEvent}:error`, { error: normalizeError(error) });\n dbg(roomJoinEvent, {\n type: 'rooms',\n phase: 'handler_error',\n payload: { rooms: list, meta: parsed.data.meta } ,\n socketId: socket.id,\n issues:[error],\n action:'join'\n });\n }\n };\n\n // heartbeat, wrapped with sys:ping/sys:pong\n const pingHandler = async (msg: unknown) => {\n if (!heartbeatEnabled) {\n dbg(null, {\n type: 'heartbeat',\n phase: 'skip',\n socketId: socket.id,\n details: { reason: 'heartbeat_disabled' },\n error: false,\n });\n return;\n }\n\n const parsedPing = pingPayloadSchema.safeParse(msg);\n if (!parsedPing.success) {\n socket.emit(`${pingEvent}:error`, {\n eventName: pingEvent,\n issues: parsedPing.error.issues,\n });\n dbg(null, {\n type: 'heartbeat',\n phase: 'ping',\n socketId: socket.id,\n payload: includeRaw ? msg : undefined,\n issues: parsedPing.error.issues,\n error: true,\n details: { step: 'parse' },\n });\n return;\n }\n const ctx = createCtx(socket);\n\n dbg(null, {\n type: 'heartbeat',\n phase: 'ping',\n socketId: socket.id,\n payload: parsedPing.data,\n error: false,\n });\n\n let pongPayload: z.output<C['pongPayload']>;\n try {\n pongPayload = await getSysEvent('sys:ping')({ping:parsedPing.data, ctx, socket, helper});\n } catch (error) {\n socket.emit(`${pingEvent}:error`, { error: normalizeError(error) });\n dbg(null, {\n type: 'heartbeat',\n phase: 'ping',\n socketId: socket.id,\n payload: parsedPing.data,\n error: true,\n details: { step: 'sys_handler_error' },\n });\n return;\n }\n\n const parsedPong = pongPayloadSchema.safeParse(pongPayload);\n if (!parsedPong.success) {\n socket.emit(`${pongEvent}:error`, {\n eventName: pongEvent,\n issues: parsedPong.error.issues,\n });\n dbg(null, {\n type: 'heartbeat',\n phase: 'pong',\n socketId: socket.id,\n payload: includeRaw ? pongPayload : undefined,\n issues: parsedPong.error.issues,\n error: true,\n details: { step: 'parse' },\n });\n return;\n }\n socket.emit(pongEvent, parsedPong.data);\n dbg(null, {\n type: 'heartbeat',\n phase: 'pong',\n socketId: socket.id,\n payload: parsedPong.data,\n error: false,\n });\n };\n\n // attach built-in handlers\n socket.on(roomJoinEvent, joinHandler);\n socket.on(roomLeaveEvent, leaveHandler);\n if (heartbeatEnabled) {\n socket.on(pingEvent, pingHandler);\n }\n\n const cleanup = (reason:string) => {\n dbg(null, {\n type: 'lifecycle',\n stage: 'connection_cleanup',\n socketId: socket.id,\n nsp: socket.nsp.name,\n details: { reason },\n });\n socket.off(roomJoinEvent, joinHandler);\n socket.off(roomLeaveEvent, leaveHandler);\n if (heartbeatEnabled) {\n socket.off(pingEvent, pingHandler);\n }\n };\n\n socketTeardowns.set(socket, cleanup);\n dbg(null, {\n type: 'lifecycle',\n stage: 'connection_handlers_attached',\n socketId: socket.id,\n nsp: socket.nsp.name,\n details: {\n heartbeatEnabled,\n joinEvent: roomJoinEvent,\n leaveEvent: roomLeaveEvent,\n pingEvent: heartbeatEnabled ? pingEvent : undefined,\n },\n });\n\n socket.once('disconnect', (reason) => {\n dbg('sys:disconnect', {\n type: 'lifecycle',\n stage:'connection_cleanup',\n nsp: socket.nsp.name,\n socketId: socket.id,\n details: { reason },\n });\n const defaultDisconnect = () => {\n cleanup(reason);\n socketTeardowns.delete(socket);\n };\n getSysEvent('sys:disconnect')({\n socket,\n helper,\n reason: String(reason),\n cleanup: defaultDisconnect,\n });\n });\n };\n getSysEvent('sys:connect')({\n socket,\n helper,\n complete: defaultConnect,\n });\n };\n\n return {\n builtInConnectionListener,\n socketTeardowns,\n roomJoinEvent,\n roomLeaveEvent,\n pingEvent,\n };\n}\n","// socket.server.index.ts\nimport { Server, Socket } from 'socket.io';\nimport { z } from 'zod';\nimport type { EventMap, SocketConnectionConfig, Payload } from '@emeryld/rrroutes-contract';\nimport { createDebugger } from './socket.server.debug';\nimport type { SocketServerDebugEvent, SocketDebugOptions } from './socket.server.debug';\nimport { createBuiltInConnectionHandlers } from './socket.server.sys';\nimport type {\n HeartbeatServerOptions,\n SocketConnectionHelper,\n SysServerEventMap,\n} from './socket.server.sys';\nimport type { HandlerCtx, HandlerCtxNoAck } from './socket.server.types';\n\nconst createBaseHandlerCtx = (socket: Socket): HandlerCtxNoAck => ({\n sentAt: new Date(),\n socket,\n socketId: socket.id,\n nsp: socket.nsp.name,\n rooms: Array.from(socket.rooms),\n user: socket.data?.user,\n scopes: socket.data?.scopes,\n});\n\nconst normalizeError = (error: unknown, verbose?: boolean) => {\n if (error instanceof Error) {\n return {\n name: error.name,\n message: error.message,\n stack: verbose ? error.stack : undefined,\n };\n }\n if (typeof error === 'string') return { message: error };\n if (typeof error === 'object' && error !== null) {\n return verbose ? error : { message: 'Unknown error' };\n }\n return { message: String(error) };\n};\n\nexport interface SocketConnection<T extends EventMap> {\n on<K extends keyof T & string>(\n eventName: K,\n handler: (payload: Payload<T, K>, ctx: HandlerCtx) => void | Promise<void>\n ): () => void;\n\n off<K extends keyof T & string>(eventName: K): void;\n\n emit<K extends keyof T & string>(\n eventName: K,\n payload: Payload<T, K>,\n toRooms?: string[] | string,\n metadata?: Record<string, unknown>,\n onAck?: (ack: unknown) => void\n ): void;\n\n /** Dispose all listeners, timers, and room memberships created by this instance. */\n destroy(): void;\n}\n\nexport function createSocketConnections<\n T extends EventMap,\n TConfig extends SocketConnectionConfig = SocketConnectionConfig,\n>(\n io: Server,\n events: T,\n opts: {\n debug?: SocketDebugOptions;\n heartbeat?: HeartbeatServerOptions;\n /** System event customization (connect / disconnect / ping / pong / room join/leave) */\n sys: SysServerEventMap<TConfig, T>;\n config: TConfig;\n }\n): SocketConnection<T> {\n const dbg = createDebugger(opts?.debug);\n const socketConfig = opts.config;\n const heartbeatEnabled = opts?.heartbeat?.enabled !== false;\n const eventNames = Object.keys(events);\n dbg(null, {\n type: 'lifecycle',\n stage: 'server_init',\n details: {\n prefinedEvents: eventNames,\n heartbeatEnabled,\n path: io?.path(),\n namespaces: Array.from(io._nsps.keys()),\n transport: io?._opts.transports,\n sysEvents: Object.keys(opts.sys ?? {}),\n },\n });\n\n const getSchema = <K extends keyof T & string>(k: K) => events[k].message;\n const toArray = (rooms?: string[] | string): string[] =>\n rooms == null ? [] : Array.isArray(rooms) ? rooms : [rooms];\n const emitToTargets = <K extends keyof T & string>(\n eventName: K,\n payload: Payload<T, K>,\n targets: string[],\n metadata?: Record<string, unknown>,\n ) => {\n const schema = getSchema(eventName);\n const check = schema.safeParse(payload);\n if (!check.success) {\n dbg(String(eventName), {\n type: 'emit',\n event: String(eventName),\n rooms: targets,\n ...(opts?.debug?.verbose ? { attemptedPayload: payload } : {}),\n error: {\n reason: 'invalid_payload',\n message: check.error.message,\n issues: check.error.issues\n },\n metadata\n });\n throw new Error(`Invalid payload for \"${String(eventName)}\": ${check.error.message}`);\n }\n\n const envelope = {\n eventName,\n sentAt: new Date(),\n sentTo: targets,\n data: check.data as Payload<T, K>,\n metadata: metadata ?? {},\n };\n\n if (targets.length === 0) io.emit(String(eventName), envelope);\n else if (targets.length === 1) {\n const sid = targets[0]!;\n const sock = io.sockets.sockets.get(sid as any);\n if (sock) {\n sock.emit(String(eventName), envelope);\n }else{\n io.to(targets).emit(String(eventName), envelope);\n }\n } else{\n io.to(targets).emit(String(eventName), envelope);\n }\n\n dbg(String(eventName), {\n type: 'emit',\n event: String(eventName),\n rooms: targets,\n envelope: opts?.debug?.verbose ? envelope : undefined,\n });\n };\n const createSocketHelper = (socket: Socket): SocketConnectionHelper<T> => ({\n emit<K extends keyof T & string>(\n eventName: K,\n payload: Payload<T, K>,\n metadata?: Record<string, unknown>,\n ) {\n emitToTargets(eventName, payload, [socket.id], metadata);\n },\n });\n\n // registrations\n const registrations = new Map<\n string,\n Set<{\n connectionListener: (socket: Socket) => void;\n socketListeners: WeakMap<Socket, (raw: unknown) => void>;\n }>\n >();\n\n const addRegistration = (\n eventName: string,\n reg: {\n connectionListener: (socket: Socket) => void;\n socketListeners: WeakMap<Socket, (raw: unknown) => void>;\n }\n ) => {\n let set = registrations.get(eventName);\n if (!set) {\n set = new Set();\n registrations.set(eventName, set);\n }\n set.add(reg);\n };\n\n const removeAllForEvent = (eventName: string) => {\n const set = registrations.get(eventName);\n if (!set) {\n dbg(null, {\n type: 'register',\n event: eventName,\n action: 'unregister',\nmsg:'no handlers registered'\n });\n return;\n }\n for (const reg of set) {\n io.off('connection', reg.connectionListener);\n for (const socket of io.sockets.sockets.values()) {\n const wrapped = reg.socketListeners.get(socket);\n if (wrapped) socket.off(String(eventName), wrapped);\n }\n }\n registrations.delete(eventName);\n dbg(eventName, { type: 'register', action: 'unregister', event: eventName, msg:'unregistered' });\n };\n\n const {\n builtInConnectionListener,\n socketTeardowns,\n roomJoinEvent,\n roomLeaveEvent,\n pingEvent,\n } = createBuiltInConnectionHandlers<TConfig, T>({\n heartbeat: opts?.heartbeat,\n sys: opts.sys,\n dbg,\n config: socketConfig,\n createCtx: createBaseHandlerCtx,\n debugVerbose: opts?.debug?.verbose === true,\n createHelper: createSocketHelper,\n });\n\n // install built-in connection listener\n io.on('connection', builtInConnectionListener);\n\n const conn = {\n on<K extends keyof T & string>(\n eventName: K,\n handler: (payload: Payload<T, K>, ctx: HandlerCtx) => void | Promise<void>\n ): () => void {\n const socketListeners = new WeakMap<Socket, (raw: unknown) => void>();\n\n const connectionListener = (socket: Socket) => {\n const wrapped = async (raw: unknown) => {\n const schema = getSchema(eventName);\n const parsed = schema.safeParse(raw);\n\n const ctx = createBaseHandlerCtx(socket);\n\n dbg(String(eventName), {\n type: 'handler',\n phase: 'receive',\n event: String(eventName),\n socketId: ctx.socketId,\n nsp: ctx.nsp,\n rooms: ctx.rooms,\n raw: opts?.debug?.verbose ? raw : undefined,\n });\n\n if (!parsed.success) {\n socket.emit(`${String(eventName)}:error`, {\n eventName,\n sentAt: ctx.sentAt,\n issues: parsed.error.issues,\n });\n dbg(String(eventName), {\n type: 'handler',\n phase: 'validation_error',\n event: String(eventName),\n socketId: ctx.socketId,\n nsp: ctx.nsp,\n issues: parsed.error.issues,\n });\n return;\n }\n\n try {\n await handler(parsed.data as Payload<T, K>, ctx);\n dbg(String(eventName), {\n type: 'handler',\n phase: 'handler_success',\n event: String(eventName),\n socketId: ctx.socketId,\n nsp: ctx.nsp,\n rooms: ctx.rooms,\n });\n } catch (error) {\n dbg(String(eventName), {\n type: 'handler',\n phase: 'handler_error',\n event: String(eventName),\n socketId: ctx.socketId,\n nsp: ctx.nsp,\n rooms: ctx.rooms,\n error,\n });\n socket.emit(`${String(eventName)}:error`, {\n eventName,\n sentAt: ctx.sentAt,\n error: normalizeError(error, opts?.debug?.verbose),\n });\n }\n };\n\n socketListeners.set(socket, wrapped);\n socket.on(String(eventName), wrapped);\n socket.once('disconnect', () => {\n const w = socketListeners.get(socket);\n if (w) socket.off(String(eventName), w);\n });\n };\n\n io.on('connection', connectionListener);\n addRegistration(String(eventName), { connectionListener, socketListeners });\n dbg(String(eventName), {\n type: 'register',\n action: 'register',\n event: String(eventName),\n });\n\n return () => {\n const set = registrations.get(String(eventName));\n if (!set) {\n dbg(null, {\n type: 'register',\n action:'unregister',\n event: String(eventName),msg:`No registration under ${eventName}`\n });\n return;\n }\n for (const reg of Array.from(set)) {\n if (reg.connectionListener === connectionListener) {\n io.off('connection', reg.connectionListener);\n for (const socket of io.sockets.sockets.values()) {\n const wrapped = reg.socketListeners.get(socket);\n if (wrapped) socket.off(String(eventName), wrapped);\n }\n set.delete(reg);\n break;\n }\n }\n if (set.size === 0) registrations.delete(String(eventName));\n dbg(String(eventName), {\n type: 'register',\n action: 'unregister',\n event: String(eventName),\n });\n };\n },\n\n off<K extends keyof T & string>(eventName: K): void {\n removeAllForEvent(String(eventName));\n },\n\n emit<K extends keyof T & string>(\n eventName: K,\n payload: Payload<T, K>,\n rooms?: string[] | string,\n metadata?: Record<string, unknown>,\n ): void {\n const targets = toArray(rooms);\n emitToTargets(eventName, payload, targets, metadata);\n },\n\n destroy(): void {\n dbg(null, {\n type: 'lifecycle',\n stage: 'destroy_start',\n details: {\n socketCount: io.sockets.sockets.size,\n registrationCount: registrations.size,\n },\n });\n // 1) Remove built-in connection listener so no new sockets get handlers\n io.off('connection', builtInConnectionListener);\n\n // 2) Cleanup built-in handlers for all current sockets and leave rooms\n for (const socket of io.sockets.sockets.values()) {\n const cleanup = socketTeardowns.get(socket);\n if (cleanup) {\n cleanup('destroy');\n socketTeardowns.delete(socket);\n } else {\n dbg(null, {\n type: 'lifecycle',\n stage: 'connection_cleanup_fallback',\n socketId: socket.id,\n nsp: socket.nsp.name,\n details: { reason: 'teardown_missing' },\n });\n // Fallback if socket was attached before map population\n try {\n socket.removeAllListeners(roomJoinEvent);\n socket.removeAllListeners(roomLeaveEvent);\n socket.removeAllListeners(pingEvent);\n } catch {\n // noop\n }\n }\n }\n\n // 3) Remove all user-registered event listeners and their connection hooks\n for (const eventName of Array.from(registrations.keys())) {\n removeAllForEvent(eventName);\n }\n\n // 4) Defensive: clear any residual maps\n registrations.clear();\n dbg(null, {\n type: 'lifecycle',\n stage: 'destroy_complete',\n details: {\n socketCount: io.sockets.sockets.size,\n registrationCount: registrations.size,\n },\n });\n },\n } as const satisfies SocketConnection<T>;\n\n return conn;\n}\n\nexport type { EventMap, Payload };\nexport type { HandlerCtx } from './socket.server.types';\nexport type {\n SocketServerDebugEvent,\n SocketDebugOptions,\n SocketServerConfigSnapshot,\n SocketServerLifecycleStage,\n SocketServerHeartbeatPhase,\n} from './socket.server.debug';\nexport type {\n HeartbeatServerOptions,\n SocketConnectionHelper,\n SysServerEventMap,\n} from './socket.server.sys';\n","import type { IncomingHttpHeaders } from 'http';\nimport type { Socket } from 'socket.io';\n\nexport type ConnectionMiddlewareStage = 'incoming';\n\nexport type ConnectionMiddlewareContext = {\n socketId?: string;\n nsp?: string;\n rooms: string[];\n user?: unknown;\n scopes?: string[];\n address?: string;\n transport?: string;\n protocol?: string;\n handshake: {\n url?: string;\n issued?: number;\n time?: string;\n query?: Record<string, unknown>;\n auth?: Record<string, unknown>;\n headers?: IncomingHttpHeaders;\n };\n};\n\nexport type ConnectionMiddlewareEvent = {\n type: 'connection';\n stage: ConnectionMiddlewareStage;\n timestamp: Date;\n context: ConnectionMiddlewareContext;\n};\n\nexport type ConnectionLoggingMiddlewareOptions = {\n /**\n * Custom logger invoked with the structured event.\n * Defaults to console.info.\n */\n logger?: (event: ConnectionMiddlewareEvent) => void;\n /**\n * Include raw headers from the handshake. Defaults to false to avoid leaking PII.\n */\n includeHeaders?: boolean;\n /**\n * List of auth keys that should be redacted (case-insensitive). Defaults to ['authorization'].\n */\n redactAuthKeys?: string[];\n};\n\nconst defaultRedactedValue = '[REDACTED]';\n\nconst defaultLogger = (event: ConnectionMiddlewareEvent) => {\n const {\n stage,\n context: { socketId, nsp, address, transport, handshake },\n } = event;\n // eslint-disable-next-line no-console\n console.info('[socket-connection]', {\n stage,\n socketId,\n nsp,\n address,\n transport,\n url: handshake.url,\n query: handshake.query,\n auth: handshake.auth,\n });\n};\n\nconst redactAuth = (\n auth: Record<string, unknown> | undefined,\n redactKeys: Set<string>\n): Record<string, unknown> | undefined => {\n if (!auth) return undefined;\n if (redactKeys.size === 0) return auth;\n\n const clone: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(auth)) {\n const normalizedKey = key.toLowerCase();\n clone[key] = redactKeys.has(normalizedKey) ? defaultRedactedValue : value;\n }\n return clone;\n};\n\nconst buildContext = (\n socket: Socket,\n includeHeaders: boolean,\n redactKeys: Set<string>\n): ConnectionMiddlewareContext => {\n const conn = socket.conn as\n | {\n remoteAddress?: string;\n transport?: { name?: string };\n protocol?: string | number;\n }\n | undefined;\n\n const handshake = socket.handshake ?? {};\n\n const protocolValue = conn?.protocol;\n\n return {\n socketId: socket.id,\n nsp: socket.nsp?.name,\n rooms: Array.from(socket.rooms ?? []),\n user: (socket.data as any)?.user,\n scopes: (socket.data as any)?.scopes,\n address: conn?.remoteAddress ?? (handshake as any).address,\n transport: conn?.transport?.name,\n protocol: protocolValue != null ? String(protocolValue) : undefined,\n handshake: {\n url: handshake.url,\n issued: handshake.issued,\n time: handshake.time,\n query: handshake.query as Record<string, unknown>,\n auth: redactAuth(handshake.auth as Record<string, unknown>, redactKeys),\n headers: includeHeaders ? (handshake.headers as IncomingHttpHeaders) : undefined,\n },\n };\n};\n\nexport const createConnectionLoggingMiddleware = (\n options: ConnectionLoggingMiddlewareOptions = {}\n) => {\n const logger = options.logger ?? defaultLogger;\n const includeHeaders = options.includeHeaders ?? false;\n const redactKeys = new Set(\n (options.redactAuthKeys ?? ['authorization', 'token']).map((key) => key.toLowerCase())\n );\n\n return (socket: Socket, next: (err?: Error) => void) => {\n const context = buildContext(socket, includeHeaders, redactKeys);\n logger({\n type: 'connection',\n stage: 'incoming',\n timestamp: new Date(),\n context,\n });\n next();\n };\n};\n\nexport type ConnectionLoggingMiddleware = ReturnType<typeof createConnectionLoggingMiddleware>;\n"],"mappings":"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","names":["normalizeError","toArray"]}
@@ -1,10 +1,8 @@
1
1
  import { Server } from 'socket.io';
2
- import { z } from 'zod';
3
- import type { EventMap, SocketConnectionConfig } from '@emeryld/rrroutes-contract';
2
+ import type { EventMap, SocketConnectionConfig, Payload } from '@emeryld/rrroutes-contract';
4
3
  import type { SocketDebugOptions } from './socket.server.debug';
5
4
  import type { HeartbeatServerOptions, SysServerEventMap } from './socket.server.sys';
6
5
  import type { HandlerCtx } from './socket.server.types';
7
- type Payload<T extends EventMap, K extends keyof T> = z.infer<T[K]['message']>;
8
6
  export interface SocketConnection<T extends EventMap> {
9
7
  on<K extends keyof T & string>(eventName: K, handler: (payload: Payload<T, K>, ctx: HandlerCtx) => void | Promise<void>): () => void;
10
8
  off<K extends keyof T & string>(eventName: K): void;
@@ -1,11 +1,10 @@
1
1
  import type { Socket } from 'socket.io';
2
2
  import { z } from 'zod';
3
- import type { EventMap, SocketConnectionConfig } from '@emeryld/rrroutes-contract';
3
+ import type { EventMap, Payload, SocketConnectionConfig } from '@emeryld/rrroutes-contract';
4
4
  import type { SocketServerDebugEvent } from './socket.server.debug';
5
5
  import type { HandlerCtxNoAck } from './socket.server.types';
6
- type EventPayload<Events extends EventMap, K extends keyof Events & string> = z.infer<Events[K]['message']>;
7
6
  export type SocketConnectionHelper<Events extends EventMap> = {
8
- emit<K extends keyof Events & string>(event: K, payload: EventPayload<Events, K>, metadata?: Record<string, unknown>, onAck?: (ack: unknown) => void): void;
7
+ emit<K extends keyof Events & string>(event: K, payload: Payload<Events, K>, metadata?: Record<string, unknown>, onAck?: (ack: unknown) => void): void;
9
8
  };
10
9
  /** Heartbeat configuration that is not tied to payload shapes (which live in sys event schemas). */
11
10
  export type HeartbeatServerOptions = {
@@ -61,7 +60,7 @@ export declare function createBuiltInConnectionHandlers<C extends SocketConnecti
61
60
  createHelper: (socket: Socket) => SocketConnectionHelper<Events>;
62
61
  }): {
63
62
  builtInConnectionListener: (socket: Socket) => void;
64
- socketTeardowns: WeakMap<Socket<import("socket.io").DefaultEventsMap, import("socket.io").DefaultEventsMap, import("socket.io").DefaultEventsMap, any>, () => void>;
63
+ socketTeardowns: WeakMap<Socket<import("socket.io").DefaultEventsMap, import("socket.io").DefaultEventsMap, import("socket.io").DefaultEventsMap, any>, (reason: string) => void>;
65
64
  roomJoinEvent: "sys:room_join";
66
65
  roomLeaveEvent: "sys:room_leave";
67
66
  pingEvent: "sys:ping";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@emeryld/rrroutes-server",
3
- "version": "2.1.0",
3
+ "version": "2.1.2",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",