shardwire 0.0.1

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/transport/ws/consumer-socket.ts","../src/utils/id.ts","../src/utils/backoff.ts","../src/utils/logger.ts","../src/core/protocol.ts","../src/runtime/validation.ts","../src/consumer/index.ts","../src/discord/client.ts","../src/runtime/reliability.ts","../src/transport/ws/host-server.ts","../src/runtime/security.ts","../src/host/index.ts"],"sourcesContent":["import { createConsumerShardwire } from \"./consumer\";\nimport { resolveDiscordClient } from \"./discord/client\";\nimport { createHostShardwire } from \"./host\";\nimport { assertConsumerOptions, assertHostOptions } from \"./runtime/validation\";\nimport type {\n CommandMap,\n ConsumerOptions,\n ConsumerShardwire,\n EventMap,\n HostOptions,\n HostShardwire,\n} from \"./core/types\";\n\nfunction isHostOptions<C extends CommandMap, E extends EventMap>(\n options: HostOptions<C, E> | ConsumerOptions<C, E>,\n): options is HostOptions<C, E> {\n return \"server\" in options;\n}\n\nexport function createShardwire<C extends CommandMap = {}, E extends EventMap = {}>(\n options: HostOptions<C, E>,\n): HostShardwire<C, E>;\nexport function createShardwire<C extends CommandMap = {}, E extends EventMap = {}>(\n options: ConsumerOptions<C, E>,\n): ConsumerShardwire<C, E>;\nexport function createShardwire<C extends CommandMap = {}, E extends EventMap = {}>(\n options: HostOptions<C, E> | ConsumerOptions<C, E>,\n): HostShardwire<C, E> | ConsumerShardwire<C, E> {\n if (!isHostOptions(options)) {\n assertConsumerOptions(options);\n return createConsumerShardwire<C, E>(options);\n }\n assertHostOptions(options);\n\n let ownedClientPromise: Promise<{ destroy: () => void } | undefined> | undefined;\n\n if (!options.client && options.token) {\n ownedClientPromise = resolveDiscordClient(options)\n .then((state) => {\n if (!state.owned || !state.client) {\n return undefined;\n }\n return {\n destroy: () => state.client?.destroy(),\n };\n })\n .catch((error) => {\n options.logger?.error?.(\"Failed to initialize discord.js client from token.\", {\n error: String(error),\n });\n return undefined;\n });\n }\n\n return createHostShardwire<C, E>(options, {\n onClose: async () => {\n const owned = await ownedClientPromise;\n owned?.destroy();\n },\n });\n}\n\nexport type {\n CommandContext,\n CommandFailure,\n CommandMap,\n CommandResult,\n CommandSuccess,\n ConsumerOptions,\n ConsumerShardwire,\n DiscordClientLike,\n EventMap,\n EventMeta,\n HostOptions,\n HostShardwire,\n ShardwireLogger,\n Unsubscribe,\n} from \"./core/types\";\n","import { WebSocket } from \"ws\";\n\nexport interface WebSocketLike {\n readyState: number;\n send(data: string): void;\n close(code?: number, reason?: string): void;\n on(event: \"open\", listener: () => void): void;\n on(event: \"message\", listener: (data: unknown) => void): void;\n on(event: \"close\", listener: () => void): void;\n on(event: \"error\", listener: (error: unknown) => void): void;\n once(event: \"close\", listener: () => void): void;\n}\n\nexport function createNodeWebSocket(url: string): WebSocketLike {\n return new WebSocket(url) as unknown as WebSocketLike;\n}\n","import { randomUUID } from \"node:crypto\";\n\nexport function createRequestId(): string {\n return randomUUID();\n}\n\nexport function createConnectionId(): string {\n return randomUUID();\n}\n","export interface BackoffConfig {\n initialDelayMs: number;\n maxDelayMs: number;\n jitter: boolean;\n}\n\nexport function getBackoffDelay(attempt: number, config: BackoffConfig): number {\n const base = Math.min(config.maxDelayMs, config.initialDelayMs * 2 ** attempt);\n if (!config.jitter) {\n return base;\n }\n const spread = Math.floor(base * 0.2);\n const min = Math.max(0, base - spread);\n const max = base + spread;\n return Math.floor(Math.random() * (max - min + 1)) + min;\n}\n","import type { ShardwireLogger } from \"../core/types\";\n\nexport function withLogger(logger?: ShardwireLogger): Required<ShardwireLogger> {\n return {\n debug: logger?.debug ?? (() => undefined),\n info: logger?.info ?? (() => undefined),\n warn: logger?.warn ?? (() => undefined),\n error: logger?.error ?? (() => undefined),\n };\n}\n","import type { CommandResult } from \"./types\";\n\nexport const PROTOCOL_VERSION = 1 as const;\n\nexport type WireType =\n | \"auth.hello\"\n | \"auth.ok\"\n | \"auth.error\"\n | \"command.request\"\n | \"command.result\"\n | \"command.error\"\n | \"event.emit\"\n | \"ping\"\n | \"pong\";\n\nexport type WireEnvelope<TType extends WireType = WireType, TPayload = unknown> = {\n v: typeof PROTOCOL_VERSION;\n type: TType;\n ts: number;\n requestId?: string;\n source?: string;\n payload: TPayload;\n};\n\nexport interface AuthHelloPayload {\n secret: string;\n clientName?: string;\n}\n\nexport interface AuthOkPayload {\n connectionId: string;\n}\n\nexport interface AuthErrorPayload {\n code: \"AUTH_ERROR\";\n message: string;\n}\n\nexport interface CommandRequestPayload {\n name: string;\n data: unknown;\n}\n\nexport interface EventEmitPayload {\n name: string;\n data: unknown;\n}\n\nexport type CommandResultPayload = CommandResult;\n\nexport function makeEnvelope<TType extends WireType, TPayload>(\n type: TType,\n payload: TPayload,\n extras?: { requestId?: string; source?: string },\n): WireEnvelope<TType, TPayload> {\n const envelope: WireEnvelope<TType, TPayload> = {\n v: PROTOCOL_VERSION,\n type,\n ts: Date.now(),\n payload,\n };\n if (extras?.requestId) {\n envelope.requestId = extras.requestId;\n }\n if (extras?.source) {\n envelope.source = extras.source;\n }\n return envelope;\n}\n\nexport function parseEnvelope(raw: string): WireEnvelope {\n const parsed = JSON.parse(raw) as WireEnvelope;\n if (!parsed || parsed.v !== PROTOCOL_VERSION || typeof parsed.type !== \"string\") {\n throw new Error(\"Invalid wire envelope.\");\n }\n return parsed;\n}\n\nexport function stringifyEnvelope(envelope: WireEnvelope): string {\n return JSON.stringify(envelope);\n}\n","import type { ConsumerOptions, HostOptions } from \"../core/types\";\n\nfunction isNonEmptyString(value: unknown): value is string {\n return typeof value === \"string\" && value.trim().length > 0;\n}\n\nfunction assertPositiveNumber(name: string, value: unknown): void {\n if (typeof value !== \"number\" || Number.isNaN(value) || value <= 0) {\n throw new Error(`${name} must be a positive number.`);\n }\n}\n\nexport function assertHostOptions(options: HostOptions<any, any>): void {\n if (!options.server) {\n throw new Error(\"Host mode requires a server configuration.\");\n }\n assertPositiveNumber(\"server.port\", options.server.port);\n if (!isNonEmptyString(options.server.secret)) {\n throw new Error(\"server.secret is required.\");\n }\n if (options.server.heartbeatMs !== undefined) {\n assertPositiveNumber(\"server.heartbeatMs\", options.server.heartbeatMs);\n }\n if (options.server.commandTimeoutMs !== undefined) {\n assertPositiveNumber(\"server.commandTimeoutMs\", options.server.commandTimeoutMs);\n }\n if (options.server.maxPayloadBytes !== undefined) {\n assertPositiveNumber(\"server.maxPayloadBytes\", options.server.maxPayloadBytes);\n }\n}\n\nexport function assertConsumerOptions(options: ConsumerOptions<any, any>): void {\n if (!isNonEmptyString(options.url)) {\n throw new Error(\"Consumer mode requires `url`.\");\n }\n if (!isNonEmptyString(options.secret)) {\n throw new Error(\"Consumer mode requires `secret`.\");\n }\n if (options.requestTimeoutMs !== undefined) {\n assertPositiveNumber(\"requestTimeoutMs\", options.requestTimeoutMs);\n }\n if (options.reconnect?.initialDelayMs !== undefined) {\n assertPositiveNumber(\"reconnect.initialDelayMs\", options.reconnect.initialDelayMs);\n }\n if (options.reconnect?.maxDelayMs !== undefined) {\n assertPositiveNumber(\"reconnect.maxDelayMs\", options.reconnect.maxDelayMs);\n }\n}\n\nexport function assertMessageName(kind: \"command\" | \"event\", name: string): void {\n if (!isNonEmptyString(name)) {\n throw new Error(`${kind} name must be a non-empty string.`);\n }\n}\n\nexport function assertJsonPayload(kind: \"command\" | \"event\", name: string, payload: unknown): void {\n try {\n JSON.stringify(payload);\n } catch {\n throw new Error(`${kind} \"${name}\" payload must be JSON-serializable.`);\n }\n}\n","import type {\n CommandFailure,\n CommandMap,\n CommandResult,\n ConsumerOptions,\n ConsumerShardwire,\n EventMap,\n EventMeta,\n} from \"../core/types\";\nimport { createNodeWebSocket, type WebSocketLike } from \"../transport/ws/consumer-socket\";\nimport { createRequestId } from \"../utils/id\";\nimport { getBackoffDelay } from \"../utils/backoff\";\nimport { withLogger } from \"../utils/logger\";\nimport {\n makeEnvelope,\n parseEnvelope,\n stringifyEnvelope,\n type AuthErrorPayload,\n type CommandResultPayload,\n type EventEmitPayload,\n} from \"../core/protocol\";\nimport { assertJsonPayload, assertMessageName } from \"../runtime/validation\";\n\ntype EventHandler = (payload: unknown, meta: EventMeta) => void;\n\ninterface PendingRequest {\n resolve: (value: CommandResult) => void;\n reject: (error: Error) => void;\n timer: NodeJS.Timeout;\n}\n\nconst DEFAULT_REQUEST_TIMEOUT_MS = 10000;\n\nexport function createConsumerShardwire<C extends CommandMap, E extends EventMap>(\n options: ConsumerOptions<C, E>,\n): ConsumerShardwire<C, E> {\n const logger = withLogger(options.logger);\n const reconnectEnabled = options.reconnect?.enabled ?? true;\n const initialDelayMs = options.reconnect?.initialDelayMs ?? 500;\n const maxDelayMs = options.reconnect?.maxDelayMs ?? 10000;\n const jitter = options.reconnect?.jitter ?? true;\n const requestTimeoutMs = options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;\n\n let socket: WebSocketLike | null = null;\n let isClosed = false;\n let isAuthed = false;\n let reconnectAttempts = 0;\n let reconnectTimer: NodeJS.Timeout | null = null;\n let connectPromise: Promise<void> | null = null;\n let connectResolve: (() => void) | null = null;\n let connectReject: ((error: Error) => void) | null = null;\n let authTimeoutTimer: NodeJS.Timeout | null = null;\n\n const pendingRequests = new Map<string, PendingRequest>();\n const eventHandlers = new Map<string, Set<EventHandler>>();\n\n function clearAuthTimeout(): void {\n if (authTimeoutTimer) {\n clearTimeout(authTimeoutTimer);\n authTimeoutTimer = null;\n }\n }\n\n function resolveConnect(): void {\n clearAuthTimeout();\n connectResolve?.();\n connectResolve = null;\n connectReject = null;\n connectPromise = null;\n }\n\n function rejectConnect(message: string): void {\n clearAuthTimeout();\n if (connectReject) {\n connectReject(new Error(message));\n }\n connectResolve = null;\n connectReject = null;\n connectPromise = null;\n }\n\n function sendRaw(data: string): void {\n if (!socket || socket.readyState !== 1) {\n throw new Error(\"Shardwire consumer is not connected.\");\n }\n socket.send(data);\n }\n\n function rejectAllPending(reason: string): void {\n for (const [requestId, pending] of pendingRequests.entries()) {\n clearTimeout(pending.timer);\n pending.reject(new Error(reason));\n pendingRequests.delete(requestId);\n }\n }\n\n function scheduleReconnect(): void {\n if (isClosed || !reconnectEnabled || reconnectTimer) {\n return;\n }\n const delay = getBackoffDelay(reconnectAttempts, { initialDelayMs, maxDelayMs, jitter });\n reconnectAttempts += 1;\n reconnectTimer = setTimeout(() => {\n reconnectTimer = null;\n void connect().catch((error) => {\n logger.warn(\"Reconnect attempt failed.\", { error: String(error) });\n });\n }, delay);\n }\n\n function handleEvent(name: string, payload: unknown, meta: EventMeta): void {\n const handlers = eventHandlers.get(name);\n if (!handlers || handlers.size === 0) {\n return;\n }\n for (const handler of handlers) {\n try {\n handler(payload, meta);\n } catch (error) {\n logger.warn(\"Event handler threw an error.\", { name, error: String(error) });\n }\n }\n }\n\n async function connect(): Promise<void> {\n if (isClosed) {\n return;\n }\n if (socket && socket.readyState === 1 && isAuthed) {\n return;\n }\n if (connectPromise) {\n return connectPromise;\n }\n\n connectPromise = new Promise<void>((resolve, reject) => {\n connectResolve = resolve;\n connectReject = reject;\n });\n\n socket = options.webSocketFactory\n ? (options.webSocketFactory(options.url) as WebSocketLike)\n : createNodeWebSocket(options.url);\n\n socket.on(\"open\", () => {\n reconnectAttempts = 0;\n isAuthed = false;\n const hello = makeEnvelope(\"auth.hello\", { secret: options.secret });\n socket?.send(stringifyEnvelope(hello));\n authTimeoutTimer = setTimeout(() => {\n if (!isAuthed) {\n rejectConnect(\"Shardwire auth timed out.\");\n socket?.close();\n }\n }, requestTimeoutMs);\n });\n\n socket.on(\"message\", (raw) => {\n try {\n const serialized = typeof raw === \"string\" ? raw : String(raw);\n const envelope = parseEnvelope(serialized);\n switch (envelope.type) {\n case \"auth.ok\":\n isAuthed = true;\n resolveConnect();\n break;\n case \"auth.error\": {\n const payload = envelope.payload as AuthErrorPayload;\n logger.error(\"Authentication failed for consumer.\", {\n code: payload.code,\n message: payload.message,\n });\n rejectConnect(payload.message);\n rejectAllPending(\"Shardwire authentication failed.\");\n socket?.close();\n break;\n }\n case \"command.result\":\n case \"command.error\": {\n const requestId = envelope.requestId;\n if (!requestId) {\n return;\n }\n const pending = pendingRequests.get(requestId);\n if (!pending) {\n return;\n }\n clearTimeout(pending.timer);\n pending.resolve(envelope.payload as CommandResultPayload);\n pendingRequests.delete(requestId);\n break;\n }\n case \"event.emit\": {\n const payload = envelope.payload as EventEmitPayload;\n const meta: EventMeta = { ts: envelope.ts };\n if (envelope.source) {\n meta.source = envelope.source;\n }\n handleEvent(payload.name, payload.data, meta);\n break;\n }\n case \"ping\":\n sendRaw(stringifyEnvelope(makeEnvelope(\"pong\", {})));\n break;\n default:\n break;\n }\n } catch (error) {\n logger.warn(\"Failed to parse consumer message.\", { error: String(error) });\n }\n });\n\n socket.on(\"close\", () => {\n rejectConnect(\"Shardwire connection closed.\");\n isAuthed = false;\n if (!isClosed) {\n scheduleReconnect();\n }\n });\n\n socket.on(\"error\", (error) => {\n logger.warn(\"Consumer socket error.\", { error: String(error) });\n });\n\n return connectPromise;\n }\n\n void connect().catch((error) => {\n logger.warn(\"Initial connection attempt failed.\", { error: String(error) });\n });\n\n return {\n mode: \"consumer\",\n async send(name, payload, sendOptions) {\n assertMessageName(\"command\", name);\n assertJsonPayload(\"command\", name, payload);\n if (!isAuthed) {\n try {\n await connect();\n } catch (error) {\n return {\n ok: false,\n requestId: sendOptions?.requestId ?? \"unknown\",\n ts: Date.now(),\n error: {\n code: \"AUTH_ERROR\",\n message: error instanceof Error ? error.message : \"Failed to authenticate.\",\n },\n } satisfies CommandFailure;\n }\n }\n if (!socket || socket.readyState !== 1) {\n return {\n ok: false,\n requestId: sendOptions?.requestId ?? \"unknown\",\n ts: Date.now(),\n error: {\n code: \"TIMEOUT\",\n message: \"Not connected to Shardwire host.\",\n },\n } satisfies CommandFailure;\n }\n\n const requestId = sendOptions?.requestId ?? createRequestId();\n const timeoutMs = sendOptions?.timeoutMs ?? requestTimeoutMs;\n\n const promise = new Promise<CommandResult>((resolve, reject) => {\n const timer = setTimeout(() => {\n pendingRequests.delete(requestId);\n reject(new Error(`Command \"${name}\" timed out after ${timeoutMs}ms.`));\n }, timeoutMs);\n\n pendingRequests.set(requestId, { resolve, reject, timer });\n });\n\n sendRaw(\n stringifyEnvelope(\n makeEnvelope(\n \"command.request\",\n {\n name,\n data: payload,\n },\n { requestId },\n ),\n ),\n );\n\n try {\n return await promise;\n } catch (error) {\n return {\n ok: false,\n requestId,\n ts: Date.now(),\n error: {\n code: \"TIMEOUT\",\n message: error instanceof Error ? error.message : \"Command request timeout.\",\n },\n } satisfies CommandFailure;\n }\n },\n on(name, handler) {\n assertMessageName(\"event\", name);\n const casted = handler as EventHandler;\n const existing = eventHandlers.get(name);\n if (existing) {\n existing.add(casted);\n } else {\n eventHandlers.set(name, new Set<EventHandler>([casted]));\n }\n return () => {\n const handlers = eventHandlers.get(name);\n if (!handlers) {\n return;\n }\n handlers.delete(casted);\n if (handlers.size === 0) {\n eventHandlers.delete(name);\n }\n };\n },\n off(name, handler) {\n assertMessageName(\"event\", name);\n const handlers = eventHandlers.get(name);\n if (!handlers) {\n return;\n }\n handlers.delete(handler as EventHandler);\n if (handlers.size === 0) {\n eventHandlers.delete(name);\n }\n },\n connected() {\n return Boolean(socket && socket.readyState === 1 && isAuthed);\n },\n async close() {\n isClosed = true;\n isAuthed = false;\n rejectConnect(\"Shardwire consumer has been closed.\");\n if (reconnectTimer) {\n clearTimeout(reconnectTimer);\n reconnectTimer = null;\n }\n rejectAllPending(\"Shardwire consumer has been closed.\");\n if (!socket) {\n return;\n }\n await new Promise<void>((resolve) => {\n const current = socket;\n if (!current) {\n resolve();\n return;\n }\n current.once(\"close\", () => resolve());\n current.close();\n });\n socket = null;\n },\n };\n}\n","import type { DiscordClientLike, HostOptions } from \"../core/types\";\n\ninterface OwnedClientState {\n client?: DiscordClientLike;\n owned: boolean;\n}\n\nexport async function resolveDiscordClient<C extends Record<string, unknown>, E extends Record<string, unknown>>(\n options: HostOptions<C, E>,\n): Promise<OwnedClientState> {\n if (options.client) {\n return { client: options.client, owned: false };\n }\n\n if (!options.token) {\n return { owned: false };\n }\n\n const discordModule = await import(\"discord.js\");\n const created = new discordModule.Client({\n intents: [],\n });\n await created.login(options.token);\n return { client: created as unknown as DiscordClientLike, owned: true };\n}\n","export async function withTimeout<T>(\n promise: Promise<T>,\n timeoutMs: number,\n timeoutMessage = \"Operation timed out.\",\n): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new Error(timeoutMessage));\n }, timeoutMs);\n\n promise\n .then((value) => {\n clearTimeout(timeout);\n resolve(value);\n })\n .catch((error) => {\n clearTimeout(timeout);\n reject(error);\n });\n });\n}\n\nexport class DedupeCache<T> {\n private readonly cache = new Map<string, { value: T; expiresAt: number }>();\n\n constructor(private readonly ttlMs: number) {}\n\n get(key: string): T | undefined {\n const entry = this.cache.get(key);\n if (!entry) {\n return undefined;\n }\n if (entry.expiresAt <= Date.now()) {\n this.cache.delete(key);\n return undefined;\n }\n return entry.value;\n }\n\n set(key: string, value: T): void {\n this.cache.set(key, { value, expiresAt: Date.now() + this.ttlMs });\n }\n}\n","import { WebSocketServer, type WebSocket } from \"ws\";\nimport type { IncomingMessage } from \"node:http\";\nimport {\n makeEnvelope,\n parseEnvelope,\n stringifyEnvelope,\n type AuthHelloPayload,\n type CommandRequestPayload,\n type EventEmitPayload,\n type WireEnvelope,\n} from \"../../core/protocol\";\nimport type { CommandFailure, CommandSuccess, HostOptions, ShardwireLogger } from \"../../core/types\";\nimport { withLogger } from \"../../utils/logger\";\nimport { createConnectionId } from \"../../utils/id\";\nimport type { HostConnectionState } from \"../../runtime/state\";\nimport { isSecretValid } from \"../../runtime/security\";\n\nconst CLOSE_AUTH_REQUIRED = 4001;\nconst CLOSE_AUTH_FAILED = 4003;\nconst CLOSE_INVALID_PAYLOAD = 4004;\n\ninterface HostServerConfig {\n options: HostOptions<any, any>;\n onCommandRequest: (\n connection: HostConnectionState,\n payload: CommandRequestPayload,\n requestId: string,\n source?: string,\n ) => Promise<CommandSuccess | CommandFailure>;\n}\n\nexport class HostWebSocketServer {\n private readonly wss: WebSocketServer;\n private readonly connections = new Map<WebSocket, HostConnectionState>();\n private readonly logger: Required<ShardwireLogger>;\n private readonly heartbeatMs: number;\n private readonly authTimeoutMs = 5000;\n private readonly interval: NodeJS.Timeout;\n\n constructor(private readonly config: HostServerConfig) {\n const serverConfig = config.options.server;\n this.heartbeatMs = serverConfig.heartbeatMs ?? 30000;\n this.logger = withLogger(config.options.logger);\n\n this.wss = new WebSocketServer({\n host: serverConfig.host,\n port: serverConfig.port,\n path: serverConfig.path ?? \"/shardwire\",\n maxPayload: serverConfig.maxPayloadBytes ?? 65536,\n });\n\n this.wss.on(\"connection\", (socket, request) => this.handleConnection(socket, request));\n this.wss.on(\"error\", (error) =>\n this.logger.error(\"Shardwire host server error.\", { error: String(error) }),\n );\n\n this.interval = setInterval(() => {\n this.checkHeartbeats();\n }, this.heartbeatMs);\n }\n\n emitEvent(name: string, data: unknown, source?: string): void {\n const envelope = makeEnvelope(\n \"event.emit\",\n { name, data } satisfies EventEmitPayload,\n source ? { source } : undefined,\n );\n const raw = stringifyEnvelope(envelope);\n\n for (const state of this.connections.values()) {\n if (!state.authenticated) {\n continue;\n }\n this.safeSend(state.socket, raw);\n }\n }\n\n async close(): Promise<void> {\n clearInterval(this.interval);\n for (const connection of this.connections.values()) {\n connection.socket.close();\n }\n this.connections.clear();\n await new Promise<void>((resolve, reject) => {\n this.wss.close((error) => {\n if (error) {\n reject(error);\n return;\n }\n resolve();\n });\n });\n }\n\n private handleConnection(socket: WebSocket, request: IncomingMessage): void {\n const allowlist = this.config.options.server.corsOrigins;\n if (allowlist && allowlist.length > 0) {\n const origin = request.headers.origin;\n if (!origin || !allowlist.includes(origin)) {\n socket.close(CLOSE_AUTH_FAILED, \"Origin not allowed.\");\n return;\n }\n }\n\n const state: HostConnectionState = {\n id: createConnectionId(),\n socket,\n authenticated: false,\n lastHeartbeatAt: Date.now(),\n };\n this.connections.set(socket, state);\n\n const authTimer = setTimeout(() => {\n if (!state.authenticated) {\n socket.close(CLOSE_AUTH_REQUIRED, \"Authentication required.\");\n }\n }, this.authTimeoutMs);\n\n socket.on(\"message\", async (raw) => {\n try {\n const parsed = parseEnvelope(raw.toString());\n await this.handleMessage(state, parsed);\n } catch (error) {\n this.logger.warn(\"Invalid message payload from client.\", { error: String(error) });\n socket.close(CLOSE_INVALID_PAYLOAD, \"Invalid payload.\");\n }\n });\n\n socket.on(\"close\", () => {\n clearTimeout(authTimer);\n this.connections.delete(socket);\n });\n\n socket.on(\"error\", (error) =>\n this.logger.warn(\"Socket error.\", { connectionId: state.id, error: String(error) }),\n );\n }\n\n private async handleMessage(state: HostConnectionState, envelope: WireEnvelope): Promise<void> {\n if (envelope.type === \"ping\") {\n state.lastHeartbeatAt = Date.now();\n this.safeSend(state.socket, stringifyEnvelope(makeEnvelope(\"pong\", {})));\n return;\n }\n if (envelope.type === \"pong\") {\n state.lastHeartbeatAt = Date.now();\n return;\n }\n\n if (!state.authenticated) {\n if (envelope.type !== \"auth.hello\") {\n state.socket.close(CLOSE_AUTH_REQUIRED, \"Authentication required.\");\n return;\n }\n\n const payload = envelope.payload as AuthHelloPayload;\n if (!payload?.secret || !isSecretValid(payload.secret, this.config.options.server.secret)) {\n this.safeSend(\n state.socket,\n stringifyEnvelope(\n makeEnvelope(\"auth.error\", {\n code: \"AUTH_ERROR\",\n message: \"Invalid shared secret.\",\n }),\n ),\n );\n state.socket.close(CLOSE_AUTH_FAILED, \"Invalid secret.\");\n return;\n }\n\n state.authenticated = true;\n state.lastHeartbeatAt = Date.now();\n if (payload.clientName) {\n state.clientName = payload.clientName;\n }\n this.safeSend(\n state.socket,\n stringifyEnvelope(makeEnvelope(\"auth.ok\", { connectionId: state.id })),\n );\n return;\n }\n\n if (envelope.type === \"command.request\") {\n const payload = envelope.payload as CommandRequestPayload;\n if (!envelope.requestId || !payload?.name) {\n const invalid: CommandFailure = {\n ok: false,\n requestId: envelope.requestId ?? \"unknown\",\n ts: Date.now(),\n error: {\n code: \"VALIDATION_ERROR\",\n message: \"Invalid command request envelope.\",\n },\n };\n this.safeSend(\n state.socket,\n stringifyEnvelope(makeEnvelope(\"command.error\", invalid, { requestId: invalid.requestId })),\n );\n return;\n }\n\n const response = await this.config.onCommandRequest(\n state,\n payload,\n envelope.requestId,\n envelope.source,\n );\n const responseType = response.ok ? \"command.result\" : \"command.error\";\n this.safeSend(\n state.socket,\n stringifyEnvelope(makeEnvelope(responseType, response, { requestId: response.requestId })),\n );\n return;\n }\n }\n\n private checkHeartbeats(): void {\n const now = Date.now();\n const threshold = this.heartbeatMs * 2;\n\n for (const state of this.connections.values()) {\n if (!state.authenticated) {\n continue;\n }\n\n if (now - state.lastHeartbeatAt > threshold) {\n state.socket.terminate();\n this.connections.delete(state.socket);\n continue;\n }\n\n this.safeSend(state.socket, stringifyEnvelope(makeEnvelope(\"ping\", {})));\n }\n }\n\n private safeSend(socket: WebSocket, payload: string): void {\n if (socket.readyState === 1) {\n socket.send(payload);\n }\n }\n}\n","import { timingSafeEqual } from \"node:crypto\";\n\nexport function isSecretValid(provided: string, expected: string): boolean {\n const providedBuffer = Buffer.from(provided);\n const expectedBuffer = Buffer.from(expected);\n\n if (providedBuffer.length !== expectedBuffer.length) {\n return false;\n }\n\n return timingSafeEqual(providedBuffer, expectedBuffer);\n}\n","import type {\n CommandContext,\n CommandFailure,\n CommandMap,\n CommandSuccess,\n EventMap,\n HostOptions,\n HostShardwire,\n} from \"../core/types\";\nimport { withTimeout, DedupeCache } from \"../runtime/reliability\";\nimport type { CommandHandler } from \"../runtime/state\";\nimport { HostWebSocketServer } from \"../transport/ws/host-server\";\nimport { assertJsonPayload, assertMessageName } from \"../runtime/validation\";\n\nconst DEFAULT_COMMAND_TIMEOUT_MS = 10000;\n\nexport function createHostShardwire<C extends CommandMap, E extends EventMap>(\n options: HostOptions<C, E>,\n runtimeHooks?: {\n onClose?: () => Promise<void> | void;\n },\n): HostShardwire<C, E> {\n const commandHandlers = new Map<string, CommandHandler>();\n const commandTimeoutMs = options.server.commandTimeoutMs ?? DEFAULT_COMMAND_TIMEOUT_MS;\n const dedupeCache = new DedupeCache<CommandSuccess | CommandFailure>(commandTimeoutMs * 2);\n\n const hostServer = new HostWebSocketServer({\n options,\n onCommandRequest: async (connection, payload, requestId, source) => {\n const cacheKey = `${requestId}:${payload.name}`;\n const cached = dedupeCache.get(cacheKey);\n if (cached) {\n return cached;\n }\n\n const handler = commandHandlers.get(payload.name);\n if (!handler) {\n const failure: CommandFailure = {\n ok: false,\n requestId,\n ts: Date.now(),\n error: {\n code: \"COMMAND_NOT_FOUND\",\n message: `No command handler registered for \"${payload.name}\".`,\n },\n };\n dedupeCache.set(cacheKey, failure);\n return failure;\n }\n\n const context: CommandContext = {\n requestId,\n connectionId: connection.id,\n receivedAt: Date.now(),\n };\n if (source) {\n context.source = source;\n }\n\n try {\n const maybePromise = Promise.resolve(handler(payload.data, context));\n const value = await withTimeout(\n maybePromise,\n commandTimeoutMs,\n `Command \"${payload.name}\" timed out after ${commandTimeoutMs}ms.`,\n );\n const success: CommandSuccess = {\n ok: true,\n requestId,\n ts: Date.now(),\n data: value,\n };\n dedupeCache.set(cacheKey, success);\n return success;\n } catch (error) {\n const isTimeout = error instanceof Error && /timed out/i.test(error.message);\n const failure: CommandFailure = {\n ok: false,\n requestId,\n ts: Date.now(),\n error: {\n code: isTimeout ? \"TIMEOUT\" : \"INTERNAL_ERROR\",\n message: error instanceof Error ? error.message : \"Unknown command execution error.\",\n },\n };\n dedupeCache.set(cacheKey, failure);\n return failure;\n }\n },\n });\n\n return {\n mode: \"host\",\n onCommand(name, handler) {\n assertMessageName(\"command\", name);\n commandHandlers.set(name, handler as CommandHandler);\n return () => {\n commandHandlers.delete(name);\n };\n },\n emitEvent(name, payload) {\n assertMessageName(\"event\", name);\n assertJsonPayload(\"event\", name, payload);\n hostServer.emitEvent(name, payload, options.name);\n },\n broadcast(name, payload) {\n assertMessageName(\"event\", name);\n assertJsonPayload(\"event\", name, payload);\n hostServer.emitEvent(name, payload, options.name);\n },\n close() {\n return hostServer.close().then(async () => {\n await runtimeHooks?.onClose?.();\n });\n },\n };\n}\n"],"mappings":"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","names":["import_ws","import_node_crypto"]}