durablews 1.0.1 → 2.0.0-alpha.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/backoff.ts","../src/codec.ts","../src/fsm.ts","../src/heartbeat.ts","../src/helpers/event-bus.ts","../src/pipeline.ts","../src/queue.ts","../src/schema.ts","../src/client.ts","../src/compat.ts"],"names":["promise"],"mappings":"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","file":"compat.cjs","sourcesContent":["import type { ReconnectOptions } from \"@/types\";\n\n/** `ReconnectOptions` with every field filled in. */\nexport type ResolvedReconnect = Required<ReconnectOptions>;\n\n/**\n * The durable-by-default reconnection policy: full-jitter exponential backoff,\n * never give up. See the RFC's M3 decisions for the rationale behind each value.\n */\nexport const RECONNECT_DEFAULTS: ResolvedReconnect = {\n baseDelay: 500,\n factor: 2,\n maxDelay: 30_000,\n jitter: true,\n maxRetries: Number.POSITIVE_INFINITY,\n shouldReconnect: () => true\n};\n\n/**\n * Resolve the user's `reconnect` config: `false` disables reconnection\n * entirely (`null`), anything else is merged over the defaults.\n */\nexport function resolveReconnect(\n option: false | ReconnectOptions | undefined\n): ResolvedReconnect | null {\n if (option === false) {\n return null;\n }\n return { ...RECONNECT_DEFAULTS, ...option };\n}\n\n/**\n * Compute the backoff delay for a retry.\n *\n * The exponential delay is `baseDelay × factorᵃᵗᵗᵉᵐᵖᵗ`, capped at `maxDelay`.\n * With jitter (the default), the actual delay is drawn uniformly from\n * `[0, exponential]` — \"full jitter\", which spreads a fleet of simultaneously\n * dropped clients across the whole window instead of letting them retry in\n * synchronized waves.\n *\n * @param attempt - 0-based: the first retry is attempt `0`.\n * @param random - injectable for deterministic tests; defaults to `Math.random`.\n */\nexport function computeDelay(\n attempt: number,\n options: ResolvedReconnect,\n random: () => number = Math.random\n): number {\n const exponential = Math.min(\n options.maxDelay,\n options.baseDelay * options.factor ** attempt\n );\n return options.jitter ? random() * exponential : exponential;\n}\n","import type { Codec } from \"@/types\";\n\n/**\n * Parse a string as JSON, falling back to the raw string when it isn't valid\n * JSON. Lets text protocols that mix JSON and plain strings work unchanged.\n */\nfunction safeJSONParse(data: string): unknown {\n try {\n return JSON.parse(data);\n } catch {\n return data;\n }\n}\n\n/**\n * Whether a value is already a WebSocket-sendable binary frame and should be\n * passed through rather than JSON-encoded (`ArrayBuffer`, any typed array or\n * `DataView`, or a `Blob`).\n *\n * The predicate claims `BufferSource` (what `WebSocket.send` accepts), which\n * asserts the view is not backed by a `SharedArrayBuffer` — `send` rejects\n * those at runtime, so they were never sendable anyway.\n */\nfunction isBinary(data: unknown): data is BufferSource | Blob {\n return (\n data instanceof ArrayBuffer ||\n ArrayBuffer.isView(data) ||\n (typeof Blob !== \"undefined\" && data instanceof Blob)\n );\n}\n\n/**\n * The default codec: JSON over text frames, binary passed through.\n *\n * - `encode` — strings and binary frames (`ArrayBuffer`/typed arrays/`Blob`)\n * are sent verbatim; everything else is `JSON.stringify`d.\n * - `decode` — text frames are JSON-parsed (falling back to the raw string);\n * binary frames are passed through untouched.\n */\nexport const jsonCodec: Codec = {\n encode(data: unknown) {\n if (typeof data === \"string\" || isBinary(data)) {\n return data;\n }\n return JSON.stringify(data);\n },\n decode(data: unknown) {\n return typeof data === \"string\" ? safeJSONParse(data) : data;\n }\n};\n","import type { ConnectionEvent, ConnectionState } from \"@/types\";\n\n/**\n * The connection lifecycle as an explicit finite state machine.\n *\n * A connection has a small, fixed set of legal states and transitions. Modelling\n * it as a table — rather than a free-form reducer — means an illegal transition\n * (e.g. a `CLOSED` event arriving while already `closed`) is *representable as the\n * absence of an entry* and can be rejected, instead of silently doing nothing.\n * That silent no-op is exactly what allowed the original close/error bug.\n *\n * `ERROR` is deliberately absent from the table: a transport error does not by\n * itself change the connection state (the browser/runtime fires `error` and then\n * `close`), so it is handled out-of-band by the client (record + emit) and the\n * following `CLOSED` event performs the actual transition.\n */\nconst TRANSITIONS: Record<\n ConnectionState,\n Partial<Record<ConnectionEvent, ConnectionState>>\n> = {\n idle: { CONNECT: \"connecting\" },\n connecting: {\n OPEN: \"open\",\n CLOSE_REQUESTED: \"closing\",\n CLOSED: \"closed\",\n RETRY: \"reconnecting\"\n },\n open: {\n CLOSE_REQUESTED: \"closing\",\n CLOSED: \"closed\",\n RETRY: \"reconnecting\"\n },\n closing: { CLOSED: \"closed\" },\n // `reconnecting` = waiting out the backoff delay; no socket exists, so\n // CLOSE_REQUESTED goes straight to `closed` (there is nothing to wait for)\n // and OPEN/CLOSED cannot legally occur.\n reconnecting: {\n CONNECT: \"connecting\",\n CLOSE_REQUESTED: \"closed\"\n },\n closed: { CONNECT: \"connecting\" }\n};\n\n/**\n * Resolve the next state for an `(state, event)` pair.\n *\n * @returns the destination state, or `null` if the transition is illegal.\n */\nexport function nextState(\n state: ConnectionState,\n event: ConnectionEvent\n): ConnectionState | null {\n return TRANSITIONS[state][event] ?? null;\n}\n\n/**\n * Whether `(state, event)` is a legal transition.\n */\nexport function canTransition(\n state: ConnectionState,\n event: ConnectionEvent\n): boolean {\n return nextState(state, event) !== null;\n}\n","import type { HeartbeatOptions } from \"@/types\";\n\n/** `HeartbeatOptions` with every field filled in. */\nexport interface ResolvedHeartbeat {\n readonly interval: number;\n readonly message: unknown;\n readonly timeout: number;\n}\n\n/**\n * The close code used when the heartbeat declares the link dead (app-reserved\n * 4xxx range, mnemonic for HTTP 408 Request Timeout). Useful in a custom\n * `shouldReconnect` to distinguish heartbeat closes from server closes.\n */\nexport const HEARTBEAT_TIMEOUT_CODE = 4408;\n\n/**\n * Resolve the user's `heartbeat` config. Heartbeat is **opt-in**: absence means\n * off (`null`) — a naive \"no traffic → reconnect\" would kill legitimately\n * quiet-but-healthy connections, and any ping depends on app-level semantics\n * the library can't assume (see the RFC's M3 decisions).\n */\nexport function resolveHeartbeat(\n option: HeartbeatOptions | undefined\n): ResolvedHeartbeat | null {\n if (option === undefined) {\n return null;\n }\n return {\n interval: option.interval,\n message: option.message ?? \"ping\",\n timeout: option.timeout ?? option.interval\n };\n}\n","import type { EventBus } from \"@/types\";\n\n/**\n * Creates an event bus for managing event subscriptions and emissions.\n * Provides a simple pub/sub pattern with type-safe event handling.\n *\n * @returns EventBus instance with on, off, emit, and once methods\n *\n * @example\n * ```typescript\n * const eventBus = defineEventBus();\n *\n * // Subscribe to events\n * eventBus.on('user-login', (user) => {\n * console.log('User logged in:', user);\n * });\n *\n * // Emit events\n * eventBus.emit('user-login', { id: 1, name: 'John' });\n *\n * // One-time subscription\n * eventBus.once('app-ready', () => {\n * console.log('App is ready!');\n * });\n * ```\n */\nexport function defineEventBus(): EventBus {\n const listeners = new Map<string, Array<(payload: unknown) => void>>();\n\n /**\n * Subscribes to an event with a handler function.\n *\n * @template T - The type of the event payload\n * @param eventName - The name of the event to listen for\n * @param handler - Function to call when the event is emitted\n */\n function on<T = unknown>(\n eventName: string,\n handler: (payload: T) => void\n ): void {\n const handlers = listeners.get(eventName) ?? [];\n handlers.push(handler as (payload: unknown) => void);\n listeners.set(eventName, handlers);\n }\n\n /**\n * Unsubscribes a handler from an event.\n *\n * @template T - The type of the event payload\n * @param eventName - The name of the event to stop listening for\n * @param handler - The handler function to remove\n */\n function off<T = unknown>(\n eventName: string,\n handler: (payload: T) => void\n ) {\n const handlers = listeners.get(eventName);\n if (!handlers) {\n return;\n }\n listeners.set(\n eventName,\n handlers.filter((h) => h !== handler)\n );\n }\n\n /**\n * Subscribes to an event with a handler that will only be called once.\n * The handler is automatically removed after the first emission.\n *\n * @template T - The type of the event payload\n * @param eventName - The name of the event to listen for\n * @param handler - Function to call when the event is emitted (only once)\n */\n function once<T = unknown>(\n eventName: string,\n handler: (payload: T) => void\n ): void {\n const onceHandler = (payload: T) => {\n // Remove the handler after first invocation\n off(eventName, onceHandler as (payload: unknown) => void);\n // Call the original handler\n handler(payload);\n };\n\n // Add the wrapper handler\n on(eventName, onceHandler);\n }\n\n /**\n * Emits an event to all subscribed handlers.\n *\n * @template T - The type of the event payload\n * @param eventName - The name of the event to emit\n * @param payload - The data to pass to event handlers\n */\n function emit<T = unknown>(eventName: string, payload?: T) {\n const handlers = listeners.get(eventName);\n handlers?.forEach((fn) => {\n fn(payload);\n });\n }\n\n return { on, off, emit, once };\n}\n","/**\n * The functional shape shared by inbound and outbound middleware: receive a\n * context and a `next`, optionally async. The context type is the only thing\n * that differs per direction.\n */\ntype PipelineMiddleware<TContext> = (\n ctx: TContext,\n next: () => void | Promise<void>\n) => void | Promise<void>;\n\n/**\n * Runs a message through a middleware chain (onion model).\n *\n * Each middleware receives the shared context and a `next` it may call to pass\n * control onward. When the chain runs to completion, `terminal` is invoked —\n * for inbound messages that is where the client emits `message`; for outbound,\n * where it encodes and writes to the socket. A middleware that returns without\n * calling `next()` short-circuits the chain (and `terminal`).\n *\n * Mirrors the guard from the old store pipeline: calling `next()` more than once\n * in a single middleware is a bug and throws.\n *\n * @returns `void`, or a `Promise` if any middleware in the chain is async.\n */\nexport function runPipeline<TContext>(\n middlewares: readonly PipelineMiddleware<TContext>[],\n ctx: TContext,\n terminal: () => void\n): void | Promise<void> {\n let invoked = -1;\n\n function dispatch(i: number): void | Promise<void> {\n if (i <= invoked) {\n throw new Error(\"next() called multiple times\");\n }\n invoked = i;\n\n const middleware = middlewares[i];\n if (!middleware) {\n return terminal();\n }\n return middleware(ctx, () => dispatch(i + 1));\n }\n\n return dispatch(0);\n}\n","import type { QueueOptions } from \"@/types\";\n\n/** `QueueOptions` with every field filled in. */\nexport type ResolvedQueue = Required<QueueOptions>;\n\n/**\n * The default outbound-queue policy: bounded at 256 messages, drop-oldest.\n * Never silently unbounded (a memory leak), never silently lossy (every drop\n * emits a `drop` event). See the RFC's M3 decisions.\n */\nexport const QUEUE_DEFAULTS: ResolvedQueue = {\n maxSize: 256\n};\n\n/**\n * Resolve the user's `queue` config: `false` disables queueing entirely\n * (`null`), anything else is merged over the defaults.\n */\nexport function resolveQueue(\n option: false | QueueOptions | undefined\n): ResolvedQueue | null {\n if (option === false) {\n return null;\n }\n return { ...QUEUE_DEFAULTS, ...option };\n}\n","/**\n * The Standard Schema v1 interface (https://standardschema.dev), vendored as\n * types-only per the spec's guidance — implementing libraries (zod, valibot,\n * arktype, …) conform to this shape, so DurableWS can accept any of them\n * without depending on any of them. Keeps core zero-dependency.\n */\nexport interface StandardSchemaV1<Input = unknown, Output = Input> {\n readonly \"~standard\": StandardSchemaV1.Props<Input, Output>;\n}\n\nexport declare namespace StandardSchemaV1 {\n export interface Props<Input = unknown, Output = Input> {\n readonly version: 1;\n readonly vendor: string;\n readonly validate: (\n value: unknown\n ) => Result<Output> | Promise<Result<Output>>;\n readonly types?: Types<Input, Output> | undefined;\n }\n\n export type Result<Output> = SuccessResult<Output> | FailureResult;\n\n export interface SuccessResult<Output> {\n readonly value: Output;\n readonly issues?: undefined;\n }\n\n export interface FailureResult {\n readonly issues: ReadonlyArray<Issue>;\n }\n\n export interface Issue {\n readonly message: string;\n readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined;\n }\n\n export interface PathSegment {\n readonly key: PropertyKey;\n }\n\n export interface Types<Input = unknown, Output = Input> {\n readonly input: Input;\n readonly output: Output;\n }\n\n export type InferInput<Schema extends StandardSchemaV1> = NonNullable<\n Schema[\"~standard\"][\"types\"]\n >[\"input\"];\n\n export type InferOutput<Schema extends StandardSchemaV1> = NonNullable<\n Schema[\"~standard\"][\"types\"]\n >[\"output\"];\n}\n\n/**\n * Thrown (as an `error` event payload) when an inbound message fails the\n * configured schema. The message is **not** emitted — handlers only ever see\n * data that passed validation.\n */\nexport class SchemaValidationError extends Error {\n readonly issues: ReadonlyArray<StandardSchemaV1.Issue>;\n\n constructor(issues: ReadonlyArray<StandardSchemaV1.Issue>) {\n super(\n `Inbound message failed schema validation: ${issues\n .map((issue) => issue.message)\n .join(\"; \")}`\n );\n this.name = \"SchemaValidationError\";\n this.issues = issues;\n }\n}\n","import { computeDelay, resolveReconnect } from \"@/backoff\";\nimport { jsonCodec } from \"@/codec\";\nimport { nextState } from \"@/fsm\";\nimport { HEARTBEAT_TIMEOUT_CODE, resolveHeartbeat } from \"@/heartbeat\";\nimport { defineEventBus } from \"@/helpers/event-bus\";\nimport { runPipeline } from \"@/pipeline\";\nimport { resolveQueue } from \"@/queue\";\nimport { SchemaValidationError, type StandardSchemaV1 } from \"@/schema\";\nimport type {\n ClientEventMap,\n ClientState,\n ConnectionEvent,\n ConnectionState,\n DirectionalMiddleware,\n Middleware,\n OutboundMiddleware,\n WebSocketClient,\n WebSocketClientConfig\n} from \"@/types\";\n\n/**\n * Creates a WebSocket client driven by an explicit connection FSM.\n *\n * Durable by default: an unexpected disconnect schedules a reconnect with\n * full-jitter exponential backoff (see `backoff.ts`); pass `reconnect: false`\n * to opt out.\n *\n * @param config - Connection configuration (at minimum, a `url`).\n *\n * @example\n * ```typescript\n * const ws = client({ url: \"wss://example.com/socket\" });\n *\n * ws.on(\"message\", (data) => console.log(\"received:\", data));\n * ws.on(\"reconnecting\", ({ attempt, delay }) => {\n * console.log(`retry #${attempt} in ${Math.round(delay)}ms`);\n * });\n *\n * await ws.connect();\n * ws.send({ type: \"hello\", message: \"world\" });\n *\n * ws.close();\n * ```\n */\nexport function client(config: WebSocketClientConfig): WebSocketClient {\n const bus = defineEventBus();\n const codec = config.codec ?? jsonCodec;\n const reconnect = resolveReconnect(config.reconnect);\n const queue = resolveQueue(config.queue);\n const heartbeat = resolveHeartbeat(config.heartbeat);\n const middlewares: Middleware[] = [];\n const outboundMiddlewares: OutboundMiddleware[] = [];\n\n // Outbound messages awaiting an open socket, in send() order. Original\n // (un-encoded) values: encoding happens at flush, so a drop event can hand\n // the user back exactly what they passed to send().\n const queued: unknown[] = [];\n\n let socket: WebSocket | null = null;\n let state: ConnectionState = \"idle\";\n let lastError: Event | Error | null = null;\n\n // Heartbeat bookkeeping: when the last inbound frame (of any kind)\n // arrived, the ping interval, and the per-ping liveness deadline.\n let lastInboundAt = 0;\n let heartbeatTimer: ReturnType<typeof setInterval> | null = null;\n let heartbeatDeadline: ReturnType<typeof setTimeout> | null = null;\n\n // The serialized outbound path (in play only when outbound middleware is\n // registered). `outboundTail` is the tail of the in-flight chain: while\n // set, every new message chains behind it, so socket writes keep send()\n // order even when a middleware awaits. `requeueIndex` keeps messages that\n // were mid-pipeline when the connection dropped ahead of newer queued\n // sends; it resets on every socket close.\n let outboundTail: Promise<void> | null = null;\n let requeueIndex = 0;\n\n // True between a user close() and the next connect(); suppresses\n // reconnection so \"the user hung up\" is never retried.\n let closeRequested = false;\n // Retries used in the current disconnection episode (see ClientState).\n let retryAttempt = 0;\n let retryTimer: ReturnType<typeof setTimeout> | null = null;\n\n // subscribe() listeners plus the cached getState() snapshot. The cache\n // makes snapshots referentially stable between changes — required by\n // React's useSyncExternalStore (a fresh object per getSnapshot() call\n // would loop the renderer).\n const subscribers = new Set<() => void>();\n let snapshot: ClientState | null = null;\n\n // The in-flight connect() promise and its settlers. A single promise is\n // shared across concurrent/repeat connect() calls so the method is\n // idempotent, and it survives failed attempts while reconnection is\n // active — it settles only on first open or terminal failure.\n let pending: {\n readonly promise: Promise<void>;\n readonly resolve: () => void;\n readonly reject: (reason: Error) => void;\n } | null = null;\n\n /**\n * Applies an FSM event. Legal transitions update the state and emit\n * `statechange`; illegal ones are ignored (the table is the guard).\n *\n * @returns the new state if a transition occurred, otherwise `null`.\n */\n /**\n * Invalidates the cached snapshot and fires subscribe() listeners. Called\n * after every mutation of the observable state, before the corresponding\n * bus event, so any observer reading getState() sees fresh data.\n */\n function notify() {\n snapshot = null;\n for (const listener of [...subscribers]) {\n listener();\n }\n }\n\n function transition(event: ConnectionEvent): ConnectionState | null {\n const next = nextState(state, event);\n if (next === null || next === state) {\n return null;\n }\n\n const previous = state;\n state = next;\n notify();\n bus.emit(\"statechange\", { previous, current: next });\n return next;\n }\n\n function settleConnected() {\n pending?.resolve();\n pending = null;\n }\n\n function settleFailed(reason: Error) {\n pending?.reject(reason);\n pending = null;\n }\n\n function clearRetryTimer() {\n if (retryTimer !== null) {\n clearTimeout(retryTimer);\n retryTimer = null;\n }\n }\n\n function stopHeartbeat() {\n if (heartbeatTimer !== null) {\n clearInterval(heartbeatTimer);\n heartbeatTimer = null;\n }\n if (heartbeatDeadline !== null) {\n clearTimeout(heartbeatDeadline);\n heartbeatDeadline = null;\n }\n }\n\n /**\n * While open, sends the heartbeat message every `interval` ms and arms a\n * liveness deadline after each ping. Any inbound frame before the deadline\n * proves the link; none means it's dead — force-close with code 4408,\n * which flows into the normal reconnect machinery (the close is not\n * user-initiated, so it is retryable).\n */\n function startHeartbeat() {\n if (heartbeat === null) {\n return;\n }\n stopHeartbeat();\n heartbeatTimer = setInterval(() => {\n if (state !== \"open\" || !socket) {\n return;\n }\n const pingSentAt = Date.now();\n try {\n socket.send(codec.encode(heartbeat.message));\n } catch (error) {\n bus.emit(\"error\", toError(error));\n }\n if (heartbeatDeadline !== null) {\n clearTimeout(heartbeatDeadline);\n }\n heartbeatDeadline = setTimeout(() => {\n heartbeatDeadline = null;\n if (state === \"open\" && socket && lastInboundAt < pingSentAt) {\n const failure = new Error(\n `Heartbeat timeout: no inbound traffic within ${heartbeat.timeout}ms of a ping`\n );\n lastError = failure;\n notify();\n bus.emit(\"error\", failure);\n socket.close(HEARTBEAT_TIMEOUT_CODE, \"heartbeat timeout\");\n }\n }, heartbeat.timeout);\n }, heartbeat.interval);\n }\n\n /**\n * Final stage of the outbound pipeline: encode the (possibly transformed)\n * message and write it to the socket. The connection may have changed\n * while middleware awaited, so re-check here: if a retry is underway, the\n * *original* value is re-queued ahead of newer sends (middleware re-runs\n * at the next transmission, keeping e.g. tokens fresh); on a dead-end\n * state it surfaces as a `drop` — never silently lost.\n */\n function wire(transformed: unknown, original: unknown) {\n if (socket && state === \"open\") {\n socket.send(codec.encode(transformed));\n return;\n }\n if (\n queue !== null &&\n (state === \"connecting\" || state === \"reconnecting\")\n ) {\n if (queued.length >= queue.maxSize) {\n bus.emit(\"drop\", {\n data: queued.shift(),\n reason: \"overflow\"\n });\n if (requeueIndex > 0) {\n requeueIndex -= 1;\n }\n }\n queued.splice(requeueIndex, 0, original);\n requeueIndex += 1;\n notify();\n return;\n }\n bus.emit(\"drop\", { data: original, reason: \"close\" });\n }\n\n /**\n * Runs one message through the outbound middleware chain. Errors are\n * per-message: a throw/rejection surfaces as `error` and only this\n * message is skipped.\n */\n function runOutbound(data: unknown): void | Promise<void> {\n const ctx = { data, client: api };\n try {\n const result = runPipeline(outboundMiddlewares, ctx, () => {\n wire(ctx.data, data);\n });\n if (result instanceof Promise) {\n return result.catch((error: unknown) => {\n bus.emit(\"error\", toError(error));\n });\n }\n } catch (error) {\n bus.emit(\"error\", toError(error));\n }\n }\n\n /**\n * Sends a message through the outbound middleware pipeline, preserving\n * send() order: while any message is in flight (async middleware), newer\n * messages chain behind it. With no middleware in flight and an all-sync\n * chain, the path stays fully synchronous.\n */\n function transmit(data: unknown) {\n if (outboundTail === null) {\n const result = runOutbound(data);\n if (result instanceof Promise) {\n setOutboundTail(result);\n }\n return;\n }\n setOutboundTail(outboundTail.then(() => runOutbound(data)));\n }\n\n function setOutboundTail(run: Promise<void>) {\n const tail = run.then(() => {\n // Chain drained: restore the synchronous fast path.\n if (outboundTail === tail) {\n outboundTail = null;\n }\n });\n outboundTail = tail;\n }\n\n /**\n * Sends every queued message in order. Called once the socket opens,\n * *before* the `open` event, so the backlog (sent earlier in time)\n * precedes anything an `open` handler sends — under async outbound\n * middleware \"precedes\" means pipeline order; socket writes follow it.\n * A per-message encode/send failure surfaces as an `error` event and\n * flushing continues.\n */\n function flushQueue() {\n const hadQueued = queued.length > 0;\n requeueIndex = 0;\n while (queued.length > 0 && socket && state === \"open\") {\n const data = queued.shift();\n if (outboundMiddlewares.length === 0) {\n try {\n socket.send(codec.encode(data));\n } catch (error) {\n bus.emit(\"error\", toError(error));\n }\n } else {\n transmit(data);\n }\n }\n if (hadQueued) {\n notify();\n }\n }\n\n /**\n * Empties the queue as `drop` events — these messages will never be sent\n * (user `close()` or terminal failure). Never silently lossy.\n */\n function dropQueued() {\n const hadQueued = queued.length > 0;\n while (queued.length > 0) {\n bus.emit(\"drop\", { data: queued.shift(), reason: \"close\" });\n }\n if (hadQueued) {\n notify();\n }\n }\n\n /**\n * Whether an unexpected close should be retried: reconnection enabled, not\n * a user `close()`, retries left, and no `shouldReconnect` veto.\n */\n function isRetryable(event: CloseEvent): boolean {\n return (\n reconnect !== null &&\n !closeRequested &&\n retryAttempt < reconnect.maxRetries &&\n reconnect.shouldReconnect(event)\n );\n }\n\n function openSocket() {\n if (lastError !== null) {\n lastError = null;\n notify();\n }\n socket = config.protocols\n ? new WebSocket(config.url, config.protocols)\n : new WebSocket(config.url);\n if (config.binaryType) {\n socket.binaryType = config.binaryType;\n }\n\n socket.onopen = () => {\n retryAttempt = 0;\n transition(\"OPEN\");\n flushQueue();\n startHeartbeat();\n bus.emit(\"open\");\n settleConnected();\n };\n\n socket.onmessage = (event: MessageEvent) => {\n lastInboundAt = Date.now();\n deliver(event.data);\n };\n\n socket.onerror = (event: Event) => {\n lastError = event;\n notify();\n bus.emit(\"error\", event);\n };\n\n socket.onclose = (event: CloseEvent) => {\n const wasConnecting = state === \"connecting\";\n socket = null;\n stopHeartbeat();\n // A new disconnected period begins: in-flight outbound messages\n // re-queue from the front (see wire()).\n requeueIndex = 0;\n\n if (reconnect !== null && isRetryable(event)) {\n // Event order is deliberate: statechange (state already moved\n // to `reconnecting`), then the close that caused it, then the\n // retry announcement with attempt + delay.\n retryAttempt += 1;\n const delay = computeDelay(retryAttempt - 1, reconnect);\n transition(\"RETRY\");\n bus.emit(\"close\", event);\n bus.emit(\"reconnecting\", { attempt: retryAttempt, delay });\n retryTimer = setTimeout(() => {\n retryTimer = null;\n if (transition(\"CONNECT\") !== null) {\n openSocket();\n }\n }, delay);\n return; // pending connect() survives the retry\n }\n\n transition(\"CLOSED\");\n dropQueued();\n bus.emit(\"close\", event);\n // Terminal for any in-flight connect(): closed before first open\n // with no (further) retries coming.\n if (wasConnecting || pending) {\n settleFailed(\n new Error(\n retryAttempt > 0\n ? `WebSocket reconnect gave up after ${retryAttempt} attempt(s) (code ${event.code})`\n : `WebSocket closed before opening (code ${event.code}${\n event.reason ? `: ${event.reason}` : \"\"\n })`\n )\n );\n }\n };\n }\n\n /**\n * Runs a decoded — and, if a schema is configured, validated — inbound\n * message through the middleware chain. If the chain completes, the\n * message is emitted as `message`; a middleware that throws or rejects\n * surfaces as an `error`. Validation precedes middleware, so middleware\n * only ever sees trusted data; an invalid message surfaces as an `error`\n * (`SchemaValidationError`) and never reaches middleware or `message`.\n */\n function deliver(raw: unknown) {\n const decoded = codec.decode(raw);\n if (config.schema === undefined) {\n dispatchMessage(decoded);\n return;\n }\n let result: ReturnType<StandardSchemaV1[\"~standard\"][\"validate\"]>;\n try {\n result = config.schema[\"~standard\"].validate(decoded);\n } catch (error) {\n bus.emit(\"error\", toError(error));\n return;\n }\n if (result instanceof Promise) {\n result.then(handleValidated, (error: unknown) => {\n bus.emit(\"error\", toError(error));\n });\n return;\n }\n handleValidated(result);\n }\n\n function handleValidated(result: StandardSchemaV1.Result<unknown>) {\n if (result.issues) {\n bus.emit(\"error\", new SchemaValidationError(result.issues));\n return;\n }\n dispatchMessage(result.value);\n }\n\n function dispatchMessage(data: unknown) {\n const ctx = { data, client: api };\n const emit = () => {\n bus.emit(\"message\", ctx.data);\n };\n try {\n const result = runPipeline(middlewares, ctx, emit);\n if (result instanceof Promise) {\n result.catch((error: unknown) => {\n bus.emit(\"error\", toError(error));\n });\n }\n } catch (error) {\n bus.emit(\"error\", toError(error));\n }\n }\n\n /** Lazily create (or reuse) the shared connect() promise. */\n function ensurePending(): Promise<void> {\n if (pending) {\n return pending.promise;\n }\n let resolve!: () => void;\n let reject!: (reason: Error) => void;\n const promise = new Promise<void>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n pending = { promise, resolve, reject };\n return promise;\n }\n\n const api: WebSocketClient = {\n get state() {\n return state;\n },\n\n connect() {\n if (state === \"open\") {\n return Promise.resolve();\n }\n if (state === \"connecting\") {\n return ensurePending();\n }\n if (state === \"closing\") {\n return Promise.reject(\n new Error(\n \"Cannot connect() while the connection is closing\"\n )\n );\n }\n if (state === \"reconnecting\") {\n // Skip the rest of the backoff wait and attempt now.\n clearRetryTimer();\n const promise = ensurePending();\n transition(\"CONNECT\");\n openSocket();\n return promise;\n }\n\n // idle or closed → start a fresh episode.\n closeRequested = false;\n retryAttempt = 0;\n if (transition(\"CONNECT\") === null) {\n return Promise.reject(\n new Error(`Cannot connect() from state \"${state}\"`)\n );\n }\n\n const promise = ensurePending();\n try {\n openSocket();\n } catch (error) {\n transition(\"CLOSED\");\n socket = null;\n settleFailed(toError(error));\n }\n\n return promise;\n },\n\n send(data: unknown) {\n if (socket && state === \"open\") {\n if (outboundMiddlewares.length === 0) {\n // No outbound middleware: today's direct path, including\n // synchronous encode errors thrown to the caller.\n socket.send(codec.encode(data));\n } else {\n transmit(data);\n }\n return;\n }\n // An open is coming (or being retried): queue, bounded drop-oldest.\n if (\n queue !== null &&\n (state === \"connecting\" || state === \"reconnecting\")\n ) {\n if (queued.length >= queue.maxSize) {\n bus.emit(\"drop\", {\n data: queued.shift(),\n reason: \"overflow\"\n });\n }\n queued.push(data);\n notify();\n return;\n }\n throw new Error(\n `Cannot send: connection is not open (state: \"${state}\")`\n );\n },\n\n close(code?: number, reason?: string) {\n closeRequested = true;\n clearRetryTimer();\n stopHeartbeat();\n if (retryAttempt !== 0) {\n retryAttempt = 0;\n notify();\n }\n // The user hung up: queued messages will never send. Surface them\n // now (deterministically), not when the socket finishes closing.\n dropQueued();\n\n if (state === \"reconnecting\") {\n // No socket exists while waiting out the backoff: go straight\n // to closed and terminate any in-flight connect().\n transition(\"CLOSE_REQUESTED\");\n settleFailed(\n new Error(\"close() called before the connection opened\")\n );\n return;\n }\n if (!socket) {\n return;\n }\n transition(\"CLOSE_REQUESTED\");\n socket.close(code, reason);\n },\n\n on<K extends keyof ClientEventMap>(\n event: K,\n handler: (payload: ClientEventMap[K]) => void\n ) {\n bus.on(event, handler);\n return () => bus.off(event, handler);\n },\n\n use(middleware: Middleware | DirectionalMiddleware) {\n if (typeof middleware === \"function\") {\n middlewares.push(middleware);\n return api;\n }\n if (middleware.inbound) {\n middlewares.push(middleware.inbound);\n }\n if (middleware.outbound) {\n outboundMiddlewares.push(middleware.outbound);\n }\n return api;\n },\n\n getState(): ClientState {\n if (snapshot === null) {\n snapshot = Object.freeze({\n state,\n lastError,\n retryAttempt,\n queueLength: queued.length\n });\n }\n return snapshot;\n },\n\n subscribe(listener: () => void) {\n subscribers.add(listener);\n return () => {\n subscribers.delete(listener);\n };\n }\n };\n\n return api;\n}\n\n/** Normalize an unknown thrown value into an `Error`. */\nfunction toError(value: unknown): Error {\n return value instanceof Error ? value : new Error(String(value));\n}\n","/**\n * Drop-in `WebSocket` compatibility — `import { WebSocket } from \"durablews/compat\"`.\n *\n * A `WebSocket`-shaped class over the durable core, for two audiences:\n * one-line migration of app code that constructs sockets directly, and\n * `webSocketImpl`-style injection points in existing libraries (graphql-ws,\n * y-websocket, realtime SDKs). Fidelity is scoped to those use cases — the\n * known deviations are documented on the docs site, not hidden.\n */\nimport { client } from \"@/client\";\nimport type { Codec, WebSocketClient, WebSocketClientConfig } from \"@/types\";\n\n/**\n * Compat is wire-faithful: no JSON, no transforms. What you send is what the\n * socket sends; what arrives is what you receive.\n */\nconst rawCodec: Codec = {\n // The class's send() signature restricts inputs to WebSocket-sendable\n // values, so the cast only widens what TypeScript already enforced there.\n encode: (data) => data as string | BufferSource | Blob,\n decode: (data) => data\n};\n\ntype CloseEventInitLike = {\n code?: number;\n reason?: string;\n wasClean?: boolean;\n};\n\n/**\n * `CloseEvent` exists in browsers, Deno, Bun, and recent Node — but not in\n * every runtime durablews supports, so fall back to a structural equivalent.\n */\nconst CloseEventCtor: new (\n type: string,\n init?: CloseEventInitLike\n) => CloseEvent =\n typeof CloseEvent !== \"undefined\"\n ? CloseEvent\n : (class extends Event {\n readonly code: number;\n readonly reason: string;\n readonly wasClean: boolean;\n constructor(type: string, init: CloseEventInitLike = {}) {\n super(type);\n this.code = init.code ?? 0;\n this.reason = init.reason ?? \"\";\n this.wasClean = init.wasClean ?? false;\n }\n } as unknown as new (\n type: string,\n init?: CloseEventInitLike\n ) => CloseEvent);\n\n/** The durablews options accepted as the constructor's third argument. */\nexport type DurableWebSocketOptions = Omit<\n WebSocketClientConfig,\n \"url\" | \"protocols\" | \"codec\" | \"schema\"\n>;\n\n/**\n * A drop-in `WebSocket` that reconnects, with the durable core underneath:\n * full-jitter backoff, bounded queueing, opt-in heartbeat.\n *\n * ```ts\n * import { WebSocket } from \"durablews/compat\";\n *\n * const ws = new WebSocket(\"wss://example.com/socket\");\n * ws.onmessage = (event) => console.log(event.data);\n * ```\n *\n * Or injected where a library accepts an implementation:\n *\n * ```ts\n * createClient({ url, webSocketImpl: WebSocket }); // graphql-ws\n * ```\n *\n * The underlying durablews client is exposed as `.client` for everything the\n * `WebSocket` shape can't say (state machine, `drop` events, middleware).\n */\nexport class DurableWebSocket extends EventTarget {\n static readonly CONNECTING = 0 as const;\n static readonly OPEN = 1 as const;\n static readonly CLOSING = 2 as const;\n static readonly CLOSED = 3 as const;\n\n readonly CONNECTING = 0 as const;\n readonly OPEN = 1 as const;\n readonly CLOSING = 2 as const;\n readonly CLOSED = 3 as const;\n\n /** The underlying durablews client — the escape hatch to the full API. */\n readonly client: WebSocketClient;\n\n readonly url: string;\n /** Always `\"\"` — see the known-deviations table in the docs. */\n readonly protocol = \"\";\n /** Always `\"\"` — see the known-deviations table in the docs. */\n readonly extensions = \"\";\n /** Always `0` — see the known-deviations table in the docs. */\n readonly bufferedAmount = 0;\n\n onopen: ((event: Event) => void) | null = null;\n onmessage: ((event: MessageEvent) => void) | null = null;\n onclose: ((event: CloseEvent) => void) | null = null;\n onerror: ((event: Event) => void) | null = null;\n\n #binaryType: BinaryType;\n // Serializes Blob → ArrayBuffer conversions so message order survives the\n // async hop when binaryType is reassigned after construction. While no\n // conversion is pending, delivery is fully synchronous (native-faithful).\n #deliveryChain: Promise<void> = Promise.resolve();\n #pendingDeliveries = 0;\n\n constructor(\n url: string | URL,\n protocols?: string | string[],\n options: DurableWebSocketOptions = {}\n ) {\n super();\n this.url = String(url);\n this.#binaryType = options.binaryType ?? \"blob\";\n this.client = client({\n ...options,\n url,\n protocols,\n codec: rawCodec\n });\n\n this.client.on(\"open\", () => {\n const event = new Event(\"open\");\n this.dispatchEvent(event);\n this.onopen?.call(this, event);\n });\n this.client.on(\"message\", (data) => {\n this.#deliverMessage(data);\n });\n this.client.on(\"close\", (event) => {\n // Re-dispatched as a fresh event: the original already completed\n // its dispatch on the underlying socket.\n const compatEvent = new CloseEventCtor(\"close\", {\n code: event.code,\n reason: event.reason,\n wasClean: event.wasClean\n });\n this.dispatchEvent(compatEvent);\n this.onclose?.call(this, compatEvent);\n });\n this.client.on(\"error\", () => {\n // Native WebSocket error events carry no payload either.\n const event = new Event(\"error\");\n this.dispatchEvent(event);\n this.onerror?.call(this, event);\n });\n\n // A WebSocket connects on construction. Failures surface as\n // error/close events, exactly like the native class.\n this.client.connect().catch(() => {});\n }\n\n /**\n * Maps the durable lifecycle onto the four native states. Deviation by\n * design: during automatic reconnection this returns to `CONNECTING`,\n * which a native (one-shot) socket can never do.\n */\n get readyState(): number {\n switch (this.client.state) {\n case \"open\":\n return DurableWebSocket.OPEN;\n case \"closing\":\n return DurableWebSocket.CLOSING;\n case \"closed\":\n return DurableWebSocket.CLOSED;\n default: // idle | connecting | reconnecting\n return DurableWebSocket.CONNECTING;\n }\n }\n\n get binaryType(): BinaryType {\n return this.#binaryType;\n }\n\n /**\n * Honored at any time: when set to `\"arraybuffer\"` after construction,\n * `Blob` frames are converted on delivery (order-preserving). Prefer\n * passing `binaryType` in the constructor options, which configures the\n * socket itself and avoids the conversion copy.\n */\n set binaryType(value: BinaryType) {\n this.#binaryType = value;\n }\n\n /**\n * Sends data, with durability semantics: while (re)connecting the message\n * is queued and flushed on open (a native socket would throw). After\n * `close()` it is silently discarded, matching native behavior.\n */\n send(data: string | ArrayBufferLike | Blob | ArrayBufferView) {\n if (\n this.client.state === \"idle\" ||\n this.client.state === \"closing\" ||\n this.client.state === \"closed\"\n ) {\n // Native sockets don't throw on send-after-close; stay faithful.\n return;\n }\n this.client.send(data);\n }\n\n close(code?: number, reason?: string) {\n this.client.close(code, reason);\n }\n\n #deliverMessage(data: unknown) {\n const dispatch = (value: unknown) => {\n const event = new MessageEvent(\"message\", { data: value });\n this.dispatchEvent(event);\n this.onmessage?.call(this, event);\n };\n // Emulation path: binaryType was set to \"arraybuffer\" after\n // construction, but the socket is still delivering Blobs.\n if (\n this.#binaryType === \"arraybuffer\" &&\n typeof Blob !== \"undefined\" &&\n data instanceof Blob\n ) {\n this.#queueDelivery(async () => {\n try {\n dispatch(await blobToArrayBuffer(data));\n } catch {\n // Conversion unavailable: raw delivery beats silence.\n dispatch(data);\n }\n });\n return;\n }\n if (this.#pendingDeliveries === 0) {\n // The common case: no conversion in flight → synchronous,\n // exactly like a native socket.\n dispatch(data);\n return;\n }\n // A conversion is ahead of us: queue behind it to preserve order.\n this.#queueDelivery(() => {\n dispatch(data);\n });\n }\n\n #queueDelivery(deliver: () => void | Promise<void>) {\n this.#pendingDeliveries += 1;\n this.#deliveryChain = this.#deliveryChain\n .then(deliver)\n // A listener throwing must not poison the chain for later\n // messages; native dispatch isolates listener errors too.\n .catch(() => {})\n .finally(() => {\n this.#pendingDeliveries -= 1;\n });\n }\n}\n\n/**\n * `Blob.arrayBuffer()` with a `FileReader` fallback — jsdom (a popular test\n * environment for apps using this class) ships `Blob` without the method.\n */\nfunction blobToArrayBuffer(blob: Blob): Promise<ArrayBuffer> {\n if (typeof blob.arrayBuffer === \"function\") {\n return blob.arrayBuffer();\n }\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => {\n resolve(reader.result as ArrayBuffer);\n };\n reader.onerror = () => {\n reject(reader.error ?? new Error(\"Blob read failed\"));\n };\n reader.readAsArrayBuffer(blob);\n });\n}\n\nexport { DurableWebSocket as WebSocket };\n"]}
@@ -0,0 +1,72 @@
1
+ import { W as WebSocketClient, a as WebSocketClientConfig } from './types-BDvztGcG.cjs';
2
+
3
+ /** The durablews options accepted as the constructor's third argument. */
4
+ type DurableWebSocketOptions = Omit<WebSocketClientConfig, "url" | "protocols" | "codec" | "schema">;
5
+ /**
6
+ * A drop-in `WebSocket` that reconnects, with the durable core underneath:
7
+ * full-jitter backoff, bounded queueing, opt-in heartbeat.
8
+ *
9
+ * ```ts
10
+ * import { WebSocket } from "durablews/compat";
11
+ *
12
+ * const ws = new WebSocket("wss://example.com/socket");
13
+ * ws.onmessage = (event) => console.log(event.data);
14
+ * ```
15
+ *
16
+ * Or injected where a library accepts an implementation:
17
+ *
18
+ * ```ts
19
+ * createClient({ url, webSocketImpl: WebSocket }); // graphql-ws
20
+ * ```
21
+ *
22
+ * The underlying durablews client is exposed as `.client` for everything the
23
+ * `WebSocket` shape can't say (state machine, `drop` events, middleware).
24
+ */
25
+ declare class DurableWebSocket extends EventTarget {
26
+ #private;
27
+ static readonly CONNECTING: 0;
28
+ static readonly OPEN: 1;
29
+ static readonly CLOSING: 2;
30
+ static readonly CLOSED: 3;
31
+ readonly CONNECTING: 0;
32
+ readonly OPEN: 1;
33
+ readonly CLOSING: 2;
34
+ readonly CLOSED: 3;
35
+ /** The underlying durablews client — the escape hatch to the full API. */
36
+ readonly client: WebSocketClient;
37
+ readonly url: string;
38
+ /** Always `""` — see the known-deviations table in the docs. */
39
+ readonly protocol = "";
40
+ /** Always `""` — see the known-deviations table in the docs. */
41
+ readonly extensions = "";
42
+ /** Always `0` — see the known-deviations table in the docs. */
43
+ readonly bufferedAmount = 0;
44
+ onopen: ((event: Event) => void) | null;
45
+ onmessage: ((event: MessageEvent) => void) | null;
46
+ onclose: ((event: CloseEvent) => void) | null;
47
+ onerror: ((event: Event) => void) | null;
48
+ constructor(url: string | URL, protocols?: string | string[], options?: DurableWebSocketOptions);
49
+ /**
50
+ * Maps the durable lifecycle onto the four native states. Deviation by
51
+ * design: during automatic reconnection this returns to `CONNECTING`,
52
+ * which a native (one-shot) socket can never do.
53
+ */
54
+ get readyState(): number;
55
+ get binaryType(): BinaryType;
56
+ /**
57
+ * Honored at any time: when set to `"arraybuffer"` after construction,
58
+ * `Blob` frames are converted on delivery (order-preserving). Prefer
59
+ * passing `binaryType` in the constructor options, which configures the
60
+ * socket itself and avoids the conversion copy.
61
+ */
62
+ set binaryType(value: BinaryType);
63
+ /**
64
+ * Sends data, with durability semantics: while (re)connecting the message
65
+ * is queued and flushed on open (a native socket would throw). After
66
+ * `close()` it is silently discarded, matching native behavior.
67
+ */
68
+ send(data: string | ArrayBufferLike | Blob | ArrayBufferView): void;
69
+ close(code?: number, reason?: string): void;
70
+ }
71
+
72
+ export { DurableWebSocket, type DurableWebSocketOptions, DurableWebSocket as WebSocket };
@@ -0,0 +1,72 @@
1
+ import { W as WebSocketClient, a as WebSocketClientConfig } from './types-BDvztGcG.js';
2
+
3
+ /** The durablews options accepted as the constructor's third argument. */
4
+ type DurableWebSocketOptions = Omit<WebSocketClientConfig, "url" | "protocols" | "codec" | "schema">;
5
+ /**
6
+ * A drop-in `WebSocket` that reconnects, with the durable core underneath:
7
+ * full-jitter backoff, bounded queueing, opt-in heartbeat.
8
+ *
9
+ * ```ts
10
+ * import { WebSocket } from "durablews/compat";
11
+ *
12
+ * const ws = new WebSocket("wss://example.com/socket");
13
+ * ws.onmessage = (event) => console.log(event.data);
14
+ * ```
15
+ *
16
+ * Or injected where a library accepts an implementation:
17
+ *
18
+ * ```ts
19
+ * createClient({ url, webSocketImpl: WebSocket }); // graphql-ws
20
+ * ```
21
+ *
22
+ * The underlying durablews client is exposed as `.client` for everything the
23
+ * `WebSocket` shape can't say (state machine, `drop` events, middleware).
24
+ */
25
+ declare class DurableWebSocket extends EventTarget {
26
+ #private;
27
+ static readonly CONNECTING: 0;
28
+ static readonly OPEN: 1;
29
+ static readonly CLOSING: 2;
30
+ static readonly CLOSED: 3;
31
+ readonly CONNECTING: 0;
32
+ readonly OPEN: 1;
33
+ readonly CLOSING: 2;
34
+ readonly CLOSED: 3;
35
+ /** The underlying durablews client — the escape hatch to the full API. */
36
+ readonly client: WebSocketClient;
37
+ readonly url: string;
38
+ /** Always `""` — see the known-deviations table in the docs. */
39
+ readonly protocol = "";
40
+ /** Always `""` — see the known-deviations table in the docs. */
41
+ readonly extensions = "";
42
+ /** Always `0` — see the known-deviations table in the docs. */
43
+ readonly bufferedAmount = 0;
44
+ onopen: ((event: Event) => void) | null;
45
+ onmessage: ((event: MessageEvent) => void) | null;
46
+ onclose: ((event: CloseEvent) => void) | null;
47
+ onerror: ((event: Event) => void) | null;
48
+ constructor(url: string | URL, protocols?: string | string[], options?: DurableWebSocketOptions);
49
+ /**
50
+ * Maps the durable lifecycle onto the four native states. Deviation by
51
+ * design: during automatic reconnection this returns to `CONNECTING`,
52
+ * which a native (one-shot) socket can never do.
53
+ */
54
+ get readyState(): number;
55
+ get binaryType(): BinaryType;
56
+ /**
57
+ * Honored at any time: when set to `"arraybuffer"` after construction,
58
+ * `Blob` frames are converted on delivery (order-preserving). Prefer
59
+ * passing `binaryType` in the constructor options, which configures the
60
+ * socket itself and avoids the conversion copy.
61
+ */
62
+ set binaryType(value: BinaryType);
63
+ /**
64
+ * Sends data, with durability semantics: while (re)connecting the message
65
+ * is queued and flushed on open (a native socket would throw). After
66
+ * `close()` it is silently discarded, matching native behavior.
67
+ */
68
+ send(data: string | ArrayBufferLike | Blob | ArrayBufferView): void;
69
+ close(code?: number, reason?: string): void;
70
+ }
71
+
72
+ export { DurableWebSocket, type DurableWebSocketOptions, DurableWebSocket as WebSocket };
package/dist/compat.js ADDED
@@ -0,0 +1,177 @@
1
+ import { client } from './chunk-MG4TK53H.js';
2
+
3
+ // src/compat.ts
4
+ var rawCodec = {
5
+ // The class's send() signature restricts inputs to WebSocket-sendable
6
+ // values, so the cast only widens what TypeScript already enforced there.
7
+ encode: (data) => data,
8
+ decode: (data) => data
9
+ };
10
+ var CloseEventCtor = typeof CloseEvent !== "undefined" ? CloseEvent : class extends Event {
11
+ code;
12
+ reason;
13
+ wasClean;
14
+ constructor(type, init = {}) {
15
+ super(type);
16
+ this.code = init.code ?? 0;
17
+ this.reason = init.reason ?? "";
18
+ this.wasClean = init.wasClean ?? false;
19
+ }
20
+ };
21
+ var DurableWebSocket = class _DurableWebSocket extends EventTarget {
22
+ static CONNECTING = 0;
23
+ static OPEN = 1;
24
+ static CLOSING = 2;
25
+ static CLOSED = 3;
26
+ CONNECTING = 0;
27
+ OPEN = 1;
28
+ CLOSING = 2;
29
+ CLOSED = 3;
30
+ /** The underlying durablews client — the escape hatch to the full API. */
31
+ client;
32
+ url;
33
+ /** Always `""` — see the known-deviations table in the docs. */
34
+ protocol = "";
35
+ /** Always `""` — see the known-deviations table in the docs. */
36
+ extensions = "";
37
+ /** Always `0` — see the known-deviations table in the docs. */
38
+ bufferedAmount = 0;
39
+ onopen = null;
40
+ onmessage = null;
41
+ onclose = null;
42
+ onerror = null;
43
+ #binaryType;
44
+ // Serializes Blob → ArrayBuffer conversions so message order survives the
45
+ // async hop when binaryType is reassigned after construction. While no
46
+ // conversion is pending, delivery is fully synchronous (native-faithful).
47
+ #deliveryChain = Promise.resolve();
48
+ #pendingDeliveries = 0;
49
+ constructor(url, protocols, options = {}) {
50
+ super();
51
+ this.url = String(url);
52
+ this.#binaryType = options.binaryType ?? "blob";
53
+ this.client = client({
54
+ ...options,
55
+ url,
56
+ protocols,
57
+ codec: rawCodec
58
+ });
59
+ this.client.on("open", () => {
60
+ const event = new Event("open");
61
+ this.dispatchEvent(event);
62
+ this.onopen?.call(this, event);
63
+ });
64
+ this.client.on("message", (data) => {
65
+ this.#deliverMessage(data);
66
+ });
67
+ this.client.on("close", (event) => {
68
+ const compatEvent = new CloseEventCtor("close", {
69
+ code: event.code,
70
+ reason: event.reason,
71
+ wasClean: event.wasClean
72
+ });
73
+ this.dispatchEvent(compatEvent);
74
+ this.onclose?.call(this, compatEvent);
75
+ });
76
+ this.client.on("error", () => {
77
+ const event = new Event("error");
78
+ this.dispatchEvent(event);
79
+ this.onerror?.call(this, event);
80
+ });
81
+ this.client.connect().catch(() => {
82
+ });
83
+ }
84
+ /**
85
+ * Maps the durable lifecycle onto the four native states. Deviation by
86
+ * design: during automatic reconnection this returns to `CONNECTING`,
87
+ * which a native (one-shot) socket can never do.
88
+ */
89
+ get readyState() {
90
+ switch (this.client.state) {
91
+ case "open":
92
+ return _DurableWebSocket.OPEN;
93
+ case "closing":
94
+ return _DurableWebSocket.CLOSING;
95
+ case "closed":
96
+ return _DurableWebSocket.CLOSED;
97
+ default:
98
+ return _DurableWebSocket.CONNECTING;
99
+ }
100
+ }
101
+ get binaryType() {
102
+ return this.#binaryType;
103
+ }
104
+ /**
105
+ * Honored at any time: when set to `"arraybuffer"` after construction,
106
+ * `Blob` frames are converted on delivery (order-preserving). Prefer
107
+ * passing `binaryType` in the constructor options, which configures the
108
+ * socket itself and avoids the conversion copy.
109
+ */
110
+ set binaryType(value) {
111
+ this.#binaryType = value;
112
+ }
113
+ /**
114
+ * Sends data, with durability semantics: while (re)connecting the message
115
+ * is queued and flushed on open (a native socket would throw). After
116
+ * `close()` it is silently discarded, matching native behavior.
117
+ */
118
+ send(data) {
119
+ if (this.client.state === "idle" || this.client.state === "closing" || this.client.state === "closed") {
120
+ return;
121
+ }
122
+ this.client.send(data);
123
+ }
124
+ close(code, reason) {
125
+ this.client.close(code, reason);
126
+ }
127
+ #deliverMessage(data) {
128
+ const dispatch = (value) => {
129
+ const event = new MessageEvent("message", { data: value });
130
+ this.dispatchEvent(event);
131
+ this.onmessage?.call(this, event);
132
+ };
133
+ if (this.#binaryType === "arraybuffer" && typeof Blob !== "undefined" && data instanceof Blob) {
134
+ this.#queueDelivery(async () => {
135
+ try {
136
+ dispatch(await blobToArrayBuffer(data));
137
+ } catch {
138
+ dispatch(data);
139
+ }
140
+ });
141
+ return;
142
+ }
143
+ if (this.#pendingDeliveries === 0) {
144
+ dispatch(data);
145
+ return;
146
+ }
147
+ this.#queueDelivery(() => {
148
+ dispatch(data);
149
+ });
150
+ }
151
+ #queueDelivery(deliver) {
152
+ this.#pendingDeliveries += 1;
153
+ this.#deliveryChain = this.#deliveryChain.then(deliver).catch(() => {
154
+ }).finally(() => {
155
+ this.#pendingDeliveries -= 1;
156
+ });
157
+ }
158
+ };
159
+ function blobToArrayBuffer(blob) {
160
+ if (typeof blob.arrayBuffer === "function") {
161
+ return blob.arrayBuffer();
162
+ }
163
+ return new Promise((resolve, reject) => {
164
+ const reader = new FileReader();
165
+ reader.onload = () => {
166
+ resolve(reader.result);
167
+ };
168
+ reader.onerror = () => {
169
+ reject(reader.error ?? new Error("Blob read failed"));
170
+ };
171
+ reader.readAsArrayBuffer(blob);
172
+ });
173
+ }
174
+
175
+ export { DurableWebSocket, DurableWebSocket as WebSocket };
176
+ //# sourceMappingURL=compat.js.map
177
+ //# sourceMappingURL=compat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/compat.ts"],"names":[],"mappings":"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","file":"compat.js","sourcesContent":["/**\n * Drop-in `WebSocket` compatibility — `import { WebSocket } from \"durablews/compat\"`.\n *\n * A `WebSocket`-shaped class over the durable core, for two audiences:\n * one-line migration of app code that constructs sockets directly, and\n * `webSocketImpl`-style injection points in existing libraries (graphql-ws,\n * y-websocket, realtime SDKs). Fidelity is scoped to those use cases — the\n * known deviations are documented on the docs site, not hidden.\n */\nimport { client } from \"@/client\";\nimport type { Codec, WebSocketClient, WebSocketClientConfig } from \"@/types\";\n\n/**\n * Compat is wire-faithful: no JSON, no transforms. What you send is what the\n * socket sends; what arrives is what you receive.\n */\nconst rawCodec: Codec = {\n // The class's send() signature restricts inputs to WebSocket-sendable\n // values, so the cast only widens what TypeScript already enforced there.\n encode: (data) => data as string | BufferSource | Blob,\n decode: (data) => data\n};\n\ntype CloseEventInitLike = {\n code?: number;\n reason?: string;\n wasClean?: boolean;\n};\n\n/**\n * `CloseEvent` exists in browsers, Deno, Bun, and recent Node — but not in\n * every runtime durablews supports, so fall back to a structural equivalent.\n */\nconst CloseEventCtor: new (\n type: string,\n init?: CloseEventInitLike\n) => CloseEvent =\n typeof CloseEvent !== \"undefined\"\n ? CloseEvent\n : (class extends Event {\n readonly code: number;\n readonly reason: string;\n readonly wasClean: boolean;\n constructor(type: string, init: CloseEventInitLike = {}) {\n super(type);\n this.code = init.code ?? 0;\n this.reason = init.reason ?? \"\";\n this.wasClean = init.wasClean ?? false;\n }\n } as unknown as new (\n type: string,\n init?: CloseEventInitLike\n ) => CloseEvent);\n\n/** The durablews options accepted as the constructor's third argument. */\nexport type DurableWebSocketOptions = Omit<\n WebSocketClientConfig,\n \"url\" | \"protocols\" | \"codec\" | \"schema\"\n>;\n\n/**\n * A drop-in `WebSocket` that reconnects, with the durable core underneath:\n * full-jitter backoff, bounded queueing, opt-in heartbeat.\n *\n * ```ts\n * import { WebSocket } from \"durablews/compat\";\n *\n * const ws = new WebSocket(\"wss://example.com/socket\");\n * ws.onmessage = (event) => console.log(event.data);\n * ```\n *\n * Or injected where a library accepts an implementation:\n *\n * ```ts\n * createClient({ url, webSocketImpl: WebSocket }); // graphql-ws\n * ```\n *\n * The underlying durablews client is exposed as `.client` for everything the\n * `WebSocket` shape can't say (state machine, `drop` events, middleware).\n */\nexport class DurableWebSocket extends EventTarget {\n static readonly CONNECTING = 0 as const;\n static readonly OPEN = 1 as const;\n static readonly CLOSING = 2 as const;\n static readonly CLOSED = 3 as const;\n\n readonly CONNECTING = 0 as const;\n readonly OPEN = 1 as const;\n readonly CLOSING = 2 as const;\n readonly CLOSED = 3 as const;\n\n /** The underlying durablews client — the escape hatch to the full API. */\n readonly client: WebSocketClient;\n\n readonly url: string;\n /** Always `\"\"` — see the known-deviations table in the docs. */\n readonly protocol = \"\";\n /** Always `\"\"` — see the known-deviations table in the docs. */\n readonly extensions = \"\";\n /** Always `0` — see the known-deviations table in the docs. */\n readonly bufferedAmount = 0;\n\n onopen: ((event: Event) => void) | null = null;\n onmessage: ((event: MessageEvent) => void) | null = null;\n onclose: ((event: CloseEvent) => void) | null = null;\n onerror: ((event: Event) => void) | null = null;\n\n #binaryType: BinaryType;\n // Serializes Blob → ArrayBuffer conversions so message order survives the\n // async hop when binaryType is reassigned after construction. While no\n // conversion is pending, delivery is fully synchronous (native-faithful).\n #deliveryChain: Promise<void> = Promise.resolve();\n #pendingDeliveries = 0;\n\n constructor(\n url: string | URL,\n protocols?: string | string[],\n options: DurableWebSocketOptions = {}\n ) {\n super();\n this.url = String(url);\n this.#binaryType = options.binaryType ?? \"blob\";\n this.client = client({\n ...options,\n url,\n protocols,\n codec: rawCodec\n });\n\n this.client.on(\"open\", () => {\n const event = new Event(\"open\");\n this.dispatchEvent(event);\n this.onopen?.call(this, event);\n });\n this.client.on(\"message\", (data) => {\n this.#deliverMessage(data);\n });\n this.client.on(\"close\", (event) => {\n // Re-dispatched as a fresh event: the original already completed\n // its dispatch on the underlying socket.\n const compatEvent = new CloseEventCtor(\"close\", {\n code: event.code,\n reason: event.reason,\n wasClean: event.wasClean\n });\n this.dispatchEvent(compatEvent);\n this.onclose?.call(this, compatEvent);\n });\n this.client.on(\"error\", () => {\n // Native WebSocket error events carry no payload either.\n const event = new Event(\"error\");\n this.dispatchEvent(event);\n this.onerror?.call(this, event);\n });\n\n // A WebSocket connects on construction. Failures surface as\n // error/close events, exactly like the native class.\n this.client.connect().catch(() => {});\n }\n\n /**\n * Maps the durable lifecycle onto the four native states. Deviation by\n * design: during automatic reconnection this returns to `CONNECTING`,\n * which a native (one-shot) socket can never do.\n */\n get readyState(): number {\n switch (this.client.state) {\n case \"open\":\n return DurableWebSocket.OPEN;\n case \"closing\":\n return DurableWebSocket.CLOSING;\n case \"closed\":\n return DurableWebSocket.CLOSED;\n default: // idle | connecting | reconnecting\n return DurableWebSocket.CONNECTING;\n }\n }\n\n get binaryType(): BinaryType {\n return this.#binaryType;\n }\n\n /**\n * Honored at any time: when set to `\"arraybuffer\"` after construction,\n * `Blob` frames are converted on delivery (order-preserving). Prefer\n * passing `binaryType` in the constructor options, which configures the\n * socket itself and avoids the conversion copy.\n */\n set binaryType(value: BinaryType) {\n this.#binaryType = value;\n }\n\n /**\n * Sends data, with durability semantics: while (re)connecting the message\n * is queued and flushed on open (a native socket would throw). After\n * `close()` it is silently discarded, matching native behavior.\n */\n send(data: string | ArrayBufferLike | Blob | ArrayBufferView) {\n if (\n this.client.state === \"idle\" ||\n this.client.state === \"closing\" ||\n this.client.state === \"closed\"\n ) {\n // Native sockets don't throw on send-after-close; stay faithful.\n return;\n }\n this.client.send(data);\n }\n\n close(code?: number, reason?: string) {\n this.client.close(code, reason);\n }\n\n #deliverMessage(data: unknown) {\n const dispatch = (value: unknown) => {\n const event = new MessageEvent(\"message\", { data: value });\n this.dispatchEvent(event);\n this.onmessage?.call(this, event);\n };\n // Emulation path: binaryType was set to \"arraybuffer\" after\n // construction, but the socket is still delivering Blobs.\n if (\n this.#binaryType === \"arraybuffer\" &&\n typeof Blob !== \"undefined\" &&\n data instanceof Blob\n ) {\n this.#queueDelivery(async () => {\n try {\n dispatch(await blobToArrayBuffer(data));\n } catch {\n // Conversion unavailable: raw delivery beats silence.\n dispatch(data);\n }\n });\n return;\n }\n if (this.#pendingDeliveries === 0) {\n // The common case: no conversion in flight → synchronous,\n // exactly like a native socket.\n dispatch(data);\n return;\n }\n // A conversion is ahead of us: queue behind it to preserve order.\n this.#queueDelivery(() => {\n dispatch(data);\n });\n }\n\n #queueDelivery(deliver: () => void | Promise<void>) {\n this.#pendingDeliveries += 1;\n this.#deliveryChain = this.#deliveryChain\n .then(deliver)\n // A listener throwing must not poison the chain for later\n // messages; native dispatch isolates listener errors too.\n .catch(() => {})\n .finally(() => {\n this.#pendingDeliveries -= 1;\n });\n }\n}\n\n/**\n * `Blob.arrayBuffer()` with a `FileReader` fallback — jsdom (a popular test\n * environment for apps using this class) ships `Blob` without the method.\n */\nfunction blobToArrayBuffer(blob: Blob): Promise<ArrayBuffer> {\n if (typeof blob.arrayBuffer === \"function\") {\n return blob.arrayBuffer();\n }\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => {\n resolve(reader.result as ArrayBuffer);\n };\n reader.onerror = () => {\n reject(reader.error ?? new Error(\"Blob read failed\"));\n };\n reader.readAsArrayBuffer(blob);\n });\n}\n\nexport { DurableWebSocket as WebSocket };\n"]}