@rlanz/socket 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -4
- package/build/{base_channel-CasBQV5I.d.ts → base_channel-DFyd3hVE.d.ts} +0 -3
- package/build/index.d.ts +2 -3
- package/build/providers/socket_provider.d.ts +2 -2
- package/build/providers/socket_provider.js +8 -11
- package/build/providers/socket_provider.js.map +1 -1
- package/build/services/socket.d.ts +2 -2
- package/build/{socket_service-C2YRbhrO.d.ts → socket_service-to3tlbrV.d.ts} +1 -1
- package/build/src/decorators.d.ts +1 -2
- package/build/src/health_check.d.ts +2 -2
- package/build/src/otel.js +1 -1
- package/build/src/otel.js.map +1 -1
- package/build/src/types.d.ts +1 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -206,10 +206,8 @@ export default defineConfig({
|
|
|
206
206
|
Upgrade middleware and channel middleware have different jobs. Upgrade middleware prepares the HTTP
|
|
207
207
|
handshake. Channel middleware authorizes one subscription.
|
|
208
208
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
async-local storage. Put mutable socket-lifetime state in `socket.raw.data`. Copy durable identity
|
|
212
|
-
into `socket.user` instead of retaining response-bound resources.
|
|
209
|
+
Socket releases the upgrade request and HTTP context after authentication. Copy durable identity
|
|
210
|
+
into `socket.user`, and put mutable socket-lifetime state in `socket.raw.data`.
|
|
213
211
|
|
|
214
212
|
## Define channels
|
|
215
213
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { WebSocket } from 'ws';
|
|
2
|
-
import { IncomingMessage } from 'node:http';
|
|
3
2
|
import { MiddlewareAsClass } from '@adonisjs/core/types/http';
|
|
4
3
|
import { HttpContext } from '@adonisjs/core/http';
|
|
5
4
|
import { TransportFactory } from '@boringnode/bus/types/main';
|
|
@@ -104,8 +103,6 @@ interface RawSocket {
|
|
|
104
103
|
id: string;
|
|
105
104
|
data: Record<string, unknown>;
|
|
106
105
|
connection: WebSocket;
|
|
107
|
-
request: IncomingMessage;
|
|
108
|
-
httpContext: HttpContext;
|
|
109
106
|
}
|
|
110
107
|
/**
|
|
111
108
|
* Socket exposed to channels after the HTTP upgrade.
|
package/build/index.d.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { S as SocketAuthenticationHandler, a as SocketConfig } from './base_channel-
|
|
2
|
-
export { A as AuthenticatedSocket, B as BaseChannel, C as ChannelOptions, D as Duration, M as Middleware, b as MiddlewareClass, c as MiddlewareConstructor, d as MiddlewareContext, e as MiddlewareFn, f as PresenceInfo, g as PresenceMember, R as RawSocket, h as SocketAuthenticationResult, i as SocketEvents, j as SocketHealthSnapshot, k as SocketHttpMiddleware, l as SocketOriginResolver, m as SocketOriginValues, n as SocketResponseError, o as SocketRetryQueueConfig, p as SocketServiceStatus, q as SocketTransportConfig, r as SocketUpgradeContext } from './base_channel-
|
|
1
|
+
import { S as SocketAuthenticationHandler, a as SocketConfig } from './base_channel-DFyd3hVE.js';
|
|
2
|
+
export { A as AuthenticatedSocket, B as BaseChannel, C as ChannelOptions, D as Duration, M as Middleware, b as MiddlewareClass, c as MiddlewareConstructor, d as MiddlewareContext, e as MiddlewareFn, f as PresenceInfo, g as PresenceMember, R as RawSocket, h as SocketAuthenticationResult, i as SocketEvents, j as SocketHealthSnapshot, k as SocketHttpMiddleware, l as SocketOriginResolver, m as SocketOriginValues, n as SocketResponseError, o as SocketRetryQueueConfig, p as SocketServiceStatus, q as SocketTransportConfig, r as SocketUpgradeContext } from './base_channel-DFyd3hVE.js';
|
|
3
3
|
import ConfigureCommand from '@adonisjs/core/commands/configure';
|
|
4
4
|
export { a as ChannelAck, b as ChannelMessage, C as ChannelServerEventsOf } from './shared_types-B11CaOr5.js';
|
|
5
5
|
import 'ws';
|
|
6
|
-
import 'node:http';
|
|
7
6
|
import '@adonisjs/core/types/http';
|
|
8
7
|
import '@adonisjs/core/http';
|
|
9
8
|
import '@boringnode/bus/types/main';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ApplicationService } from '@adonisjs/core/types';
|
|
2
|
-
import { S as SocketService, C as ChannelRouter } from '../socket_service-
|
|
3
|
-
import { P as PresenceManager } from '../base_channel-
|
|
2
|
+
import { S as SocketService, C as ChannelRouter } from '../socket_service-to3tlbrV.js';
|
|
3
|
+
import { P as PresenceManager } from '../base_channel-DFyd3hVE.js';
|
|
4
4
|
import 'node:http';
|
|
5
5
|
import '@adonisjs/logger';
|
|
6
6
|
import 'emittery';
|
|
@@ -1019,7 +1019,7 @@ var SocketUpgrader = class _SocketUpgrader {
|
|
|
1019
1019
|
return true;
|
|
1020
1020
|
}
|
|
1021
1021
|
this.server.handleUpgrade(request, socket, head, (connection) => {
|
|
1022
|
-
accept(connection,
|
|
1022
|
+
accept(connection, result.accepted);
|
|
1023
1023
|
});
|
|
1024
1024
|
return true;
|
|
1025
1025
|
}
|
|
@@ -1087,7 +1087,7 @@ var SocketUpgrader = class _SocketUpgrader {
|
|
|
1087
1087
|
async #authenticate(httpContext) {
|
|
1088
1088
|
const config = this.config;
|
|
1089
1089
|
if (!config?.authenticate) {
|
|
1090
|
-
return {
|
|
1090
|
+
return {};
|
|
1091
1091
|
}
|
|
1092
1092
|
try {
|
|
1093
1093
|
const ctx = {
|
|
@@ -1098,7 +1098,6 @@ var SocketUpgrader = class _SocketUpgrader {
|
|
|
1098
1098
|
return null;
|
|
1099
1099
|
}
|
|
1100
1100
|
return {
|
|
1101
|
-
httpContext,
|
|
1102
1101
|
user: result
|
|
1103
1102
|
};
|
|
1104
1103
|
} catch (error) {
|
|
@@ -1411,8 +1410,8 @@ var SocketService = class extends Emittery {
|
|
|
1411
1410
|
(message, error) => this.#warn(message, error)
|
|
1412
1411
|
);
|
|
1413
1412
|
const upgradeHandler = (request, socket, head) => {
|
|
1414
|
-
upgrader.handle(request, socket, head, (connection,
|
|
1415
|
-
this.#handleConnection(connection,
|
|
1413
|
+
upgrader.handle(request, socket, head, (connection, accepted) => {
|
|
1414
|
+
this.#handleConnection(connection, accepted, inboundMessageConfig);
|
|
1416
1415
|
}).catch((error) => {
|
|
1417
1416
|
this.#warn("failed to upgrade socket connection: %s", error);
|
|
1418
1417
|
SocketUpgrader.reject(socket, 500, "Internal Server Error");
|
|
@@ -1450,12 +1449,12 @@ var SocketService = class extends Emittery {
|
|
|
1450
1449
|
throw error;
|
|
1451
1450
|
}
|
|
1452
1451
|
}
|
|
1453
|
-
#handleConnection(connection,
|
|
1452
|
+
#handleConnection(connection, upgrade, inboundMessageConfig) {
|
|
1454
1453
|
if (this.#lifecycle.status !== "ready") {
|
|
1455
1454
|
connection.terminate();
|
|
1456
1455
|
return;
|
|
1457
1456
|
}
|
|
1458
|
-
const socket = this.#wrapSocket(connection,
|
|
1457
|
+
const socket = this.#wrapSocket(connection, upgrade);
|
|
1459
1458
|
connectChannel.traceSync(
|
|
1460
1459
|
() => {
|
|
1461
1460
|
this.#sockets.set(socket.id, socket);
|
|
@@ -1628,13 +1627,11 @@ var SocketService = class extends Emittery {
|
|
|
1628
1627
|
}
|
|
1629
1628
|
return this.#channelSubscriptions.relayWhisper(socket, payload);
|
|
1630
1629
|
}
|
|
1631
|
-
#wrapSocket(connection,
|
|
1630
|
+
#wrapSocket(connection, upgrade) {
|
|
1632
1631
|
const raw = {
|
|
1633
1632
|
id: randomUUID2(),
|
|
1634
1633
|
data: {},
|
|
1635
|
-
connection
|
|
1636
|
-
request,
|
|
1637
|
-
httpContext: upgrade.httpContext
|
|
1634
|
+
connection
|
|
1638
1635
|
};
|
|
1639
1636
|
return {
|
|
1640
1637
|
id: raw.id,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../providers/socket_provider.ts","../../src/socket_service.ts","../../src/channel_subscription_storage.ts","../../src/channel_subscriptions.ts","../../src/protocol/reply.ts","../../src/protocol/message.ts","../../src/message_queue.ts","../../src/socket_bus.ts","../../src/presence_manager.ts","../../src/presence_socket_frame.ts","../../src/duration.ts","../../src/socket_upgrader.ts","../../src/channel_pattern.ts","../../src/channel_router.ts"],"sourcesContent":["import type { ApplicationService } from '@adonisjs/core/types'\nimport type { HttpContext, Server as AdonisServer } from '@adonisjs/core/http'\nimport type { Logger } from '@adonisjs/logger'\nimport type { MiddlewareAsClass } from '@adonisjs/core/types/http'\nimport { ServerResponse } from 'node:http'\nimport { SocketService } from '../src/socket_service.js'\nimport { ChannelRouter } from '../src/channel_router.js'\nimport { BaseChannel } from '../src/base_channel.js'\nimport { PresenceManager } from '../src/presence_manager.js'\nimport type { SocketUpgradeContextRunner } from '../src/socket_upgrader.js'\nimport type { SocketConfig, SocketHttpMiddleware } from '../src/types.js'\n\ndeclare module '@adonisjs/core/types' {\n interface ContainerBindings {\n 'socket': SocketService\n 'socket.router': ChannelRouter\n 'socket.presence': PresenceManager\n }\n}\n\nexport default class SocketProvider {\n constructor(protected app: ApplicationService) {}\n\n /**\n * Registers the bindings in the container.\n */\n register(): void {\n this.app.container.singleton('socket.router', () => {\n return new ChannelRouter(\n (channel) => this.app.container.make(channel),\n () => {\n const resolver = this.app.container.createResolver()\n\n return async (Middleware, ctx, next) => {\n const instance = await resolver.make(Middleware)\n await resolver.call(instance, 'handle', [ctx, next])\n }\n }\n )\n })\n\n this.app.container.singleton('socket.presence', () => {\n return new PresenceManager()\n })\n\n this.app.container.singleton('socket', () => {\n return new SocketService()\n })\n }\n\n /**\n * Boots the provider.\n */\n async boot(): Promise<void> {\n const router = await this.app.container.make('socket.router')\n\n // Discover and register channel classes.\n await this.#registerChannels(router)\n }\n\n /**\n * Called when the app is ready and the HTTP server is running.\n */\n async ready(): Promise<void> {\n const socket = await this.app.container.make('socket')\n const router = await this.app.container.make('socket.router')\n const presence = await this.app.container.make('socket.presence')\n const logger = await this.#resolveLogger()\n const config = this.app.config.get<SocketConfig>('socket', {})\n\n socket.setPresenceManager(presence)\n\n logger.info('router has %d channels registered', router.size)\n\n const server = await this.app.container.make('server')\n const httpServer = server.getNodeServer()\n\n if (!httpServer) {\n const error = new Error('HTTP server not available.')\n socket.markFailed(error)\n logger.warn('HTTP server not available; socket server was not started')\n return\n }\n\n try {\n await socket.boot(\n httpServer,\n config,\n router,\n logger,\n this.#createUpgradeContextRunner(config, server)\n )\n logger.info('server started')\n } catch (error) {\n socket.markFailed(error)\n throw error\n }\n }\n\n /**\n * Performs a clean shutdown.\n */\n async shutdown(): Promise<void> {\n const socket = await this.app.container.make('socket')\n await socket.close()\n }\n\n /**\n * Resolves the AdonisJS logger and creates a child logger for the socket context.\n */\n async #resolveLogger(): Promise<Logger> {\n const logger = await this.app.container.make('logger')\n return logger.child({ module: 'socket' })\n }\n\n /**\n * Creates an AdonisJS HTTP context for WebSocket upgrade requests.\n */\n #createUpgradeContextRunner(\n config: SocketConfig,\n server: AdonisServer\n ): SocketUpgradeContextRunner {\n const middleware = config.websocket?.middleware ?? []\n\n return async (request, handler, shortCircuitBeforeMiddleware) => {\n const response = new ServerResponse(request)\n const adonisRequest = server.createRequest(request, response)\n const adonisResponse = server.createResponse(request, response)\n const httpContext = server.createHttpContext(\n adonisRequest,\n adonisResponse,\n this.app.container.createResolver()\n )\n\n const earlyResult = await shortCircuitBeforeMiddleware?.(httpContext)\n if (earlyResult !== undefined) {\n return earlyResult\n }\n\n return this.#runUpgradeMiddleware(server, middleware, httpContext, handler)\n }\n }\n\n /**\n * Runs middleware attached to WebSocket upgrade requests.\n */\n async #runUpgradeMiddleware<Result>(\n server: AdonisServer,\n middleware: NonNullable<NonNullable<SocketConfig['websocket']>['middleware']>,\n httpContext: HttpContext,\n handler: (httpContext: HttpContext) => Promise<Result>\n ): Promise<Result> {\n if (middleware.length === 0) {\n return handler(httpContext)\n }\n\n const middlewareClasses: MiddlewareAsClass[] = await Promise.all(\n middleware.map(async (one): Promise<MiddlewareAsClass> => {\n if (one.prototype?.handle) {\n return one as MiddlewareAsClass\n }\n\n const moduleExports = await (one as Exclude<SocketHttpMiddleware, MiddlewareAsClass>)()\n return moduleExports.default\n })\n )\n\n let outcome: { value: Result } | undefined\n\n await server\n .pipeline(middlewareClasses)\n .errorHandler((error) => {\n throw error\n })\n .finalHandler(async () => {\n outcome = { value: await handler(httpContext) }\n })\n .run(httpContext)\n\n if (!outcome) {\n throw new Error('WebSocket upgrade middleware must call next()')\n }\n\n return outcome.value\n }\n\n /**\n * Scans and registers channel classes.\n */\n async #registerChannels(router: ChannelRouter): Promise<void> {\n const logger = await this.#resolveLogger()\n\n let generated: { socketChannels?: unknown }\n try {\n generated = await this.app.import('#generated/socket_channels')\n } catch (error) {\n throw new Error('Failed to load generated socket channels', { cause: error })\n }\n\n if (!Array.isArray(generated.socketChannels)) {\n throw new Error('Generated socket channel manifest must export a socketChannels array')\n }\n\n for (const [index, channelClass] of generated.socketChannels.entries()) {\n const source = `generated channel at index ${index}`\n if (\n typeof channelClass !== 'function' ||\n !(channelClass.prototype instanceof BaseChannel) ||\n !channelClass.pattern\n ) {\n throw new Error(`Socket channel ${source} must default export a BaseChannel with a pattern`)\n }\n\n try {\n router.register(channelClass)\n } catch (error) {\n throw new Error(`Failed to register socket channel from ${source}`, { cause: error })\n }\n\n logger.info('registered channel: %s', channelClass.pattern)\n }\n\n logger.info('total channels registered: %d', router.size)\n }\n}\n","import { randomUUID } from 'node:crypto'\nimport type { IncomingMessage } from 'node:http'\nimport type { Server as HttpServer } from 'node:http'\nimport type { Logger } from '@adonisjs/logger'\nimport Emittery from 'emittery'\nimport { WebSocket, WebSocketServer } from 'ws'\nimport type { RawData } from 'ws'\nimport type {\n AuthenticatedSocket,\n SocketConfig,\n SocketEvents,\n ChannelAck,\n RawSocket,\n SocketHealthSnapshot,\n SocketServiceStatus,\n} from './types.js'\nimport type { SocketUpgradeContextRunner } from './socket_upgrader.js'\nimport {\n SERVER_DISCONNECT_CODE,\n type ChannelMessage,\n type ServerProtocolMessage,\n} from './shared_types.js'\nimport type { ChannelRouter } from './channel_router.js'\nimport type { PresenceManager } from './presence_manager.js'\nimport { ChannelSubscriptions, type ChannelSubscriptionLimits } from './channel_subscriptions.js'\nimport { Message, type TransportMessage } from './protocol/message.js'\nimport { MessageQueue } from './message_queue.js'\nimport { Reply } from './protocol/reply.js'\nimport type { SocketEmission, SocketEmissionSink } from './broadcasting.js'\nimport { SocketFake } from './fake_socket.js'\nimport { SocketBus } from './socket_bus.js'\nimport { PresenceSocketFrame, type SerializablePresenceSocket } from './presence_socket_frame.js'\nimport {\n SocketUpgrader,\n type AcceptedUpgrade,\n type SocketUpgradeHandler,\n} from './socket_upgrader.js'\nimport { parseDuration, type Duration } from './duration.js'\nimport { SocketResponseError } from './base_channel.js'\nimport {\n broadcastChannel,\n channelMessageChannel,\n connectChannel,\n disconnectChannel,\n subscribeChannel,\n unsubscribeChannel,\n} from './tracing_channels.js'\nimport type {\n SocketBroadcastMessage,\n SocketChannelMessage,\n SocketSubscribeMessage,\n SocketUnsubscribeMessage,\n} from './types/tracing_channels.js'\n\nconst DEFAULT_PING_INTERVAL = 25_000\nconst DEFAULT_PING_TIMEOUT = 5_000\nconst DEFAULT_MAX_PAYLOAD = 1024 * 1024\nconst DEFAULT_MAX_QUEUED_MESSAGES = 100\nconst DEFAULT_MAX_MESSAGES_PER_INTERVAL = 1000\nconst DEFAULT_MESSAGE_RATE_INTERVAL = 1000\nconst DEFAULT_MAX_BUFFERED_AMOUNT = 16 * 1024 * 1024\nconst DEFAULT_MAX_OUTBOUND_PAYLOAD = 1024 * 1024\nconst DEFAULT_MAX_SUBSCRIPTIONS_PER_SOCKET = 100\nconst DEFAULT_MAX_CHANNEL_NAME_LENGTH = 255\nconst DEFAULT_SHUTDOWN_TIMEOUT = 5_000\nconst CLOSE_POLICY_VIOLATION = 1008\nconst CLOSE_MESSAGE_TOO_BIG = 1009\nconst CLOSE_OUTBOUND_BUFFER_LIMIT = 'Socket outbound buffer limit exceeded'\nconst CLOSE_OUTBOUND_MESSAGE_TOO_BIG = 'Socket outbound message too big'\nconst SERVER_DISCONNECT_REASON = 'Socket server disconnected'\n\ninterface InboundMessageConfig {\n maxPayload: number\n maxQueuedMessages: number\n maxMessagesPerInterval: number\n messageRateInterval: number\n subscriptionLimits: ChannelSubscriptionLimits\n}\n\ninterface OutboundMessageConfig {\n maxBufferedAmount: number\n maxOutboundPayload: number\n}\n\ninterface SocketMessageRate {\n count: number\n intervalStartedAt: number\n}\n\nasync function settleBeforeDeadline<Result>(\n promise: Promise<Result>,\n deadline: number\n): Promise<PromiseSettledResult<Result> | null> {\n const remaining = deadline - Date.now()\n if (remaining <= 0) {\n void promise.catch(() => {})\n return null\n }\n\n let timer: ReturnType<typeof setTimeout> | undefined\n try {\n return await Promise.race([\n promise.then(\n (value): PromiseFulfilledResult<Result> => ({ status: 'fulfilled', value }),\n (reason): PromiseRejectedResult => ({ status: 'rejected', reason })\n ),\n new Promise<null>((resolve) => {\n timer = setTimeout(() => resolve(null), remaining)\n }),\n ])\n } finally {\n if (timer) clearTimeout(timer)\n }\n}\n\nfunction serializeFrame(frame: ServerProtocolMessage): string {\n return JSON.stringify(frame)\n}\n\nfunction sendFrame(\n connection: WebSocket,\n frame: ServerProtocolMessage,\n config: OutboundMessageConfig\n): boolean {\n const serializedFrame = serializeFrame(frame)\n return sendSerializedFrameWithBackpressure(connection, serializedFrame, config)\n}\n\nfunction sendSerializedFrameWithBackpressure(\n connection: WebSocket,\n serializedFrame: string,\n config: OutboundMessageConfig\n): boolean {\n if (connection.readyState !== WebSocket.OPEN) {\n return false\n }\n\n const payloadSize = Buffer.byteLength(serializedFrame)\n if (payloadSize > config.maxOutboundPayload) {\n closeConnection(connection, CLOSE_MESSAGE_TOO_BIG, CLOSE_OUTBOUND_MESSAGE_TOO_BIG)\n return false\n }\n\n if (connection.bufferedAmount + payloadSize > config.maxBufferedAmount) {\n closeConnection(connection, CLOSE_POLICY_VIOLATION, CLOSE_OUTBOUND_BUFFER_LIMIT)\n return false\n }\n\n connection.send(serializedFrame)\n return true\n}\n\nfunction parsePositiveInteger(name: string, value: number | undefined, fallback: number): number {\n if (value === undefined) {\n return fallback\n }\n\n if (!Number.isSafeInteger(value) || value <= 0) {\n throw new Error(`${name} must be a positive integer`)\n }\n\n return value\n}\n\nfunction resolveHeartbeatConfig(\n config: { pingInterval?: Duration; pingTimeout?: Duration } | undefined\n): { interval: number; timeout: number } | null {\n const pingInterval = parseDuration('websocket.pingInterval', config?.pingInterval)\n const pingTimeout = parseDuration('websocket.pingTimeout', config?.pingTimeout)\n\n if (pingInterval === undefined && pingTimeout === undefined) {\n return null\n }\n\n return {\n interval: pingInterval ?? DEFAULT_PING_INTERVAL,\n timeout: pingTimeout ?? DEFAULT_PING_TIMEOUT,\n }\n}\n\nfunction resolveInboundMessageConfig(\n config:\n | {\n maxPayload?: number\n maxQueuedMessages?: number\n maxMessagesPerInterval?: number\n messageRateInterval?: Duration\n maxSubscriptionsPerSocket?: number\n maxChannelNameLength?: number\n }\n | undefined\n): InboundMessageConfig {\n const messageRateInterval =\n parseDuration('websocket.messageRateInterval', config?.messageRateInterval) ??\n DEFAULT_MESSAGE_RATE_INTERVAL\n\n return {\n maxPayload: parsePositiveInteger(\n 'websocket.maxPayload',\n config?.maxPayload,\n DEFAULT_MAX_PAYLOAD\n ),\n maxQueuedMessages: parsePositiveInteger(\n 'websocket.maxQueuedMessages',\n config?.maxQueuedMessages,\n DEFAULT_MAX_QUEUED_MESSAGES\n ),\n maxMessagesPerInterval: parsePositiveInteger(\n 'websocket.maxMessagesPerInterval',\n config?.maxMessagesPerInterval,\n DEFAULT_MAX_MESSAGES_PER_INTERVAL\n ),\n messageRateInterval,\n subscriptionLimits: {\n maxSubscriptionsPerSocket: parsePositiveInteger(\n 'websocket.maxSubscriptionsPerSocket',\n config?.maxSubscriptionsPerSocket,\n DEFAULT_MAX_SUBSCRIPTIONS_PER_SOCKET\n ),\n maxChannelNameLength: parsePositiveInteger(\n 'websocket.maxChannelNameLength',\n config?.maxChannelNameLength,\n DEFAULT_MAX_CHANNEL_NAME_LENGTH\n ),\n },\n }\n}\n\nfunction resolveOutboundMessageConfig(\n config:\n | {\n maxBufferedAmount?: number\n maxOutboundPayload?: number\n }\n | undefined\n): OutboundMessageConfig {\n return {\n maxBufferedAmount: parsePositiveInteger(\n 'websocket.maxBufferedAmount',\n config?.maxBufferedAmount,\n DEFAULT_MAX_BUFFERED_AMOUNT\n ),\n maxOutboundPayload: parsePositiveInteger(\n 'websocket.maxOutboundPayload',\n config?.maxOutboundPayload,\n DEFAULT_MAX_OUTBOUND_PAYLOAD\n ),\n }\n}\n\nfunction getRawDataByteLength(data: RawData): number {\n if (Array.isArray(data)) {\n return data.reduce((total, chunk) => total + chunk.byteLength, 0)\n }\n\n return data.byteLength\n}\n\nfunction closeConnection(connection: WebSocket, code: number, reason: string): void {\n if (connection.readyState === WebSocket.OPEN) {\n connection.close(code, reason)\n }\n}\n\ninterface SocketServiceRuntime<User> {\n kind: 'runtime'\n server: WebSocketServer\n httpServer: HttpServer\n upgradeHandler: SocketUpgradeHandler\n channelSubscriptions: ChannelSubscriptions<User>\n bus: SocketBus | null\n}\n\ninterface SocketServiceBootOperation<User> {\n kind: 'boot'\n promise: Promise<void>\n closeRequested: boolean\n channelSubscriptions?: ChannelSubscriptions<User>\n bus?: SocketBus\n busCloseBeforeStart?: Promise<void>\n busCloseAfterStart?: Promise<void>\n runtime?: SocketServiceRuntime<User>\n}\n\ntype SocketServiceResources<User> = SocketServiceBootOperation<User> | SocketServiceRuntime<User>\n\ntype SocketServiceLifecycle<User> =\n | { status: 'stopped' }\n | { status: 'starting'; operation: SocketServiceBootOperation<User> }\n | { status: 'ready'; runtime: SocketServiceRuntime<User> }\n | {\n status: 'stopping'\n resources: SocketServiceResources<User>\n close: Promise<void>\n }\n | {\n status: 'failed'\n error: Error\n resources?: SocketServiceResources<User>\n close?: Promise<void>\n }\n\n/**\n * Main service for managing WebSocket connections.\n */\nexport class SocketService<User = unknown> extends Emittery<SocketEvents<User>> {\n #sockets = new Map<string, AuthenticatedSocket<User>>()\n #presenceManager: PresenceManager | null = null\n #fake: SocketFake | null = null\n #deliverySink: SocketEmissionSink = {\n dispatch: (emission) => {\n this.#deliverBroadcast(emission)\n },\n }\n #broadcastSink: SocketEmissionSink = this.#deliverySink\n #lifecycle: SocketServiceLifecycle<User> = { status: 'stopped' }\n #heartbeatInterval: ReturnType<typeof setInterval> | null = null\n #heartbeatTimeouts = new Map<string, ReturnType<typeof setTimeout>>()\n #messageQueue = new MessageQueue()\n #messageRates = new Map<string, SocketMessageRate>()\n #socketFinalizations = new Map<string, Promise<void>>()\n #outboundMessageConfig = resolveOutboundMessageConfig(undefined)\n #shutdownTimeout = DEFAULT_SHUTDOWN_TIMEOUT\n #logger: Logger | null = null\n\n /**\n * Accesses the underlying ws server.\n */\n get server(): WebSocketServer {\n const runtime = this.#runtime\n if (!runtime) {\n throw new Error('WebSocket server is not initialized. Call boot() first.')\n }\n\n return runtime.server\n }\n\n get #resources(): SocketServiceResources<User> | undefined {\n switch (this.#lifecycle.status) {\n case 'starting':\n return this.#lifecycle.operation\n case 'ready':\n return this.#lifecycle.runtime\n case 'stopping':\n case 'failed':\n return this.#lifecycle.resources\n case 'stopped':\n return undefined\n }\n }\n\n get #runtime(): SocketServiceRuntime<User> | undefined {\n if (this.#lifecycle.status === 'ready') return this.#lifecycle.runtime\n if (this.#lifecycle.status !== 'failed') return undefined\n\n const resources = this.#lifecycle.resources\n if (!resources) return undefined\n if (resources.kind === 'runtime') return resources\n return resources.runtime\n }\n\n get #channelSubscriptions(): ChannelSubscriptions<User> | undefined {\n const resources = this.#resources\n if (!resources) return undefined\n if (resources.kind === 'runtime') return resources.channelSubscriptions\n return resources.runtime?.channelSubscriptions ?? resources.channelSubscriptions\n }\n\n get #bus(): SocketBus | null | undefined {\n const resources = this.#resources\n if (!resources) return undefined\n if (resources.kind === 'runtime') return resources.bus\n return resources.runtime?.bus ?? resources.bus\n }\n\n #isStarting(operation: SocketServiceBootOperation<User>): boolean {\n return this.#lifecycle.status === 'starting' && this.#lifecycle.operation === operation\n }\n\n #closeBootBusAfterStart(operation: SocketServiceBootOperation<User>): Promise<void> {\n const bus = operation.bus\n if (!bus) return Promise.resolve()\n if (operation.busCloseAfterStart) return operation.busCloseAfterStart\n\n const close = bus.close()\n operation.busCloseAfterStart = close\n return close\n }\n\n setPresenceManager(presenceManager: PresenceManager): void {\n this.#presenceManager = presenceManager\n this.#channelSubscriptions?.setPresenceManager(presenceManager)\n this.#configurePresenceFetcher(this.#bus)\n }\n\n boot(\n httpServer: HttpServer,\n config: SocketConfig<User>,\n channelRouter: ChannelRouter,\n logger: Logger,\n runWithHttpContext: SocketUpgradeContextRunner\n ): Promise<void> {\n if (this.#lifecycle.status === 'ready') return Promise.resolve()\n if (this.#lifecycle.status === 'starting') return this.#lifecycle.operation.promise\n if (this.#lifecycle.status === 'stopping') {\n return Promise.reject(new Error('Socket service is stopping'))\n }\n if (this.#lifecycle.status === 'failed' && this.#lifecycle.resources) {\n return Promise.reject(new Error('Socket service must be closed before rebooting'))\n }\n\n this.#logger = logger\n const deferred = Promise.withResolvers<void>()\n const operation: SocketServiceBootOperation<User> = {\n kind: 'boot',\n promise: deferred.promise,\n closeRequested: false,\n }\n this.#lifecycle = { status: 'starting', operation }\n\n void this.#boot(httpServer, config, channelRouter, logger, runWithHttpContext, operation).then(\n deferred.resolve,\n deferred.reject\n )\n return operation.promise\n }\n\n async #boot(\n httpServer: HttpServer,\n config: SocketConfig<User>,\n channelRouter: ChannelRouter,\n logger: Logger,\n runWithHttpContext: SocketUpgradeContextRunner,\n operation: SocketServiceBootOperation<User>\n ): Promise<void> {\n try {\n const websocketConfig = config.websocket\n const heartbeatConfig = resolveHeartbeatConfig(websocketConfig)\n const inboundMessageConfig = resolveInboundMessageConfig(websocketConfig)\n this.#outboundMessageConfig = resolveOutboundMessageConfig(websocketConfig)\n this.#shutdownTimeout =\n parseDuration('websocket.shutdownTimeout', websocketConfig?.shutdownTimeout) ??\n DEFAULT_SHUTDOWN_TIMEOUT\n\n operation.channelSubscriptions = new ChannelSubscriptions(\n this,\n channelRouter,\n logger,\n this.#presenceManager ?? undefined,\n inboundMessageConfig.subscriptionLimits\n )\n\n if (config.transport) {\n operation.bus = new SocketBus(config.transport, {\n channel: (message) => {\n this.#traceBroadcast(\n {\n target: 'channel',\n channel: message.channel,\n event: message.event,\n via: 'bus',\n except: message.except,\n },\n () =>\n this.#emitToChannelLocally(\n message.channel,\n message.event,\n message.data,\n message.except\n )\n )\n },\n broadcast: (message) => {\n this.#traceBroadcast({ target: 'global', event: message.event, via: 'bus' }, () =>\n this.#broadcastLocally(message.event, message.data)\n )\n },\n presenceSockets: (channel) => {\n return this.#getLocalPresenceSockets(channel)\n },\n })\n\n await operation.bus.start()\n if (!this.#isStarting(operation)) {\n throw new Error('Socket service boot interrupted by shutdown')\n }\n }\n\n const websocketServer = new WebSocketServer({\n noServer: true,\n maxPayload: inboundMessageConfig.maxPayload,\n })\n\n const upgrader = new SocketUpgrader<User>(\n websocketServer,\n websocketConfig,\n runWithHttpContext,\n (message, error) => this.#warn(message, error)\n )\n\n const upgradeHandler: SocketUpgradeHandler = (request, socket, head) => {\n upgrader\n .handle(request, socket, head, (connection, upgradeRequest, accepted) => {\n this.#handleConnection(connection, upgradeRequest, accepted, inboundMessageConfig)\n })\n .catch((error) => {\n this.#warn('failed to upgrade socket connection: %s', error)\n SocketUpgrader.reject(socket, 500, 'Internal Server Error')\n })\n }\n const runtime: SocketServiceRuntime<User> = {\n kind: 'runtime',\n server: websocketServer,\n httpServer,\n upgradeHandler,\n channelSubscriptions: operation.channelSubscriptions,\n bus: operation.bus ?? null,\n }\n operation.runtime = runtime\n httpServer.on('upgrade', upgradeHandler)\n\n this.#startHeartbeat(heartbeatConfig)\n if (!this.#isStarting(operation)) {\n throw new Error('Socket service boot interrupted by shutdown')\n }\n\n this.#lifecycle = { status: 'ready', runtime }\n this.#configurePresenceFetcher(runtime.bus)\n } catch (error) {\n if (!this.#isStarting(operation)) {\n if (operation.closeRequested) {\n await this.#closeBootBusAfterStart(operation)\n }\n if (\n this.#lifecycle.status === 'failed' &&\n this.#lifecycle.resources === operation &&\n !this.#lifecycle.close\n ) {\n await this.close()\n }\n throw error\n }\n\n const failure = error instanceof Error ? error : new Error('Socket service boot failed')\n this.#lifecycle = { status: 'failed', error: failure, resources: operation }\n await this.close()\n throw error\n }\n }\n\n #handleConnection(\n connection: WebSocket,\n request: IncomingMessage,\n upgrade: AcceptedUpgrade<User>,\n inboundMessageConfig: InboundMessageConfig\n ): void {\n if (this.#lifecycle.status !== 'ready') {\n connection.terminate()\n return\n }\n\n const socket = this.#wrapSocket(connection, request, upgrade)\n\n connectChannel.traceSync(\n () => {\n this.#sockets.set(socket.id, socket)\n this.#emitLifecycleEvent('connect', { socket })\n },\n { socketId: socket.id }\n )\n\n connection.on('error', () => {})\n\n connection.on('message', (data) => {\n if (getRawDataByteLength(data) > inboundMessageConfig.maxPayload) {\n closeConnection(connection, CLOSE_MESSAGE_TOO_BIG, 'Message too big')\n return\n }\n\n if (!this.#acceptMessageRate(socket.id, inboundMessageConfig)) {\n closeConnection(connection, CLOSE_POLICY_VIOLATION, 'Socket message rate limit exceeded')\n return\n }\n\n const message = Message.fromTransport(data.toString())\n\n if (message.type === 'ping') {\n sendFrame(\n socket.raw.connection,\n { id: message.id, type: 'pong' },\n this.#outboundMessageConfig\n )\n return\n }\n\n const enqueued = this.#messageQueue.enqueue(\n socket.id,\n async () => {\n await this.#handleMessage(socket, message).catch((error) => {\n try {\n this.#logger?.warn('unexpected socket message failure: %s', error)\n } catch {\n // Logging must never prevent a protocol response.\n }\n\n sendFrame(\n connection,\n message.id === undefined\n ? { type: 'error', error: 'Unexpected socket error' }\n : Reply.error(message.id, 'Unexpected socket error').toFrame(),\n this.#outboundMessageConfig\n )\n })\n },\n { maxDepth: inboundMessageConfig.maxQueuedMessages }\n )\n\n if (!enqueued) {\n closeConnection(connection, CLOSE_POLICY_VIOLATION, 'Socket message queue limit exceeded')\n }\n })\n\n connection.on('pong', () => {\n this.#clearHeartbeatTimeout(socket.id)\n })\n\n connection.on('close', () => {\n void Promise.resolve()\n .then(() => this.#finalizeSocket(socket))\n .catch((error) => this.markFailed(error))\n })\n }\n\n #finalizeSocket(socket: AuthenticatedSocket<User>): Promise<void> {\n const pending = this.#socketFinalizations.get(socket.id)\n if (pending) {\n return pending\n }\n\n if (!this.#sockets.has(socket.id)) {\n return Promise.resolve()\n }\n\n const channelSubscriptions = this.#channelSubscriptions\n const finalization = disconnectChannel\n .tracePromise(\n async () => {\n this.#clearHeartbeatTimeout(socket.id)\n this.#messageRates.delete(socket.id)\n await this.#messageQueue.drain(socket.id)\n this.#messageQueue.delete(socket.id)\n await channelSubscriptions?.leaveAll(socket)\n channelSubscriptions?.deleteSocket(socket.id)\n this.#sockets.delete(socket.id)\n this.#emitLifecycleEvent('disconnect', { socket, reason: 'close' })\n },\n {\n socketId: socket.id,\n reason: 'close',\n subscriptions: channelSubscriptions?.subscriptionCountFor(socket.id) ?? 0,\n }\n )\n .finally(() => {\n this.#socketFinalizations.delete(socket.id)\n })\n\n this.#socketFinalizations.set(socket.id, finalization)\n return finalization\n }\n\n async #handleMessage(\n socket: AuthenticatedSocket<User>,\n message: TransportMessage\n ): Promise<void> {\n if (!message.valid) {\n sendFrame(socket.raw.connection, message.toRejectionFrame(), this.#outboundMessageConfig)\n return\n }\n\n switch (message.type) {\n case 'ping':\n return\n case 'subscribe': {\n const traceMessage: SocketSubscribeMessage = {\n socketId: socket.id,\n channel: message.channel,\n }\n\n await subscribeChannel.tracePromise(async () => {\n const result = await this.#channelSubscriptions?.subscribe(socket, message.channel)\n\n traceMessage.created = result?.created ?? false\n traceMessage.ok = result?.ack.ok ?? false\n if (!result?.ack.ok) {\n traceMessage.error = result?.ack.error ?? 'Socket service is not initialized'\n }\n\n if (result?.created) {\n this.#emitLifecycleEvent('subscribe', { socket, channel: message.channel })\n }\n\n sendFrame(\n socket.raw.connection,\n Reply.fromSubscribeResult(message.id, result).toFrame(),\n this.#outboundMessageConfig\n )\n }, traceMessage)\n return\n }\n case 'unsubscribe': {\n const traceMessage: SocketUnsubscribeMessage = {\n socketId: socket.id,\n channel: message.channel,\n }\n\n await unsubscribeChannel.tracePromise(async () => {\n traceMessage.removed =\n (await this.#channelSubscriptions?.leave(socket, message.channel)) ?? false\n traceMessage.ok = true\n if (traceMessage.removed) {\n this.#emitLifecycleEvent('unsubscribe', { socket, channel: message.channel })\n }\n sendFrame(\n socket.raw.connection,\n Reply.ok(message.id).toFrame(),\n this.#outboundMessageConfig\n )\n }, traceMessage)\n return\n }\n case 'message':\n case 'whisper': {\n await this.#handleChannelFrame(socket, message)\n return\n }\n }\n }\n\n async #handleChannelFrame(\n socket: AuthenticatedSocket<User>,\n message: Extract<TransportMessage, { type: 'message' | 'whisper' }>\n ): Promise<void> {\n const payload = message.toChannelMessage()\n const traceMessage: SocketChannelMessage = {\n socketId: socket.id,\n channel: payload.channel,\n event: payload.event,\n }\n\n await channelMessageChannel.tracePromise(async () => {\n const ack = await this.#handleChannelPayload(socket, message.type, payload)\n traceMessage.ok = ack.ok\n if (!ack.ok) {\n traceMessage.error = ack.error\n }\n\n sendFrame(\n socket.raw.connection,\n Reply.fromChannelAck(message.id, ack).toFrame(),\n this.#outboundMessageConfig\n )\n }, traceMessage)\n }\n\n async #handleChannelPayload(\n socket: AuthenticatedSocket<User>,\n type: 'message' | 'whisper',\n payload: ChannelMessage\n ): Promise<ChannelAck> {\n if (typeof payload.channel !== 'string' || typeof payload.event !== 'string') {\n return { ok: false, error: `Invalid channel ${type}` }\n }\n\n if (type === 'message') {\n return this.#channelSubscriptions!.handleMessage(socket, payload)\n }\n\n return this.#channelSubscriptions!.relayWhisper(socket, payload)\n }\n\n #wrapSocket(\n connection: WebSocket,\n request: IncomingMessage,\n upgrade: AcceptedUpgrade<User>\n ): AuthenticatedSocket<User> {\n const raw: RawSocket = {\n id: randomUUID(),\n data: {},\n connection,\n request,\n httpContext: upgrade.httpContext,\n }\n\n return {\n id: raw.id,\n user: upgrade.user,\n\n getUserOrFail() {\n if (this.user === undefined) {\n throw new SocketResponseError('Unauthorized')\n }\n\n return this.user\n },\n\n emit: (event, data) => {\n this.#sendSerializedEventFrame(connection, serializeFrame({ type: 'event', event, data }))\n },\n\n disconnect() {\n connection.close(SERVER_DISCONNECT_CODE, SERVER_DISCONNECT_REASON)\n },\n\n raw,\n }\n }\n\n to(channel: string) {\n return {\n emit: (event: string, data: unknown) => {\n this.#broadcastSink.dispatch({ target: 'channel', channel, event, data })\n },\n except: (socketId: string) => ({\n emit: (event: string, data: unknown) => {\n this.#broadcastSink.dispatch({\n target: 'channel',\n channel,\n event,\n data,\n except: [socketId],\n })\n },\n }),\n }\n }\n\n broadcast(event: string, data: unknown): void {\n this.#broadcastSink.dispatch({ target: 'global', event, data })\n }\n\n #deliverBroadcast(emission: SocketEmission): void {\n switch (emission.target) {\n case 'channel': {\n const channel = emission.channel\n const serializedFrame = serializeFrame({\n type: 'event',\n channel,\n event: emission.event,\n data: emission.data,\n })\n this.#bus?.publishChannel(channel, emission.event, emission.data, emission.except)\n\n const traceMessage: SocketBroadcastMessage = {\n target: 'channel',\n channel,\n event: emission.event,\n via: 'local',\n }\n if (emission.except) {\n traceMessage.except = emission.except\n }\n\n this.#traceBroadcast(traceMessage, () =>\n this.#emitToChannelLocally(\n channel,\n emission.event,\n emission.data,\n emission.except,\n serializedFrame\n )\n )\n return\n }\n case 'global': {\n const serializedFrame = serializeFrame({\n type: 'event',\n event: emission.event,\n data: emission.data,\n })\n this.#bus?.publishBroadcast(emission.event, emission.data)\n this.#traceBroadcast({ target: 'global', event: emission.event, via: 'local' }, () =>\n this.#broadcastLocally(emission.event, emission.data, serializedFrame)\n )\n }\n }\n }\n\n #traceBroadcast(message: SocketBroadcastMessage, deliver: () => number): void {\n broadcastChannel.traceSync(() => {\n message.delivered = deliver()\n }, message)\n }\n\n #sendSerializedEventFrame(connection: WebSocket, serializedFrame: string): boolean {\n return sendSerializedFrameWithBackpressure(\n connection,\n serializedFrame,\n this.#outboundMessageConfig\n )\n }\n\n #emitToChannelLocally(\n channel: string,\n event: string,\n data: unknown,\n except: string[] = [],\n serializedFrame = serializeFrame({ type: 'event', channel, event, data })\n ): number {\n let delivered = 0\n\n for (const socketId of this.#channelSubscriptions?.getSocketIds(channel) ?? []) {\n if (except.includes(socketId)) {\n continue\n }\n\n const socket = this.#sockets.get(socketId)\n if (socket && this.#sendSerializedEventFrame(socket.raw.connection, serializedFrame)) {\n delivered += 1\n }\n }\n\n return delivered\n }\n\n #broadcastLocally(\n event: string,\n data: unknown,\n serializedFrame = serializeFrame({ type: 'event', event, data })\n ): number {\n let delivered = 0\n\n for (const socket of this.#sockets.values()) {\n if (this.#sendSerializedEventFrame(socket.raw.connection, serializedFrame)) {\n delivered += 1\n }\n }\n\n return delivered\n }\n\n #configurePresenceFetcher(bus: SocketBus | null | undefined): void {\n if (!this.#presenceManager || !bus) {\n return\n }\n\n this.#presenceManager.setSocketFetcher(async (channel) => {\n return [\n ...this.#presenceManager!.getLocalSockets(channel),\n ...(await bus.fetchPresenceSockets(channel)),\n ]\n })\n }\n\n #getLocalPresenceSockets(channel: string): SerializablePresenceSocket[] {\n return (this.#presenceManager?.getLocalSockets(channel) ?? []).map((socket) => {\n return PresenceSocketFrame.fromSocket(channel, socket).toTransport()\n })\n }\n\n getSocket(socketId: string): AuthenticatedSocket<User> | undefined {\n return this.#sockets.get(socketId)\n }\n\n get connectionsCount(): number {\n return this.#sockets.size\n }\n\n get status(): SocketServiceStatus {\n return this.#lifecycle.status\n }\n\n get ready(): boolean {\n return this.#lifecycle.status === 'ready'\n }\n\n fake(): SocketFake {\n const fake = new SocketFake(() => {\n if (this.#fake === fake) {\n this.restore()\n }\n })\n\n this.#fake = fake\n this.#broadcastSink = fake\n return fake\n }\n\n restore(): void {\n this.#fake = null\n this.#broadcastSink = this.#deliverySink\n }\n\n markFailed(error: unknown): void {\n const failure = error instanceof Error ? error : new Error('Socket service failed')\n const lifecycle = this.#lifecycle\n\n if (lifecycle.status === 'stopped') {\n this.#lifecycle = { status: 'failed', error: failure }\n return\n }\n if (lifecycle.status === 'starting') {\n this.#lifecycle = { status: 'failed', error: failure, resources: lifecycle.operation }\n return\n }\n if (lifecycle.status === 'ready') {\n this.#lifecycle = { status: 'failed', error: failure, resources: lifecycle.runtime }\n return\n }\n\n this.#lifecycle = { ...lifecycle, status: 'failed', error: failure }\n }\n\n #warn(message: string, error: unknown): void {\n try {\n this.#logger?.warn(message, error)\n } catch {\n // Logging must never change socket behavior.\n }\n }\n\n #emitLifecycleEvent<EventName extends keyof SocketEvents<User>>(\n eventName: EventName,\n event: SocketEvents<User>[EventName]\n ): void {\n void this.emit(eventName, event).catch((error) => {\n try {\n this.#logger?.warn('socket %s listener failed: %s', eventName, error)\n } catch {\n // Lifecycle observers and their reporting must not affect the socket service.\n }\n })\n }\n\n health(): SocketHealthSnapshot {\n const error = this.#lifecycle.status === 'failed' ? this.#lifecycle.error : undefined\n return {\n status: this.#lifecycle.status,\n ready: this.ready,\n connections: this.#sockets.size,\n channels: this.#channelSubscriptions?.channelsCount ?? 0,\n ...(error ? { lastError: error.message } : {}),\n }\n }\n\n #startHeartbeat(config: { interval: number; timeout: number } | null): void {\n this.#stopHeartbeat()\n\n if (!config) {\n return\n }\n\n this.#heartbeatInterval = setInterval(() => {\n this.#pingSockets(config.timeout)\n }, config.interval)\n }\n\n #pingSockets(timeout: number): void {\n for (const socket of this.#sockets.values()) {\n const { connection } = socket.raw\n\n if (connection.readyState !== WebSocket.OPEN) {\n this.#clearHeartbeatTimeout(socket.id)\n continue\n }\n\n if (this.#heartbeatTimeouts.has(socket.id)) {\n continue\n }\n\n const timeoutId = setTimeout(() => {\n this.#heartbeatTimeouts.delete(socket.id)\n connection.terminate()\n }, timeout)\n\n this.#heartbeatTimeouts.set(socket.id, timeoutId)\n\n try {\n connection.ping()\n } catch {\n this.#clearHeartbeatTimeout(socket.id)\n connection.terminate()\n }\n }\n }\n\n #clearHeartbeatTimeout(socketId: string): void {\n const timeout = this.#heartbeatTimeouts.get(socketId)\n\n if (!timeout) {\n return\n }\n\n clearTimeout(timeout)\n this.#heartbeatTimeouts.delete(socketId)\n }\n\n #stopHeartbeat(): void {\n if (this.#heartbeatInterval) {\n clearInterval(this.#heartbeatInterval)\n this.#heartbeatInterval = null\n }\n\n for (const timeout of this.#heartbeatTimeouts.values()) {\n clearTimeout(timeout)\n }\n\n this.#heartbeatTimeouts.clear()\n }\n\n #acceptMessageRate(socketId: string, config: InboundMessageConfig): boolean {\n const now = Date.now()\n const rate = this.#messageRates.get(socketId)\n\n if (!rate || now - rate.intervalStartedAt >= config.messageRateInterval) {\n this.#messageRates.set(socketId, { count: 1, intervalStartedAt: now })\n return true\n }\n\n if (rate.count >= config.maxMessagesPerInterval) {\n return false\n }\n\n rate.count += 1\n return true\n }\n\n #cleanup(channelSubscriptions: ChannelSubscriptions<User> | undefined): void {\n this.#stopHeartbeat()\n this.#sockets.clear()\n this.#messageQueue.clear()\n this.#messageRates.clear()\n this.#socketFinalizations.clear()\n channelSubscriptions?.clear()\n }\n\n close(): Promise<void> {\n const lifecycle = this.#lifecycle\n if (lifecycle.status === 'stopped') return Promise.resolve()\n if (lifecycle.status === 'stopping') return lifecycle.close\n if (lifecycle.status === 'failed' && lifecycle.close) return lifecycle.close\n if (lifecycle.status === 'failed' && !lifecycle.resources) return Promise.resolve()\n\n if (lifecycle.status === 'starting') {\n return this.#startClose(lifecycle.operation, lifecycle.operation.promise)\n }\n if (lifecycle.status === 'ready') return this.#startClose(lifecycle.runtime)\n\n return this.#startClose(lifecycle.resources!, undefined, lifecycle.error)\n }\n\n #startClose(\n resources: SocketServiceResources<User>,\n pendingBoot?: Promise<void>,\n preservedError?: Error\n ): Promise<void> {\n const deferred = Promise.withResolvers<void>()\n const close = deferred.promise\n if (resources.kind === 'boot') resources.closeRequested = true\n this.#lifecycle = preservedError\n ? { status: 'failed', error: preservedError, resources, close }\n : { status: 'stopping', resources, close }\n\n void this.#close(resources, pendingBoot).then(\n () => {\n if (!('close' in this.#lifecycle) || this.#lifecycle.close !== close) return\n\n this.#lifecycle =\n this.#lifecycle.status === 'failed'\n ? { status: 'failed', error: this.#lifecycle.error, close }\n : { status: 'stopped' }\n deferred.resolve()\n },\n (error) => {\n const failure = error instanceof Error ? error : new Error('Socket service shutdown failed')\n if ('close' in this.#lifecycle && this.#lifecycle.close === close) {\n this.#lifecycle = { status: 'failed', error: failure, close }\n }\n deferred.reject(error)\n }\n )\n return close\n }\n\n async #waitForBootClose(pendingBoot: Promise<void>, deadline: number): Promise<void> {\n const result = await settleBeforeDeadline(pendingBoot, deadline)\n if (result === null) {\n this.#warn(\n 'socket boot exceeded the %dms shutdown timeout; forcing cleanup',\n this.#shutdownTimeout\n )\n }\n }\n\n #startServerClose(server: WebSocketServer | undefined): Promise<unknown | null> {\n if (!server) return Promise.resolve(null)\n\n return new Promise((resolve) => {\n server.close((error) => resolve(error ?? null))\n })\n }\n\n async #closeSockets(deadline: number): Promise<unknown[]> {\n this.#stopHeartbeat()\n const sockets = [...this.#sockets.values()]\n for (const socket of sockets) {\n const { connection } = socket.raw\n connection.close(SERVER_DISCONNECT_CODE, SERVER_DISCONNECT_REASON)\n const terminateTimer = setTimeout(() => connection.terminate(), 50)\n connection.once('close', () => clearTimeout(terminateTimer))\n }\n\n const finalizations = sockets.map((socket) => {\n return Promise.resolve().then(() => this.#finalizeSocket(socket))\n })\n const results = await settleBeforeDeadline(Promise.allSettled(finalizations), deadline)\n if (results === null) {\n this.#warn(\n 'socket finalization exceeded the %dms shutdown timeout; forcing cleanup',\n this.#shutdownTimeout\n )\n return []\n }\n if (results.status === 'rejected') return []\n\n const errors: unknown[] = []\n for (const result of results.value) {\n if (result.status === 'rejected') errors.push(result.reason)\n }\n return errors\n }\n\n async #closeBus(\n resources: SocketServiceResources<User>,\n bus: SocketBus | null | undefined,\n deadline: number\n ): Promise<unknown[]> {\n if (!bus) return []\n\n const close =\n resources.kind === 'boot'\n ? (resources.busCloseAfterStart ?? (resources.busCloseBeforeStart ??= bus.close()))\n : bus.close()\n const result = await settleBeforeDeadline(close, deadline)\n if (result === null) {\n this.#warn(\n 'socket transport exceeded the %dms shutdown timeout; forcing cleanup',\n this.#shutdownTimeout\n )\n return []\n }\n return result.status === 'rejected' ? [result.reason] : []\n }\n\n async #finishServerClose(close: Promise<unknown | null>, deadline: number): Promise<unknown[]> {\n const result = await settleBeforeDeadline(close, deadline)\n if (result === null) {\n this.#warn(\n 'socket server exceeded the %dms shutdown timeout; forcing cleanup',\n this.#shutdownTimeout\n )\n return []\n }\n if (result.status === 'rejected' || !result.value) return []\n return [result.value]\n }\n\n async #close(\n resources: SocketServiceResources<User>,\n pendingBoot?: Promise<void>\n ): Promise<void> {\n const deadline = Date.now() + this.#shutdownTimeout\n if (pendingBoot) await this.#waitForBootClose(pendingBoot, deadline)\n\n const runtime = resources.kind === 'runtime' ? resources : resources.runtime\n const channelSubscriptions =\n runtime?.channelSubscriptions ??\n (resources.kind === 'boot' ? resources.channelSubscriptions : undefined)\n const server = runtime?.server\n const bus = runtime?.bus ?? (resources.kind === 'boot' ? resources.bus : undefined)\n const httpServer = runtime?.httpServer\n const upgradeHandler = runtime?.upgradeHandler\n\n if (httpServer && upgradeHandler) {\n httpServer.off('upgrade', upgradeHandler)\n }\n\n const serverClose = this.#startServerClose(server)\n const errors = await this.#closeSockets(deadline)\n\n this.#cleanup(channelSubscriptions)\n this.#presenceManager?.setSocketFetcher(null)\n\n errors.push(...(await this.#closeBus(resources, bus, deadline)))\n errors.push(...(await this.#finishServerClose(serverClose, deadline)))\n\n if (errors.length > 0) {\n const error =\n errors.length === 1 && errors[0] instanceof Error\n ? errors[0]\n : new AggregateError(errors, 'Socket service shutdown failed')\n throw error\n }\n }\n}\n","import type { BaseChannel } from './base_channel.js'\n\nexport interface StoredChannelSubscription {\n channelName: string\n instance: BaseChannel<any, any>\n paramValues: string[]\n}\n\n/**\n * Stores durable Channel subscriptions and keeps Socket/Channel indexes in sync.\n */\nexport class ChannelSubscriptionStorage {\n #subscriptions = new Map<string, Map<string, StoredChannelSubscription>>()\n #subscribers = new Map<string, Set<string>>()\n\n has(socketId: string, channelName: string): boolean {\n return this.#subscriptions.get(socketId)?.has(channelName) ?? false\n }\n\n get(socketId: string, channelName: string): StoredChannelSubscription | undefined {\n return this.#subscriptions.get(socketId)?.get(channelName)\n }\n\n set(socketId: string, channelName: string, subscription: StoredChannelSubscription): void {\n if (!this.#subscriptions.has(socketId)) {\n this.#subscriptions.set(socketId, new Map())\n }\n\n this.#subscriptions.get(socketId)!.set(channelName, subscription)\n\n if (!this.#subscribers.has(channelName)) {\n this.#subscribers.set(channelName, new Set())\n }\n\n this.#subscribers.get(channelName)!.add(socketId)\n }\n\n delete(socketId: string, channelName: string): void {\n const subscriptions = this.#subscriptions.get(socketId)\n\n if (!subscriptions) {\n return\n }\n\n subscriptions.delete(channelName)\n if (subscriptions.size === 0) {\n this.#subscriptions.delete(socketId)\n }\n\n const subscribers = this.#subscribers.get(channelName)\n subscribers?.delete(socketId)\n if (subscribers?.size === 0) {\n this.#subscribers.delete(channelName)\n }\n }\n\n deleteSocket(socketId: string): void {\n for (const channelName of this.channelNamesFor(socketId)) {\n this.delete(socketId, channelName)\n }\n }\n\n channelNamesFor(socketId: string): string[] {\n return [...(this.#subscriptions.get(socketId)?.keys() ?? [])]\n }\n\n countForSocket(socketId: string): number {\n return this.#subscriptions.get(socketId)?.size ?? 0\n }\n\n socketIdsFor(channelName: string): string[] {\n return [...(this.#subscribers.get(channelName) ?? [])]\n }\n\n get channelsCount(): number {\n return this.#subscribers.size\n }\n\n clear(): void {\n this.#subscriptions.clear()\n this.#subscribers.clear()\n }\n}\n","import type { Logger } from '@adonisjs/logger'\nimport { SocketResponseError } from './base_channel.js'\nimport type { BaseChannel } from './base_channel.js'\nimport {\n ChannelSubscriptionStorage,\n type StoredChannelSubscription,\n} from './channel_subscription_storage.js'\nimport type { ChannelRouter } from './channel_router.js'\nimport type { PresenceData, PresenceManager } from './presence_manager.js'\nimport type { SocketService } from './socket_service.js'\nimport type { AuthenticatedSocket, ChannelAck, ChannelMessage } from './types.js'\n\ninterface AuthorizedChannel<User> {\n instance: BaseChannel<User>\n params: Record<string, string>\n paramValues: string[]\n presenceData: Record<string, unknown> | PresenceData | null\n}\n\nexport type ChannelSubscribeAck =\n | {\n ok: true\n presenceData?: Record<string, unknown> | PresenceData | null\n error?: never\n }\n | { ok: false; error: string; presenceData?: never }\n\nexport interface ChannelSubscribeResult {\n ack: ChannelSubscribeAck\n created: boolean\n}\n\nexport interface ChannelSubscriptionLimits {\n maxSubscriptionsPerSocket: number\n maxChannelNameLength: number\n}\n\n/**\n * Durable channel subscriptions for sockets.\n */\nexport class ChannelSubscriptions<User = unknown> {\n #storage = new ChannelSubscriptionStorage()\n #channelOperations = new Map<string, Promise<void>>()\n\n static #serializePresenceData(presenceData: PresenceData): Record<string, unknown> {\n return {\n ...presenceData,\n users: presenceData.users.map((user) => ({\n ...user,\n joinedAt: user.joinedAt.toISOString(),\n })),\n }\n }\n\n constructor(\n private socketService: SocketService<User>,\n private channelRouter: ChannelRouter,\n private logger: Logger,\n private presenceManager?: PresenceManager,\n private limits?: ChannelSubscriptionLimits\n ) {}\n\n setPresenceManager(presenceManager: PresenceManager): void {\n this.presenceManager = presenceManager\n }\n\n async subscribe(\n socket: AuthenticatedSocket<User>,\n channelName: string\n ): Promise<ChannelSubscribeResult> {\n return this.#subscribe(socket, channelName)\n }\n\n async #subscribe(\n socket: AuthenticatedSocket<User>,\n channelName: string\n ): Promise<ChannelSubscribeResult> {\n const existing = await this.#refreshExistingSubscription(socket, channelName)\n if (existing) {\n return existing\n }\n\n if (this.limits && channelName.length > this.limits.maxChannelNameLength) {\n return {\n ack: { ok: false, error: 'Channel name is too long' },\n created: false,\n }\n }\n\n if (\n this.limits &&\n this.#storage.channelNamesFor(socket.id).length >= this.limits.maxSubscriptionsPerSocket\n ) {\n return {\n ack: { ok: false, error: 'Socket subscription limit exceeded' },\n created: false,\n }\n }\n\n const result = await this.channelRouter.authorize(socket, channelName)\n\n if (!result.success) {\n if ('cause' in result && !(result.cause instanceof SocketResponseError)) {\n this.#warn(`failed to authorize channel \"${channelName}\": %s`, result.cause)\n }\n\n return {\n ack: { ok: false, error: result.error },\n created: false,\n }\n }\n\n if (this.#usesPresence(result.instance)) {\n return this.#withChannelOperation(`${socket.id}\\0${channelName}`, async () => {\n const concurrentSubscription = await this.#refreshExistingSubscription(socket, channelName)\n if (concurrentSubscription) {\n return concurrentSubscription\n }\n\n return this.#completeSubscription(socket, channelName, result)\n })\n }\n\n return this.#completeSubscription(socket, channelName, result)\n }\n\n async #completeSubscription(\n socket: AuthenticatedSocket<User>,\n channelName: string,\n result: AuthorizedChannel<User>\n ): Promise<ChannelSubscribeResult> {\n result.instance.$setContext(\n this.socketService,\n channelName,\n result.params,\n this.presenceManager\n )\n\n let presenceData: Record<string, unknown> | PresenceData | null = result.presenceData\n let presenceSnapshot: PresenceData | null = null\n let presenceJoined = false\n let serializationError: unknown\n\n try {\n if (this.#usesPresence(result.instance)) {\n const presenceInfo = result.instance.$getPresenceInfo(socket)\n const joinedUser = this.presenceManager!.join(channelName, socket.raw, presenceInfo)\n const { joinedAt: _joinedAt, ...member } = joinedUser\n presenceJoined = true\n\n presenceSnapshot = await this.presenceManager!.snapshot(channelName)\n presenceData = presenceSnapshot\n const visibleUser = presenceSnapshot.users.find((user) => user.id === presenceInfo.id)\n const wasPresent = Boolean(visibleUser && visibleUser !== joinedUser)\n\n try {\n JSON.stringify(presenceData)\n } catch (error) {\n serializationError = error\n throw error\n }\n\n if (!wasPresent) {\n await result.instance.onMemberJoin?.(socket, member, ...result.paramValues)\n }\n await result.instance.onJoin?.(socket, ...result.paramValues)\n } else {\n try {\n JSON.stringify(presenceData)\n } catch (error) {\n serializationError = error\n throw error\n }\n\n await result.instance.onJoin?.(socket, ...result.paramValues)\n }\n\n this.#storage.set(socket.id, channelName, {\n channelName,\n instance: result.instance,\n paramValues: result.paramValues,\n })\n\n if (presenceSnapshot) {\n this.socketService\n .to(channelName)\n .except(socket.id)\n .emit('presence:update', ChannelSubscriptions.#serializePresenceData(presenceSnapshot))\n }\n } catch (error) {\n if (presenceJoined) {\n this.presenceManager!.leave(channelName, socket.raw)\n\n const rollbackData = await this.presenceManager!.snapshot(channelName).catch(() => null)\n if (rollbackData) {\n this.socketService\n .to(channelName)\n .emit('presence:update', ChannelSubscriptions.#serializePresenceData(rollbackData))\n }\n }\n\n this.#storage.delete(socket.id, channelName)\n\n if (serializationError) {\n this.#warn(\n `failed to serialize subscription response for channel \"${channelName}\": %s`,\n serializationError\n )\n } else if (!(error instanceof SocketResponseError)) {\n this.#warn(`failed to join channel \"${channelName}\": %s`, error)\n }\n\n return {\n ack: {\n ok: false,\n error: serializationError\n ? 'Subscription response is not serializable'\n : error instanceof SocketResponseError\n ? error.message\n : 'Join failed',\n },\n created: false,\n }\n }\n\n return {\n ack: { ok: true, presenceData },\n created: true,\n }\n }\n\n async leave(socket: AuthenticatedSocket<User>, channelName: string): Promise<boolean> {\n const subscription = this.#storage.get(socket.id, channelName)\n if (!subscription) {\n return false\n }\n\n this.#storage.delete(socket.id, channelName)\n\n if (this.#usesPresence(subscription.instance)) {\n await this.#withChannelOperation(`${socket.id}\\0${channelName}`, () =>\n this.#cleanupAfterLeave(socket, channelName, subscription)\n )\n } else {\n await this.#cleanupAfterLeave(socket, channelName, subscription)\n }\n\n return true\n }\n\n async #cleanupAfterLeave(\n socket: AuthenticatedSocket<User>,\n channelName: string,\n subscription: StoredChannelSubscription\n ): Promise<void> {\n if (this.#usesPresence(subscription.instance)) {\n const presenceUser = this.presenceManager!.getLocalUser(channelName, socket.id)\n this.presenceManager!.leave(channelName, socket.raw)\n\n try {\n const presenceData = await this.presenceManager!.snapshot(channelName)\n\n this.socketService\n .to(channelName)\n .emit('presence:update', ChannelSubscriptions.#serializePresenceData(presenceData))\n\n if (presenceUser && !presenceData.users.some((user) => user.id === presenceUser.id)) {\n const { joinedAt: _joinedAt, ...member } = presenceUser\n await subscription.instance.onMemberLeave?.(socket, member, ...subscription.paramValues)\n }\n } catch (error) {\n this.#warn(`failed to update presence while leaving channel \"${channelName}\": %s`, error)\n }\n }\n\n try {\n await subscription.instance.onLeave?.(socket, ...subscription.paramValues)\n } catch (error) {\n this.#warn(`failed to leave channel \"${channelName}\": %s`, error)\n }\n }\n\n async leaveAll(socket: AuthenticatedSocket<User>): Promise<void> {\n for (const channelName of this.#storage.channelNamesFor(socket.id)) {\n await this.leave(socket, channelName)\n }\n }\n\n async handleMessage(\n socket: AuthenticatedSocket<User>,\n payload: ChannelMessage\n ): Promise<ChannelAck> {\n const subscription = this.#storage.get(socket.id, payload.channel)\n\n if (!subscription) {\n return { ok: false, error: 'Not subscribed' }\n }\n\n try {\n const result = await subscription.instance.$handleMessage(socket, payload.event, payload.data)\n\n try {\n JSON.stringify(result)\n } catch (error) {\n this.#warn(\n `failed to serialize handler response for channel \"${payload.channel}\": %s`,\n error\n )\n return { ok: false, error: 'Handler response is not serializable' }\n }\n\n return { ok: true, data: result }\n } catch (error) {\n if (!(error instanceof SocketResponseError)) {\n this.#warn(`channel handler failed for \"${payload.channel}\": %s`, error)\n }\n\n return {\n ok: false,\n error: error instanceof SocketResponseError ? error.message : 'Handler error',\n }\n }\n }\n\n relayWhisper(socket: AuthenticatedSocket<User>, payload: ChannelMessage): ChannelAck {\n if (!this.#storage.has(socket.id, payload.channel)) {\n return { ok: false, error: 'Not subscribed' }\n }\n\n this.socketService\n .to(payload.channel)\n .except(socket.id)\n .emit(`client:${payload.event}`, payload.data)\n\n return { ok: true }\n }\n\n deleteSocket(socketId: string): void {\n this.#storage.deleteSocket(socketId)\n }\n\n clear(): void {\n this.#storage.clear()\n this.#channelOperations.clear()\n }\n\n getSocketIds(channelName: string): string[] {\n return this.#storage.socketIdsFor(channelName)\n }\n\n subscriptionCountFor(socketId: string): number {\n return this.#storage.countForSocket(socketId)\n }\n\n get channelsCount(): number {\n return this.#storage.channelsCount\n }\n\n #warn(message: string, error: unknown): void {\n try {\n this.logger.warn(message, error)\n } catch {\n // Logging must never change the socket protocol outcome.\n }\n }\n\n async #withChannelOperation<Result>(\n operationKey: string,\n operation: () => Promise<Result>\n ): Promise<Result> {\n const previous = this.#channelOperations.get(operationKey) ?? Promise.resolve()\n const release = Promise.withResolvers<void>()\n const queued = previous.then(() => release.promise)\n this.#channelOperations.set(operationKey, queued)\n\n await previous\n try {\n return await operation()\n } finally {\n release.resolve()\n if (this.#channelOperations.get(operationKey) === queued) {\n this.#channelOperations.delete(operationKey)\n }\n }\n }\n\n #usesPresence(instance: BaseChannel<any, any>): boolean {\n return Boolean(\n (instance.constructor as typeof BaseChannel).options?.presence && this.presenceManager\n )\n }\n\n async #refreshExistingSubscription(\n socket: AuthenticatedSocket<User>,\n channelName: string\n ): Promise<ChannelSubscribeResult | null> {\n if (!this.#storage.has(socket.id, channelName)) {\n return null\n }\n\n let presenceData: PresenceData | undefined\n\n try {\n presenceData = await this.#getPresenceData(socket, channelName)\n } catch (error) {\n this.#warn(`failed to refresh subscription for channel \"${channelName}\": %s`, error)\n return {\n ack: { ok: false, error: 'Subscribe failed' },\n created: false,\n }\n }\n\n try {\n JSON.stringify(presenceData)\n } catch (error) {\n this.#warn(\n `failed to serialize subscription response for channel \"${channelName}\": %s`,\n error\n )\n return {\n ack: { ok: false, error: 'Subscription response is not serializable' },\n created: false,\n }\n }\n\n return {\n ack: {\n ok: true,\n presenceData,\n },\n created: false,\n }\n }\n\n async #getPresenceData(\n socket: AuthenticatedSocket<User>,\n channelName: string\n ): Promise<PresenceData | undefined> {\n if (!this.presenceManager?.hasLocal(channelName, socket.id)) {\n return undefined\n }\n\n return this.presenceManager.snapshot(channelName)\n }\n}\n","import type { ChannelAck, ServerProtocolMessage } from '../shared_types.js'\nimport type { ChannelSubscribeResult } from '../channel_subscriptions.js'\n\nconst INVALID_SOCKET_MESSAGE = 'Invalid socket message'\n\nexport class Reply {\n #id: string | undefined\n #ack: ChannelAck\n\n private constructor(id: string | undefined, ack: ChannelAck) {\n this.#id = id\n this.#ack = ack\n }\n\n static ok(id: string | undefined, data?: unknown): Reply {\n return new Reply(id, { ok: true, data })\n }\n\n static error(id: string | undefined, error: string): Reply {\n return new Reply(id, { ok: false, error })\n }\n\n static invalidMessage(id: string | undefined): ServerProtocolMessage {\n if (id === undefined) {\n return { type: 'error', error: INVALID_SOCKET_MESSAGE }\n }\n\n return Reply.error(id, INVALID_SOCKET_MESSAGE).toFrame()\n }\n\n static fromSubscribeResult(\n id: string | undefined,\n result: ChannelSubscribeResult | undefined\n ): Reply {\n if (!result) {\n return Reply.error(id, 'Socket service is not initialized')\n }\n\n if (!result.ack.ok) {\n return Reply.error(id, result.ack.error)\n }\n\n const data = result.ack.presenceData\n ? {\n presenceData: result.ack.presenceData,\n }\n : undefined\n\n return Reply.ok(id, data)\n }\n\n static fromChannelAck(id: string | undefined, ack: ChannelAck): Reply {\n return ack.ok ? Reply.ok(id, ack.data) : Reply.error(id, ack.error)\n }\n\n toFrame(): Extract<ServerProtocolMessage, { type: 'ack' }> {\n if (!this.#ack.ok) {\n return {\n id: this.#id,\n type: 'ack',\n ok: false,\n error: this.#ack.error,\n }\n }\n\n return this.#ack.data === undefined\n ? { id: this.#id, type: 'ack', ok: true }\n : { id: this.#id, type: 'ack', ok: true, data: this.#ack.data }\n }\n}\n","import type {\n ChannelMessage,\n ClientProtocolMessage,\n ServerProtocolMessage,\n} from '../shared_types.js'\nimport { Reply } from './reply.js'\n\ntype ClientMessageType = ClientProtocolMessage['type']\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nexport abstract class Message {\n abstract readonly valid: boolean\n abstract readonly type: ClientMessageType | 'invalid'\n\n static fromTransport(raw: string): TransportMessage {\n try {\n return Message.fromParsedTransport(JSON.parse(raw))\n } catch {\n return new InvalidMessage(undefined)\n }\n }\n\n private static fromParsedTransport(value: unknown): TransportMessage {\n if (!isRecord(value)) {\n return new InvalidMessage(undefined)\n }\n\n const id = typeof value.id === 'string' ? value.id : undefined\n\n if ('id' in value && typeof value.id !== 'string') {\n return new InvalidMessage(undefined)\n }\n\n if (!isClientMessageType(value.type)) {\n return new InvalidMessage(id)\n }\n\n if (value.type === 'ping') {\n return new PingMessage(id)\n }\n\n if (value.type === 'subscribe' && typeof value.channel === 'string') {\n return new SubscribeMessage(id, value.channel)\n }\n\n if (value.type === 'unsubscribe' && typeof value.channel === 'string') {\n return new UnsubscribeMessage(id, value.channel)\n }\n\n if (\n (value.type === 'message' || value.type === 'whisper') &&\n typeof value.channel === 'string' &&\n typeof value.event === 'string'\n ) {\n return new ChannelProtocolMessage(id, value.type, value.channel, value.event, value.data)\n }\n\n return new InvalidMessage(id)\n }\n}\n\nexport class InvalidMessage extends Message {\n readonly valid = false\n readonly type = 'invalid'\n\n constructor(readonly id: string | undefined) {\n super()\n }\n\n toRejectionFrame(): ServerProtocolMessage {\n return Reply.invalidMessage(this.id)\n }\n}\n\nexport class PingMessage extends Message {\n readonly valid = true\n readonly type = 'ping'\n\n constructor(readonly id: string | undefined) {\n super()\n }\n}\n\nexport class SubscribeMessage extends Message {\n readonly valid = true\n readonly type = 'subscribe'\n\n constructor(\n readonly id: string | undefined,\n readonly channel: string\n ) {\n super()\n }\n}\n\nexport class UnsubscribeMessage extends Message {\n readonly valid = true\n readonly type = 'unsubscribe'\n\n constructor(\n readonly id: string | undefined,\n readonly channel: string\n ) {\n super()\n }\n}\n\nexport class ChannelProtocolMessage extends Message {\n readonly valid = true\n\n constructor(\n readonly id: string | undefined,\n readonly type: 'message' | 'whisper',\n readonly channel: string,\n readonly event: string,\n readonly data: unknown\n ) {\n super()\n }\n\n toChannelMessage(): ChannelMessage {\n return {\n channel: this.channel,\n event: this.event,\n data: this.data,\n }\n }\n}\n\nexport type TransportMessage =\n | InvalidMessage\n | PingMessage\n | SubscribeMessage\n | UnsubscribeMessage\n | ChannelProtocolMessage\n\nfunction isClientMessageType(value: unknown): value is ClientMessageType {\n return (\n value === 'ping' ||\n value === 'subscribe' ||\n value === 'unsubscribe' ||\n value === 'message' ||\n value === 'whisper'\n )\n}\n","export class MessageQueue<Key = string> {\n #queues = new Map<Key, Promise<void>>()\n #depths = new Map<Key, number>()\n\n enqueue(key: Key, task: () => Promise<void>, options: { maxDepth?: number } = {}): boolean {\n const depth = this.#depths.get(key) ?? 0\n\n if (options.maxDepth !== undefined && depth >= options.maxDepth) {\n return false\n }\n\n this.#depths.set(key, depth + 1)\n\n const previous = this.#queues.get(key) ?? Promise.resolve()\n const next = previous\n .catch(() => {})\n .then(task)\n .catch(() => {})\n .finally(() => {\n const nextDepth = (this.#depths.get(key) ?? 1) - 1\n\n if (nextDepth <= 0) {\n this.#depths.delete(key)\n } else {\n this.#depths.set(key, nextDepth)\n }\n\n if (this.#queues.get(key) === next) {\n this.#queues.delete(key)\n }\n })\n\n this.#queues.set(key, next)\n return true\n }\n\n drain(key: Key): Promise<void> {\n return this.#queues.get(key) ?? Promise.resolve()\n }\n\n delete(key: Key): void {\n this.#queues.delete(key)\n this.#depths.delete(key)\n }\n\n clear(): void {\n this.#queues.clear()\n this.#depths.clear()\n }\n}\n","import { randomUUID } from 'node:crypto'\nimport { Bus } from '@boringnode/bus'\nimport type { Serializable, TransportFactory } from '@boringnode/bus/types/main'\nimport type { PresenceSocket } from './presence_manager.js'\nimport { PresenceSocketFrame, type SerializablePresenceSocket } from './presence_socket_frame.js'\nimport { parseDuration, type Duration } from './duration.js'\n\nexport type { SerializablePresenceSocket } from './presence_socket_frame.js'\n\nconst DEFAULT_CHANNEL = 'socket::broadcast'\nconst DEFAULT_PRESENCE_TIMEOUT = 100\nexport const DEFAULT_RETRY_QUEUE_MAX_SIZE = 1000\n\ntype ChannelEventMessage = {\n [key: string]: Serializable\n type: 'channel:event'\n origin: string\n channel: string\n event: string\n data: Serializable\n except: string[]\n}\n\ntype BroadcastEventMessage = {\n [key: string]: Serializable\n type: 'broadcast:event'\n origin: string\n event: string\n data: Serializable\n}\n\ntype PresenceSocketsRequestMessage = {\n [key: string]: Serializable\n type: 'presence:sockets:request'\n origin: string\n requestId: string\n channel: string\n}\n\ntype PresenceSocketsResponseMessage = {\n [key: string]: Serializable\n type: 'presence:sockets:response'\n origin: string\n target: string\n requestId: string\n sockets: SerializablePresenceSocket[]\n}\n\nexport type SocketBusMessage =\n | ChannelEventMessage\n | BroadcastEventMessage\n | PresenceSocketsRequestMessage\n | PresenceSocketsResponseMessage\n\nexport interface SocketTransportConfig {\n driver: TransportFactory\n channel?: string\n /**\n * How long to wait for other instances to answer a presence snapshot request.\n */\n presenceTimeout?: Duration\n /**\n * In-memory retry policy for transport publications that fail.\n *\n * The queue is enabled and limited to 1000 distinct messages by default.\n * Set maxSize to null only when an unbounded queue is explicitly desired.\n */\n retryQueue?: SocketRetryQueueConfig\n}\n\nexport interface SocketRetryQueueConfig {\n enabled?: boolean\n removeDuplicates?: boolean\n maxSize?: number | null\n retryInterval?: Duration | false\n}\n\nfunction resolveRetryQueueConfig(config: SocketRetryQueueConfig | undefined) {\n const maxSize = config?.maxSize === undefined ? DEFAULT_RETRY_QUEUE_MAX_SIZE : config.maxSize\n\n if (maxSize !== null && (!Number.isSafeInteger(maxSize) || maxSize <= 0)) {\n throw new Error('transport.retryQueue.maxSize must be a positive integer or null')\n }\n\n return {\n enabled: true,\n maxSize,\n ...config,\n }\n}\n\ninterface SocketBusHandlers {\n channel(message: Extract<SocketBusMessage, { type: 'channel:event' }>): void\n broadcast(message: Extract<SocketBusMessage, { type: 'broadcast:event' }>): void\n presenceSockets(channel: string): SerializablePresenceSocket[]\n}\n\ninterface PendingPresenceRequest {\n sockets: PresenceSocketFrame[]\n resolve(sockets: PresenceSocket[]): void\n timeout: ReturnType<typeof setTimeout>\n}\n\ntype ParsedPresenceSocketsResponseMessage = {\n type: 'presence:sockets:response'\n origin: string\n target: string\n requestId: string\n sockets: PresenceSocketFrame[]\n}\n\ntype ParsedSocketBusMessage =\n | Exclude<SocketBusMessage, PresenceSocketsResponseMessage>\n | ParsedPresenceSocketsResponseMessage\n\nfunction parseBusMessage(payload: unknown): ParsedSocketBusMessage | null {\n if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {\n return null\n }\n\n const message = payload as Record<string, unknown>\n if (typeof message.origin !== 'string') {\n return null\n }\n\n switch (message.type) {\n case 'channel:event':\n return typeof message.channel === 'string' &&\n typeof message.event === 'string' &&\n Array.isArray(message.except) &&\n message.except.every((socketId) => typeof socketId === 'string')\n ? (message as ChannelEventMessage)\n : null\n case 'broadcast:event':\n return typeof message.event === 'string' ? (message as BroadcastEventMessage) : null\n case 'presence:sockets:request':\n return typeof message.requestId === 'string' && typeof message.channel === 'string'\n ? (message as PresenceSocketsRequestMessage)\n : null\n case 'presence:sockets:response':\n if (\n typeof message.target !== 'string' ||\n typeof message.requestId !== 'string' ||\n !Array.isArray(message.sockets)\n ) {\n return null\n }\n\n const sockets = Array.from(message.sockets, PresenceSocketFrame.fromTransport)\n return sockets.every((socket) => socket !== null)\n ? ({ ...message, sockets } as ParsedPresenceSocketsResponseMessage)\n : null\n default:\n return null\n }\n}\n\nexport class SocketBus {\n #origin = randomUUID()\n #channel: string\n #bus: Bus\n #presenceTimeout: number\n #pendingPresenceRequests = new Map<string, PendingPresenceRequest>()\n\n constructor(\n transport: SocketTransportConfig,\n private handlers: SocketBusHandlers\n ) {\n this.#channel = transport.channel ?? DEFAULT_CHANNEL\n this.#presenceTimeout =\n parseDuration('transport.presenceTimeout', transport.presenceTimeout) ??\n DEFAULT_PRESENCE_TIMEOUT\n this.#bus = new Bus(transport.driver(), {\n retryQueue: resolveRetryQueueConfig(transport.retryQueue),\n })\n }\n\n async start(): Promise<void> {\n await this.#bus.subscribe(this.#channel, (payload) => {\n try {\n const message = parseBusMessage(payload)\n if (!message || message.origin === this.#origin) {\n return\n }\n\n switch (message.type) {\n case 'channel:event':\n this.handlers.channel(message)\n return\n case 'broadcast:event':\n this.handlers.broadcast(message)\n return\n case 'presence:sockets:request':\n void this.#respondToPresenceRequest(message).catch(() => {})\n return\n case 'presence:sockets:response':\n this.#handlePresenceResponse(message)\n return\n }\n } catch {\n return\n }\n })\n }\n\n publishChannel(channel: string, event: string, data: unknown, except?: string[]): void {\n const message: SocketBusMessage = {\n type: 'channel:event',\n origin: this.#origin,\n channel,\n event,\n data: data as Serializable,\n except: except ?? [],\n }\n\n void this.#bus.publish(this.#channel, message)\n }\n\n publishBroadcast(event: string, data: unknown): void {\n const message: BroadcastEventMessage = {\n type: 'broadcast:event',\n origin: this.#origin,\n event,\n data: data as Serializable,\n }\n void this.#bus.publish(this.#channel, message)\n }\n\n fetchPresenceSockets(channel: string): Promise<PresenceSocket[]> {\n const requestId = randomUUID()\n\n return new Promise((resolve) => {\n const timeout = setTimeout(() => {\n const request = this.#pendingPresenceRequests.get(requestId)\n\n if (!request) {\n return\n }\n\n this.#pendingPresenceRequests.delete(requestId)\n resolve(request.sockets.map((socket) => socket.toSocket()))\n }, this.#presenceTimeout)\n\n this.#pendingPresenceRequests.set(requestId, {\n sockets: [],\n resolve,\n timeout,\n })\n\n const message: PresenceSocketsRequestMessage = {\n type: 'presence:sockets:request',\n origin: this.#origin,\n requestId,\n channel,\n }\n void this.#bus.publish(this.#channel, message)\n })\n }\n\n async close(): Promise<void> {\n for (const [requestId, request] of this.#pendingPresenceRequests) {\n clearTimeout(request.timeout)\n request.resolve(request.sockets.map((socket) => socket.toSocket()))\n this.#pendingPresenceRequests.delete(requestId)\n }\n\n await this.#bus.disconnect()\n }\n\n async #respondToPresenceRequest(\n message: Extract<SocketBusMessage, { type: 'presence:sockets:request' }>\n ): Promise<void> {\n const response: PresenceSocketsResponseMessage = {\n type: 'presence:sockets:response',\n origin: this.#origin,\n target: message.origin,\n requestId: message.requestId,\n sockets: this.handlers.presenceSockets(message.channel),\n }\n await this.#bus.publish(this.#channel, response as Serializable)\n }\n\n #handlePresenceResponse(message: ParsedPresenceSocketsResponseMessage): void {\n if (message.target !== this.#origin) {\n return\n }\n\n const request = this.#pendingPresenceRequests.get(message.requestId)\n\n if (!request) {\n return\n }\n\n request.sockets.push(...message.sockets)\n }\n}\n","import type { PresenceInfo } from './types.js'\n\nexport const PRESENCE_DATA_KEY = '__rlanzSocketPresence'\n\ntype PresenceSocketData = Record<string, unknown> & {\n [PRESENCE_DATA_KEY]?: Record<string, PresenceUser>\n}\n\nexport interface PresenceUser {\n id: string\n joinedAt: Date\n [key: string]: unknown\n}\n\nexport interface PresenceData {\n channel: string\n users: PresenceUser[]\n count: number\n}\n\nexport interface PresenceSocket {\n id: string\n data: PresenceSocketData\n}\n\n/**\n * Tracks user presence in channels.\n *\n * channel -> socketId -> PresenceUser\n */\nexport class PresenceManager {\n #presence = new Map<string, Map<string, PresenceUser>>()\n #fetchSockets: ((channel: string) => Promise<PresenceSocket[]>) | null = null\n\n /**\n * Sets the socket fetcher used to build distributed snapshots.\n */\n setSocketFetcher(fetchSockets: ((channel: string) => Promise<PresenceSocket[]>) | null): void {\n this.#fetchSockets = fetchSockets\n }\n\n /**\n * Adds a user to a channel.\n */\n join(channel: string, socket: PresenceSocket, member: PresenceInfo): PresenceUser {\n const user = {\n ...member.data,\n id: member.id,\n joinedAt: new Date(),\n }\n\n const users = this.#presence.get(channel) ?? new Map()\n users.set(socket.id, user)\n this.#presence.set(channel, users)\n this.#setSocketPresence(socket, channel, user)\n\n return user\n }\n\n /**\n * Removes a user from a channel.\n */\n leave(channel: string, socket: PresenceSocket): void {\n const channelPresence = this.#presence.get(channel)\n\n if (channelPresence) {\n channelPresence.delete(socket.id)\n\n if (channelPresence.size === 0) {\n this.#presence.delete(channel)\n }\n }\n\n this.#deleteSocketPresence(socket, channel)\n }\n\n /**\n * Removes a user from every channel.\n * Returns the list of channels the user left.\n */\n leaveAll(socket: PresenceSocket): string[] {\n const leftChannels: string[] = []\n\n for (const [channel, users] of this.#presence) {\n if (users.has(socket.id)) {\n users.delete(socket.id)\n leftChannels.push(channel)\n\n if (users.size === 0) {\n this.#presence.delete(channel)\n }\n\n this.#deleteSocketPresence(socket, channel)\n }\n }\n\n return leftChannels\n }\n\n /**\n * Gets presence data for a channel.\n */\n async snapshot(channel: string): Promise<PresenceData> {\n if (this.#fetchSockets) {\n return this.#getFromSockets(channel)\n }\n\n return this.#localSnapshot(channel)\n }\n\n /**\n * Gets the number of users in a channel.\n */\n async count(channel: string): Promise<number> {\n return (await this.snapshot(channel)).count\n }\n\n /**\n * Checks whether a socket is locally present in a channel.\n */\n hasLocal(channel: string, socketId: string): boolean {\n return this.#presence.get(channel)?.has(socketId) || false\n }\n\n /**\n * Gets the presence user retained for one local socket.\n */\n getLocalUser(channel: string, socketId: string): PresenceUser | undefined {\n return this.#presence.get(channel)?.get(socketId)\n }\n\n /**\n * Lists every local channel where a socket is present.\n */\n getLocalChannelsForSocket(socketId: string): string[] {\n const channels: string[] = []\n\n for (const [channel, users] of this.#presence) {\n if (users.has(socketId)) {\n channels.push(channel)\n }\n }\n\n return channels\n }\n\n /**\n * Lists sockets that are locally present in a channel.\n */\n getLocalSockets(channel: string): PresenceSocket[] {\n const users = this.#presence.get(channel)\n\n if (!users) {\n return []\n }\n\n return Array.from(users.entries()).map(([socketId, user]) => ({\n id: socketId,\n data: {\n [PRESENCE_DATA_KEY]: {\n [channel]: user,\n },\n },\n }))\n }\n\n #localSnapshot(channel: string): PresenceData {\n return this.#createSnapshot(channel, Array.from(this.#presence.get(channel)?.entries() ?? []))\n }\n\n async #getFromSockets(channel: string): Promise<PresenceData> {\n const sockets = await this.#fetchSockets!(channel)\n const users = sockets.flatMap((socket): Array<[string, PresenceUser]> => {\n const user = socket.data?.[PRESENCE_DATA_KEY]?.[channel]\n return user ? [[socket.id, user]] : []\n })\n\n return this.#createSnapshot(channel, users)\n }\n\n #createSnapshot(\n channel: string,\n connections: Array<[socketId: string, user: PresenceUser]>\n ): PresenceData {\n const usersById = new Map<string, [socketId: string, user: PresenceUser]>()\n\n for (const connection of connections) {\n const current = usersById.get(connection[1].id)\n if (!current || this.#compareConnections(connection, current) < 0) {\n usersById.set(connection[1].id, connection)\n }\n }\n\n const users = [...usersById.values()]\n .sort((left, right) => this.#compareConnections(left, right))\n .map(([, user]) => user)\n\n return {\n channel,\n users,\n count: users.length,\n }\n }\n\n #compareConnections(\n [leftSocketId, leftUser]: [string, PresenceUser],\n [rightSocketId, rightUser]: [string, PresenceUser]\n ): number {\n const joinedAtDifference = leftUser.joinedAt.getTime() - rightUser.joinedAt.getTime()\n return joinedAtDifference || leftSocketId.localeCompare(rightSocketId)\n }\n\n #setSocketPresence(socket: PresenceSocket, channel: string, user: PresenceUser): void {\n socket.data[PRESENCE_DATA_KEY] ??= {}\n socket.data[PRESENCE_DATA_KEY][channel] = user\n }\n\n #deleteSocketPresence(socket: PresenceSocket, channel: string): void {\n if (!socket.data[PRESENCE_DATA_KEY]) {\n return\n }\n\n delete socket.data[PRESENCE_DATA_KEY][channel]\n\n if (Object.keys(socket.data[PRESENCE_DATA_KEY]).length === 0) {\n delete socket.data[PRESENCE_DATA_KEY]\n }\n }\n}\n","import type { Serializable } from '@boringnode/bus/types/main'\nimport { PRESENCE_DATA_KEY, type PresenceSocket, type PresenceUser } from './presence_manager.js'\n\ntype SerializablePresenceUser = {\n [key: string]: Serializable\n id: string\n joinedAt: string\n}\n\nexport interface SerializablePresenceSocket {\n [key: string]: Serializable\n id: string\n data: {\n [key: string]: Serializable\n }\n}\n\n/**\n * Transport representation of one socket participating in distributed presence.\n */\nexport class PresenceSocketFrame {\n private constructor(\n private readonly transportValue: SerializablePresenceSocket,\n private readonly socketValue: PresenceSocket\n ) {}\n\n /**\n * Create one transport frame from a local socket presence entry.\n */\n static fromSocket(channel: string, socket: PresenceSocket): PresenceSocketFrame {\n const user = socket.data[PRESENCE_DATA_KEY]?.[channel]\n if (!user || Number.isNaN(user.joinedAt.getTime())) {\n throw new Error(`Socket \"${socket.id}\" has no valid presence for channel \"${channel}\"`)\n }\n\n const transport: SerializablePresenceSocket = {\n id: socket.id,\n data: {\n [PRESENCE_DATA_KEY]: {\n [channel]: {\n // Keep custom fields. Convert only the presence timestamp.\n ...user,\n joinedAt: user.joinedAt.toISOString(),\n } as SerializablePresenceUser,\n },\n },\n }\n\n return new PresenceSocketFrame(transport, socket)\n }\n\n /**\n * Validate one transport value and restore its presence timestamps.\n */\n static fromTransport(value: unknown): PresenceSocketFrame | null {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return null\n }\n\n const transport = value as Record<string, unknown>\n\n // A valid frame needs a socket ID and one object for socket data.\n if (\n typeof transport.id !== 'string' ||\n !transport.data ||\n typeof transport.data !== 'object' ||\n Array.isArray(transport.data)\n ) {\n return null\n }\n\n const data = transport.data as Record<string, unknown>\n const presence = data[PRESENCE_DATA_KEY]\n\n // A socket can have no presence entries.\n if (presence === undefined) {\n return new PresenceSocketFrame(transport as SerializablePresenceSocket, {\n id: transport.id,\n data: { ...data },\n })\n }\n if (!presence || typeof presence !== 'object' || Array.isArray(presence)) {\n return null\n }\n\n // Validate all members before this frame becomes a PresenceSocket.\n const restoredPresence: Record<string, PresenceUser> = {}\n for (const [channel, candidate] of Object.entries(presence)) {\n if (!candidate || typeof candidate !== 'object' || Array.isArray(candidate)) {\n return null\n }\n\n const user = candidate as Record<string, unknown>\n if (\n typeof user.id !== 'string' ||\n typeof user.joinedAt !== 'string' ||\n Number.isNaN(Date.parse(user.joinedAt))\n ) {\n return null\n }\n\n // Keep custom fields. Restore only the presence timestamp.\n restoredPresence[channel] = {\n ...user,\n id: user.id,\n joinedAt: new Date(user.joinedAt),\n }\n }\n\n return new PresenceSocketFrame(transport as SerializablePresenceSocket, {\n id: transport.id,\n data: {\n ...data,\n [PRESENCE_DATA_KEY]: restoredPresence,\n },\n })\n }\n\n /**\n * Return the validated transport value.\n */\n toTransport(): SerializablePresenceSocket {\n return this.transportValue\n }\n\n /**\n * Return the socket value with restored presence timestamps.\n */\n toSocket(): PresenceSocket {\n return this.socketValue\n }\n}\n","import { parse as parseDurationExpression } from '@lukeed/ms'\n\n/**\n * Duration can be specified as milliseconds or as a human-readable string.\n */\nexport type Duration = number | string\n\nexport function parseDuration(name: string, duration: Duration | undefined): number | undefined {\n if (duration === undefined) {\n return undefined\n }\n\n const milliseconds = typeof duration === 'number' ? duration : parseDurationExpression(duration)\n\n if (typeof milliseconds === 'undefined' || !Number.isFinite(milliseconds) || milliseconds <= 0) {\n throw new Error(`${name} must be a positive duration`)\n }\n\n return milliseconds\n}\n","import type { IncomingMessage } from 'node:http'\nimport type { Duplex } from 'node:stream'\nimport type { WebSocket, WebSocketServer } from 'ws'\nimport type { HttpContext } from '@adonisjs/core/http'\nimport type { SocketConfig, SocketUpgradeContext } from './types.js'\n\nexport const DEFAULT_WEBSOCKET_PATH = '/socket'\n\nexport interface AcceptedUpgrade<User> {\n httpContext: HttpContext\n user?: User\n}\n\nexport type SocketUpgradeHandler = (request: IncomingMessage, socket: Duplex, head: Buffer) => void\n\ntype AcceptUpgrade<User> = (\n connection: WebSocket,\n request: IncomingMessage,\n upgrade: AcceptedUpgrade<User>\n) => void\n\nexport type SocketUpgradeContextRunner = <Result>(\n request: IncomingMessage,\n handler: (httpContext: HttpContext) => Promise<Result>,\n shortCircuitBeforeMiddleware?: (\n httpContext: HttpContext\n ) => Result | undefined | Promise<Result | undefined>\n) => Promise<Result>\n\ntype UpgradeResult<User> =\n | { accepted: AcceptedUpgrade<User> }\n | { rejected: 'authentication' | 'origin' }\n\nexport class SocketUpgrader<User = unknown> {\n #path: string\n\n constructor(\n private server: WebSocketServer,\n private config: SocketConfig<User>['websocket'] | undefined,\n private runWithHttpContext: SocketUpgradeContextRunner,\n private reportError: (message: string, error: unknown) => void = () => {}\n ) {\n this.#path = config?.path ?? DEFAULT_WEBSOCKET_PATH\n }\n\n async handle(\n request: IncomingMessage,\n socket: Duplex,\n head: Buffer,\n accept: AcceptUpgrade<User>\n ): Promise<boolean> {\n if (!this.#matchesPath(request)) {\n return false\n }\n\n const result = await this.#prepareUpgrade(request)\n\n if ('rejected' in result) {\n if (result.rejected === 'origin') {\n SocketUpgrader.reject(socket, 403, 'Forbidden')\n return true\n }\n\n SocketUpgrader.reject(socket, 401, 'Unauthorized')\n return true\n }\n\n this.server.handleUpgrade(request, socket, head, (connection) => {\n accept(connection, request, result.accepted)\n })\n\n return true\n }\n\n static reject(socket: Duplex, statusCode: number, reason: string): void {\n if (!socket.writableEnded) {\n socket.write(`HTTP/1.1 ${statusCode} ${reason}\\r\\n\\r\\n`)\n }\n\n socket.destroy()\n }\n\n #matchesPath(request: IncomingMessage): boolean {\n const url = new URL(request.url ?? '/', 'ws://localhost')\n return url.pathname === this.#path\n }\n\n #isOriginAllowed(request: IncomingMessage, httpContext: HttpContext): boolean {\n const origin = request.headers.origin\n if (!origin) {\n return true\n }\n\n if (this.config?.origin !== undefined) {\n return this.#matchesOriginPolicy(origin, httpContext)\n }\n\n const host = request.headers.host\n if (!host) {\n return false\n }\n\n const forwardedHeader = request.headers['x-forwarded-proto']\n const forwardedProtocol = (\n Array.isArray(forwardedHeader) ? forwardedHeader[0] : forwardedHeader\n )\n ?.split(',')[0]\n ?.trim()\n const protocol =\n forwardedProtocol === 'http' || forwardedProtocol === 'https'\n ? forwardedProtocol\n : (request.socket as typeof request.socket & { encrypted?: boolean }).encrypted\n ? 'https'\n : 'http'\n\n try {\n return origin === new URL(`${protocol}://${host}`).origin\n } catch {\n return false\n }\n }\n\n #matchesOriginPolicy(origin: string, httpContext: HttpContext): boolean {\n let originPolicy = this.config?.origin ?? false\n\n if (typeof originPolicy === 'function') {\n originPolicy = originPolicy(origin, httpContext)\n }\n\n if (originPolicy === true || originPolicy === '*') {\n return true\n }\n\n if (originPolicy === false) {\n return false\n }\n\n if (Array.isArray(originPolicy)) {\n return originPolicy.includes(origin)\n }\n\n return originPolicy.split(',').includes(origin)\n }\n\n async #prepareUpgrade(request: IncomingMessage): Promise<UpgradeResult<User>> {\n return this.runWithHttpContext<UpgradeResult<User>>(\n request,\n async (httpContext) => {\n const accepted = await this.#authenticate(httpContext)\n return accepted ? { accepted } : { rejected: 'authentication' }\n },\n (httpContext) => {\n return this.#isOriginAllowed(request, httpContext) ? undefined : { rejected: 'origin' }\n }\n )\n }\n\n async #authenticate(httpContext: HttpContext): Promise<AcceptedUpgrade<User> | null> {\n const config = this.config\n if (!config?.authenticate) {\n return { httpContext }\n }\n\n try {\n const ctx: SocketUpgradeContext = {\n httpContext,\n }\n\n const result = await config.authenticate(ctx)\n\n if (result === false || result === null || result === undefined) {\n return null\n }\n\n return {\n httpContext,\n user: result,\n }\n } catch (error) {\n try {\n this.reportError('socket authentication failed: %s', error)\n } catch {\n // Error reporting must never change an authentication rejection.\n }\n return null\n }\n }\n}\n","import type { BaseChannelConstructor } from './base_channel.js'\nimport { ChannelPatternSyntax } from './channel_pattern_syntax.js'\n\ntype MatchParams = Record<string, string>\n\nexport interface ChannelPatternMatch {\n pattern: ChannelPattern\n channel: BaseChannelConstructor\n params: MatchParams\n}\n\ninterface MatchCandidate {\n pattern: ChannelPattern\n channel: BaseChannelConstructor\n}\n\nexport class ChannelPattern {\n private readonly syntax: ChannelPatternSyntax\n\n private constructor(readonly value: string) {\n this.syntax = ChannelPatternSyntax.from(value)\n }\n\n /**\n * Parse one runtime channel pattern.\n */\n static from(value: string): ChannelPattern {\n return new ChannelPattern(value)\n }\n\n /**\n * Match one concrete channel name.\n */\n match(channelName: string): MatchParams | null {\n return this.syntax.match(channelName)\n }\n\n /**\n * Return the most specific matching candidate. Static segments have the highest score.\n * Parameters score above optional parameters. Wildcards have the lowest score.\n * Insertion order is preserved for ties.\n */\n static firstMatch(\n channelName: string,\n candidates: Iterable<MatchCandidate>\n ): ChannelPatternMatch | null {\n const sorted = [...candidates].sort((left, right) => {\n return ChannelPattern.#compareSpecificity(left.pattern, right.pattern)\n })\n const matched = ChannelPatternSyntax.firstMatch(\n sorted.map(({ pattern }) => pattern.syntax),\n channelName\n )\n if (!matched) return null\n\n const { pattern, channel } = sorted[matched.index]\n return { pattern, channel, params: matched.params }\n }\n\n static #compareSpecificity(left: ChannelPattern, right: ChannelPattern): number {\n return left.syntax.compareSpecificity(right.syntax)\n }\n}\n","import {\n SocketResponseError,\n type BaseChannel,\n type BaseChannelConstructor,\n type ChannelMiddlewareRunnerFactory,\n} from './base_channel.js'\nimport { ChannelPattern } from './channel_pattern.js'\nimport type { AuthenticatedSocket, ChannelMatch, MiddlewareContext } from './types.js'\n\ninterface RegisteredChannel {\n pattern: ChannelPattern\n channel: BaseChannelConstructor\n}\n\nexport type ChannelFactory = (\n channel: BaseChannelConstructor\n) => BaseChannel<any> | Promise<BaseChannel<any>>\n\n/**\n * Matches channel names against registered patterns.\n *\n * Pattern: chat/:roomId\n * Channel: chat/general\n *\n * chat / :roomId\n * | |\n * chat / general => { roomId: \"general\" }\n */\nexport class ChannelRouter {\n /**\n * Registered channels keyed by their pattern.\n */\n #channels = new Map<string, RegisteredChannel>()\n\n constructor(\n private makeChannel: ChannelFactory = (channel) => new channel(),\n private createMiddlewareRunner?: ChannelMiddlewareRunnerFactory\n ) {}\n\n /**\n * Registers a channel.\n */\n register(channel: BaseChannelConstructor): void {\n const patternValue = channel.pattern\n\n if (!patternValue) {\n throw new Error(`Channel ${channel.name} must define a static pattern`)\n }\n\n if (this.#channels.has(patternValue)) {\n throw new Error(`Channel pattern \"${patternValue}\" is already registered`)\n }\n\n const pattern = ChannelPattern.from(patternValue)\n\n this.#channels.set(pattern.value, { pattern, channel })\n }\n\n /**\n * Matches a channel name against registered patterns.\n */\n match(channelName: string): ChannelMatch | null {\n const matched = ChannelPattern.firstMatch(channelName, this.#channels.values())\n\n if (!matched) {\n return null\n }\n\n return {\n channel: matched.channel,\n pattern: matched.pattern.value,\n params: matched.params,\n }\n }\n\n /**\n * Authorizes a socket before it joins a channel.\n */\n async authorize<User = unknown>(socket: AuthenticatedSocket<User>, channelName: string) {\n const matched = this.match(channelName)\n\n if (!matched) {\n return {\n success: false,\n error: 'Channel not found',\n } as const\n }\n\n const instance = (await this.makeChannel(matched.channel)) as BaseChannel<User>\n const paramValues = Object.values(matched.params)\n\n const ctx: MiddlewareContext<User> = {\n socket,\n channel: channelName,\n params: matched.params,\n presenceData: undefined,\n setPresenceData(data) {\n ctx.presenceData = data\n },\n }\n\n // Run authorization middlewares.\n try {\n await instance.$runMiddlewares(ctx, this.createMiddlewareRunner?.())\n } catch (error) {\n return {\n success: false,\n error: error instanceof SocketResponseError ? error.message : 'Authorization failed',\n cause: error,\n } as const\n }\n\n return {\n success: true,\n instance,\n params: matched.params,\n paramValues,\n presenceData: ctx.presenceData ?? null,\n } as const\n }\n\n /**\n * Lists all registered channels.\n */\n list() {\n return [...this.#channels.values()].map(({ pattern, channel }) => ({\n pattern: pattern.value,\n name: channel.name,\n options: channel.options,\n }))\n }\n\n /**\n * Number of registered channels.\n */\n get size(): number {\n return this.#channels.size\n }\n}\n"],"mappings":"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","names":["randomUUID","randomUUID","pattern"]}
|
|
1
|
+
{"version":3,"sources":["../../providers/socket_provider.ts","../../src/socket_service.ts","../../src/channel_subscription_storage.ts","../../src/channel_subscriptions.ts","../../src/protocol/reply.ts","../../src/protocol/message.ts","../../src/message_queue.ts","../../src/socket_bus.ts","../../src/presence_manager.ts","../../src/presence_socket_frame.ts","../../src/duration.ts","../../src/socket_upgrader.ts","../../src/channel_pattern.ts","../../src/channel_router.ts"],"sourcesContent":["import type { ApplicationService } from '@adonisjs/core/types'\nimport type { HttpContext, Server as AdonisServer } from '@adonisjs/core/http'\nimport type { Logger } from '@adonisjs/logger'\nimport type { MiddlewareAsClass } from '@adonisjs/core/types/http'\nimport { ServerResponse } from 'node:http'\nimport { SocketService } from '../src/socket_service.js'\nimport { ChannelRouter } from '../src/channel_router.js'\nimport { BaseChannel } from '../src/base_channel.js'\nimport { PresenceManager } from '../src/presence_manager.js'\nimport type { SocketUpgradeContextRunner } from '../src/socket_upgrader.js'\nimport type { SocketConfig, SocketHttpMiddleware } from '../src/types.js'\n\ndeclare module '@adonisjs/core/types' {\n interface ContainerBindings {\n 'socket': SocketService\n 'socket.router': ChannelRouter\n 'socket.presence': PresenceManager\n }\n}\n\nexport default class SocketProvider {\n constructor(protected app: ApplicationService) {}\n\n /**\n * Registers the bindings in the container.\n */\n register(): void {\n this.app.container.singleton('socket.router', () => {\n return new ChannelRouter(\n (channel) => this.app.container.make(channel),\n () => {\n const resolver = this.app.container.createResolver()\n\n return async (Middleware, ctx, next) => {\n const instance = await resolver.make(Middleware)\n await resolver.call(instance, 'handle', [ctx, next])\n }\n }\n )\n })\n\n this.app.container.singleton('socket.presence', () => {\n return new PresenceManager()\n })\n\n this.app.container.singleton('socket', () => {\n return new SocketService()\n })\n }\n\n /**\n * Boots the provider.\n */\n async boot(): Promise<void> {\n const router = await this.app.container.make('socket.router')\n\n // Discover and register channel classes.\n await this.#registerChannels(router)\n }\n\n /**\n * Called when the app is ready and the HTTP server is running.\n */\n async ready(): Promise<void> {\n const socket = await this.app.container.make('socket')\n const router = await this.app.container.make('socket.router')\n const presence = await this.app.container.make('socket.presence')\n const logger = await this.#resolveLogger()\n const config = this.app.config.get<SocketConfig>('socket', {})\n\n socket.setPresenceManager(presence)\n\n logger.info('router has %d channels registered', router.size)\n\n const server = await this.app.container.make('server')\n const httpServer = server.getNodeServer()\n\n if (!httpServer) {\n const error = new Error('HTTP server not available.')\n socket.markFailed(error)\n logger.warn('HTTP server not available; socket server was not started')\n return\n }\n\n try {\n await socket.boot(\n httpServer,\n config,\n router,\n logger,\n this.#createUpgradeContextRunner(config, server)\n )\n logger.info('server started')\n } catch (error) {\n socket.markFailed(error)\n throw error\n }\n }\n\n /**\n * Performs a clean shutdown.\n */\n async shutdown(): Promise<void> {\n const socket = await this.app.container.make('socket')\n await socket.close()\n }\n\n /**\n * Resolves the AdonisJS logger and creates a child logger for the socket context.\n */\n async #resolveLogger(): Promise<Logger> {\n const logger = await this.app.container.make('logger')\n return logger.child({ module: 'socket' })\n }\n\n /**\n * Creates an AdonisJS HTTP context for WebSocket upgrade requests.\n */\n #createUpgradeContextRunner(\n config: SocketConfig,\n server: AdonisServer\n ): SocketUpgradeContextRunner {\n const middleware = config.websocket?.middleware ?? []\n\n return async (request, handler, shortCircuitBeforeMiddleware) => {\n const response = new ServerResponse(request)\n const adonisRequest = server.createRequest(request, response)\n const adonisResponse = server.createResponse(request, response)\n const httpContext = server.createHttpContext(\n adonisRequest,\n adonisResponse,\n this.app.container.createResolver()\n )\n\n const earlyResult = await shortCircuitBeforeMiddleware?.(httpContext)\n if (earlyResult !== undefined) {\n return earlyResult\n }\n\n return this.#runUpgradeMiddleware(server, middleware, httpContext, handler)\n }\n }\n\n /**\n * Runs middleware attached to WebSocket upgrade requests.\n */\n async #runUpgradeMiddleware<Result>(\n server: AdonisServer,\n middleware: NonNullable<NonNullable<SocketConfig['websocket']>['middleware']>,\n httpContext: HttpContext,\n handler: (httpContext: HttpContext) => Promise<Result>\n ): Promise<Result> {\n if (middleware.length === 0) {\n return handler(httpContext)\n }\n\n const middlewareClasses: MiddlewareAsClass[] = await Promise.all(\n middleware.map(async (one): Promise<MiddlewareAsClass> => {\n if (one.prototype?.handle) {\n return one as MiddlewareAsClass\n }\n\n const moduleExports = await (one as Exclude<SocketHttpMiddleware, MiddlewareAsClass>)()\n return moduleExports.default\n })\n )\n\n let outcome: { value: Result } | undefined\n\n await server\n .pipeline(middlewareClasses)\n .errorHandler((error) => {\n throw error\n })\n .finalHandler(async () => {\n outcome = { value: await handler(httpContext) }\n })\n .run(httpContext)\n\n if (!outcome) {\n throw new Error('WebSocket upgrade middleware must call next()')\n }\n\n return outcome.value\n }\n\n /**\n * Scans and registers channel classes.\n */\n async #registerChannels(router: ChannelRouter): Promise<void> {\n const logger = await this.#resolveLogger()\n\n let generated: { socketChannels?: unknown }\n try {\n generated = await this.app.import('#generated/socket_channels')\n } catch (error) {\n throw new Error('Failed to load generated socket channels', { cause: error })\n }\n\n if (!Array.isArray(generated.socketChannels)) {\n throw new Error('Generated socket channel manifest must export a socketChannels array')\n }\n\n for (const [index, channelClass] of generated.socketChannels.entries()) {\n const source = `generated channel at index ${index}`\n if (\n typeof channelClass !== 'function' ||\n !(channelClass.prototype instanceof BaseChannel) ||\n !channelClass.pattern\n ) {\n throw new Error(`Socket channel ${source} must default export a BaseChannel with a pattern`)\n }\n\n try {\n router.register(channelClass)\n } catch (error) {\n throw new Error(`Failed to register socket channel from ${source}`, { cause: error })\n }\n\n logger.info('registered channel: %s', channelClass.pattern)\n }\n\n logger.info('total channels registered: %d', router.size)\n }\n}\n","import { randomUUID } from 'node:crypto'\nimport type { Server as HttpServer } from 'node:http'\nimport type { Logger } from '@adonisjs/logger'\nimport Emittery from 'emittery'\nimport { WebSocket, WebSocketServer } from 'ws'\nimport type { RawData } from 'ws'\nimport type {\n AuthenticatedSocket,\n SocketConfig,\n SocketEvents,\n ChannelAck,\n RawSocket,\n SocketHealthSnapshot,\n SocketServiceStatus,\n} from './types.js'\nimport type { SocketUpgradeContextRunner } from './socket_upgrader.js'\nimport {\n SERVER_DISCONNECT_CODE,\n type ChannelMessage,\n type ServerProtocolMessage,\n} from './shared_types.js'\nimport type { ChannelRouter } from './channel_router.js'\nimport type { PresenceManager } from './presence_manager.js'\nimport { ChannelSubscriptions, type ChannelSubscriptionLimits } from './channel_subscriptions.js'\nimport { Message, type TransportMessage } from './protocol/message.js'\nimport { MessageQueue } from './message_queue.js'\nimport { Reply } from './protocol/reply.js'\nimport type { SocketEmission, SocketEmissionSink } from './broadcasting.js'\nimport { SocketFake } from './fake_socket.js'\nimport { SocketBus } from './socket_bus.js'\nimport { PresenceSocketFrame, type SerializablePresenceSocket } from './presence_socket_frame.js'\nimport {\n SocketUpgrader,\n type AcceptedUpgrade,\n type SocketUpgradeHandler,\n} from './socket_upgrader.js'\nimport { parseDuration, type Duration } from './duration.js'\nimport { SocketResponseError } from './base_channel.js'\nimport {\n broadcastChannel,\n channelMessageChannel,\n connectChannel,\n disconnectChannel,\n subscribeChannel,\n unsubscribeChannel,\n} from './tracing_channels.js'\nimport type {\n SocketBroadcastMessage,\n SocketChannelMessage,\n SocketSubscribeMessage,\n SocketUnsubscribeMessage,\n} from './types/tracing_channels.js'\n\nconst DEFAULT_PING_INTERVAL = 25_000\nconst DEFAULT_PING_TIMEOUT = 5_000\nconst DEFAULT_MAX_PAYLOAD = 1024 * 1024\nconst DEFAULT_MAX_QUEUED_MESSAGES = 100\nconst DEFAULT_MAX_MESSAGES_PER_INTERVAL = 1000\nconst DEFAULT_MESSAGE_RATE_INTERVAL = 1000\nconst DEFAULT_MAX_BUFFERED_AMOUNT = 16 * 1024 * 1024\nconst DEFAULT_MAX_OUTBOUND_PAYLOAD = 1024 * 1024\nconst DEFAULT_MAX_SUBSCRIPTIONS_PER_SOCKET = 100\nconst DEFAULT_MAX_CHANNEL_NAME_LENGTH = 255\nconst DEFAULT_SHUTDOWN_TIMEOUT = 5_000\nconst CLOSE_POLICY_VIOLATION = 1008\nconst CLOSE_MESSAGE_TOO_BIG = 1009\nconst CLOSE_OUTBOUND_BUFFER_LIMIT = 'Socket outbound buffer limit exceeded'\nconst CLOSE_OUTBOUND_MESSAGE_TOO_BIG = 'Socket outbound message too big'\nconst SERVER_DISCONNECT_REASON = 'Socket server disconnected'\n\ninterface InboundMessageConfig {\n maxPayload: number\n maxQueuedMessages: number\n maxMessagesPerInterval: number\n messageRateInterval: number\n subscriptionLimits: ChannelSubscriptionLimits\n}\n\ninterface OutboundMessageConfig {\n maxBufferedAmount: number\n maxOutboundPayload: number\n}\n\ninterface SocketMessageRate {\n count: number\n intervalStartedAt: number\n}\n\nasync function settleBeforeDeadline<Result>(\n promise: Promise<Result>,\n deadline: number\n): Promise<PromiseSettledResult<Result> | null> {\n const remaining = deadline - Date.now()\n if (remaining <= 0) {\n void promise.catch(() => {})\n return null\n }\n\n let timer: ReturnType<typeof setTimeout> | undefined\n try {\n return await Promise.race([\n promise.then(\n (value): PromiseFulfilledResult<Result> => ({ status: 'fulfilled', value }),\n (reason): PromiseRejectedResult => ({ status: 'rejected', reason })\n ),\n new Promise<null>((resolve) => {\n timer = setTimeout(() => resolve(null), remaining)\n }),\n ])\n } finally {\n if (timer) clearTimeout(timer)\n }\n}\n\nfunction serializeFrame(frame: ServerProtocolMessage): string {\n return JSON.stringify(frame)\n}\n\nfunction sendFrame(\n connection: WebSocket,\n frame: ServerProtocolMessage,\n config: OutboundMessageConfig\n): boolean {\n const serializedFrame = serializeFrame(frame)\n return sendSerializedFrameWithBackpressure(connection, serializedFrame, config)\n}\n\nfunction sendSerializedFrameWithBackpressure(\n connection: WebSocket,\n serializedFrame: string,\n config: OutboundMessageConfig\n): boolean {\n if (connection.readyState !== WebSocket.OPEN) {\n return false\n }\n\n const payloadSize = Buffer.byteLength(serializedFrame)\n if (payloadSize > config.maxOutboundPayload) {\n closeConnection(connection, CLOSE_MESSAGE_TOO_BIG, CLOSE_OUTBOUND_MESSAGE_TOO_BIG)\n return false\n }\n\n if (connection.bufferedAmount + payloadSize > config.maxBufferedAmount) {\n closeConnection(connection, CLOSE_POLICY_VIOLATION, CLOSE_OUTBOUND_BUFFER_LIMIT)\n return false\n }\n\n connection.send(serializedFrame)\n return true\n}\n\nfunction parsePositiveInteger(name: string, value: number | undefined, fallback: number): number {\n if (value === undefined) {\n return fallback\n }\n\n if (!Number.isSafeInteger(value) || value <= 0) {\n throw new Error(`${name} must be a positive integer`)\n }\n\n return value\n}\n\nfunction resolveHeartbeatConfig(\n config: { pingInterval?: Duration; pingTimeout?: Duration } | undefined\n): { interval: number; timeout: number } | null {\n const pingInterval = parseDuration('websocket.pingInterval', config?.pingInterval)\n const pingTimeout = parseDuration('websocket.pingTimeout', config?.pingTimeout)\n\n if (pingInterval === undefined && pingTimeout === undefined) {\n return null\n }\n\n return {\n interval: pingInterval ?? DEFAULT_PING_INTERVAL,\n timeout: pingTimeout ?? DEFAULT_PING_TIMEOUT,\n }\n}\n\nfunction resolveInboundMessageConfig(\n config:\n | {\n maxPayload?: number\n maxQueuedMessages?: number\n maxMessagesPerInterval?: number\n messageRateInterval?: Duration\n maxSubscriptionsPerSocket?: number\n maxChannelNameLength?: number\n }\n | undefined\n): InboundMessageConfig {\n const messageRateInterval =\n parseDuration('websocket.messageRateInterval', config?.messageRateInterval) ??\n DEFAULT_MESSAGE_RATE_INTERVAL\n\n return {\n maxPayload: parsePositiveInteger(\n 'websocket.maxPayload',\n config?.maxPayload,\n DEFAULT_MAX_PAYLOAD\n ),\n maxQueuedMessages: parsePositiveInteger(\n 'websocket.maxQueuedMessages',\n config?.maxQueuedMessages,\n DEFAULT_MAX_QUEUED_MESSAGES\n ),\n maxMessagesPerInterval: parsePositiveInteger(\n 'websocket.maxMessagesPerInterval',\n config?.maxMessagesPerInterval,\n DEFAULT_MAX_MESSAGES_PER_INTERVAL\n ),\n messageRateInterval,\n subscriptionLimits: {\n maxSubscriptionsPerSocket: parsePositiveInteger(\n 'websocket.maxSubscriptionsPerSocket',\n config?.maxSubscriptionsPerSocket,\n DEFAULT_MAX_SUBSCRIPTIONS_PER_SOCKET\n ),\n maxChannelNameLength: parsePositiveInteger(\n 'websocket.maxChannelNameLength',\n config?.maxChannelNameLength,\n DEFAULT_MAX_CHANNEL_NAME_LENGTH\n ),\n },\n }\n}\n\nfunction resolveOutboundMessageConfig(\n config:\n | {\n maxBufferedAmount?: number\n maxOutboundPayload?: number\n }\n | undefined\n): OutboundMessageConfig {\n return {\n maxBufferedAmount: parsePositiveInteger(\n 'websocket.maxBufferedAmount',\n config?.maxBufferedAmount,\n DEFAULT_MAX_BUFFERED_AMOUNT\n ),\n maxOutboundPayload: parsePositiveInteger(\n 'websocket.maxOutboundPayload',\n config?.maxOutboundPayload,\n DEFAULT_MAX_OUTBOUND_PAYLOAD\n ),\n }\n}\n\nfunction getRawDataByteLength(data: RawData): number {\n if (Array.isArray(data)) {\n return data.reduce((total, chunk) => total + chunk.byteLength, 0)\n }\n\n return data.byteLength\n}\n\nfunction closeConnection(connection: WebSocket, code: number, reason: string): void {\n if (connection.readyState === WebSocket.OPEN) {\n connection.close(code, reason)\n }\n}\n\ninterface SocketServiceRuntime<User> {\n kind: 'runtime'\n server: WebSocketServer\n httpServer: HttpServer\n upgradeHandler: SocketUpgradeHandler\n channelSubscriptions: ChannelSubscriptions<User>\n bus: SocketBus | null\n}\n\ninterface SocketServiceBootOperation<User> {\n kind: 'boot'\n promise: Promise<void>\n closeRequested: boolean\n channelSubscriptions?: ChannelSubscriptions<User>\n bus?: SocketBus\n busCloseBeforeStart?: Promise<void>\n busCloseAfterStart?: Promise<void>\n runtime?: SocketServiceRuntime<User>\n}\n\ntype SocketServiceResources<User> = SocketServiceBootOperation<User> | SocketServiceRuntime<User>\n\ntype SocketServiceLifecycle<User> =\n | { status: 'stopped' }\n | { status: 'starting'; operation: SocketServiceBootOperation<User> }\n | { status: 'ready'; runtime: SocketServiceRuntime<User> }\n | {\n status: 'stopping'\n resources: SocketServiceResources<User>\n close: Promise<void>\n }\n | {\n status: 'failed'\n error: Error\n resources?: SocketServiceResources<User>\n close?: Promise<void>\n }\n\n/**\n * Main service for managing WebSocket connections.\n */\nexport class SocketService<User = unknown> extends Emittery<SocketEvents<User>> {\n #sockets = new Map<string, AuthenticatedSocket<User>>()\n #presenceManager: PresenceManager | null = null\n #fake: SocketFake | null = null\n #deliverySink: SocketEmissionSink = {\n dispatch: (emission) => {\n this.#deliverBroadcast(emission)\n },\n }\n #broadcastSink: SocketEmissionSink = this.#deliverySink\n #lifecycle: SocketServiceLifecycle<User> = { status: 'stopped' }\n #heartbeatInterval: ReturnType<typeof setInterval> | null = null\n #heartbeatTimeouts = new Map<string, ReturnType<typeof setTimeout>>()\n #messageQueue = new MessageQueue()\n #messageRates = new Map<string, SocketMessageRate>()\n #socketFinalizations = new Map<string, Promise<void>>()\n #outboundMessageConfig = resolveOutboundMessageConfig(undefined)\n #shutdownTimeout = DEFAULT_SHUTDOWN_TIMEOUT\n #logger: Logger | null = null\n\n /**\n * Accesses the underlying ws server.\n */\n get server(): WebSocketServer {\n const runtime = this.#runtime\n if (!runtime) {\n throw new Error('WebSocket server is not initialized. Call boot() first.')\n }\n\n return runtime.server\n }\n\n get #resources(): SocketServiceResources<User> | undefined {\n switch (this.#lifecycle.status) {\n case 'starting':\n return this.#lifecycle.operation\n case 'ready':\n return this.#lifecycle.runtime\n case 'stopping':\n case 'failed':\n return this.#lifecycle.resources\n case 'stopped':\n return undefined\n }\n }\n\n get #runtime(): SocketServiceRuntime<User> | undefined {\n if (this.#lifecycle.status === 'ready') return this.#lifecycle.runtime\n if (this.#lifecycle.status !== 'failed') return undefined\n\n const resources = this.#lifecycle.resources\n if (!resources) return undefined\n if (resources.kind === 'runtime') return resources\n return resources.runtime\n }\n\n get #channelSubscriptions(): ChannelSubscriptions<User> | undefined {\n const resources = this.#resources\n if (!resources) return undefined\n if (resources.kind === 'runtime') return resources.channelSubscriptions\n return resources.runtime?.channelSubscriptions ?? resources.channelSubscriptions\n }\n\n get #bus(): SocketBus | null | undefined {\n const resources = this.#resources\n if (!resources) return undefined\n if (resources.kind === 'runtime') return resources.bus\n return resources.runtime?.bus ?? resources.bus\n }\n\n #isStarting(operation: SocketServiceBootOperation<User>): boolean {\n return this.#lifecycle.status === 'starting' && this.#lifecycle.operation === operation\n }\n\n #closeBootBusAfterStart(operation: SocketServiceBootOperation<User>): Promise<void> {\n const bus = operation.bus\n if (!bus) return Promise.resolve()\n if (operation.busCloseAfterStart) return operation.busCloseAfterStart\n\n const close = bus.close()\n operation.busCloseAfterStart = close\n return close\n }\n\n setPresenceManager(presenceManager: PresenceManager): void {\n this.#presenceManager = presenceManager\n this.#channelSubscriptions?.setPresenceManager(presenceManager)\n this.#configurePresenceFetcher(this.#bus)\n }\n\n boot(\n httpServer: HttpServer,\n config: SocketConfig<User>,\n channelRouter: ChannelRouter,\n logger: Logger,\n runWithHttpContext: SocketUpgradeContextRunner\n ): Promise<void> {\n if (this.#lifecycle.status === 'ready') return Promise.resolve()\n if (this.#lifecycle.status === 'starting') return this.#lifecycle.operation.promise\n if (this.#lifecycle.status === 'stopping') {\n return Promise.reject(new Error('Socket service is stopping'))\n }\n if (this.#lifecycle.status === 'failed' && this.#lifecycle.resources) {\n return Promise.reject(new Error('Socket service must be closed before rebooting'))\n }\n\n this.#logger = logger\n const deferred = Promise.withResolvers<void>()\n const operation: SocketServiceBootOperation<User> = {\n kind: 'boot',\n promise: deferred.promise,\n closeRequested: false,\n }\n this.#lifecycle = { status: 'starting', operation }\n\n void this.#boot(httpServer, config, channelRouter, logger, runWithHttpContext, operation).then(\n deferred.resolve,\n deferred.reject\n )\n return operation.promise\n }\n\n async #boot(\n httpServer: HttpServer,\n config: SocketConfig<User>,\n channelRouter: ChannelRouter,\n logger: Logger,\n runWithHttpContext: SocketUpgradeContextRunner,\n operation: SocketServiceBootOperation<User>\n ): Promise<void> {\n try {\n const websocketConfig = config.websocket\n const heartbeatConfig = resolveHeartbeatConfig(websocketConfig)\n const inboundMessageConfig = resolveInboundMessageConfig(websocketConfig)\n this.#outboundMessageConfig = resolveOutboundMessageConfig(websocketConfig)\n this.#shutdownTimeout =\n parseDuration('websocket.shutdownTimeout', websocketConfig?.shutdownTimeout) ??\n DEFAULT_SHUTDOWN_TIMEOUT\n\n operation.channelSubscriptions = new ChannelSubscriptions(\n this,\n channelRouter,\n logger,\n this.#presenceManager ?? undefined,\n inboundMessageConfig.subscriptionLimits\n )\n\n if (config.transport) {\n operation.bus = new SocketBus(config.transport, {\n channel: (message) => {\n this.#traceBroadcast(\n {\n target: 'channel',\n channel: message.channel,\n event: message.event,\n via: 'bus',\n except: message.except,\n },\n () =>\n this.#emitToChannelLocally(\n message.channel,\n message.event,\n message.data,\n message.except\n )\n )\n },\n broadcast: (message) => {\n this.#traceBroadcast({ target: 'global', event: message.event, via: 'bus' }, () =>\n this.#broadcastLocally(message.event, message.data)\n )\n },\n presenceSockets: (channel) => {\n return this.#getLocalPresenceSockets(channel)\n },\n })\n\n await operation.bus.start()\n if (!this.#isStarting(operation)) {\n throw new Error('Socket service boot interrupted by shutdown')\n }\n }\n\n const websocketServer = new WebSocketServer({\n noServer: true,\n maxPayload: inboundMessageConfig.maxPayload,\n })\n\n const upgrader = new SocketUpgrader<User>(\n websocketServer,\n websocketConfig,\n runWithHttpContext,\n (message, error) => this.#warn(message, error)\n )\n\n const upgradeHandler: SocketUpgradeHandler = (request, socket, head) => {\n upgrader\n .handle(request, socket, head, (connection, accepted) => {\n this.#handleConnection(connection, accepted, inboundMessageConfig)\n })\n .catch((error) => {\n this.#warn('failed to upgrade socket connection: %s', error)\n SocketUpgrader.reject(socket, 500, 'Internal Server Error')\n })\n }\n const runtime: SocketServiceRuntime<User> = {\n kind: 'runtime',\n server: websocketServer,\n httpServer,\n upgradeHandler,\n channelSubscriptions: operation.channelSubscriptions,\n bus: operation.bus ?? null,\n }\n operation.runtime = runtime\n httpServer.on('upgrade', upgradeHandler)\n\n this.#startHeartbeat(heartbeatConfig)\n if (!this.#isStarting(operation)) {\n throw new Error('Socket service boot interrupted by shutdown')\n }\n\n this.#lifecycle = { status: 'ready', runtime }\n this.#configurePresenceFetcher(runtime.bus)\n } catch (error) {\n if (!this.#isStarting(operation)) {\n if (operation.closeRequested) {\n await this.#closeBootBusAfterStart(operation)\n }\n if (\n this.#lifecycle.status === 'failed' &&\n this.#lifecycle.resources === operation &&\n !this.#lifecycle.close\n ) {\n await this.close()\n }\n throw error\n }\n\n const failure = error instanceof Error ? error : new Error('Socket service boot failed')\n this.#lifecycle = { status: 'failed', error: failure, resources: operation }\n await this.close()\n throw error\n }\n }\n\n #handleConnection(\n connection: WebSocket,\n upgrade: AcceptedUpgrade<User>,\n inboundMessageConfig: InboundMessageConfig\n ): void {\n if (this.#lifecycle.status !== 'ready') {\n connection.terminate()\n return\n }\n\n const socket = this.#wrapSocket(connection, upgrade)\n\n connectChannel.traceSync(\n () => {\n this.#sockets.set(socket.id, socket)\n this.#emitLifecycleEvent('connect', { socket })\n },\n { socketId: socket.id }\n )\n\n connection.on('error', () => {})\n\n connection.on('message', (data) => {\n if (getRawDataByteLength(data) > inboundMessageConfig.maxPayload) {\n closeConnection(connection, CLOSE_MESSAGE_TOO_BIG, 'Message too big')\n return\n }\n\n if (!this.#acceptMessageRate(socket.id, inboundMessageConfig)) {\n closeConnection(connection, CLOSE_POLICY_VIOLATION, 'Socket message rate limit exceeded')\n return\n }\n\n const message = Message.fromTransport(data.toString())\n\n if (message.type === 'ping') {\n sendFrame(\n socket.raw.connection,\n { id: message.id, type: 'pong' },\n this.#outboundMessageConfig\n )\n return\n }\n\n const enqueued = this.#messageQueue.enqueue(\n socket.id,\n async () => {\n await this.#handleMessage(socket, message).catch((error) => {\n try {\n this.#logger?.warn('unexpected socket message failure: %s', error)\n } catch {\n // Logging must never prevent a protocol response.\n }\n\n sendFrame(\n connection,\n message.id === undefined\n ? { type: 'error', error: 'Unexpected socket error' }\n : Reply.error(message.id, 'Unexpected socket error').toFrame(),\n this.#outboundMessageConfig\n )\n })\n },\n { maxDepth: inboundMessageConfig.maxQueuedMessages }\n )\n\n if (!enqueued) {\n closeConnection(connection, CLOSE_POLICY_VIOLATION, 'Socket message queue limit exceeded')\n }\n })\n\n connection.on('pong', () => {\n this.#clearHeartbeatTimeout(socket.id)\n })\n\n connection.on('close', () => {\n void Promise.resolve()\n .then(() => this.#finalizeSocket(socket))\n .catch((error) => this.markFailed(error))\n })\n }\n\n #finalizeSocket(socket: AuthenticatedSocket<User>): Promise<void> {\n const pending = this.#socketFinalizations.get(socket.id)\n if (pending) {\n return pending\n }\n\n if (!this.#sockets.has(socket.id)) {\n return Promise.resolve()\n }\n\n const channelSubscriptions = this.#channelSubscriptions\n const finalization = disconnectChannel\n .tracePromise(\n async () => {\n this.#clearHeartbeatTimeout(socket.id)\n this.#messageRates.delete(socket.id)\n await this.#messageQueue.drain(socket.id)\n this.#messageQueue.delete(socket.id)\n await channelSubscriptions?.leaveAll(socket)\n channelSubscriptions?.deleteSocket(socket.id)\n this.#sockets.delete(socket.id)\n this.#emitLifecycleEvent('disconnect', { socket, reason: 'close' })\n },\n {\n socketId: socket.id,\n reason: 'close',\n subscriptions: channelSubscriptions?.subscriptionCountFor(socket.id) ?? 0,\n }\n )\n .finally(() => {\n this.#socketFinalizations.delete(socket.id)\n })\n\n this.#socketFinalizations.set(socket.id, finalization)\n return finalization\n }\n\n async #handleMessage(\n socket: AuthenticatedSocket<User>,\n message: TransportMessage\n ): Promise<void> {\n if (!message.valid) {\n sendFrame(socket.raw.connection, message.toRejectionFrame(), this.#outboundMessageConfig)\n return\n }\n\n switch (message.type) {\n case 'ping':\n return\n case 'subscribe': {\n const traceMessage: SocketSubscribeMessage = {\n socketId: socket.id,\n channel: message.channel,\n }\n\n await subscribeChannel.tracePromise(async () => {\n const result = await this.#channelSubscriptions?.subscribe(socket, message.channel)\n\n traceMessage.created = result?.created ?? false\n traceMessage.ok = result?.ack.ok ?? false\n if (!result?.ack.ok) {\n traceMessage.error = result?.ack.error ?? 'Socket service is not initialized'\n }\n\n if (result?.created) {\n this.#emitLifecycleEvent('subscribe', { socket, channel: message.channel })\n }\n\n sendFrame(\n socket.raw.connection,\n Reply.fromSubscribeResult(message.id, result).toFrame(),\n this.#outboundMessageConfig\n )\n }, traceMessage)\n return\n }\n case 'unsubscribe': {\n const traceMessage: SocketUnsubscribeMessage = {\n socketId: socket.id,\n channel: message.channel,\n }\n\n await unsubscribeChannel.tracePromise(async () => {\n traceMessage.removed =\n (await this.#channelSubscriptions?.leave(socket, message.channel)) ?? false\n traceMessage.ok = true\n if (traceMessage.removed) {\n this.#emitLifecycleEvent('unsubscribe', { socket, channel: message.channel })\n }\n sendFrame(\n socket.raw.connection,\n Reply.ok(message.id).toFrame(),\n this.#outboundMessageConfig\n )\n }, traceMessage)\n return\n }\n case 'message':\n case 'whisper': {\n await this.#handleChannelFrame(socket, message)\n return\n }\n }\n }\n\n async #handleChannelFrame(\n socket: AuthenticatedSocket<User>,\n message: Extract<TransportMessage, { type: 'message' | 'whisper' }>\n ): Promise<void> {\n const payload = message.toChannelMessage()\n const traceMessage: SocketChannelMessage = {\n socketId: socket.id,\n channel: payload.channel,\n event: payload.event,\n }\n\n await channelMessageChannel.tracePromise(async () => {\n const ack = await this.#handleChannelPayload(socket, message.type, payload)\n traceMessage.ok = ack.ok\n if (!ack.ok) {\n traceMessage.error = ack.error\n }\n\n sendFrame(\n socket.raw.connection,\n Reply.fromChannelAck(message.id, ack).toFrame(),\n this.#outboundMessageConfig\n )\n }, traceMessage)\n }\n\n async #handleChannelPayload(\n socket: AuthenticatedSocket<User>,\n type: 'message' | 'whisper',\n payload: ChannelMessage\n ): Promise<ChannelAck> {\n if (typeof payload.channel !== 'string' || typeof payload.event !== 'string') {\n return { ok: false, error: `Invalid channel ${type}` }\n }\n\n if (type === 'message') {\n return this.#channelSubscriptions!.handleMessage(socket, payload)\n }\n\n return this.#channelSubscriptions!.relayWhisper(socket, payload)\n }\n\n #wrapSocket(connection: WebSocket, upgrade: AcceptedUpgrade<User>): AuthenticatedSocket<User> {\n const raw: RawSocket = {\n id: randomUUID(),\n data: {},\n connection,\n }\n\n return {\n id: raw.id,\n user: upgrade.user,\n\n getUserOrFail() {\n if (this.user === undefined) {\n throw new SocketResponseError('Unauthorized')\n }\n\n return this.user\n },\n\n emit: (event, data) => {\n this.#sendSerializedEventFrame(connection, serializeFrame({ type: 'event', event, data }))\n },\n\n disconnect() {\n connection.close(SERVER_DISCONNECT_CODE, SERVER_DISCONNECT_REASON)\n },\n\n raw,\n }\n }\n\n to(channel: string) {\n return {\n emit: (event: string, data: unknown) => {\n this.#broadcastSink.dispatch({ target: 'channel', channel, event, data })\n },\n except: (socketId: string) => ({\n emit: (event: string, data: unknown) => {\n this.#broadcastSink.dispatch({\n target: 'channel',\n channel,\n event,\n data,\n except: [socketId],\n })\n },\n }),\n }\n }\n\n broadcast(event: string, data: unknown): void {\n this.#broadcastSink.dispatch({ target: 'global', event, data })\n }\n\n #deliverBroadcast(emission: SocketEmission): void {\n switch (emission.target) {\n case 'channel': {\n const channel = emission.channel\n const serializedFrame = serializeFrame({\n type: 'event',\n channel,\n event: emission.event,\n data: emission.data,\n })\n this.#bus?.publishChannel(channel, emission.event, emission.data, emission.except)\n\n const traceMessage: SocketBroadcastMessage = {\n target: 'channel',\n channel,\n event: emission.event,\n via: 'local',\n }\n if (emission.except) {\n traceMessage.except = emission.except\n }\n\n this.#traceBroadcast(traceMessage, () =>\n this.#emitToChannelLocally(\n channel,\n emission.event,\n emission.data,\n emission.except,\n serializedFrame\n )\n )\n return\n }\n case 'global': {\n const serializedFrame = serializeFrame({\n type: 'event',\n event: emission.event,\n data: emission.data,\n })\n this.#bus?.publishBroadcast(emission.event, emission.data)\n this.#traceBroadcast({ target: 'global', event: emission.event, via: 'local' }, () =>\n this.#broadcastLocally(emission.event, emission.data, serializedFrame)\n )\n }\n }\n }\n\n #traceBroadcast(message: SocketBroadcastMessage, deliver: () => number): void {\n broadcastChannel.traceSync(() => {\n message.delivered = deliver()\n }, message)\n }\n\n #sendSerializedEventFrame(connection: WebSocket, serializedFrame: string): boolean {\n return sendSerializedFrameWithBackpressure(\n connection,\n serializedFrame,\n this.#outboundMessageConfig\n )\n }\n\n #emitToChannelLocally(\n channel: string,\n event: string,\n data: unknown,\n except: string[] = [],\n serializedFrame = serializeFrame({ type: 'event', channel, event, data })\n ): number {\n let delivered = 0\n\n for (const socketId of this.#channelSubscriptions?.getSocketIds(channel) ?? []) {\n if (except.includes(socketId)) {\n continue\n }\n\n const socket = this.#sockets.get(socketId)\n if (socket && this.#sendSerializedEventFrame(socket.raw.connection, serializedFrame)) {\n delivered += 1\n }\n }\n\n return delivered\n }\n\n #broadcastLocally(\n event: string,\n data: unknown,\n serializedFrame = serializeFrame({ type: 'event', event, data })\n ): number {\n let delivered = 0\n\n for (const socket of this.#sockets.values()) {\n if (this.#sendSerializedEventFrame(socket.raw.connection, serializedFrame)) {\n delivered += 1\n }\n }\n\n return delivered\n }\n\n #configurePresenceFetcher(bus: SocketBus | null | undefined): void {\n if (!this.#presenceManager || !bus) {\n return\n }\n\n this.#presenceManager.setSocketFetcher(async (channel) => {\n return [\n ...this.#presenceManager!.getLocalSockets(channel),\n ...(await bus.fetchPresenceSockets(channel)),\n ]\n })\n }\n\n #getLocalPresenceSockets(channel: string): SerializablePresenceSocket[] {\n return (this.#presenceManager?.getLocalSockets(channel) ?? []).map((socket) => {\n return PresenceSocketFrame.fromSocket(channel, socket).toTransport()\n })\n }\n\n getSocket(socketId: string): AuthenticatedSocket<User> | undefined {\n return this.#sockets.get(socketId)\n }\n\n get connectionsCount(): number {\n return this.#sockets.size\n }\n\n get status(): SocketServiceStatus {\n return this.#lifecycle.status\n }\n\n get ready(): boolean {\n return this.#lifecycle.status === 'ready'\n }\n\n fake(): SocketFake {\n const fake = new SocketFake(() => {\n if (this.#fake === fake) {\n this.restore()\n }\n })\n\n this.#fake = fake\n this.#broadcastSink = fake\n return fake\n }\n\n restore(): void {\n this.#fake = null\n this.#broadcastSink = this.#deliverySink\n }\n\n markFailed(error: unknown): void {\n const failure = error instanceof Error ? error : new Error('Socket service failed')\n const lifecycle = this.#lifecycle\n\n if (lifecycle.status === 'stopped') {\n this.#lifecycle = { status: 'failed', error: failure }\n return\n }\n if (lifecycle.status === 'starting') {\n this.#lifecycle = { status: 'failed', error: failure, resources: lifecycle.operation }\n return\n }\n if (lifecycle.status === 'ready') {\n this.#lifecycle = { status: 'failed', error: failure, resources: lifecycle.runtime }\n return\n }\n\n this.#lifecycle = { ...lifecycle, status: 'failed', error: failure }\n }\n\n #warn(message: string, error: unknown): void {\n try {\n this.#logger?.warn(message, error)\n } catch {\n // Logging must never change socket behavior.\n }\n }\n\n #emitLifecycleEvent<EventName extends keyof SocketEvents<User>>(\n eventName: EventName,\n event: SocketEvents<User>[EventName]\n ): void {\n void this.emit(eventName, event).catch((error) => {\n try {\n this.#logger?.warn('socket %s listener failed: %s', eventName, error)\n } catch {\n // Lifecycle observers and their reporting must not affect the socket service.\n }\n })\n }\n\n health(): SocketHealthSnapshot {\n const error = this.#lifecycle.status === 'failed' ? this.#lifecycle.error : undefined\n return {\n status: this.#lifecycle.status,\n ready: this.ready,\n connections: this.#sockets.size,\n channels: this.#channelSubscriptions?.channelsCount ?? 0,\n ...(error ? { lastError: error.message } : {}),\n }\n }\n\n #startHeartbeat(config: { interval: number; timeout: number } | null): void {\n this.#stopHeartbeat()\n\n if (!config) {\n return\n }\n\n this.#heartbeatInterval = setInterval(() => {\n this.#pingSockets(config.timeout)\n }, config.interval)\n }\n\n #pingSockets(timeout: number): void {\n for (const socket of this.#sockets.values()) {\n const { connection } = socket.raw\n\n if (connection.readyState !== WebSocket.OPEN) {\n this.#clearHeartbeatTimeout(socket.id)\n continue\n }\n\n if (this.#heartbeatTimeouts.has(socket.id)) {\n continue\n }\n\n const timeoutId = setTimeout(() => {\n this.#heartbeatTimeouts.delete(socket.id)\n connection.terminate()\n }, timeout)\n\n this.#heartbeatTimeouts.set(socket.id, timeoutId)\n\n try {\n connection.ping()\n } catch {\n this.#clearHeartbeatTimeout(socket.id)\n connection.terminate()\n }\n }\n }\n\n #clearHeartbeatTimeout(socketId: string): void {\n const timeout = this.#heartbeatTimeouts.get(socketId)\n\n if (!timeout) {\n return\n }\n\n clearTimeout(timeout)\n this.#heartbeatTimeouts.delete(socketId)\n }\n\n #stopHeartbeat(): void {\n if (this.#heartbeatInterval) {\n clearInterval(this.#heartbeatInterval)\n this.#heartbeatInterval = null\n }\n\n for (const timeout of this.#heartbeatTimeouts.values()) {\n clearTimeout(timeout)\n }\n\n this.#heartbeatTimeouts.clear()\n }\n\n #acceptMessageRate(socketId: string, config: InboundMessageConfig): boolean {\n const now = Date.now()\n const rate = this.#messageRates.get(socketId)\n\n if (!rate || now - rate.intervalStartedAt >= config.messageRateInterval) {\n this.#messageRates.set(socketId, { count: 1, intervalStartedAt: now })\n return true\n }\n\n if (rate.count >= config.maxMessagesPerInterval) {\n return false\n }\n\n rate.count += 1\n return true\n }\n\n #cleanup(channelSubscriptions: ChannelSubscriptions<User> | undefined): void {\n this.#stopHeartbeat()\n this.#sockets.clear()\n this.#messageQueue.clear()\n this.#messageRates.clear()\n this.#socketFinalizations.clear()\n channelSubscriptions?.clear()\n }\n\n close(): Promise<void> {\n const lifecycle = this.#lifecycle\n if (lifecycle.status === 'stopped') return Promise.resolve()\n if (lifecycle.status === 'stopping') return lifecycle.close\n if (lifecycle.status === 'failed' && lifecycle.close) return lifecycle.close\n if (lifecycle.status === 'failed' && !lifecycle.resources) return Promise.resolve()\n\n if (lifecycle.status === 'starting') {\n return this.#startClose(lifecycle.operation, lifecycle.operation.promise)\n }\n if (lifecycle.status === 'ready') return this.#startClose(lifecycle.runtime)\n\n return this.#startClose(lifecycle.resources!, undefined, lifecycle.error)\n }\n\n #startClose(\n resources: SocketServiceResources<User>,\n pendingBoot?: Promise<void>,\n preservedError?: Error\n ): Promise<void> {\n const deferred = Promise.withResolvers<void>()\n const close = deferred.promise\n if (resources.kind === 'boot') resources.closeRequested = true\n this.#lifecycle = preservedError\n ? { status: 'failed', error: preservedError, resources, close }\n : { status: 'stopping', resources, close }\n\n void this.#close(resources, pendingBoot).then(\n () => {\n if (!('close' in this.#lifecycle) || this.#lifecycle.close !== close) return\n\n this.#lifecycle =\n this.#lifecycle.status === 'failed'\n ? { status: 'failed', error: this.#lifecycle.error, close }\n : { status: 'stopped' }\n deferred.resolve()\n },\n (error) => {\n const failure = error instanceof Error ? error : new Error('Socket service shutdown failed')\n if ('close' in this.#lifecycle && this.#lifecycle.close === close) {\n this.#lifecycle = { status: 'failed', error: failure, close }\n }\n deferred.reject(error)\n }\n )\n return close\n }\n\n async #waitForBootClose(pendingBoot: Promise<void>, deadline: number): Promise<void> {\n const result = await settleBeforeDeadline(pendingBoot, deadline)\n if (result === null) {\n this.#warn(\n 'socket boot exceeded the %dms shutdown timeout; forcing cleanup',\n this.#shutdownTimeout\n )\n }\n }\n\n #startServerClose(server: WebSocketServer | undefined): Promise<unknown | null> {\n if (!server) return Promise.resolve(null)\n\n return new Promise((resolve) => {\n server.close((error) => resolve(error ?? null))\n })\n }\n\n async #closeSockets(deadline: number): Promise<unknown[]> {\n this.#stopHeartbeat()\n const sockets = [...this.#sockets.values()]\n for (const socket of sockets) {\n const { connection } = socket.raw\n connection.close(SERVER_DISCONNECT_CODE, SERVER_DISCONNECT_REASON)\n const terminateTimer = setTimeout(() => connection.terminate(), 50)\n connection.once('close', () => clearTimeout(terminateTimer))\n }\n\n const finalizations = sockets.map((socket) => {\n return Promise.resolve().then(() => this.#finalizeSocket(socket))\n })\n const results = await settleBeforeDeadline(Promise.allSettled(finalizations), deadline)\n if (results === null) {\n this.#warn(\n 'socket finalization exceeded the %dms shutdown timeout; forcing cleanup',\n this.#shutdownTimeout\n )\n return []\n }\n if (results.status === 'rejected') return []\n\n const errors: unknown[] = []\n for (const result of results.value) {\n if (result.status === 'rejected') errors.push(result.reason)\n }\n return errors\n }\n\n async #closeBus(\n resources: SocketServiceResources<User>,\n bus: SocketBus | null | undefined,\n deadline: number\n ): Promise<unknown[]> {\n if (!bus) return []\n\n const close =\n resources.kind === 'boot'\n ? (resources.busCloseAfterStart ?? (resources.busCloseBeforeStart ??= bus.close()))\n : bus.close()\n const result = await settleBeforeDeadline(close, deadline)\n if (result === null) {\n this.#warn(\n 'socket transport exceeded the %dms shutdown timeout; forcing cleanup',\n this.#shutdownTimeout\n )\n return []\n }\n return result.status === 'rejected' ? [result.reason] : []\n }\n\n async #finishServerClose(close: Promise<unknown | null>, deadline: number): Promise<unknown[]> {\n const result = await settleBeforeDeadline(close, deadline)\n if (result === null) {\n this.#warn(\n 'socket server exceeded the %dms shutdown timeout; forcing cleanup',\n this.#shutdownTimeout\n )\n return []\n }\n if (result.status === 'rejected' || !result.value) return []\n return [result.value]\n }\n\n async #close(\n resources: SocketServiceResources<User>,\n pendingBoot?: Promise<void>\n ): Promise<void> {\n const deadline = Date.now() + this.#shutdownTimeout\n if (pendingBoot) await this.#waitForBootClose(pendingBoot, deadline)\n\n const runtime = resources.kind === 'runtime' ? resources : resources.runtime\n const channelSubscriptions =\n runtime?.channelSubscriptions ??\n (resources.kind === 'boot' ? resources.channelSubscriptions : undefined)\n const server = runtime?.server\n const bus = runtime?.bus ?? (resources.kind === 'boot' ? resources.bus : undefined)\n const httpServer = runtime?.httpServer\n const upgradeHandler = runtime?.upgradeHandler\n\n if (httpServer && upgradeHandler) {\n httpServer.off('upgrade', upgradeHandler)\n }\n\n const serverClose = this.#startServerClose(server)\n const errors = await this.#closeSockets(deadline)\n\n this.#cleanup(channelSubscriptions)\n this.#presenceManager?.setSocketFetcher(null)\n\n errors.push(...(await this.#closeBus(resources, bus, deadline)))\n errors.push(...(await this.#finishServerClose(serverClose, deadline)))\n\n if (errors.length > 0) {\n const error =\n errors.length === 1 && errors[0] instanceof Error\n ? errors[0]\n : new AggregateError(errors, 'Socket service shutdown failed')\n throw error\n }\n }\n}\n","import type { BaseChannel } from './base_channel.js'\n\nexport interface StoredChannelSubscription {\n channelName: string\n instance: BaseChannel<any, any>\n paramValues: string[]\n}\n\n/**\n * Stores durable Channel subscriptions and keeps Socket/Channel indexes in sync.\n */\nexport class ChannelSubscriptionStorage {\n #subscriptions = new Map<string, Map<string, StoredChannelSubscription>>()\n #subscribers = new Map<string, Set<string>>()\n\n has(socketId: string, channelName: string): boolean {\n return this.#subscriptions.get(socketId)?.has(channelName) ?? false\n }\n\n get(socketId: string, channelName: string): StoredChannelSubscription | undefined {\n return this.#subscriptions.get(socketId)?.get(channelName)\n }\n\n set(socketId: string, channelName: string, subscription: StoredChannelSubscription): void {\n if (!this.#subscriptions.has(socketId)) {\n this.#subscriptions.set(socketId, new Map())\n }\n\n this.#subscriptions.get(socketId)!.set(channelName, subscription)\n\n if (!this.#subscribers.has(channelName)) {\n this.#subscribers.set(channelName, new Set())\n }\n\n this.#subscribers.get(channelName)!.add(socketId)\n }\n\n delete(socketId: string, channelName: string): void {\n const subscriptions = this.#subscriptions.get(socketId)\n\n if (!subscriptions) {\n return\n }\n\n subscriptions.delete(channelName)\n if (subscriptions.size === 0) {\n this.#subscriptions.delete(socketId)\n }\n\n const subscribers = this.#subscribers.get(channelName)\n subscribers?.delete(socketId)\n if (subscribers?.size === 0) {\n this.#subscribers.delete(channelName)\n }\n }\n\n deleteSocket(socketId: string): void {\n for (const channelName of this.channelNamesFor(socketId)) {\n this.delete(socketId, channelName)\n }\n }\n\n channelNamesFor(socketId: string): string[] {\n return [...(this.#subscriptions.get(socketId)?.keys() ?? [])]\n }\n\n countForSocket(socketId: string): number {\n return this.#subscriptions.get(socketId)?.size ?? 0\n }\n\n socketIdsFor(channelName: string): string[] {\n return [...(this.#subscribers.get(channelName) ?? [])]\n }\n\n get channelsCount(): number {\n return this.#subscribers.size\n }\n\n clear(): void {\n this.#subscriptions.clear()\n this.#subscribers.clear()\n }\n}\n","import type { Logger } from '@adonisjs/logger'\nimport { SocketResponseError } from './base_channel.js'\nimport type { BaseChannel } from './base_channel.js'\nimport {\n ChannelSubscriptionStorage,\n type StoredChannelSubscription,\n} from './channel_subscription_storage.js'\nimport type { ChannelRouter } from './channel_router.js'\nimport type { PresenceData, PresenceManager } from './presence_manager.js'\nimport type { SocketService } from './socket_service.js'\nimport type { AuthenticatedSocket, ChannelAck, ChannelMessage } from './types.js'\n\ninterface AuthorizedChannel<User> {\n instance: BaseChannel<User>\n params: Record<string, string>\n paramValues: string[]\n presenceData: Record<string, unknown> | PresenceData | null\n}\n\nexport type ChannelSubscribeAck =\n | {\n ok: true\n presenceData?: Record<string, unknown> | PresenceData | null\n error?: never\n }\n | { ok: false; error: string; presenceData?: never }\n\nexport interface ChannelSubscribeResult {\n ack: ChannelSubscribeAck\n created: boolean\n}\n\nexport interface ChannelSubscriptionLimits {\n maxSubscriptionsPerSocket: number\n maxChannelNameLength: number\n}\n\n/**\n * Durable channel subscriptions for sockets.\n */\nexport class ChannelSubscriptions<User = unknown> {\n #storage = new ChannelSubscriptionStorage()\n #channelOperations = new Map<string, Promise<void>>()\n\n static #serializePresenceData(presenceData: PresenceData): Record<string, unknown> {\n return {\n ...presenceData,\n users: presenceData.users.map((user) => ({\n ...user,\n joinedAt: user.joinedAt.toISOString(),\n })),\n }\n }\n\n constructor(\n private socketService: SocketService<User>,\n private channelRouter: ChannelRouter,\n private logger: Logger,\n private presenceManager?: PresenceManager,\n private limits?: ChannelSubscriptionLimits\n ) {}\n\n setPresenceManager(presenceManager: PresenceManager): void {\n this.presenceManager = presenceManager\n }\n\n async subscribe(\n socket: AuthenticatedSocket<User>,\n channelName: string\n ): Promise<ChannelSubscribeResult> {\n return this.#subscribe(socket, channelName)\n }\n\n async #subscribe(\n socket: AuthenticatedSocket<User>,\n channelName: string\n ): Promise<ChannelSubscribeResult> {\n const existing = await this.#refreshExistingSubscription(socket, channelName)\n if (existing) {\n return existing\n }\n\n if (this.limits && channelName.length > this.limits.maxChannelNameLength) {\n return {\n ack: { ok: false, error: 'Channel name is too long' },\n created: false,\n }\n }\n\n if (\n this.limits &&\n this.#storage.channelNamesFor(socket.id).length >= this.limits.maxSubscriptionsPerSocket\n ) {\n return {\n ack: { ok: false, error: 'Socket subscription limit exceeded' },\n created: false,\n }\n }\n\n const result = await this.channelRouter.authorize(socket, channelName)\n\n if (!result.success) {\n if ('cause' in result && !(result.cause instanceof SocketResponseError)) {\n this.#warn(`failed to authorize channel \"${channelName}\": %s`, result.cause)\n }\n\n return {\n ack: { ok: false, error: result.error },\n created: false,\n }\n }\n\n if (this.#usesPresence(result.instance)) {\n return this.#withChannelOperation(`${socket.id}\\0${channelName}`, async () => {\n const concurrentSubscription = await this.#refreshExistingSubscription(socket, channelName)\n if (concurrentSubscription) {\n return concurrentSubscription\n }\n\n return this.#completeSubscription(socket, channelName, result)\n })\n }\n\n return this.#completeSubscription(socket, channelName, result)\n }\n\n async #completeSubscription(\n socket: AuthenticatedSocket<User>,\n channelName: string,\n result: AuthorizedChannel<User>\n ): Promise<ChannelSubscribeResult> {\n result.instance.$setContext(\n this.socketService,\n channelName,\n result.params,\n this.presenceManager\n )\n\n let presenceData: Record<string, unknown> | PresenceData | null = result.presenceData\n let presenceSnapshot: PresenceData | null = null\n let presenceJoined = false\n let serializationError: unknown\n\n try {\n if (this.#usesPresence(result.instance)) {\n const presenceInfo = result.instance.$getPresenceInfo(socket)\n const joinedUser = this.presenceManager!.join(channelName, socket.raw, presenceInfo)\n const { joinedAt: _joinedAt, ...member } = joinedUser\n presenceJoined = true\n\n presenceSnapshot = await this.presenceManager!.snapshot(channelName)\n presenceData = presenceSnapshot\n const visibleUser = presenceSnapshot.users.find((user) => user.id === presenceInfo.id)\n const wasPresent = Boolean(visibleUser && visibleUser !== joinedUser)\n\n try {\n JSON.stringify(presenceData)\n } catch (error) {\n serializationError = error\n throw error\n }\n\n if (!wasPresent) {\n await result.instance.onMemberJoin?.(socket, member, ...result.paramValues)\n }\n await result.instance.onJoin?.(socket, ...result.paramValues)\n } else {\n try {\n JSON.stringify(presenceData)\n } catch (error) {\n serializationError = error\n throw error\n }\n\n await result.instance.onJoin?.(socket, ...result.paramValues)\n }\n\n this.#storage.set(socket.id, channelName, {\n channelName,\n instance: result.instance,\n paramValues: result.paramValues,\n })\n\n if (presenceSnapshot) {\n this.socketService\n .to(channelName)\n .except(socket.id)\n .emit('presence:update', ChannelSubscriptions.#serializePresenceData(presenceSnapshot))\n }\n } catch (error) {\n if (presenceJoined) {\n this.presenceManager!.leave(channelName, socket.raw)\n\n const rollbackData = await this.presenceManager!.snapshot(channelName).catch(() => null)\n if (rollbackData) {\n this.socketService\n .to(channelName)\n .emit('presence:update', ChannelSubscriptions.#serializePresenceData(rollbackData))\n }\n }\n\n this.#storage.delete(socket.id, channelName)\n\n if (serializationError) {\n this.#warn(\n `failed to serialize subscription response for channel \"${channelName}\": %s`,\n serializationError\n )\n } else if (!(error instanceof SocketResponseError)) {\n this.#warn(`failed to join channel \"${channelName}\": %s`, error)\n }\n\n return {\n ack: {\n ok: false,\n error: serializationError\n ? 'Subscription response is not serializable'\n : error instanceof SocketResponseError\n ? error.message\n : 'Join failed',\n },\n created: false,\n }\n }\n\n return {\n ack: { ok: true, presenceData },\n created: true,\n }\n }\n\n async leave(socket: AuthenticatedSocket<User>, channelName: string): Promise<boolean> {\n const subscription = this.#storage.get(socket.id, channelName)\n if (!subscription) {\n return false\n }\n\n this.#storage.delete(socket.id, channelName)\n\n if (this.#usesPresence(subscription.instance)) {\n await this.#withChannelOperation(`${socket.id}\\0${channelName}`, () =>\n this.#cleanupAfterLeave(socket, channelName, subscription)\n )\n } else {\n await this.#cleanupAfterLeave(socket, channelName, subscription)\n }\n\n return true\n }\n\n async #cleanupAfterLeave(\n socket: AuthenticatedSocket<User>,\n channelName: string,\n subscription: StoredChannelSubscription\n ): Promise<void> {\n if (this.#usesPresence(subscription.instance)) {\n const presenceUser = this.presenceManager!.getLocalUser(channelName, socket.id)\n this.presenceManager!.leave(channelName, socket.raw)\n\n try {\n const presenceData = await this.presenceManager!.snapshot(channelName)\n\n this.socketService\n .to(channelName)\n .emit('presence:update', ChannelSubscriptions.#serializePresenceData(presenceData))\n\n if (presenceUser && !presenceData.users.some((user) => user.id === presenceUser.id)) {\n const { joinedAt: _joinedAt, ...member } = presenceUser\n await subscription.instance.onMemberLeave?.(socket, member, ...subscription.paramValues)\n }\n } catch (error) {\n this.#warn(`failed to update presence while leaving channel \"${channelName}\": %s`, error)\n }\n }\n\n try {\n await subscription.instance.onLeave?.(socket, ...subscription.paramValues)\n } catch (error) {\n this.#warn(`failed to leave channel \"${channelName}\": %s`, error)\n }\n }\n\n async leaveAll(socket: AuthenticatedSocket<User>): Promise<void> {\n for (const channelName of this.#storage.channelNamesFor(socket.id)) {\n await this.leave(socket, channelName)\n }\n }\n\n async handleMessage(\n socket: AuthenticatedSocket<User>,\n payload: ChannelMessage\n ): Promise<ChannelAck> {\n const subscription = this.#storage.get(socket.id, payload.channel)\n\n if (!subscription) {\n return { ok: false, error: 'Not subscribed' }\n }\n\n try {\n const result = await subscription.instance.$handleMessage(socket, payload.event, payload.data)\n\n try {\n JSON.stringify(result)\n } catch (error) {\n this.#warn(\n `failed to serialize handler response for channel \"${payload.channel}\": %s`,\n error\n )\n return { ok: false, error: 'Handler response is not serializable' }\n }\n\n return { ok: true, data: result }\n } catch (error) {\n if (!(error instanceof SocketResponseError)) {\n this.#warn(`channel handler failed for \"${payload.channel}\": %s`, error)\n }\n\n return {\n ok: false,\n error: error instanceof SocketResponseError ? error.message : 'Handler error',\n }\n }\n }\n\n relayWhisper(socket: AuthenticatedSocket<User>, payload: ChannelMessage): ChannelAck {\n if (!this.#storage.has(socket.id, payload.channel)) {\n return { ok: false, error: 'Not subscribed' }\n }\n\n this.socketService\n .to(payload.channel)\n .except(socket.id)\n .emit(`client:${payload.event}`, payload.data)\n\n return { ok: true }\n }\n\n deleteSocket(socketId: string): void {\n this.#storage.deleteSocket(socketId)\n }\n\n clear(): void {\n this.#storage.clear()\n this.#channelOperations.clear()\n }\n\n getSocketIds(channelName: string): string[] {\n return this.#storage.socketIdsFor(channelName)\n }\n\n subscriptionCountFor(socketId: string): number {\n return this.#storage.countForSocket(socketId)\n }\n\n get channelsCount(): number {\n return this.#storage.channelsCount\n }\n\n #warn(message: string, error: unknown): void {\n try {\n this.logger.warn(message, error)\n } catch {\n // Logging must never change the socket protocol outcome.\n }\n }\n\n async #withChannelOperation<Result>(\n operationKey: string,\n operation: () => Promise<Result>\n ): Promise<Result> {\n const previous = this.#channelOperations.get(operationKey) ?? Promise.resolve()\n const release = Promise.withResolvers<void>()\n const queued = previous.then(() => release.promise)\n this.#channelOperations.set(operationKey, queued)\n\n await previous\n try {\n return await operation()\n } finally {\n release.resolve()\n if (this.#channelOperations.get(operationKey) === queued) {\n this.#channelOperations.delete(operationKey)\n }\n }\n }\n\n #usesPresence(instance: BaseChannel<any, any>): boolean {\n return Boolean(\n (instance.constructor as typeof BaseChannel).options?.presence && this.presenceManager\n )\n }\n\n async #refreshExistingSubscription(\n socket: AuthenticatedSocket<User>,\n channelName: string\n ): Promise<ChannelSubscribeResult | null> {\n if (!this.#storage.has(socket.id, channelName)) {\n return null\n }\n\n let presenceData: PresenceData | undefined\n\n try {\n presenceData = await this.#getPresenceData(socket, channelName)\n } catch (error) {\n this.#warn(`failed to refresh subscription for channel \"${channelName}\": %s`, error)\n return {\n ack: { ok: false, error: 'Subscribe failed' },\n created: false,\n }\n }\n\n try {\n JSON.stringify(presenceData)\n } catch (error) {\n this.#warn(\n `failed to serialize subscription response for channel \"${channelName}\": %s`,\n error\n )\n return {\n ack: { ok: false, error: 'Subscription response is not serializable' },\n created: false,\n }\n }\n\n return {\n ack: {\n ok: true,\n presenceData,\n },\n created: false,\n }\n }\n\n async #getPresenceData(\n socket: AuthenticatedSocket<User>,\n channelName: string\n ): Promise<PresenceData | undefined> {\n if (!this.presenceManager?.hasLocal(channelName, socket.id)) {\n return undefined\n }\n\n return this.presenceManager.snapshot(channelName)\n }\n}\n","import type { ChannelAck, ServerProtocolMessage } from '../shared_types.js'\nimport type { ChannelSubscribeResult } from '../channel_subscriptions.js'\n\nconst INVALID_SOCKET_MESSAGE = 'Invalid socket message'\n\nexport class Reply {\n #id: string | undefined\n #ack: ChannelAck\n\n private constructor(id: string | undefined, ack: ChannelAck) {\n this.#id = id\n this.#ack = ack\n }\n\n static ok(id: string | undefined, data?: unknown): Reply {\n return new Reply(id, { ok: true, data })\n }\n\n static error(id: string | undefined, error: string): Reply {\n return new Reply(id, { ok: false, error })\n }\n\n static invalidMessage(id: string | undefined): ServerProtocolMessage {\n if (id === undefined) {\n return { type: 'error', error: INVALID_SOCKET_MESSAGE }\n }\n\n return Reply.error(id, INVALID_SOCKET_MESSAGE).toFrame()\n }\n\n static fromSubscribeResult(\n id: string | undefined,\n result: ChannelSubscribeResult | undefined\n ): Reply {\n if (!result) {\n return Reply.error(id, 'Socket service is not initialized')\n }\n\n if (!result.ack.ok) {\n return Reply.error(id, result.ack.error)\n }\n\n const data = result.ack.presenceData\n ? {\n presenceData: result.ack.presenceData,\n }\n : undefined\n\n return Reply.ok(id, data)\n }\n\n static fromChannelAck(id: string | undefined, ack: ChannelAck): Reply {\n return ack.ok ? Reply.ok(id, ack.data) : Reply.error(id, ack.error)\n }\n\n toFrame(): Extract<ServerProtocolMessage, { type: 'ack' }> {\n if (!this.#ack.ok) {\n return {\n id: this.#id,\n type: 'ack',\n ok: false,\n error: this.#ack.error,\n }\n }\n\n return this.#ack.data === undefined\n ? { id: this.#id, type: 'ack', ok: true }\n : { id: this.#id, type: 'ack', ok: true, data: this.#ack.data }\n }\n}\n","import type {\n ChannelMessage,\n ClientProtocolMessage,\n ServerProtocolMessage,\n} from '../shared_types.js'\nimport { Reply } from './reply.js'\n\ntype ClientMessageType = ClientProtocolMessage['type']\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nexport abstract class Message {\n abstract readonly valid: boolean\n abstract readonly type: ClientMessageType | 'invalid'\n\n static fromTransport(raw: string): TransportMessage {\n try {\n return Message.fromParsedTransport(JSON.parse(raw))\n } catch {\n return new InvalidMessage(undefined)\n }\n }\n\n private static fromParsedTransport(value: unknown): TransportMessage {\n if (!isRecord(value)) {\n return new InvalidMessage(undefined)\n }\n\n const id = typeof value.id === 'string' ? value.id : undefined\n\n if ('id' in value && typeof value.id !== 'string') {\n return new InvalidMessage(undefined)\n }\n\n if (!isClientMessageType(value.type)) {\n return new InvalidMessage(id)\n }\n\n if (value.type === 'ping') {\n return new PingMessage(id)\n }\n\n if (value.type === 'subscribe' && typeof value.channel === 'string') {\n return new SubscribeMessage(id, value.channel)\n }\n\n if (value.type === 'unsubscribe' && typeof value.channel === 'string') {\n return new UnsubscribeMessage(id, value.channel)\n }\n\n if (\n (value.type === 'message' || value.type === 'whisper') &&\n typeof value.channel === 'string' &&\n typeof value.event === 'string'\n ) {\n return new ChannelProtocolMessage(id, value.type, value.channel, value.event, value.data)\n }\n\n return new InvalidMessage(id)\n }\n}\n\nexport class InvalidMessage extends Message {\n readonly valid = false\n readonly type = 'invalid'\n\n constructor(readonly id: string | undefined) {\n super()\n }\n\n toRejectionFrame(): ServerProtocolMessage {\n return Reply.invalidMessage(this.id)\n }\n}\n\nexport class PingMessage extends Message {\n readonly valid = true\n readonly type = 'ping'\n\n constructor(readonly id: string | undefined) {\n super()\n }\n}\n\nexport class SubscribeMessage extends Message {\n readonly valid = true\n readonly type = 'subscribe'\n\n constructor(\n readonly id: string | undefined,\n readonly channel: string\n ) {\n super()\n }\n}\n\nexport class UnsubscribeMessage extends Message {\n readonly valid = true\n readonly type = 'unsubscribe'\n\n constructor(\n readonly id: string | undefined,\n readonly channel: string\n ) {\n super()\n }\n}\n\nexport class ChannelProtocolMessage extends Message {\n readonly valid = true\n\n constructor(\n readonly id: string | undefined,\n readonly type: 'message' | 'whisper',\n readonly channel: string,\n readonly event: string,\n readonly data: unknown\n ) {\n super()\n }\n\n toChannelMessage(): ChannelMessage {\n return {\n channel: this.channel,\n event: this.event,\n data: this.data,\n }\n }\n}\n\nexport type TransportMessage =\n | InvalidMessage\n | PingMessage\n | SubscribeMessage\n | UnsubscribeMessage\n | ChannelProtocolMessage\n\nfunction isClientMessageType(value: unknown): value is ClientMessageType {\n return (\n value === 'ping' ||\n value === 'subscribe' ||\n value === 'unsubscribe' ||\n value === 'message' ||\n value === 'whisper'\n )\n}\n","export class MessageQueue<Key = string> {\n #queues = new Map<Key, Promise<void>>()\n #depths = new Map<Key, number>()\n\n enqueue(key: Key, task: () => Promise<void>, options: { maxDepth?: number } = {}): boolean {\n const depth = this.#depths.get(key) ?? 0\n\n if (options.maxDepth !== undefined && depth >= options.maxDepth) {\n return false\n }\n\n this.#depths.set(key, depth + 1)\n\n const previous = this.#queues.get(key) ?? Promise.resolve()\n const next = previous\n .catch(() => {})\n .then(task)\n .catch(() => {})\n .finally(() => {\n const nextDepth = (this.#depths.get(key) ?? 1) - 1\n\n if (nextDepth <= 0) {\n this.#depths.delete(key)\n } else {\n this.#depths.set(key, nextDepth)\n }\n\n if (this.#queues.get(key) === next) {\n this.#queues.delete(key)\n }\n })\n\n this.#queues.set(key, next)\n return true\n }\n\n drain(key: Key): Promise<void> {\n return this.#queues.get(key) ?? Promise.resolve()\n }\n\n delete(key: Key): void {\n this.#queues.delete(key)\n this.#depths.delete(key)\n }\n\n clear(): void {\n this.#queues.clear()\n this.#depths.clear()\n }\n}\n","import { randomUUID } from 'node:crypto'\nimport { Bus } from '@boringnode/bus'\nimport type { Serializable, TransportFactory } from '@boringnode/bus/types/main'\nimport type { PresenceSocket } from './presence_manager.js'\nimport { PresenceSocketFrame, type SerializablePresenceSocket } from './presence_socket_frame.js'\nimport { parseDuration, type Duration } from './duration.js'\n\nexport type { SerializablePresenceSocket } from './presence_socket_frame.js'\n\nconst DEFAULT_CHANNEL = 'socket::broadcast'\nconst DEFAULT_PRESENCE_TIMEOUT = 100\nexport const DEFAULT_RETRY_QUEUE_MAX_SIZE = 1000\n\ntype ChannelEventMessage = {\n [key: string]: Serializable\n type: 'channel:event'\n origin: string\n channel: string\n event: string\n data: Serializable\n except: string[]\n}\n\ntype BroadcastEventMessage = {\n [key: string]: Serializable\n type: 'broadcast:event'\n origin: string\n event: string\n data: Serializable\n}\n\ntype PresenceSocketsRequestMessage = {\n [key: string]: Serializable\n type: 'presence:sockets:request'\n origin: string\n requestId: string\n channel: string\n}\n\ntype PresenceSocketsResponseMessage = {\n [key: string]: Serializable\n type: 'presence:sockets:response'\n origin: string\n target: string\n requestId: string\n sockets: SerializablePresenceSocket[]\n}\n\nexport type SocketBusMessage =\n | ChannelEventMessage\n | BroadcastEventMessage\n | PresenceSocketsRequestMessage\n | PresenceSocketsResponseMessage\n\nexport interface SocketTransportConfig {\n driver: TransportFactory\n channel?: string\n /**\n * How long to wait for other instances to answer a presence snapshot request.\n */\n presenceTimeout?: Duration\n /**\n * In-memory retry policy for transport publications that fail.\n *\n * The queue is enabled and limited to 1000 distinct messages by default.\n * Set maxSize to null only when an unbounded queue is explicitly desired.\n */\n retryQueue?: SocketRetryQueueConfig\n}\n\nexport interface SocketRetryQueueConfig {\n enabled?: boolean\n removeDuplicates?: boolean\n maxSize?: number | null\n retryInterval?: Duration | false\n}\n\nfunction resolveRetryQueueConfig(config: SocketRetryQueueConfig | undefined) {\n const maxSize = config?.maxSize === undefined ? DEFAULT_RETRY_QUEUE_MAX_SIZE : config.maxSize\n\n if (maxSize !== null && (!Number.isSafeInteger(maxSize) || maxSize <= 0)) {\n throw new Error('transport.retryQueue.maxSize must be a positive integer or null')\n }\n\n return {\n enabled: true,\n maxSize,\n ...config,\n }\n}\n\ninterface SocketBusHandlers {\n channel(message: Extract<SocketBusMessage, { type: 'channel:event' }>): void\n broadcast(message: Extract<SocketBusMessage, { type: 'broadcast:event' }>): void\n presenceSockets(channel: string): SerializablePresenceSocket[]\n}\n\ninterface PendingPresenceRequest {\n sockets: PresenceSocketFrame[]\n resolve(sockets: PresenceSocket[]): void\n timeout: ReturnType<typeof setTimeout>\n}\n\ntype ParsedPresenceSocketsResponseMessage = {\n type: 'presence:sockets:response'\n origin: string\n target: string\n requestId: string\n sockets: PresenceSocketFrame[]\n}\n\ntype ParsedSocketBusMessage =\n | Exclude<SocketBusMessage, PresenceSocketsResponseMessage>\n | ParsedPresenceSocketsResponseMessage\n\nfunction parseBusMessage(payload: unknown): ParsedSocketBusMessage | null {\n if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {\n return null\n }\n\n const message = payload as Record<string, unknown>\n if (typeof message.origin !== 'string') {\n return null\n }\n\n switch (message.type) {\n case 'channel:event':\n return typeof message.channel === 'string' &&\n typeof message.event === 'string' &&\n Array.isArray(message.except) &&\n message.except.every((socketId) => typeof socketId === 'string')\n ? (message as ChannelEventMessage)\n : null\n case 'broadcast:event':\n return typeof message.event === 'string' ? (message as BroadcastEventMessage) : null\n case 'presence:sockets:request':\n return typeof message.requestId === 'string' && typeof message.channel === 'string'\n ? (message as PresenceSocketsRequestMessage)\n : null\n case 'presence:sockets:response':\n if (\n typeof message.target !== 'string' ||\n typeof message.requestId !== 'string' ||\n !Array.isArray(message.sockets)\n ) {\n return null\n }\n\n const sockets = Array.from(message.sockets, PresenceSocketFrame.fromTransport)\n return sockets.every((socket) => socket !== null)\n ? ({ ...message, sockets } as ParsedPresenceSocketsResponseMessage)\n : null\n default:\n return null\n }\n}\n\nexport class SocketBus {\n #origin = randomUUID()\n #channel: string\n #bus: Bus\n #presenceTimeout: number\n #pendingPresenceRequests = new Map<string, PendingPresenceRequest>()\n\n constructor(\n transport: SocketTransportConfig,\n private handlers: SocketBusHandlers\n ) {\n this.#channel = transport.channel ?? DEFAULT_CHANNEL\n this.#presenceTimeout =\n parseDuration('transport.presenceTimeout', transport.presenceTimeout) ??\n DEFAULT_PRESENCE_TIMEOUT\n this.#bus = new Bus(transport.driver(), {\n retryQueue: resolveRetryQueueConfig(transport.retryQueue),\n })\n }\n\n async start(): Promise<void> {\n await this.#bus.subscribe(this.#channel, (payload) => {\n try {\n const message = parseBusMessage(payload)\n if (!message || message.origin === this.#origin) {\n return\n }\n\n switch (message.type) {\n case 'channel:event':\n this.handlers.channel(message)\n return\n case 'broadcast:event':\n this.handlers.broadcast(message)\n return\n case 'presence:sockets:request':\n void this.#respondToPresenceRequest(message).catch(() => {})\n return\n case 'presence:sockets:response':\n this.#handlePresenceResponse(message)\n return\n }\n } catch {\n return\n }\n })\n }\n\n publishChannel(channel: string, event: string, data: unknown, except?: string[]): void {\n const message: SocketBusMessage = {\n type: 'channel:event',\n origin: this.#origin,\n channel,\n event,\n data: data as Serializable,\n except: except ?? [],\n }\n\n void this.#bus.publish(this.#channel, message)\n }\n\n publishBroadcast(event: string, data: unknown): void {\n const message: BroadcastEventMessage = {\n type: 'broadcast:event',\n origin: this.#origin,\n event,\n data: data as Serializable,\n }\n void this.#bus.publish(this.#channel, message)\n }\n\n fetchPresenceSockets(channel: string): Promise<PresenceSocket[]> {\n const requestId = randomUUID()\n\n return new Promise((resolve) => {\n const timeout = setTimeout(() => {\n const request = this.#pendingPresenceRequests.get(requestId)\n\n if (!request) {\n return\n }\n\n this.#pendingPresenceRequests.delete(requestId)\n resolve(request.sockets.map((socket) => socket.toSocket()))\n }, this.#presenceTimeout)\n\n this.#pendingPresenceRequests.set(requestId, {\n sockets: [],\n resolve,\n timeout,\n })\n\n const message: PresenceSocketsRequestMessage = {\n type: 'presence:sockets:request',\n origin: this.#origin,\n requestId,\n channel,\n }\n void this.#bus.publish(this.#channel, message)\n })\n }\n\n async close(): Promise<void> {\n for (const [requestId, request] of this.#pendingPresenceRequests) {\n clearTimeout(request.timeout)\n request.resolve(request.sockets.map((socket) => socket.toSocket()))\n this.#pendingPresenceRequests.delete(requestId)\n }\n\n await this.#bus.disconnect()\n }\n\n async #respondToPresenceRequest(\n message: Extract<SocketBusMessage, { type: 'presence:sockets:request' }>\n ): Promise<void> {\n const response: PresenceSocketsResponseMessage = {\n type: 'presence:sockets:response',\n origin: this.#origin,\n target: message.origin,\n requestId: message.requestId,\n sockets: this.handlers.presenceSockets(message.channel),\n }\n await this.#bus.publish(this.#channel, response as Serializable)\n }\n\n #handlePresenceResponse(message: ParsedPresenceSocketsResponseMessage): void {\n if (message.target !== this.#origin) {\n return\n }\n\n const request = this.#pendingPresenceRequests.get(message.requestId)\n\n if (!request) {\n return\n }\n\n request.sockets.push(...message.sockets)\n }\n}\n","import type { PresenceInfo } from './types.js'\n\nexport const PRESENCE_DATA_KEY = '__rlanzSocketPresence'\n\ntype PresenceSocketData = Record<string, unknown> & {\n [PRESENCE_DATA_KEY]?: Record<string, PresenceUser>\n}\n\nexport interface PresenceUser {\n id: string\n joinedAt: Date\n [key: string]: unknown\n}\n\nexport interface PresenceData {\n channel: string\n users: PresenceUser[]\n count: number\n}\n\nexport interface PresenceSocket {\n id: string\n data: PresenceSocketData\n}\n\n/**\n * Tracks user presence in channels.\n *\n * channel -> socketId -> PresenceUser\n */\nexport class PresenceManager {\n #presence = new Map<string, Map<string, PresenceUser>>()\n #fetchSockets: ((channel: string) => Promise<PresenceSocket[]>) | null = null\n\n /**\n * Sets the socket fetcher used to build distributed snapshots.\n */\n setSocketFetcher(fetchSockets: ((channel: string) => Promise<PresenceSocket[]>) | null): void {\n this.#fetchSockets = fetchSockets\n }\n\n /**\n * Adds a user to a channel.\n */\n join(channel: string, socket: PresenceSocket, member: PresenceInfo): PresenceUser {\n const user = {\n ...member.data,\n id: member.id,\n joinedAt: new Date(),\n }\n\n const users = this.#presence.get(channel) ?? new Map()\n users.set(socket.id, user)\n this.#presence.set(channel, users)\n this.#setSocketPresence(socket, channel, user)\n\n return user\n }\n\n /**\n * Removes a user from a channel.\n */\n leave(channel: string, socket: PresenceSocket): void {\n const channelPresence = this.#presence.get(channel)\n\n if (channelPresence) {\n channelPresence.delete(socket.id)\n\n if (channelPresence.size === 0) {\n this.#presence.delete(channel)\n }\n }\n\n this.#deleteSocketPresence(socket, channel)\n }\n\n /**\n * Removes a user from every channel.\n * Returns the list of channels the user left.\n */\n leaveAll(socket: PresenceSocket): string[] {\n const leftChannels: string[] = []\n\n for (const [channel, users] of this.#presence) {\n if (users.has(socket.id)) {\n users.delete(socket.id)\n leftChannels.push(channel)\n\n if (users.size === 0) {\n this.#presence.delete(channel)\n }\n\n this.#deleteSocketPresence(socket, channel)\n }\n }\n\n return leftChannels\n }\n\n /**\n * Gets presence data for a channel.\n */\n async snapshot(channel: string): Promise<PresenceData> {\n if (this.#fetchSockets) {\n return this.#getFromSockets(channel)\n }\n\n return this.#localSnapshot(channel)\n }\n\n /**\n * Gets the number of users in a channel.\n */\n async count(channel: string): Promise<number> {\n return (await this.snapshot(channel)).count\n }\n\n /**\n * Checks whether a socket is locally present in a channel.\n */\n hasLocal(channel: string, socketId: string): boolean {\n return this.#presence.get(channel)?.has(socketId) || false\n }\n\n /**\n * Gets the presence user retained for one local socket.\n */\n getLocalUser(channel: string, socketId: string): PresenceUser | undefined {\n return this.#presence.get(channel)?.get(socketId)\n }\n\n /**\n * Lists every local channel where a socket is present.\n */\n getLocalChannelsForSocket(socketId: string): string[] {\n const channels: string[] = []\n\n for (const [channel, users] of this.#presence) {\n if (users.has(socketId)) {\n channels.push(channel)\n }\n }\n\n return channels\n }\n\n /**\n * Lists sockets that are locally present in a channel.\n */\n getLocalSockets(channel: string): PresenceSocket[] {\n const users = this.#presence.get(channel)\n\n if (!users) {\n return []\n }\n\n return Array.from(users.entries()).map(([socketId, user]) => ({\n id: socketId,\n data: {\n [PRESENCE_DATA_KEY]: {\n [channel]: user,\n },\n },\n }))\n }\n\n #localSnapshot(channel: string): PresenceData {\n return this.#createSnapshot(channel, Array.from(this.#presence.get(channel)?.entries() ?? []))\n }\n\n async #getFromSockets(channel: string): Promise<PresenceData> {\n const sockets = await this.#fetchSockets!(channel)\n const users = sockets.flatMap((socket): Array<[string, PresenceUser]> => {\n const user = socket.data?.[PRESENCE_DATA_KEY]?.[channel]\n return user ? [[socket.id, user]] : []\n })\n\n return this.#createSnapshot(channel, users)\n }\n\n #createSnapshot(\n channel: string,\n connections: Array<[socketId: string, user: PresenceUser]>\n ): PresenceData {\n const usersById = new Map<string, [socketId: string, user: PresenceUser]>()\n\n for (const connection of connections) {\n const current = usersById.get(connection[1].id)\n if (!current || this.#compareConnections(connection, current) < 0) {\n usersById.set(connection[1].id, connection)\n }\n }\n\n const users = [...usersById.values()]\n .sort((left, right) => this.#compareConnections(left, right))\n .map(([, user]) => user)\n\n return {\n channel,\n users,\n count: users.length,\n }\n }\n\n #compareConnections(\n [leftSocketId, leftUser]: [string, PresenceUser],\n [rightSocketId, rightUser]: [string, PresenceUser]\n ): number {\n const joinedAtDifference = leftUser.joinedAt.getTime() - rightUser.joinedAt.getTime()\n return joinedAtDifference || leftSocketId.localeCompare(rightSocketId)\n }\n\n #setSocketPresence(socket: PresenceSocket, channel: string, user: PresenceUser): void {\n socket.data[PRESENCE_DATA_KEY] ??= {}\n socket.data[PRESENCE_DATA_KEY][channel] = user\n }\n\n #deleteSocketPresence(socket: PresenceSocket, channel: string): void {\n if (!socket.data[PRESENCE_DATA_KEY]) {\n return\n }\n\n delete socket.data[PRESENCE_DATA_KEY][channel]\n\n if (Object.keys(socket.data[PRESENCE_DATA_KEY]).length === 0) {\n delete socket.data[PRESENCE_DATA_KEY]\n }\n }\n}\n","import type { Serializable } from '@boringnode/bus/types/main'\nimport { PRESENCE_DATA_KEY, type PresenceSocket, type PresenceUser } from './presence_manager.js'\n\ntype SerializablePresenceUser = {\n [key: string]: Serializable\n id: string\n joinedAt: string\n}\n\nexport interface SerializablePresenceSocket {\n [key: string]: Serializable\n id: string\n data: {\n [key: string]: Serializable\n }\n}\n\n/**\n * Transport representation of one socket participating in distributed presence.\n */\nexport class PresenceSocketFrame {\n private constructor(\n private readonly transportValue: SerializablePresenceSocket,\n private readonly socketValue: PresenceSocket\n ) {}\n\n /**\n * Create one transport frame from a local socket presence entry.\n */\n static fromSocket(channel: string, socket: PresenceSocket): PresenceSocketFrame {\n const user = socket.data[PRESENCE_DATA_KEY]?.[channel]\n if (!user || Number.isNaN(user.joinedAt.getTime())) {\n throw new Error(`Socket \"${socket.id}\" has no valid presence for channel \"${channel}\"`)\n }\n\n const transport: SerializablePresenceSocket = {\n id: socket.id,\n data: {\n [PRESENCE_DATA_KEY]: {\n [channel]: {\n // Keep custom fields. Convert only the presence timestamp.\n ...user,\n joinedAt: user.joinedAt.toISOString(),\n } as SerializablePresenceUser,\n },\n },\n }\n\n return new PresenceSocketFrame(transport, socket)\n }\n\n /**\n * Validate one transport value and restore its presence timestamps.\n */\n static fromTransport(value: unknown): PresenceSocketFrame | null {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return null\n }\n\n const transport = value as Record<string, unknown>\n\n // A valid frame needs a socket ID and one object for socket data.\n if (\n typeof transport.id !== 'string' ||\n !transport.data ||\n typeof transport.data !== 'object' ||\n Array.isArray(transport.data)\n ) {\n return null\n }\n\n const data = transport.data as Record<string, unknown>\n const presence = data[PRESENCE_DATA_KEY]\n\n // A socket can have no presence entries.\n if (presence === undefined) {\n return new PresenceSocketFrame(transport as SerializablePresenceSocket, {\n id: transport.id,\n data: { ...data },\n })\n }\n if (!presence || typeof presence !== 'object' || Array.isArray(presence)) {\n return null\n }\n\n // Validate all members before this frame becomes a PresenceSocket.\n const restoredPresence: Record<string, PresenceUser> = {}\n for (const [channel, candidate] of Object.entries(presence)) {\n if (!candidate || typeof candidate !== 'object' || Array.isArray(candidate)) {\n return null\n }\n\n const user = candidate as Record<string, unknown>\n if (\n typeof user.id !== 'string' ||\n typeof user.joinedAt !== 'string' ||\n Number.isNaN(Date.parse(user.joinedAt))\n ) {\n return null\n }\n\n // Keep custom fields. Restore only the presence timestamp.\n restoredPresence[channel] = {\n ...user,\n id: user.id,\n joinedAt: new Date(user.joinedAt),\n }\n }\n\n return new PresenceSocketFrame(transport as SerializablePresenceSocket, {\n id: transport.id,\n data: {\n ...data,\n [PRESENCE_DATA_KEY]: restoredPresence,\n },\n })\n }\n\n /**\n * Return the validated transport value.\n */\n toTransport(): SerializablePresenceSocket {\n return this.transportValue\n }\n\n /**\n * Return the socket value with restored presence timestamps.\n */\n toSocket(): PresenceSocket {\n return this.socketValue\n }\n}\n","import { parse as parseDurationExpression } from '@lukeed/ms'\n\n/**\n * Duration can be specified as milliseconds or as a human-readable string.\n */\nexport type Duration = number | string\n\nexport function parseDuration(name: string, duration: Duration | undefined): number | undefined {\n if (duration === undefined) {\n return undefined\n }\n\n const milliseconds = typeof duration === 'number' ? duration : parseDurationExpression(duration)\n\n if (typeof milliseconds === 'undefined' || !Number.isFinite(milliseconds) || milliseconds <= 0) {\n throw new Error(`${name} must be a positive duration`)\n }\n\n return milliseconds\n}\n","import type { IncomingMessage } from 'node:http'\nimport type { Duplex } from 'node:stream'\nimport type { WebSocket, WebSocketServer } from 'ws'\nimport type { HttpContext } from '@adonisjs/core/http'\nimport type { SocketConfig, SocketUpgradeContext } from './types.js'\n\nexport const DEFAULT_WEBSOCKET_PATH = '/socket'\n\nexport interface AcceptedUpgrade<User> {\n user?: User\n}\n\nexport type SocketUpgradeHandler = (request: IncomingMessage, socket: Duplex, head: Buffer) => void\n\ntype AcceptUpgrade<User> = (connection: WebSocket, upgrade: AcceptedUpgrade<User>) => void\n\nexport type SocketUpgradeContextRunner = <Result>(\n request: IncomingMessage,\n handler: (httpContext: HttpContext) => Promise<Result>,\n shortCircuitBeforeMiddleware?: (\n httpContext: HttpContext\n ) => Result | undefined | Promise<Result | undefined>\n) => Promise<Result>\n\ntype UpgradeResult<User> =\n | { accepted: AcceptedUpgrade<User> }\n | { rejected: 'authentication' | 'origin' }\n\nexport class SocketUpgrader<User = unknown> {\n #path: string\n\n constructor(\n private server: WebSocketServer,\n private config: SocketConfig<User>['websocket'] | undefined,\n private runWithHttpContext: SocketUpgradeContextRunner,\n private reportError: (message: string, error: unknown) => void = () => {}\n ) {\n this.#path = config?.path ?? DEFAULT_WEBSOCKET_PATH\n }\n\n async handle(\n request: IncomingMessage,\n socket: Duplex,\n head: Buffer,\n accept: AcceptUpgrade<User>\n ): Promise<boolean> {\n if (!this.#matchesPath(request)) {\n return false\n }\n\n const result = await this.#prepareUpgrade(request)\n\n if ('rejected' in result) {\n if (result.rejected === 'origin') {\n SocketUpgrader.reject(socket, 403, 'Forbidden')\n return true\n }\n\n SocketUpgrader.reject(socket, 401, 'Unauthorized')\n return true\n }\n\n this.server.handleUpgrade(request, socket, head, (connection) => {\n accept(connection, result.accepted)\n })\n\n return true\n }\n\n static reject(socket: Duplex, statusCode: number, reason: string): void {\n if (!socket.writableEnded) {\n socket.write(`HTTP/1.1 ${statusCode} ${reason}\\r\\n\\r\\n`)\n }\n\n socket.destroy()\n }\n\n #matchesPath(request: IncomingMessage): boolean {\n const url = new URL(request.url ?? '/', 'ws://localhost')\n return url.pathname === this.#path\n }\n\n #isOriginAllowed(request: IncomingMessage, httpContext: HttpContext): boolean {\n const origin = request.headers.origin\n if (!origin) {\n return true\n }\n\n if (this.config?.origin !== undefined) {\n return this.#matchesOriginPolicy(origin, httpContext)\n }\n\n const host = request.headers.host\n if (!host) {\n return false\n }\n\n const forwardedHeader = request.headers['x-forwarded-proto']\n const forwardedProtocol = (\n Array.isArray(forwardedHeader) ? forwardedHeader[0] : forwardedHeader\n )\n ?.split(',')[0]\n ?.trim()\n const protocol =\n forwardedProtocol === 'http' || forwardedProtocol === 'https'\n ? forwardedProtocol\n : (request.socket as typeof request.socket & { encrypted?: boolean }).encrypted\n ? 'https'\n : 'http'\n\n try {\n return origin === new URL(`${protocol}://${host}`).origin\n } catch {\n return false\n }\n }\n\n #matchesOriginPolicy(origin: string, httpContext: HttpContext): boolean {\n let originPolicy = this.config?.origin ?? false\n\n if (typeof originPolicy === 'function') {\n originPolicy = originPolicy(origin, httpContext)\n }\n\n if (originPolicy === true || originPolicy === '*') {\n return true\n }\n\n if (originPolicy === false) {\n return false\n }\n\n if (Array.isArray(originPolicy)) {\n return originPolicy.includes(origin)\n }\n\n return originPolicy.split(',').includes(origin)\n }\n\n async #prepareUpgrade(request: IncomingMessage): Promise<UpgradeResult<User>> {\n return this.runWithHttpContext<UpgradeResult<User>>(\n request,\n async (httpContext) => {\n const accepted = await this.#authenticate(httpContext)\n return accepted ? { accepted } : { rejected: 'authentication' }\n },\n (httpContext) => {\n return this.#isOriginAllowed(request, httpContext) ? undefined : { rejected: 'origin' }\n }\n )\n }\n\n async #authenticate(httpContext: HttpContext): Promise<AcceptedUpgrade<User> | null> {\n const config = this.config\n if (!config?.authenticate) {\n return {}\n }\n\n try {\n const ctx: SocketUpgradeContext = {\n httpContext,\n }\n\n const result = await config.authenticate(ctx)\n\n if (result === false || result === null || result === undefined) {\n return null\n }\n\n return {\n user: result,\n }\n } catch (error) {\n try {\n this.reportError('socket authentication failed: %s', error)\n } catch {\n // Error reporting must never change an authentication rejection.\n }\n return null\n }\n }\n}\n","import type { BaseChannelConstructor } from './base_channel.js'\nimport { ChannelPatternSyntax } from './channel_pattern_syntax.js'\n\ntype MatchParams = Record<string, string>\n\nexport interface ChannelPatternMatch {\n pattern: ChannelPattern\n channel: BaseChannelConstructor\n params: MatchParams\n}\n\ninterface MatchCandidate {\n pattern: ChannelPattern\n channel: BaseChannelConstructor\n}\n\nexport class ChannelPattern {\n private readonly syntax: ChannelPatternSyntax\n\n private constructor(readonly value: string) {\n this.syntax = ChannelPatternSyntax.from(value)\n }\n\n /**\n * Parse one runtime channel pattern.\n */\n static from(value: string): ChannelPattern {\n return new ChannelPattern(value)\n }\n\n /**\n * Match one concrete channel name.\n */\n match(channelName: string): MatchParams | null {\n return this.syntax.match(channelName)\n }\n\n /**\n * Return the most specific matching candidate. Static segments have the highest score.\n * Parameters score above optional parameters. Wildcards have the lowest score.\n * Insertion order is preserved for ties.\n */\n static firstMatch(\n channelName: string,\n candidates: Iterable<MatchCandidate>\n ): ChannelPatternMatch | null {\n const sorted = [...candidates].sort((left, right) => {\n return ChannelPattern.#compareSpecificity(left.pattern, right.pattern)\n })\n const matched = ChannelPatternSyntax.firstMatch(\n sorted.map(({ pattern }) => pattern.syntax),\n channelName\n )\n if (!matched) return null\n\n const { pattern, channel } = sorted[matched.index]\n return { pattern, channel, params: matched.params }\n }\n\n static #compareSpecificity(left: ChannelPattern, right: ChannelPattern): number {\n return left.syntax.compareSpecificity(right.syntax)\n }\n}\n","import {\n SocketResponseError,\n type BaseChannel,\n type BaseChannelConstructor,\n type ChannelMiddlewareRunnerFactory,\n} from './base_channel.js'\nimport { ChannelPattern } from './channel_pattern.js'\nimport type { AuthenticatedSocket, ChannelMatch, MiddlewareContext } from './types.js'\n\ninterface RegisteredChannel {\n pattern: ChannelPattern\n channel: BaseChannelConstructor\n}\n\nexport type ChannelFactory = (\n channel: BaseChannelConstructor\n) => BaseChannel<any> | Promise<BaseChannel<any>>\n\n/**\n * Matches channel names against registered patterns.\n *\n * Pattern: chat/:roomId\n * Channel: chat/general\n *\n * chat / :roomId\n * | |\n * chat / general => { roomId: \"general\" }\n */\nexport class ChannelRouter {\n /**\n * Registered channels keyed by their pattern.\n */\n #channels = new Map<string, RegisteredChannel>()\n\n constructor(\n private makeChannel: ChannelFactory = (channel) => new channel(),\n private createMiddlewareRunner?: ChannelMiddlewareRunnerFactory\n ) {}\n\n /**\n * Registers a channel.\n */\n register(channel: BaseChannelConstructor): void {\n const patternValue = channel.pattern\n\n if (!patternValue) {\n throw new Error(`Channel ${channel.name} must define a static pattern`)\n }\n\n if (this.#channels.has(patternValue)) {\n throw new Error(`Channel pattern \"${patternValue}\" is already registered`)\n }\n\n const pattern = ChannelPattern.from(patternValue)\n\n this.#channels.set(pattern.value, { pattern, channel })\n }\n\n /**\n * Matches a channel name against registered patterns.\n */\n match(channelName: string): ChannelMatch | null {\n const matched = ChannelPattern.firstMatch(channelName, this.#channels.values())\n\n if (!matched) {\n return null\n }\n\n return {\n channel: matched.channel,\n pattern: matched.pattern.value,\n params: matched.params,\n }\n }\n\n /**\n * Authorizes a socket before it joins a channel.\n */\n async authorize<User = unknown>(socket: AuthenticatedSocket<User>, channelName: string) {\n const matched = this.match(channelName)\n\n if (!matched) {\n return {\n success: false,\n error: 'Channel not found',\n } as const\n }\n\n const instance = (await this.makeChannel(matched.channel)) as BaseChannel<User>\n const paramValues = Object.values(matched.params)\n\n const ctx: MiddlewareContext<User> = {\n socket,\n channel: channelName,\n params: matched.params,\n presenceData: undefined,\n setPresenceData(data) {\n ctx.presenceData = data\n },\n }\n\n // Run authorization middlewares.\n try {\n await instance.$runMiddlewares(ctx, this.createMiddlewareRunner?.())\n } catch (error) {\n return {\n success: false,\n error: error instanceof SocketResponseError ? error.message : 'Authorization failed',\n cause: error,\n } as const\n }\n\n return {\n success: true,\n instance,\n params: matched.params,\n paramValues,\n presenceData: ctx.presenceData ?? null,\n } as const\n }\n\n /**\n * Lists all registered channels.\n */\n list() {\n return [...this.#channels.values()].map(({ pattern, channel }) => ({\n pattern: pattern.value,\n name: channel.name,\n options: channel.options,\n }))\n }\n\n /**\n * Number of registered channels.\n */\n get size(): number {\n return this.#channels.size\n }\n}\n"],"mappings":"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","names":["randomUUID","randomUUID","pattern"]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { S as SocketService } from '../socket_service-
|
|
1
|
+
import { S as SocketService } from '../socket_service-to3tlbrV.js';
|
|
2
2
|
import 'node:http';
|
|
3
3
|
import '@adonisjs/logger';
|
|
4
4
|
import 'emittery';
|
|
5
5
|
import 'ws';
|
|
6
|
-
import '../base_channel-
|
|
6
|
+
import '../base_channel-DFyd3hVE.js';
|
|
7
7
|
import '@adonisjs/core/types/http';
|
|
8
8
|
import '@adonisjs/core/http';
|
|
9
9
|
import '@boringnode/bus/types/main';
|
|
@@ -2,7 +2,7 @@ import { IncomingMessage, Server } from 'node:http';
|
|
|
2
2
|
import { Logger } from '@adonisjs/logger';
|
|
3
3
|
import Emittery from 'emittery';
|
|
4
4
|
import { WebSocketServer } from 'ws';
|
|
5
|
-
import { s as BaseChannelConstructor, B as BaseChannel, t as ChannelMiddlewareRunnerFactory, u as ChannelMatch, A as AuthenticatedSocket, v as PresenceData, C as ChannelOptions, i as SocketEvents, P as PresenceManager, a as SocketConfig, p as SocketServiceStatus, j as SocketHealthSnapshot } from './base_channel-
|
|
5
|
+
import { s as BaseChannelConstructor, B as BaseChannel, t as ChannelMiddlewareRunnerFactory, u as ChannelMatch, A as AuthenticatedSocket, v as PresenceData, C as ChannelOptions, i as SocketEvents, P as PresenceManager, a as SocketConfig, p as SocketServiceStatus, j as SocketHealthSnapshot } from './base_channel-DFyd3hVE.js';
|
|
6
6
|
import { HttpContext } from '@adonisjs/core/http';
|
|
7
7
|
import { SocketFake } from './src/testing.js';
|
|
8
8
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { A as AuthenticatedSocket } from '../base_channel-
|
|
1
|
+
import { A as AuthenticatedSocket } from '../base_channel-DFyd3hVE.js';
|
|
2
2
|
import 'ws';
|
|
3
|
-
import 'node:http';
|
|
4
3
|
import '@adonisjs/core/types/http';
|
|
5
4
|
import '@adonisjs/core/http';
|
|
6
5
|
import '@boringnode/bus/types/main';
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { BaseCheck, Result } from '@adonisjs/core/health';
|
|
2
|
-
import { S as SocketService } from '../socket_service-
|
|
2
|
+
import { S as SocketService } from '../socket_service-to3tlbrV.js';
|
|
3
3
|
import 'node:http';
|
|
4
4
|
import '@adonisjs/logger';
|
|
5
5
|
import 'emittery';
|
|
6
6
|
import 'ws';
|
|
7
|
-
import '../base_channel-
|
|
7
|
+
import '../base_channel-DFyd3hVE.js';
|
|
8
8
|
import '@adonisjs/core/types/http';
|
|
9
9
|
import '@adonisjs/core/http';
|
|
10
10
|
import '@boringnode/bus/types/main';
|
package/build/src/otel.js
CHANGED
|
@@ -20,7 +20,7 @@ import { InstrumentationBase } from "@opentelemetry/instrumentation";
|
|
|
20
20
|
// package.json
|
|
21
21
|
var package_default = {
|
|
22
22
|
name: "@rlanz/socket",
|
|
23
|
-
version: "0.
|
|
23
|
+
version: "0.2.0",
|
|
24
24
|
description: "WebSocket integration for AdonisJS",
|
|
25
25
|
type: "module",
|
|
26
26
|
main: "./build/index.js",
|
package/build/src/otel.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/otel.ts","../../package.json"],"sourcesContent":["import {\n context,\n SpanKind,\n SpanStatusCode,\n trace,\n type Counter,\n type Span,\n type UpDownCounter,\n} from '@opentelemetry/api'\nimport type { TracingChannelSubscribers } from 'node:diagnostics_channel'\nimport { InstrumentationBase } from '@opentelemetry/instrumentation'\nimport type { InstrumentationConfig } from '@opentelemetry/instrumentation'\nimport packageJson from '../package.json' with { type: 'json' }\nimport {\n broadcastChannel,\n channelMessageChannel,\n connectChannel,\n disconnectChannel,\n subscribeChannel,\n setTracingOperationRunner,\n unsubscribeChannel,\n} from './tracing_channels.js'\nimport type {\n SocketBroadcastMessage,\n SocketChannelMessage,\n SocketConnectMessage,\n SocketDisconnectMessage,\n SocketSubscribeMessage,\n SocketUnsubscribeMessage,\n} from './types/tracing_channels.js'\n\nexport interface SocketInstrumentationConfig extends InstrumentationConfig {\n /**\n * The messaging system identifier.\n *\n * @default '@rlanz/socket'\n */\n messagingSystem?: string\n}\n\ntype AttributeValue = string | number | boolean\n\nexport class SocketInstrumentation extends InstrumentationBase<SocketInstrumentationConfig> {\n protected subscribed = false\n protected spans = new WeakMap<object, Span>()\n protected connectHandlers?: TracingChannelSubscribers<SocketConnectMessage>\n protected disconnectHandlers?: TracingChannelSubscribers<SocketDisconnectMessage>\n protected subscribeHandlers?: TracingChannelSubscribers<SocketSubscribeMessage>\n protected unsubscribeHandlers?: TracingChannelSubscribers<SocketUnsubscribeMessage>\n protected messageHandlers?: TracingChannelSubscribers<SocketChannelMessage>\n protected broadcastHandlers?: TracingChannelSubscribers<SocketBroadcastMessage>\n\n #connectionCounter!: Counter\n #disconnectionCounter!: Counter\n #activeConnections!: UpDownCounter\n #subscriptionCounter!: Counter\n #activeSubscriptions!: UpDownCounter\n #messageCounter!: Counter\n #broadcastCounter!: Counter\n #broadcastDeliveryCounter!: Counter\n\n constructor(config: SocketInstrumentationConfig = {}) {\n super('@rlanz/socket', packageJson.version, config)\n this._updateMetricInstruments()\n if (this.isEnabled()) this.enable()\n }\n\n get #messagingSystem(): string {\n return this.getConfig().messagingSystem ?? '@rlanz/socket'\n }\n\n protected init() {\n return undefined\n }\n\n protected _updateMetricInstruments() {\n if (this.subscribed === undefined) return\n\n this.#connectionCounter = this.meter.createCounter('rlanz_socket_connections_total', {\n description: 'Total number of accepted socket connections',\n })\n this.#disconnectionCounter = this.meter.createCounter('rlanz_socket_disconnections_total', {\n description: 'Total number of closed socket connections',\n })\n this.#activeConnections = this.meter.createUpDownCounter('rlanz_socket_connections_active', {\n description: 'Number of currently active socket connections',\n })\n this.#subscriptionCounter = this.meter.createCounter('rlanz_socket_subscriptions_total', {\n description: 'Total number of successful channel subscriptions',\n })\n this.#activeSubscriptions = this.meter.createUpDownCounter(\n 'rlanz_socket_subscriptions_active',\n { description: 'Number of currently active channel subscriptions' }\n )\n this.#messageCounter = this.meter.createCounter('rlanz_socket_messages_total', {\n description: 'Total number of channel messages received from clients',\n })\n this.#broadcastCounter = this.meter.createCounter('rlanz_socket_broadcasts_total', {\n description: 'Total number of broadcast operations',\n })\n this.#broadcastDeliveryCounter = this.meter.createCounter(\n 'rlanz_socket_broadcast_deliveries_total',\n { description: 'Total number of socket deliveries made by broadcast operations' }\n )\n }\n\n enable() {\n super.enable()\n // `InstrumentationBase` calls `enable()` from its constructor, before this\n // subclass's fields and private methods are installed on the instance.\n // During that premature call `this.subscribed` is still `undefined`, so the\n // guard prevents calling `#subscribe()` on a not-yet-branded instance.\n if (this.subscribed !== undefined) this.#subscribe()\n }\n\n disable() {\n if (this.subscribed !== undefined) this.#unsubscribe()\n super.disable()\n }\n\n manuallyRegister() {\n this.#subscribe()\n }\n\n #subscribe() {\n if (this.subscribed) return\n if (!this.isEnabled()) return\n\n this.subscribed = true\n\n this.connectHandlers = {\n start: (message) =>\n this.#startSpan(message, 'socket connect', SpanKind.SERVER, {\n 'network.transport': 'websocket',\n }),\n end: (message) => this.#handleConnectEnd(message),\n asyncStart: () => {},\n asyncEnd: () => {},\n error: (message) => this.#recordError(message),\n }\n\n this.disconnectHandlers = {\n start: (message) =>\n this.#startSpan(message, 'socket disconnect', SpanKind.INTERNAL, {\n 'socket.disconnect.reason': message.reason,\n 'socket.disconnect.subscriptions': message.subscriptions ?? 0,\n }),\n end: () => {},\n asyncStart: () => {},\n asyncEnd: (message) => this.#handleDisconnectEnd(message),\n error: (message) => this.#recordError(message),\n }\n\n this.subscribeHandlers = {\n start: (message) =>\n this.#startSpan(message, `socket subscribe ${message.channel}`, SpanKind.SERVER, {\n 'messaging.destination.name': message.channel,\n 'messaging.operation.name': 'subscribe',\n 'messaging.operation.type': 'receive',\n }),\n end: () => {},\n asyncStart: () => {},\n asyncEnd: (message) => this.#handleSubscribeEnd(message),\n error: (message) => this.#recordError(message),\n }\n\n this.unsubscribeHandlers = {\n start: (message) =>\n this.#startSpan(message, `socket unsubscribe ${message.channel}`, SpanKind.SERVER, {\n 'messaging.destination.name': message.channel,\n 'messaging.operation.name': 'unsubscribe',\n 'messaging.operation.type': 'receive',\n }),\n end: () => {},\n asyncStart: () => {},\n asyncEnd: (message) => this.#handleUnsubscribeEnd(message),\n error: (message) => this.#recordError(message),\n }\n\n this.messageHandlers = {\n start: (message) =>\n this.#startSpan(message, `socket message ${message.channel}`, SpanKind.SERVER, {\n 'messaging.destination.name': message.channel,\n 'messaging.operation.name': 'process',\n 'messaging.operation.type': 'receive',\n 'messaging.event.name': message.event,\n }),\n end: () => {},\n asyncStart: () => {},\n asyncEnd: (message) => this.#handleMessageEnd(message),\n error: (message) => this.#recordError(message),\n }\n\n this.broadcastHandlers = {\n start: (message) =>\n this.#startSpan(message, `socket broadcast ${message.target}`, SpanKind.PRODUCER, {\n ...this.#broadcastAttributes(message),\n }),\n end: (message) => this.#handleBroadcastEnd(message),\n asyncStart: () => {},\n asyncEnd: () => {},\n error: (message) => this.#recordError(message),\n }\n\n connectChannel.subscribe(this.connectHandlers)\n disconnectChannel.subscribe(this.disconnectHandlers)\n subscribeChannel.subscribe(this.subscribeHandlers)\n unsubscribeChannel.subscribe(this.unsubscribeHandlers)\n channelMessageChannel.subscribe(this.messageHandlers)\n broadcastChannel.subscribe(this.broadcastHandlers)\n }\n\n #unsubscribe() {\n if (!this.subscribed) return\n\n if (this.connectHandlers) connectChannel.unsubscribe(this.connectHandlers)\n if (this.disconnectHandlers) disconnectChannel.unsubscribe(this.disconnectHandlers)\n if (this.subscribeHandlers) subscribeChannel.unsubscribe(this.subscribeHandlers)\n if (this.unsubscribeHandlers) unsubscribeChannel.unsubscribe(this.unsubscribeHandlers)\n if (this.messageHandlers) channelMessageChannel.unsubscribe(this.messageHandlers)\n if (this.broadcastHandlers) broadcastChannel.unsubscribe(this.broadcastHandlers)\n\n this.subscribed = false\n this.spans = new WeakMap()\n }\n\n #startSpan(\n message: object,\n name: string,\n kind: SpanKind,\n attributes: Record<string, AttributeValue> = {}\n ) {\n const span = this.tracer.startSpan(name, {\n kind,\n attributes: {\n 'messaging.system': this.#messagingSystem,\n ...attributes,\n },\n })\n\n this.spans.set(message, span)\n const spanContext = trace.setSpan(context.active(), span)\n setTracingOperationRunner(message, (operation) => context.with(spanContext, operation))\n }\n\n #handleDisconnectEnd(message: SocketDisconnectMessage) {\n this.#disconnectionCounter.add(1, { 'socket.disconnect.reason': message.reason })\n this.#activeConnections.add(-1)\n if (message.subscriptions) {\n this.#activeSubscriptions.add(-message.subscriptions)\n }\n\n this.#endSpan(message)\n }\n\n #handleConnectEnd(message: SocketConnectMessage) {\n this.#connectionCounter.add(1)\n this.#activeConnections.add(1)\n this.#endSpan(message)\n }\n\n #handleSubscribeEnd(message: SocketSubscribeMessage) {\n const attributes = {\n 'messaging.destination.name': message.channel,\n 'socket.subscription.created': Boolean(message.created),\n }\n\n if (message.ok) {\n this.#subscriptionCounter.add(1, attributes)\n if (message.created) this.#activeSubscriptions.add(1, attributes)\n }\n\n this.#endSpanWithOutcome(message, attributes)\n }\n\n #handleUnsubscribeEnd(message: SocketUnsubscribeMessage) {\n const attributes = {\n 'messaging.destination.name': message.channel,\n 'socket.subscription.removed': Boolean(message.removed),\n }\n\n if (message.ok && message.removed) {\n this.#activeSubscriptions.add(-1, attributes)\n }\n\n this.#endSpanWithOutcome(message, attributes)\n }\n\n #handleMessageEnd(message: SocketChannelMessage) {\n const attributes = {\n 'messaging.destination.name': message.channel,\n 'messaging.event.name': message.event,\n }\n\n this.#messageCounter.add(1, {\n ...attributes,\n 'socket.message.ok': Boolean(message.ok),\n })\n\n this.#endSpanWithOutcome(message, attributes)\n }\n\n #handleBroadcastEnd(message: SocketBroadcastMessage) {\n const attributes = this.#broadcastAttributes(message)\n\n this.#broadcastCounter.add(1, attributes)\n if (message.delivered !== undefined) {\n this.#broadcastDeliveryCounter.add(message.delivered, attributes)\n }\n\n this.#endSpan(message, {\n ...attributes,\n ...(message.delivered !== undefined\n ? { 'socket.broadcast.delivered': message.delivered }\n : {}),\n })\n }\n\n #recordError(message: object & { error: unknown }) {\n const span = this.spans.get(message)\n if (!span) return\n\n if (message.error instanceof Error) {\n span.recordException(message.error)\n span.setStatus({ code: SpanStatusCode.ERROR, message: message.error.message })\n } else {\n span.setStatus({ code: SpanStatusCode.ERROR })\n }\n\n span.end()\n this.spans.delete(message)\n }\n\n #endSpanWithOutcome(\n message: SocketSubscribeMessage | SocketUnsubscribeMessage | SocketChannelMessage,\n attributes: Record<string, AttributeValue>\n ) {\n this.#endSpan(message, attributes, message)\n }\n\n #endSpan(\n message: object,\n attributes: Record<string, AttributeValue> = {},\n outcome?: { ok?: boolean; error?: string }\n ) {\n const span = this.spans.get(message)\n if (!span) return\n\n span.setAttributes(attributes)\n\n if (outcome?.ok === false) {\n span.setStatus({ code: SpanStatusCode.ERROR, message: outcome.error })\n if (outcome.error) {\n span.setAttribute('error.type', outcome.error)\n }\n } else {\n span.setStatus({ code: SpanStatusCode.OK })\n }\n\n span.end()\n this.spans.delete(message)\n }\n\n #broadcastAttributes(message: SocketBroadcastMessage): Record<string, AttributeValue> {\n const attributes: Record<string, AttributeValue> = {\n 'messaging.operation.name': 'publish',\n 'messaging.operation.type': 'send',\n 'messaging.event.name': message.event,\n 'socket.broadcast.target': message.target,\n 'socket.broadcast.via': message.via,\n }\n\n if (message.channel) attributes['messaging.destination.name'] = message.channel\n if (message.except) attributes['socket.broadcast.except_count'] = message.except.length\n\n return attributes\n }\n}\n","{\n \"name\": \"@rlanz/socket\",\n \"version\": \"0.1.1\",\n \"description\": \"WebSocket integration for AdonisJS\",\n \"type\": \"module\",\n \"main\": \"./build/index.js\",\n \"types\": \"./build/index.d.ts\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=24.0.0\"\n },\n \"packageManager\": \"yarn@4.18.0\",\n \"files\": [\n \"build\"\n ],\n \"exports\": {\n \".\": \"./build/index.js\",\n \"./provider\": \"./build/providers/socket_provider.js\",\n \"./assembler_hook\": \"./build/src/assembler_hook.js\",\n \"./services/main\": \"./build/services/socket.js\",\n \"./decorators\": \"./build/src/decorators.js\",\n \"./health_check\": \"./build/src/health_check.js\",\n \"./otel\": \"./build/src/otel.js\",\n \"./testing\": \"./build/src/testing.js\",\n \"./types\": \"./build/src/types.js\",\n \"./types/tracing_channels\": \"./build/src/types/tracing_channels.js\",\n \"./client\": \"./build/src/client/index.js\",\n \"./client/types\": \"./build/src/client/types.js\",\n \"./client/react\": \"./build/src/client/react.js\",\n \"./client/vue\": \"./build/src/client/vue.js\"\n },\n \"scripts\": {\n \"build\": \"npm run compile\",\n \"clean\": \"del-cli build\",\n \"compile\": \"npm run clean && tsup-node\",\n \"lint\": \"oxlint\",\n \"lint:fix\": \"oxlint --fix\",\n \"format\": \"oxfmt --check .\",\n \"format:fix\": \"oxfmt --write .\",\n \"prepublishOnly\": \"npm run build\",\n \"release\": \"release-it\",\n \"test\": \"node --import=@poppinss/ts-exec --enable-source-maps bin/test.ts\",\n \"typecheck\": \"tsc --noEmit\",\n \"version\": \"npm run build\"\n },\n \"dependencies\": {\n \"@boringnode/bus\": \"^0.9.1\",\n \"@lukeed/ms\": \"^2.0.2\",\n \"emittery\": \"^1.2.0\",\n \"ws\": \"^8.21.0\"\n },\n \"devDependencies\": {\n \"@adonisjs/assembler\": \"^8.0.0\",\n \"@adonisjs/core\": \"^7.0.1\",\n \"@adonisjs/tsconfig\": \"^2.0.0\",\n \"@japa/assert\": \"^4.2.0\",\n \"@japa/runner\": \"^5.3.0\",\n \"@opentelemetry/api\": \"^1.9.1\",\n \"@opentelemetry/context-async-hooks\": \"^2.7.1\",\n \"@opentelemetry/core\": \"^2.7.1\",\n \"@opentelemetry/instrumentation\": \"^0.218.0\",\n \"@opentelemetry/sdk-metrics\": \"^2.7.1\",\n \"@opentelemetry/sdk-trace-base\": \"^2.7.1\",\n \"@poppinss/ts-exec\": \"^1.4.4\",\n \"@release-it/conventional-changelog\": \"^12.0.0\",\n \"@types/node\": \"^24.0.0\",\n \"@types/react\": \"^19.1.9\",\n \"@types/react-test-renderer\": \"^19.1.0\",\n \"@types/scheduler\": \"^0\",\n \"@types/ws\": \"^8.18.1\",\n \"del-cli\": \"^7.0.0\",\n \"oxfmt\": \"^0.38.0\",\n \"oxlint\": \"^1.53.0\",\n \"react\": \"^19.1.1\",\n \"react-test-renderer\": \"^19.1.1\",\n \"reflect-metadata\": \"^0.2.2\",\n \"release-it\": \"^19.2.4\",\n \"scheduler\": \"^0.27.0\",\n \"tsup\": \"^8.5.1\",\n \"typescript\": \"^5.9.3\",\n \"vue\": \"^3.5.18\"\n },\n \"peerDependencies\": {\n \"@adonisjs/assembler\": \"^8.0.0\",\n \"@adonisjs/core\": \"^7.0.1\",\n \"@opentelemetry/api\": \"^1.9.0\",\n \"@opentelemetry/instrumentation\": \"^0.200.0\",\n \"react\": \"^18.0.0 || ^19.0.0\",\n \"typescript\": \"^5.9.0 || ^6.0.0\",\n \"vue\": \"^3.3.0\"\n },\n \"peerDependenciesMeta\": {\n \"@adonisjs/assembler\": {\n \"optional\": true\n },\n \"@opentelemetry/api\": {\n \"optional\": true\n },\n \"@opentelemetry/instrumentation\": {\n \"optional\": true\n },\n \"react\": {\n \"optional\": true\n },\n \"typescript\": {\n \"optional\": true\n },\n \"vue\": {\n \"optional\": true\n }\n },\n \"keywords\": [\n \"adonisjs\",\n \"adonis\",\n \"websocket\",\n \"realtime\"\n ],\n \"homepage\": \"https://github.com/rlanz/socket#readme\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/RomainLanz/socket\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/rlanz/socket/issues\"\n },\n \"author\": \"Romain Lanz <romain.lanz@pm.me>\",\n \"publishConfig\": {\n \"access\": \"public\",\n \"tag\": \"latest\",\n \"provenance\": true\n },\n \"release-it\": {\n \"git\": {\n \"requireCleanWorkingDir\": true,\n \"requireUpstream\": true,\n \"commitMessage\": \"chore(release): ${version}\",\n \"tagAnnotation\": \"v${version}\",\n \"push\": true,\n \"tagName\": \"v${version}\"\n },\n \"github\": {\n \"release\": true,\n \"releaseName\": \"v${version}\"\n },\n \"npm\": {\n \"publish\": true,\n \"skipChecks\": true\n },\n \"plugins\": {\n \"@release-it/conventional-changelog\": {\n \"preset\": {\n \"name\": \"angular\"\n }\n }\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/otel.ts","../../package.json"],"sourcesContent":["import {\n context,\n SpanKind,\n SpanStatusCode,\n trace,\n type Counter,\n type Span,\n type UpDownCounter,\n} from '@opentelemetry/api'\nimport type { TracingChannelSubscribers } from 'node:diagnostics_channel'\nimport { InstrumentationBase } from '@opentelemetry/instrumentation'\nimport type { InstrumentationConfig } from '@opentelemetry/instrumentation'\nimport packageJson from '../package.json' with { type: 'json' }\nimport {\n broadcastChannel,\n channelMessageChannel,\n connectChannel,\n disconnectChannel,\n subscribeChannel,\n setTracingOperationRunner,\n unsubscribeChannel,\n} from './tracing_channels.js'\nimport type {\n SocketBroadcastMessage,\n SocketChannelMessage,\n SocketConnectMessage,\n SocketDisconnectMessage,\n SocketSubscribeMessage,\n SocketUnsubscribeMessage,\n} from './types/tracing_channels.js'\n\nexport interface SocketInstrumentationConfig extends InstrumentationConfig {\n /**\n * The messaging system identifier.\n *\n * @default '@rlanz/socket'\n */\n messagingSystem?: string\n}\n\ntype AttributeValue = string | number | boolean\n\nexport class SocketInstrumentation extends InstrumentationBase<SocketInstrumentationConfig> {\n protected subscribed = false\n protected spans = new WeakMap<object, Span>()\n protected connectHandlers?: TracingChannelSubscribers<SocketConnectMessage>\n protected disconnectHandlers?: TracingChannelSubscribers<SocketDisconnectMessage>\n protected subscribeHandlers?: TracingChannelSubscribers<SocketSubscribeMessage>\n protected unsubscribeHandlers?: TracingChannelSubscribers<SocketUnsubscribeMessage>\n protected messageHandlers?: TracingChannelSubscribers<SocketChannelMessage>\n protected broadcastHandlers?: TracingChannelSubscribers<SocketBroadcastMessage>\n\n #connectionCounter!: Counter\n #disconnectionCounter!: Counter\n #activeConnections!: UpDownCounter\n #subscriptionCounter!: Counter\n #activeSubscriptions!: UpDownCounter\n #messageCounter!: Counter\n #broadcastCounter!: Counter\n #broadcastDeliveryCounter!: Counter\n\n constructor(config: SocketInstrumentationConfig = {}) {\n super('@rlanz/socket', packageJson.version, config)\n this._updateMetricInstruments()\n if (this.isEnabled()) this.enable()\n }\n\n get #messagingSystem(): string {\n return this.getConfig().messagingSystem ?? '@rlanz/socket'\n }\n\n protected init() {\n return undefined\n }\n\n protected _updateMetricInstruments() {\n if (this.subscribed === undefined) return\n\n this.#connectionCounter = this.meter.createCounter('rlanz_socket_connections_total', {\n description: 'Total number of accepted socket connections',\n })\n this.#disconnectionCounter = this.meter.createCounter('rlanz_socket_disconnections_total', {\n description: 'Total number of closed socket connections',\n })\n this.#activeConnections = this.meter.createUpDownCounter('rlanz_socket_connections_active', {\n description: 'Number of currently active socket connections',\n })\n this.#subscriptionCounter = this.meter.createCounter('rlanz_socket_subscriptions_total', {\n description: 'Total number of successful channel subscriptions',\n })\n this.#activeSubscriptions = this.meter.createUpDownCounter(\n 'rlanz_socket_subscriptions_active',\n { description: 'Number of currently active channel subscriptions' }\n )\n this.#messageCounter = this.meter.createCounter('rlanz_socket_messages_total', {\n description: 'Total number of channel messages received from clients',\n })\n this.#broadcastCounter = this.meter.createCounter('rlanz_socket_broadcasts_total', {\n description: 'Total number of broadcast operations',\n })\n this.#broadcastDeliveryCounter = this.meter.createCounter(\n 'rlanz_socket_broadcast_deliveries_total',\n { description: 'Total number of socket deliveries made by broadcast operations' }\n )\n }\n\n enable() {\n super.enable()\n // `InstrumentationBase` calls `enable()` from its constructor, before this\n // subclass's fields and private methods are installed on the instance.\n // During that premature call `this.subscribed` is still `undefined`, so the\n // guard prevents calling `#subscribe()` on a not-yet-branded instance.\n if (this.subscribed !== undefined) this.#subscribe()\n }\n\n disable() {\n if (this.subscribed !== undefined) this.#unsubscribe()\n super.disable()\n }\n\n manuallyRegister() {\n this.#subscribe()\n }\n\n #subscribe() {\n if (this.subscribed) return\n if (!this.isEnabled()) return\n\n this.subscribed = true\n\n this.connectHandlers = {\n start: (message) =>\n this.#startSpan(message, 'socket connect', SpanKind.SERVER, {\n 'network.transport': 'websocket',\n }),\n end: (message) => this.#handleConnectEnd(message),\n asyncStart: () => {},\n asyncEnd: () => {},\n error: (message) => this.#recordError(message),\n }\n\n this.disconnectHandlers = {\n start: (message) =>\n this.#startSpan(message, 'socket disconnect', SpanKind.INTERNAL, {\n 'socket.disconnect.reason': message.reason,\n 'socket.disconnect.subscriptions': message.subscriptions ?? 0,\n }),\n end: () => {},\n asyncStart: () => {},\n asyncEnd: (message) => this.#handleDisconnectEnd(message),\n error: (message) => this.#recordError(message),\n }\n\n this.subscribeHandlers = {\n start: (message) =>\n this.#startSpan(message, `socket subscribe ${message.channel}`, SpanKind.SERVER, {\n 'messaging.destination.name': message.channel,\n 'messaging.operation.name': 'subscribe',\n 'messaging.operation.type': 'receive',\n }),\n end: () => {},\n asyncStart: () => {},\n asyncEnd: (message) => this.#handleSubscribeEnd(message),\n error: (message) => this.#recordError(message),\n }\n\n this.unsubscribeHandlers = {\n start: (message) =>\n this.#startSpan(message, `socket unsubscribe ${message.channel}`, SpanKind.SERVER, {\n 'messaging.destination.name': message.channel,\n 'messaging.operation.name': 'unsubscribe',\n 'messaging.operation.type': 'receive',\n }),\n end: () => {},\n asyncStart: () => {},\n asyncEnd: (message) => this.#handleUnsubscribeEnd(message),\n error: (message) => this.#recordError(message),\n }\n\n this.messageHandlers = {\n start: (message) =>\n this.#startSpan(message, `socket message ${message.channel}`, SpanKind.SERVER, {\n 'messaging.destination.name': message.channel,\n 'messaging.operation.name': 'process',\n 'messaging.operation.type': 'receive',\n 'messaging.event.name': message.event,\n }),\n end: () => {},\n asyncStart: () => {},\n asyncEnd: (message) => this.#handleMessageEnd(message),\n error: (message) => this.#recordError(message),\n }\n\n this.broadcastHandlers = {\n start: (message) =>\n this.#startSpan(message, `socket broadcast ${message.target}`, SpanKind.PRODUCER, {\n ...this.#broadcastAttributes(message),\n }),\n end: (message) => this.#handleBroadcastEnd(message),\n asyncStart: () => {},\n asyncEnd: () => {},\n error: (message) => this.#recordError(message),\n }\n\n connectChannel.subscribe(this.connectHandlers)\n disconnectChannel.subscribe(this.disconnectHandlers)\n subscribeChannel.subscribe(this.subscribeHandlers)\n unsubscribeChannel.subscribe(this.unsubscribeHandlers)\n channelMessageChannel.subscribe(this.messageHandlers)\n broadcastChannel.subscribe(this.broadcastHandlers)\n }\n\n #unsubscribe() {\n if (!this.subscribed) return\n\n if (this.connectHandlers) connectChannel.unsubscribe(this.connectHandlers)\n if (this.disconnectHandlers) disconnectChannel.unsubscribe(this.disconnectHandlers)\n if (this.subscribeHandlers) subscribeChannel.unsubscribe(this.subscribeHandlers)\n if (this.unsubscribeHandlers) unsubscribeChannel.unsubscribe(this.unsubscribeHandlers)\n if (this.messageHandlers) channelMessageChannel.unsubscribe(this.messageHandlers)\n if (this.broadcastHandlers) broadcastChannel.unsubscribe(this.broadcastHandlers)\n\n this.subscribed = false\n this.spans = new WeakMap()\n }\n\n #startSpan(\n message: object,\n name: string,\n kind: SpanKind,\n attributes: Record<string, AttributeValue> = {}\n ) {\n const span = this.tracer.startSpan(name, {\n kind,\n attributes: {\n 'messaging.system': this.#messagingSystem,\n ...attributes,\n },\n })\n\n this.spans.set(message, span)\n const spanContext = trace.setSpan(context.active(), span)\n setTracingOperationRunner(message, (operation) => context.with(spanContext, operation))\n }\n\n #handleDisconnectEnd(message: SocketDisconnectMessage) {\n this.#disconnectionCounter.add(1, { 'socket.disconnect.reason': message.reason })\n this.#activeConnections.add(-1)\n if (message.subscriptions) {\n this.#activeSubscriptions.add(-message.subscriptions)\n }\n\n this.#endSpan(message)\n }\n\n #handleConnectEnd(message: SocketConnectMessage) {\n this.#connectionCounter.add(1)\n this.#activeConnections.add(1)\n this.#endSpan(message)\n }\n\n #handleSubscribeEnd(message: SocketSubscribeMessage) {\n const attributes = {\n 'messaging.destination.name': message.channel,\n 'socket.subscription.created': Boolean(message.created),\n }\n\n if (message.ok) {\n this.#subscriptionCounter.add(1, attributes)\n if (message.created) this.#activeSubscriptions.add(1, attributes)\n }\n\n this.#endSpanWithOutcome(message, attributes)\n }\n\n #handleUnsubscribeEnd(message: SocketUnsubscribeMessage) {\n const attributes = {\n 'messaging.destination.name': message.channel,\n 'socket.subscription.removed': Boolean(message.removed),\n }\n\n if (message.ok && message.removed) {\n this.#activeSubscriptions.add(-1, attributes)\n }\n\n this.#endSpanWithOutcome(message, attributes)\n }\n\n #handleMessageEnd(message: SocketChannelMessage) {\n const attributes = {\n 'messaging.destination.name': message.channel,\n 'messaging.event.name': message.event,\n }\n\n this.#messageCounter.add(1, {\n ...attributes,\n 'socket.message.ok': Boolean(message.ok),\n })\n\n this.#endSpanWithOutcome(message, attributes)\n }\n\n #handleBroadcastEnd(message: SocketBroadcastMessage) {\n const attributes = this.#broadcastAttributes(message)\n\n this.#broadcastCounter.add(1, attributes)\n if (message.delivered !== undefined) {\n this.#broadcastDeliveryCounter.add(message.delivered, attributes)\n }\n\n this.#endSpan(message, {\n ...attributes,\n ...(message.delivered !== undefined\n ? { 'socket.broadcast.delivered': message.delivered }\n : {}),\n })\n }\n\n #recordError(message: object & { error: unknown }) {\n const span = this.spans.get(message)\n if (!span) return\n\n if (message.error instanceof Error) {\n span.recordException(message.error)\n span.setStatus({ code: SpanStatusCode.ERROR, message: message.error.message })\n } else {\n span.setStatus({ code: SpanStatusCode.ERROR })\n }\n\n span.end()\n this.spans.delete(message)\n }\n\n #endSpanWithOutcome(\n message: SocketSubscribeMessage | SocketUnsubscribeMessage | SocketChannelMessage,\n attributes: Record<string, AttributeValue>\n ) {\n this.#endSpan(message, attributes, message)\n }\n\n #endSpan(\n message: object,\n attributes: Record<string, AttributeValue> = {},\n outcome?: { ok?: boolean; error?: string }\n ) {\n const span = this.spans.get(message)\n if (!span) return\n\n span.setAttributes(attributes)\n\n if (outcome?.ok === false) {\n span.setStatus({ code: SpanStatusCode.ERROR, message: outcome.error })\n if (outcome.error) {\n span.setAttribute('error.type', outcome.error)\n }\n } else {\n span.setStatus({ code: SpanStatusCode.OK })\n }\n\n span.end()\n this.spans.delete(message)\n }\n\n #broadcastAttributes(message: SocketBroadcastMessage): Record<string, AttributeValue> {\n const attributes: Record<string, AttributeValue> = {\n 'messaging.operation.name': 'publish',\n 'messaging.operation.type': 'send',\n 'messaging.event.name': message.event,\n 'socket.broadcast.target': message.target,\n 'socket.broadcast.via': message.via,\n }\n\n if (message.channel) attributes['messaging.destination.name'] = message.channel\n if (message.except) attributes['socket.broadcast.except_count'] = message.except.length\n\n return attributes\n }\n}\n","{\n \"name\": \"@rlanz/socket\",\n \"version\": \"0.2.0\",\n \"description\": \"WebSocket integration for AdonisJS\",\n \"type\": \"module\",\n \"main\": \"./build/index.js\",\n \"types\": \"./build/index.d.ts\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=24.0.0\"\n },\n \"packageManager\": \"yarn@4.18.0\",\n \"files\": [\n \"build\"\n ],\n \"exports\": {\n \".\": \"./build/index.js\",\n \"./provider\": \"./build/providers/socket_provider.js\",\n \"./assembler_hook\": \"./build/src/assembler_hook.js\",\n \"./services/main\": \"./build/services/socket.js\",\n \"./decorators\": \"./build/src/decorators.js\",\n \"./health_check\": \"./build/src/health_check.js\",\n \"./otel\": \"./build/src/otel.js\",\n \"./testing\": \"./build/src/testing.js\",\n \"./types\": \"./build/src/types.js\",\n \"./types/tracing_channels\": \"./build/src/types/tracing_channels.js\",\n \"./client\": \"./build/src/client/index.js\",\n \"./client/types\": \"./build/src/client/types.js\",\n \"./client/react\": \"./build/src/client/react.js\",\n \"./client/vue\": \"./build/src/client/vue.js\"\n },\n \"scripts\": {\n \"build\": \"npm run compile\",\n \"clean\": \"del-cli build\",\n \"compile\": \"npm run clean && tsup-node\",\n \"lint\": \"oxlint\",\n \"lint:fix\": \"oxlint --fix\",\n \"format\": \"oxfmt --check .\",\n \"format:fix\": \"oxfmt --write .\",\n \"prepublishOnly\": \"npm run build\",\n \"release\": \"release-it\",\n \"test\": \"node --import=@poppinss/ts-exec --enable-source-maps bin/test.ts\",\n \"typecheck\": \"tsc --noEmit\",\n \"version\": \"npm run build\"\n },\n \"dependencies\": {\n \"@boringnode/bus\": \"^0.9.1\",\n \"@lukeed/ms\": \"^2.0.2\",\n \"emittery\": \"^1.2.0\",\n \"ws\": \"^8.21.0\"\n },\n \"devDependencies\": {\n \"@adonisjs/assembler\": \"^8.0.0\",\n \"@adonisjs/core\": \"^7.0.1\",\n \"@adonisjs/tsconfig\": \"^2.0.0\",\n \"@japa/assert\": \"^4.2.0\",\n \"@japa/runner\": \"^5.3.0\",\n \"@opentelemetry/api\": \"^1.9.1\",\n \"@opentelemetry/context-async-hooks\": \"^2.7.1\",\n \"@opentelemetry/core\": \"^2.7.1\",\n \"@opentelemetry/instrumentation\": \"^0.218.0\",\n \"@opentelemetry/sdk-metrics\": \"^2.7.1\",\n \"@opentelemetry/sdk-trace-base\": \"^2.7.1\",\n \"@poppinss/ts-exec\": \"^1.4.4\",\n \"@release-it/conventional-changelog\": \"^12.0.0\",\n \"@types/node\": \"^24.0.0\",\n \"@types/react\": \"^19.1.9\",\n \"@types/react-test-renderer\": \"^19.1.0\",\n \"@types/scheduler\": \"^0\",\n \"@types/ws\": \"^8.18.1\",\n \"del-cli\": \"^7.0.0\",\n \"oxfmt\": \"^0.38.0\",\n \"oxlint\": \"^1.53.0\",\n \"react\": \"^19.1.1\",\n \"react-test-renderer\": \"^19.1.1\",\n \"reflect-metadata\": \"^0.2.2\",\n \"release-it\": \"^19.2.4\",\n \"scheduler\": \"^0.27.0\",\n \"tsup\": \"^8.5.1\",\n \"typescript\": \"^5.9.3\",\n \"vue\": \"^3.5.18\"\n },\n \"peerDependencies\": {\n \"@adonisjs/assembler\": \"^8.0.0\",\n \"@adonisjs/core\": \"^7.0.1\",\n \"@opentelemetry/api\": \"^1.9.0\",\n \"@opentelemetry/instrumentation\": \"^0.200.0\",\n \"react\": \"^18.0.0 || ^19.0.0\",\n \"typescript\": \"^5.9.0 || ^6.0.0\",\n \"vue\": \"^3.3.0\"\n },\n \"peerDependenciesMeta\": {\n \"@adonisjs/assembler\": {\n \"optional\": true\n },\n \"@opentelemetry/api\": {\n \"optional\": true\n },\n \"@opentelemetry/instrumentation\": {\n \"optional\": true\n },\n \"react\": {\n \"optional\": true\n },\n \"typescript\": {\n \"optional\": true\n },\n \"vue\": {\n \"optional\": true\n }\n },\n \"keywords\": [\n \"adonisjs\",\n \"adonis\",\n \"websocket\",\n \"realtime\"\n ],\n \"homepage\": \"https://github.com/rlanz/socket#readme\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/RomainLanz/socket\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/rlanz/socket/issues\"\n },\n \"author\": \"Romain Lanz <romain.lanz@pm.me>\",\n \"publishConfig\": {\n \"access\": \"public\",\n \"tag\": \"latest\",\n \"provenance\": true\n },\n \"release-it\": {\n \"git\": {\n \"requireCleanWorkingDir\": true,\n \"requireUpstream\": true,\n \"commitMessage\": \"chore(release): ${version}\",\n \"tagAnnotation\": \"v${version}\",\n \"push\": true,\n \"tagName\": \"v${version}\"\n },\n \"github\": {\n \"release\": true,\n \"releaseName\": \"v${version}\"\n },\n \"npm\": {\n \"publish\": true,\n \"skipChecks\": true\n },\n \"plugins\": {\n \"@release-it/conventional-changelog\": {\n \"preset\": {\n \"name\": \"angular\"\n }\n }\n }\n }\n}\n"],"mappings":"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","names":[]}
|
package/build/src/types.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
export { A as AuthenticatedSocket, u as ChannelMatch, C as ChannelOptions, D as Duration, M as Middleware, b as MiddlewareClass, c as MiddlewareConstructor, d as MiddlewareContext, e as MiddlewareFn, f as PresenceInfo, g as PresenceMember, R as RawSocket, S as SocketAuthenticationHandler, h as SocketAuthenticationResult, a as SocketConfig, i as SocketEvents, j as SocketHealthSnapshot, k as SocketHttpMiddleware, l as SocketOriginResolver, m as SocketOriginValues, o as SocketRetryQueueConfig, p as SocketServiceStatus, q as SocketTransportConfig, r as SocketUpgradeContext } from '../base_channel-
|
|
1
|
+
export { A as AuthenticatedSocket, u as ChannelMatch, C as ChannelOptions, D as Duration, M as Middleware, b as MiddlewareClass, c as MiddlewareConstructor, d as MiddlewareContext, e as MiddlewareFn, f as PresenceInfo, g as PresenceMember, R as RawSocket, S as SocketAuthenticationHandler, h as SocketAuthenticationResult, a as SocketConfig, i as SocketEvents, j as SocketHealthSnapshot, k as SocketHttpMiddleware, l as SocketOriginResolver, m as SocketOriginValues, o as SocketRetryQueueConfig, p as SocketServiceStatus, q as SocketTransportConfig, r as SocketUpgradeContext } from '../base_channel-DFyd3hVE.js';
|
|
2
2
|
import 'ws';
|
|
3
|
-
import 'node:http';
|
|
4
3
|
import '@adonisjs/core/types/http';
|
|
5
4
|
import '@adonisjs/core/http';
|
|
6
5
|
export { a as ChannelAck, b as ChannelMessage, C as ChannelServerEventsOf } from '../shared_types-B11CaOr5.js';
|