@shadow-js/realtime 1.0.0 → 1.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.
Files changed (47) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/dev/adapter.d.ts +0 -2
  3. package/dist/dev/client/core.d.ts +0 -2
  4. package/dist/dev/client/core.js +1 -2
  5. package/dist/dev/client/presence.js +1 -2
  6. package/dist/dev/client/sse.js +1 -2
  7. package/dist/dev/client/types.d.ts +0 -2
  8. package/dist/dev/client/util.js +1 -2
  9. package/dist/dev/client/ws.js +1 -2
  10. package/dist/dev/cloudflare/adapter.d.ts +0 -2
  11. package/dist/dev/cloudflare/adapter.js +1 -2
  12. package/dist/dev/cloudflare/core.js +1 -2
  13. package/dist/dev/cloudflare/link.js +1 -2
  14. package/dist/dev/cloudflare/object.d.ts +0 -2
  15. package/dist/dev/cloudflare/object.js +1 -2
  16. package/dist/dev/cloudflare/types.d.ts +0 -2
  17. package/dist/dev/cloudflare/wire.js +1 -2
  18. package/dist/dev/errors.d.ts +0 -2
  19. package/dist/dev/errors.js +1 -2
  20. package/dist/dev/hooks.d.ts +0 -2
  21. package/dist/dev/hooks.js +1 -2
  22. package/dist/dev/memory.d.ts +0 -2
  23. package/dist/dev/memory.js +1 -2
  24. package/dist/dev/protocol.d.ts +0 -2
  25. package/dist/dev/protocol.js +1 -2
  26. package/dist/dev/redis/client.d.ts +0 -2
  27. package/dist/dev/redis/client.js +1 -2
  28. package/dist/dev/redis/scripts.js +1 -2
  29. package/dist/dev/redis/topics.d.ts +0 -2
  30. package/dist/dev/redis/topics.js +1 -2
  31. package/dist/dev/redis.d.ts +0 -2
  32. package/dist/dev/redis.js +1 -2
  33. package/dist/dev/server/http.d.ts +0 -2
  34. package/dist/dev/server/http.js +1 -2
  35. package/dist/dev/server/hub.d.ts +0 -2
  36. package/dist/dev/server/hub.js +1 -2
  37. package/dist/dev/server/index.d.ts +0 -2
  38. package/dist/dev/server/index.js +1 -2
  39. package/dist/dev/server/limits.d.ts +0 -2
  40. package/dist/dev/server/limits.js +1 -2
  41. package/dist/dev/server/rules.d.ts +0 -2
  42. package/dist/dev/server/rules.js +1 -2
  43. package/dist/dev/testing.d.ts +0 -2
  44. package/dist/dev/testing.js +1 -2
  45. package/dist/prod/client/core.js +1 -1
  46. package/dist/prod/client/core.js.map +1 -1
  47. package/package.json +5 -5
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.1
4
+
5
+ ### Changed
6
+
7
+ - Released at 1.0.1 with the other packages, which share one version. No change to this package.
8
+
3
9
  ## 1.0.0
4
10
 
5
11
  ### Added
@@ -1,5 +1,4 @@
1
1
  import { Member, PresenceEvent, StoredEntry, StoredMessage } from "./protocol.js";
2
- //#region src/adapter.d.ts
3
2
  /** How a publish is retained and deduplicated. @since 1.0.0 */
4
3
  export interface PublishOptions {
5
4
  /** Messages kept per channel (0 keeps none). */
@@ -71,5 +70,4 @@ export interface Adapter {
71
70
  /** Releases connections and timers. */
72
71
  close(): Promise<void>;
73
72
  }
74
- //#endregion
75
73
  //# sourceMappingURL=adapter.d.ts.map
@@ -1,5 +1,4 @@
1
1
  import { ChannelSchema, Realtime, RealtimeOptions } from "./types.js";
2
- //#region src/client/core.d.ts
3
2
  /**
4
3
  * Creates the realtime client: one transport (WebSocket, falling back to server-sent ev), reconnects with backoff, a
5
4
  * bounded offline queue, resume from the last sequence number and typed channels. It connects when the first channel
@@ -20,5 +19,4 @@ import { ChannelSchema, Realtime, RealtimeOptions } from "./types.js";
20
19
  * @since 1.0.0
21
20
  */
22
21
  export declare function createRealtime<Schema extends ChannelSchema = ChannelSchema>(options: RealtimeOptions): Realtime<Schema>;
23
- //#endregion
24
22
  //# sourceMappingURL=core.d.ts.map
@@ -4,7 +4,7 @@ import { applyPresence } from "./presence.js";
4
4
  import { openStream } from "./sse.js";
5
5
  import { backoff, clientId, resolveUrl, sendUrl } from "./util.js";
6
6
  import { openSocket } from "./ws.js";
7
- //#region src/client/core.ts
7
+ // src/client/core.ts
8
8
  /** Close codes that mean the client did something the server will not accept again. */
9
9
  const FATAL = /* @__PURE__ */ new Set([
10
10
  1002,
@@ -839,7 +839,6 @@ function createRealtime(options) {
839
839
  close: () => shutdown()
840
840
  };
841
841
  }
842
- //#endregion
843
842
  export { createRealtime };
844
843
 
845
844
  //# sourceMappingURL=core.js.map
@@ -1,4 +1,4 @@
1
- //#region src/client/presence.ts
1
+ // src/client/presence.ts
2
2
  /**
3
3
  * Applies one presence frame to the member table, ordered by member version so a repeated or reordered event changes
4
4
  * nothing. Returns whether the table changed.
@@ -17,7 +17,6 @@ function applyPresence(table, op, payload) {
17
17
  table.set(member.id, member);
18
18
  return true;
19
19
  }
20
- //#endregion
21
20
  export { applyPresence };
22
21
 
23
22
  //# sourceMappingURL=presence.js.map
@@ -1,5 +1,5 @@
1
1
  import { decodeServerFrame } from "../protocol.js";
2
- //#region src/client/sse.ts
2
+ // src/client/sse.ts
3
3
  /** Splits an event stream into `rt` events; keeps a partial line (and a trailing CR) for the next chunk. @internal */
4
4
  function sseParser(onData) {
5
5
  let buffer = "";
@@ -70,7 +70,6 @@ function openStream(url, send, getHeaders, events) {
70
70
  close: () => control.abort()
71
71
  };
72
72
  }
73
- //#endregion
74
73
  export { openStream, sseParser };
75
74
 
76
75
  //# sourceMappingURL=sse.js.map
@@ -1,5 +1,4 @@
1
1
  import { Json, Member } from "../protocol.js";
2
- //#region src/client/types.d.ts
3
2
  /**
4
3
  * The shape of one channel in a schema: the events it carries, the presence state its members publish and the requests its
5
4
  * server handlers answer.
@@ -252,5 +251,4 @@ export interface Realtime<Schema extends ChannelSchema = ChannelSchema> {
252
251
  /** Closes the connection and every channel. Pending publishes reject with `closed`. */
253
252
  close(): void;
254
253
  }
255
- //#endregion
256
254
  //# sourceMappingURL=types.d.ts.map
@@ -1,4 +1,4 @@
1
- //#region src/client/util.ts
1
+ // src/client/util.ts
2
2
  /** The delay before reconnect attempt `attempt` (0-based): full jitter below an exponential cap. @internal */
3
3
  function backoff(attempt, min, max, random) {
4
4
  return random() * Math.min(max, min * 2 ** Math.min(attempt, 30));
@@ -24,7 +24,6 @@ function sendUrl(url) {
24
24
  next.pathname = `${next.pathname.replace(/\/$/, "")}/send`;
25
25
  return next;
26
26
  }
27
- //#endregion
28
27
  export { backoff, clientId, resolveUrl, sendUrl };
29
28
 
30
29
  //# sourceMappingURL=util.js.map
@@ -1,5 +1,5 @@
1
1
  import { decodeServerFrame } from "../protocol.js";
2
- //#region src/client/ws.ts
2
+ // src/client/ws.ts
3
3
  /** Opens a WebSocket whose text messages are protocol frames. Throws for a URL the constructor refuses. @internal */
4
4
  function openSocket(url, Socket, events) {
5
5
  const socket = new Socket(url);
@@ -33,7 +33,6 @@ function openSocket(url, Socket, events) {
33
33
  }
34
34
  };
35
35
  }
36
- //#endregion
37
36
  export { openSocket };
38
37
 
39
38
  //# sourceMappingURL=ws.js.map
@@ -1,6 +1,5 @@
1
1
  import { Adapter } from "../adapter.js";
2
2
  import { ChannelNamespace } from "./types.js";
3
- //#region src/cloudflare/adapter.d.ts
4
3
  /**
5
4
  * Options of {@link cloudflareAdapter}.
6
5
  * @since 1.0.0
@@ -76,5 +75,4 @@ export interface CloudflareRealtimeOptions {
76
75
  * @since 1.0.0
77
76
  */
78
77
  export declare function cloudflareAdapter(options: CloudflareRealtimeOptions): Adapter;
79
- //#endregion
80
78
  //# sourceMappingURL=adapter.d.ts.map
@@ -1,7 +1,7 @@
1
1
  import { RealtimeError } from "../errors.js";
2
2
  import { isWholeNumber, parseMember, parseStored } from "./wire.js";
3
3
  import { ChannelLink } from "./link.js";
4
- //#region src/cloudflare/adapter.ts
4
+ // src/cloudflare/adapter.ts
5
5
  const ORIGIN = "https://realtime.internal";
6
6
  const PAGE = 512;
7
7
  /** Codes the object answers that are the caller's to see; everything else is `unavailable`. */
@@ -341,7 +341,6 @@ function cloudflareAdapter(options) {
341
341
  }
342
342
  };
343
343
  }
344
- //#endregion
345
344
  export { cloudflareAdapter };
346
345
 
347
346
  //# sourceMappingURL=adapter.js.map
@@ -1,6 +1,6 @@
1
1
  import { RealtimeError } from "../errors.js";
2
2
  import { historyKey, seqOfKey } from "./wire.js";
3
- //#region src/cloudflare/core.ts
3
+ // src/cloudflare/core.ts
4
4
  const META = "meta";
5
5
  const MESSAGES = "h:";
6
6
  const MEMBERS = "p:";
@@ -695,7 +695,6 @@ var ChannelCore = class {
695
695
  });
696
696
  }
697
697
  };
698
- //#endregion
699
698
  export { ChannelCore };
700
699
 
701
700
  //# sourceMappingURL=core.js.map
@@ -1,6 +1,6 @@
1
1
  import { RealtimeError } from "../errors.js";
2
2
  import { decodeLinkFrame } from "./wire.js";
3
- //#region src/cloudflare/link.ts
3
+ // src/cloudflare/link.ts
4
4
  /**
5
5
  * The Worker side of a channel's subscribe socket: one socket per channel and adapter, shared by every local listener, kept
6
6
  * open with backoff, resumed with `after`, and feeding each listener through its own queue.
@@ -391,7 +391,6 @@ var ChannelLink = class {
391
391
  this.#host.forget(this);
392
392
  }
393
393
  };
394
- //#endregion
395
394
  export { ChannelLink };
396
395
 
397
396
  //# sourceMappingURL=link.js.map
@@ -1,5 +1,4 @@
1
1
  import { ChannelObjectState, ChannelSocket } from "./types.js";
2
- //#region src/cloudflare/object.d.ts
3
2
  /**
4
3
  * The pieces of the platform the object creates: a WebSocket pair, the upgrade response and the auto-response pair. The default
5
4
  * reads the Workers globals; the unit tests pass their own.
@@ -78,5 +77,4 @@ export declare class RealtimeChannelObject {
78
77
  */
79
78
  alarm(): Promise<void>;
80
79
  }
81
- //#endregion
82
80
  //# sourceMappingURL=object.d.ts.map
@@ -2,7 +2,7 @@ import { RealtimeError } from "../errors.js";
2
2
  import { isChannelName } from "../protocol.js";
3
3
  import { isOperation, parseRequest } from "./wire.js";
4
4
  import { ChannelCore } from "./core.js";
5
- //#region src/cloudflare/object.ts
5
+ // src/cloudflare/object.ts
6
6
  function workersPlatform() {
7
7
  return {
8
8
  createPair() {
@@ -208,7 +208,6 @@ var RealtimeChannelObject = class {
208
208
  await this.#core.alarm();
209
209
  }
210
210
  };
211
- //#endregion
212
211
  export { RealtimeChannelObject };
213
212
 
214
213
  //# sourceMappingURL=object.js.map
@@ -1,4 +1,3 @@
1
- //#region src/cloudflare/types.d.ts
2
1
  /**
3
2
  * The few shapes of the Cloudflare Workers runtime the Durable Object adapter touches. They are declared here, structurally, so
4
3
  * the package has no dependency on `@cloudflare/workers-types`: the real `DurableObjectNamespace`, `DurableObjectState` and
@@ -96,5 +95,4 @@ export interface ChannelNamespace<Id = unknown> {
96
95
  readonly locationHint?: string;
97
96
  }): ChannelStub;
98
97
  }
99
- //#endregion
100
98
  //# sourceMappingURL=types.d.ts.map
@@ -1,5 +1,5 @@
1
1
  import { byteLength, isChannelName, isEventName, isIdempotencyKey } from "../protocol.js";
2
- //#region src/cloudflare/wire.ts
2
+ // src/cloudflare/wire.ts
3
3
  /** The most bytes of one message (data, event and names) the object stores in one value; the platform's smallest value limit is 128 KiB. @internal */
4
4
  const MAX_ENTRY_BYTES = 122880;
5
5
  /** The most bytes of one member's state. @internal */
@@ -278,7 +278,6 @@ function historyKey(seq) {
278
278
  function seqOfKey(key) {
279
279
  return Number(key.slice(2));
280
280
  }
281
- //#endregion
282
281
  export { MAX_BODY_BYTES, MAX_ENTRY_BYTES, MAX_HISTORY, MAX_MEMBERS, MAX_STATE_BYTES, MAX_TTL_MS, decodeLinkFrame, historyKey, isOperation, isWholeNumber, parseMember, parseRequest, parseStored, seqOfKey };
283
282
 
284
283
  //# sourceMappingURL=wire.js.map
@@ -1,4 +1,3 @@
1
- //#region src/errors.d.ts
2
1
  /**
3
2
  * The codes an error of this package carries. They are the same strings the wire protocol uses in `err` frames.
4
3
  * @since 1.0.0
@@ -21,5 +20,4 @@ export declare class RealtimeError extends Error {
21
20
  readonly cause?: unknown;
22
21
  });
23
22
  }
24
- //#endregion
25
23
  //# sourceMappingURL=errors.d.ts.map
@@ -1,4 +1,4 @@
1
- //#region src/errors.ts
1
+ // src/errors.ts
2
2
  /**
3
3
  * An error with a protocol code. A request handler that throws one answers the client with its code and message; any
4
4
  * other error answers `handler_error` with no message, so internals never reach a client.
@@ -18,7 +18,6 @@ var RealtimeError = class extends Error {
18
18
  this.code = code;
19
19
  }
20
20
  };
21
- //#endregion
22
21
  export { RealtimeError };
23
22
 
24
23
  //# sourceMappingURL=errors.js.map
@@ -1,7 +1,6 @@
1
1
  import { Member } from "./protocol.js";
2
2
  import { AnyMessage, Channel, ChannelDef, ChannelOptions, ChannelSchema, ChannelStatus, MessageMeta, PresenceOf, Realtime, RequestData, RequestReply, RequestsOf, Status } from "./client/types.js";
3
3
  import { Accessor } from "@shadow-js/core";
4
- //#region src/hooks.d.ts
5
4
  /**
6
5
  * What {@link useChannel} returns: the reactive state of a channel and the calls on it.
7
6
  * @since 1.0.0
@@ -106,5 +105,4 @@ export declare function useChannelPresence<Def extends ChannelDef>(channel: Chan
106
105
  * @since 1.0.0
107
106
  */
108
107
  export declare function useRealtimeStatus<Schema extends ChannelSchema>(rt: Realtime<Schema>): Accessor<Status>;
109
- //#endregion
110
108
  //# sourceMappingURL=hooks.d.ts.map
package/dist/dev/hooks.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { RealtimeError } from "./errors.js";
2
2
  import { isServer, onCleanup, useSignal } from "@shadow-js/core";
3
- //#region src/hooks.ts
3
+ // src/hooks.ts
4
4
  /** A channel for the server render: it never connects, listens or publishes. */
5
5
  function inertChannel(name) {
6
6
  const refuse = () => Promise.reject(new RealtimeError("closed", "a realtime channel is not available during the server render"));
@@ -156,7 +156,6 @@ function useRealtimeStatus(rt) {
156
156
  if (!isServer) onCleanup(rt.onStatus((next) => setStatus(next)));
157
157
  return status;
158
158
  }
159
- //#endregion
160
159
  export { useChannel, useChannelEvent, useChannelPresence, useRealtimeStatus };
161
160
 
162
161
  //# sourceMappingURL=hooks.js.map
@@ -1,5 +1,4 @@
1
1
  import { Adapter } from "./adapter.js";
2
- //#region src/memory.d.ts
3
2
  /**
4
3
  * Options of {@link memoryAdapter}.
5
4
  * @since 1.0.0
@@ -29,5 +28,4 @@ export interface MemoryAdapterOptions {
29
28
  * @since 1.0.0
30
29
  */
31
30
  export declare function memoryAdapter(options?: MemoryAdapterOptions): Adapter;
32
- //#endregion
33
31
  //# sourceMappingURL=memory.d.ts.map
@@ -1,4 +1,4 @@
1
- //#region src/memory.ts
1
+ // src/memory.ts
2
2
  /**
3
3
  * The single-process adapter, and the default of `createHub`. Messages, history, idempotency keys and presence live in memory
4
4
  * of this process; several hubs created over one adapter object share them, which is how tests exercise two servers. Use the Redis
@@ -249,7 +249,6 @@ function memoryAdapter(options = {}) {
249
249
  }
250
250
  };
251
251
  }
252
- //#endregion
253
252
  export { memoryAdapter };
254
253
 
255
254
  //# sourceMappingURL=memory.js.map
@@ -1,5 +1,4 @@
1
1
  import { ErrorCode } from "./errors.js";
2
- //#region src/protocol.d.ts
3
2
  /**
4
3
  * The wire protocol version this package speaks (https://realtime.shadowjs.net/guides/realtime-protocol/).
5
4
  * @example
@@ -207,5 +206,4 @@ export type ServerFrame = {
207
206
  * @since 1.0.0
208
207
  */
209
208
  export declare function decodeServerFrame(text: string): ServerFrame | undefined;
210
- //#endregion
211
209
  //# sourceMappingURL=protocol.d.ts.map
@@ -1,4 +1,4 @@
1
- //#region src/protocol.ts
1
+ // src/protocol.ts
2
2
  /**
3
3
  * The wire protocol version this package speaks (https://realtime.shadowjs.net/guides/realtime-protocol/).
4
4
  * @example
@@ -394,7 +394,6 @@ function decodeServerFrame(text) {
394
394
  default: return;
395
395
  }
396
396
  }
397
- //#endregion
398
397
  export { PROTOCOL_VERSION, byteLength, decodeClientFrame, decodeServerFrame, isChannelName, isEventName, isIdempotencyKey };
399
398
 
400
399
  //# sourceMappingURL=protocol.js.map
@@ -1,4 +1,3 @@
1
- //#region src/redis/client.d.ts
2
1
  /**
3
2
  * What the Redis adapter needs from a Redis library, and the two wrappers that adapt the common ones. The adapter has no
4
3
  * dependency on a Redis package: it is written against these small interfaces, which ioredis and node-redis satisfy through
@@ -135,5 +134,4 @@ export declare function fromIoredis(client: IoredisLike): RedisClient;
135
134
  * @since 1.0.0
136
135
  */
137
136
  export declare function fromNodeRedis(client: NodeRedisLike): RedisClient;
138
- //#endregion
139
137
  //# sourceMappingURL=client.d.ts.map
@@ -1,4 +1,4 @@
1
- //#region src/redis/client.ts
1
+ // src/redis/client.ts
2
2
  /** A set of handlers with add-and-remove, shared by the two wrappers. */
3
3
  function handlers() {
4
4
  const set = /* @__PURE__ */ new Set();
@@ -140,7 +140,6 @@ function fromNodeRedis(client) {
140
140
  }
141
141
  };
142
142
  }
143
- //#endregion
144
143
  export { fromIoredis, fromNodeRedis };
145
144
 
146
145
  //# sourceMappingURL=client.js.map
@@ -1,4 +1,4 @@
1
- //#region src/redis/scripts.ts
1
+ // src/redis/scripts.ts
2
2
  function rotateLeft(value, bits) {
3
3
  return (value << bits | value >>> 32 - bits) >>> 0;
4
4
  }
@@ -269,7 +269,6 @@ for from = 1, #ids, step do
269
269
  end
270
270
  return out
271
271
  `);
272
- //#endregion
273
272
  export { HISTORY, KEEPALIVE, PRESENCE_LIST, PRESENCE_REAP, PRESENCE_REMOVE, PRESENCE_SET, PRESENCE_TOUCH, PUBLISH, sha1 };
274
273
 
275
274
  //# sourceMappingURL=scripts.js.map
@@ -1,8 +1,6 @@
1
- //#region src/redis/topics.d.ts
2
1
  /** Where a failure the adapter handled came from. */
3
2
  export interface RedisErrorContext {
4
3
  readonly where: string;
5
4
  readonly channel?: string;
6
5
  }
7
- //#endregion
8
6
  //# sourceMappingURL=topics.d.ts.map
@@ -1,4 +1,4 @@
1
- //#region src/redis/topics.ts
1
+ // src/redis/topics.ts
2
2
  /** Live messages held while a recovery reads history; a larger burst falls back to reading history again. */
3
3
  const CATCH_UP_BUFFER = 1e3;
4
4
  /** Messages read per history page during recovery. */
@@ -371,7 +371,6 @@ function createTopics(deps) {
371
371
  }
372
372
  };
373
373
  }
374
- //#endregion
375
374
  export { createTopics };
376
375
 
377
376
  //# sourceMappingURL=topics.js.map
@@ -1,7 +1,6 @@
1
1
  import { Adapter } from "./adapter.js";
2
2
  import { IoredisLike, IoredisSubscriberLike, NodeRedisLike, NodeRedisSubscriberLike, RedisClient, RedisSubscriber, fromIoredis, fromNodeRedis } from "./redis/client.js";
3
3
  import { RedisErrorContext } from "./redis/topics.js";
4
- //#region src/redis.d.ts
5
4
  /**
6
5
  * Options of {@link redisAdapter}.
7
6
  * @since 1.0.0
@@ -63,6 +62,5 @@ export interface RedisAdapterOptions {
63
62
  * @since 1.0.0
64
63
  */
65
64
  export declare function redisAdapter(options: RedisAdapterOptions): Adapter;
66
- //#endregion
67
65
  export { type IoredisLike, type IoredisSubscriberLike, type NodeRedisLike, type NodeRedisSubscriberLike, type RedisClient, type RedisErrorContext, type RedisSubscriber, fromIoredis, fromNodeRedis };
68
66
  //# sourceMappingURL=redis.d.ts.map
package/dist/dev/redis.js CHANGED
@@ -2,7 +2,7 @@ import { RealtimeError } from "./errors.js";
2
2
  import { HISTORY, KEEPALIVE, PRESENCE_LIST, PRESENCE_REAP, PRESENCE_REMOVE, PRESENCE_SET, PRESENCE_TOUCH, PUBLISH } from "./redis/scripts.js";
3
3
  import { createTopics } from "./redis/topics.js";
4
4
  import { fromIoredis, fromNodeRedis } from "./redis/client.js";
5
- //#region src/redis.ts
5
+ // src/redis.ts
6
6
  const DAY_MS = 864e5;
7
7
  const MAX_LIMIT = 1e4;
8
8
  const MAX_KEY_BYTES = 1024;
@@ -416,7 +416,6 @@ function redisAdapter(options) {
416
416
  }
417
417
  };
418
418
  }
419
- //#endregion
420
419
  export { fromIoredis, fromNodeRedis, redisAdapter };
421
420
 
422
421
  //# sourceMappingURL=redis.js.map
@@ -1,5 +1,4 @@
1
1
  import { Identity } from "./rules.js";
2
- //#region src/server/http.d.ts
3
2
  /** What a hub needs from the framework's request event. @since 1.0.0 */
4
3
  export interface RequestLike {
5
4
  readonly request: Request;
@@ -44,5 +43,4 @@ export interface SseLike {
44
43
  readonly signal: AbortSignal;
45
44
  readonly closed: boolean;
46
45
  }
47
- //#endregion
48
46
  //# sourceMappingURL=http.d.ts.map
@@ -1,7 +1,7 @@
1
1
  import { RealtimeError } from "../errors.js";
2
2
  import { byteLength } from "../protocol.js";
3
3
  import { TokenBucket } from "./limits.js";
4
- //#region src/server/http.ts
4
+ // src/server/http.ts
5
5
  const KEY = "$realtime";
6
6
  const MAX_FRAMES_PER_POST = 64;
7
7
  const MAX_SUBSCRIPTIONS_IN_QUERY = 64;
@@ -280,7 +280,6 @@ function postRoute(hub, options = {}) {
280
280
  });
281
281
  };
282
282
  }
283
- //#endregion
284
283
  export { postRoute, sseRoute, websocketRoute };
285
284
 
286
285
  //# sourceMappingURL=http.js.map
@@ -2,7 +2,6 @@ import { Json } from "../protocol.js";
2
2
  import { Adapter, PublishResult } from "../adapter.js";
3
3
  import { ChannelRule, Identity, RuleContext } from "./rules.js";
4
4
  import { HubLimits, TokenBucket } from "./limits.js";
5
- //#region src/server/hub.d.ts
6
5
  /**
7
6
  * What a hub needs from a connection's transport. A WebSocket, an SSE stream and an in-memory test client all fit.
8
7
  * @since 1.0.0
@@ -110,5 +109,4 @@ export interface HubCore {
110
109
  /** @internal Evaluates a rule permission for an identity. */
111
110
  allowed(rule: ChannelRule, op: RuleContext["op"], channel: string, params: Record<string, string>, identity: Identity): Promise<boolean>;
112
111
  }
113
- //#endregion
114
112
  //# sourceMappingURL=hub.d.ts.map
@@ -3,7 +3,7 @@ import { byteLength, decodeClientFrame, isChannelName, isEventName, isIdempotenc
3
3
  import { TokenBucket, WindowCounter, resolveLimits } from "./limits.js";
4
4
  import { memoryAdapter } from "../memory.js";
5
5
  import { compileRule, matchRule } from "./rules.js";
6
- //#region src/server/hub.ts
6
+ // src/server/hub.ts
7
7
  const REPLAY_PAGE = 500;
8
8
  const MAX_PUMP_BUFFER = 1e4;
9
9
  const ID_BYTES = 16;
@@ -821,7 +821,6 @@ function createHubCore(options = {}) {
821
821
  };
822
822
  return core;
823
823
  }
824
- //#endregion
825
824
  export { createHubCore };
826
825
 
827
826
  //# sourceMappingURL=hub.js.map
@@ -4,7 +4,6 @@ import { DEFAULT_HUB_LIMITS, HubLimits } from "./limits.js";
4
4
  import { ConnectOptions, ErrorContext, HubConnection, HubCore, HubOptions, HubStats, RevokeTarget, Transport } from "./hub.js";
5
5
  import { AuthenticateResult, HubRouteOptions, RequestLike, SseLike, WebSocketLike, WebSocketRoute } from "./http.js";
6
6
  import { memoryAdapter } from "../memory.js";
7
- //#region src/server/index.d.ts
8
7
  /**
9
8
  * The server object of `@shadow-js/realtime`: connections, channel rules, limits and an adapter, with the routes that
10
9
  * connect it to a transport.
@@ -42,6 +41,5 @@ export interface Hub extends HubCore {
42
41
  * @since 1.0.0
43
42
  */
44
43
  export declare function createHub(options?: HubOptions): Hub;
45
- //#endregion
46
44
  export { type Adapter, type AuthenticateResult, type ChannelRule, type ConnectOptions, DEFAULT_HUB_LIMITS, type ErrorContext, type HubConnection, type HubLimits, type HubOptions, type HubRouteOptions, type HubStats, type Identity, type Permission, type RequestContext, type RequestHandler, type RequestLike, type RevokeTarget, type RuleContext, type SseLike, type Transport, type WebSocketLike, type WebSocketRoute, memoryAdapter };
47
45
  //# sourceMappingURL=index.d.ts.map
@@ -2,7 +2,7 @@ import { DEFAULT_HUB_LIMITS } from "./limits.js";
2
2
  import { postRoute, sseRoute, websocketRoute } from "./http.js";
3
3
  import { memoryAdapter } from "../memory.js";
4
4
  import { createHubCore } from "./hub.js";
5
- //#region src/server/index.ts
5
+ // src/server/index.ts
6
6
  /**
7
7
  * Creates the hub: the server side of `@shadow-js/realtime`. It owns connections and channel rules (default deny), enforces the
8
8
  * limits, and talks to one adapter (in memory by default; Redis or Cloudflare when several servers share channels).
@@ -35,7 +35,6 @@ function createHub(options = {}) {
35
35
  });
36
36
  return hub;
37
37
  }
38
- //#endregion
39
38
  export { DEFAULT_HUB_LIMITS, createHub, memoryAdapter };
40
39
 
41
40
  //# sourceMappingURL=index.js.map
@@ -1,4 +1,3 @@
1
- //#region src/server/limits.d.ts
2
1
  /**
3
2
  * The limits of a hub. Every one is bounded, so a hub cannot be made to hold unbounded state (see the realtime protocol reference).
4
3
  * @since 1.0.0
@@ -50,5 +49,4 @@ export declare class TokenBucket {
50
49
  /** Takes one token; false when the bucket is empty. */
51
50
  take(now: number): boolean;
52
51
  }
53
- //#endregion
54
52
  //# sourceMappingURL=limits.d.ts.map
@@ -1,4 +1,4 @@
1
- //#region src/server/limits.ts
1
+ // src/server/limits.ts
2
2
  /** The defaults of {@link HubLimits}. @since 1.0.0 */
3
3
  const DEFAULT_HUB_LIMITS = Object.freeze({
4
4
  maxMessageBytes: 65536,
@@ -79,7 +79,6 @@ var WindowCounter = class {
79
79
  return this.#times.length >= this.#limit;
80
80
  }
81
81
  };
82
- //#endregion
83
82
  export { DEFAULT_HUB_LIMITS, MAX_HISTORY, TokenBucket, WindowCounter, resolveLimits };
84
83
 
85
84
  //# sourceMappingURL=limits.js.map
@@ -1,5 +1,4 @@
1
1
  import { Json } from "../protocol.js";
2
- //#region src/server/rules.d.ts
3
2
  /** Who a connection is. `user` identifies a person; other claims are the app's. @since 1.0.0 */
4
3
  export interface Identity {
5
4
  readonly user?: string;
@@ -39,5 +38,4 @@ export interface ChannelRule<Params extends Readonly<Record<string, string>> = R
39
38
  /** Request handlers by event name. */
40
39
  readonly handlers?: Readonly<Record<string, RequestHandler<Params>>>;
41
40
  }
42
- //#endregion
43
41
  //# sourceMappingURL=rules.d.ts.map
@@ -1,4 +1,4 @@
1
- //#region src/server/rules.ts
1
+ // src/server/rules.ts
2
2
  const PARAM = /^\{([A-Za-z_][A-Za-z0-9_]*)\}$/;
3
3
  const REST = /^\{\.\.\.([A-Za-z_][A-Za-z0-9_]*)\}$/;
4
4
  const LITERAL = /^[A-Za-z0-9_.@/-]+$/;
@@ -66,7 +66,6 @@ function matchRule(compiled, channel) {
66
66
  }
67
67
  return params;
68
68
  }
69
- //#endregion
70
69
  export { compileRule, matchRule };
71
70
 
72
71
  //# sourceMappingURL=rules.js.map
@@ -2,7 +2,6 @@ import { ServerFrame } from "./protocol.js";
2
2
  import { Adapter } from "./adapter.js";
3
3
  import { Identity } from "./server/rules.js";
4
4
  import { Hub } from "./server/index.js";
5
- //#region src/testing.d.ts
6
5
  /**
7
6
  * A connection to a hub with no network: frames go in as objects and come out decoded. For tests of an app's channel rules and
8
7
  * request handlers.
@@ -111,5 +110,4 @@ export interface ConformanceOptions {
111
110
  * @since 1.0.0
112
111
  */
113
112
  export declare function adapterConformance(options: ConformanceOptions): void;
114
- //#endregion
115
113
  //# sourceMappingURL=testing.d.ts.map
@@ -1,5 +1,5 @@
1
1
  import { decodeServerFrame } from "./protocol.js";
2
- //#region src/testing.ts
2
+ // src/testing.ts
3
3
  /**
4
4
  * Opens a {@link TestConnection} to `hub`.
5
5
  *
@@ -421,7 +421,6 @@ function adapterConformance(options) {
421
421
  });
422
422
  });
423
423
  }
424
- //#endregion
425
424
  export { adapterConformance, connectTest, memoryWebSocket };
426
425
 
427
426
  //# sourceMappingURL=testing.js.map
@@ -1,2 +1,2 @@
1
- import{RealtimeError as e}from"../errors.js";import{byteLength as t,decodeServerFrame as n,isChannelName as r,isEventName as i,isIdempotencyKey as a}from"../protocol.js";import{applyPresence as o}from"./presence.js";import{openStream as s}from"./sse.js";import{backoff as c,clientId as ee,resolveUrl as l,sendUrl as u}from"./util.js";import{openSocket as te}from"./ws.js";const ne=/* @__PURE__ */ new Set([1002,1008,1009]),re=/* @__PURE__ */ new Set([`unavailable`,`rate_limited`,`timeout`]),ie=/* @__PURE__ */ new Set([408,425,429]);function d(d){let f=d.reconnect??{},p=f.minDelayMs??250,m=f.maxDelayMs??3e4,ae=f.stableMs??5e3,h=f.random??Math.random,oe=d.maxQueued??100,se=d.queueTtlMs??3e4,ce=d.ackTimeoutMs??1e4,le=(d.transport??`auto`)===`auto`,ue=ee(),g=new AbortController,_=/* @__PURE__ */ new Map,v=/* @__PURE__ */ new Set,y=[],b=/* @__PURE__ */ new Map,x=/* @__PURE__ */ new Set,S=`connecting`,C=d.transport===`sse`?`sse`:`ws`,w=!1,T=!1,E,D=0,O=!1,k,de=65536,fe=``,pe,A=0,j=0,me=0,he=0,ge=0,M=!1,N=0,P,F,_e,ve,ye=!1,I,L=0,R=!1,z=e=>{try{d.onError===void 0?console.error(`[realtime]`,e):d.onError(e)}catch{}},B=e=>{try{e()}catch(e){z(e)}},be=(e,t)=>(d.fetch??globalThis.fetch)(e,t),xe=()=>typeof d.headers==`function`?d.headers():d.headers,V=(e,t)=>{for(let n of[...e])B(()=>n(t))},H=e=>{e!==S&&(S=e,d.onStatus!==void 0&&B(()=>d.onStatus?.(e)),V(x,e))},U=(e,t)=>{e.status!==t&&(e.status=t,V(e.sl,t))},Se=(e,t,n)=>{clearTimeout(e.timer);let r=e.settle;e.settle=void 0,r===void 0?t!==void 0&&e.kind===`pub`&&z(t):r(t,n)},W=(e,t)=>Se(e,t),Ce=(e,t)=>Se(e,void 0,t),G=(t,n)=>{clearTimeout(t.timer),t.timer=setTimeout(()=>{let n=y.indexOf(t);n>=0&&y.splice(n,1),b.get(t.n)===t&&b.delete(t.n),W(t,new e(`timeout`))},n)},K=e=>{let t=b.get(e);return t!==void 0&&b.delete(e),t},we=t=>{if(w)return new e(`closed`);let n=O&&C===`ws`;if(t.kind!==`pres`&&!n&&y.length>=oe)return new e(`queue_full`);if(t.kind===`pres`){let e=y.findIndex(e=>e.kind===`pres`&&e.chan===t.chan);e>=0&&y.splice(e,1)}else G(t,se);y.push(t),O?$():Ye()},Te=(e,t,n,r,i)=>({kind:e,chan:t,event:n,data:r,key:i.key,ack:i.ack??!0,ms:i.ms??0,order:++ge,n:0,timer:void 0,settle:i.settle}),q=n=>{let r=JSON.stringify(n.chan.name),i=n.kind===`req`||n.kind===`pub`&&n.ack;n.n=i?++me:0;let a=n.kind===`pres`?`{"t":"pres","c":${r},"s":${n.data}}`:n.kind===`req`?`{"t":"req","n":${n.n},"c":${r},"e":"${n.event}","d":${n.data},"ms":${n.ms}}`:`{"t":"pub","c":${r},"e":"${n.event}","d":${n.data}${i?`,"n":${n.n}`:``},"k":${JSON.stringify(n.key)}}`;if(t(a)>de)W(n,new e(`too_large`));else return a},Ee=e=>{e.kind!==`pres`&&(e.kind===`req`||e.ack?(b.set(e.n,e),G(e,e.kind===`req`?e.ms+1e3:ce)):clearTimeout(e.timer))},De=t=>{t.sort((e,t)=>e.order-t.order);let n=[];for(let r of t)r.kind===`req`?W(r,new e(`closed`)):(r.kind===`pub`&&G(r,se),n.push(r));y.unshift(...n)},J=e=>!e.closed&&(e.refs>0||e.state!==void 0||e.options.watch===!0||e.hd>0&&C===`ws`),Y=e=>e.state!==void 0,Oe=e=>!Y(e)&&(e.presence.size>0||e.options.watch===!0),X=e=>{e.status===`idle`&&J(e)&&U(e,`subscribing`),v.add(e),Ye()},ke=(e,t)=>{let n=Y(e),r=Oe(e),i=e.sy?e.last:e.options.replay===!0?0:void 0;return e.w={n:t,join:n,watch:r,after:i,ver:e.sv,ready:!n},U(e,e.sy?`resuming`:`subscribing`),{fields:{c:e.name,...i===void 0?{}:{after:i},...e.options.echo===!1?{echo:!1}:{},...n?{presence:e.state}:{},...r?{watch:!0}:{}}}},Ae=e=>{let t=e.w;if(t===void 0||e.state===void 0)return;t.ver=e.sv;let n=Te(`pres`,e,``,JSON.stringify(e.state),{});if(C===`ws`){let e=q(n);e!==void 0&&E?.send(e)}else we(n)},je=e=>{e.sy=!1,e.last=0,e.w=void 0,clearTimeout(e.retry),e.retry=void 0,e.fails=0,e.members.size>0&&(e.members.clear(),e.list=void 0),U(e,e.closed?`closed`:`idle`)},Me=e=>{let t=J(e),n=e.w;if(C===`ws`&&O&&(n!==void 0&&(!t||n.join!==Y(e)||n.watch!==Oe(e))&&(E?.send(`{"t":"unsub","c":${JSON.stringify(e.name)}}`),e.w=void 0),t&&e.w===void 0&&e.retry===void 0)){let t=++me;E?.send(JSON.stringify({t:`sub`,n:t,...ke(e,t).fields}))}if(!t){e.status!==`idle`&&e.status!==`closed`&&je(e);return}let r=e.w;r?.join&&r.ready&&r.ver!==e.sv&&Ae(e)},Ne=()=>{let e=[...v];v.clear();for(let t of e)Me(t)},Z=(e,t)=>{e.closed||(e.closed=!0,_.get(e.name)===e&&_.delete(e.name),e.w!==void 0&&C===`ws`&&O&&E?.send(`{"t":"unsub","c":${JSON.stringify(e.name)}}`),je(e),e.ev.clear(),e.any.clear(),e.gl.clear(),e.presence.clear(),e.sl.clear(),e.refs=0,v.delete(e),t!==void 0&&z(t),Ye())},Pe=(e,t)=>{e.w=void 0,U(e,e.sy?`resuming`:`subscribing`),t?X(e):(e.retry=setTimeout(()=>{e.retry=void 0,X(e)},c(e.fails,p,m,h)),e.fails+=1)},Fe=()=>{let t=[];for(let n of[..._.values()])J(n)&&(t.length>=64?Z(n,new e(`limit`)):t.push(ke(n,t.length+1).fields));return fe=Ie(),t},Ie=()=>{let e=``;for(let t of _.values())J(t)&&(e+=`${t.name}|${t.options.echo===!1?0:1}${+!!Y(t)}${+!!Oe(t)};`);return e},Q=()=>{if(clearTimeout(F),F=void 0,w||E!==void 0)return;D+=1;let t=D;O=!1,M=!1,N=0;let n={rx:()=>{t===D&&(M=!0)},frame:e=>{t===D&&B(()=>We(e,!1))},closed:e=>{t===D&&ze(e)}};try{if(!R&&typeof addEventListener==`function`&&(R=!0,addEventListener(`online`,Le)),C===`sse`){let e=l(d.url,!1);e.searchParams.set(`s`,JSON.stringify(Fe())),E=s(e.toString(),be,xe,n)}else E=te(l(d.url,!0).toString(),d.WebSocket??globalThis.WebSocket,n)}catch(t){D+=1,Xe(new e(`closed`,`cannot open`,{cause:t}));return}P=setTimeout(()=>{t===D&&ze({})},ce)},Le=()=>{F!==void 0&&Q()},Re=()=>{D+=1;let e=E;E=void 0,O=!1,k=void 0,clearTimeout(P),clearTimeout(_e),clearInterval(ve),ve=void 0,e?.close()},ze=t=>{let n=O,r=pe??t.code;if(pe=void 0,Re(),w)return;if(C===`ws`&&b.size>0){let e=[...b.values()];b.clear(),De(e)}for(let e of _.values())e.w=void 0,clearTimeout(e.retry),e.retry=void 0,J(e)&&U(e,e.sy?`resuming`:`subscribing`);let i=t.status!==void 0&&t.status>=400&&t.status<500&&!ie.has(t.status);if((r!==void 0&&ne.has(r)||i)&&f.retryFatal!==!0){let n=r===void 0?`the server answered ${t.status}`:`the server closed the connection with ${r}`;Xe(new e(`closed`,n));return}let a=c(j,p,m,h);j+=1,n?A=0:le&&C===`ws`&&(A+=1,A>=2&&(C=`sse`,a=0)),H(`reconnecting`),F=setTimeout(Q,a)},Be=()=>{if(M)M=!1,N=0;else if(N+=1,N>=2){ze({});return}C===`ws`&&E?.send(`{"t":"ping"}`)},Ve=()=>{Re();for(let e of _.values())e.w=void 0;Q()},He=e=>{if(!O){if(O=!0,k=e.id,de=e.max,A=0,M=!0,N=0,clearTimeout(P),e.hb>0&&(ve=setInterval(Be,e.hb)),_e=setTimeout(()=>{j=0},ae),H(`open`),C===`ws`)for(let e of _.values())v.add(e);$()}},Ue=e=>{let t=[...e.members.values()];e.list=t,V(e.presence,t)},We=(t,n)=>{switch(t.t){case`ready`:He(t);return;case`bye`:pe=t.code;return;case`subbed`:{let e=_.get(t.c),n=e?.w;if(e===void 0||n===void 0||n.n!==t.n)return;(t.reset||n.after===void 0)&&(e.last=t.head);let r={after:n.after??0,head:t.head},i=t.reset?!0:t.gap===!0&&n.after!==void 0&&!(n.after===0&&!e.sy);e.sy=!0,e.fails=0,U(e,`live`),i&&V(e.gl,{...r,reset:t.reset===!0});return}case`unsubbed`:{let n=_.get(t.c);if(n===void 0)return;t.why===`revoked`?(n.w=void 0,Z(n,new e(`forbidden`,`revoked`))):Pe(n,t.why===`gap`||t.why===`reset`);return}case`msg`:{let e=_.get(t.c);if(e===void 0||t.s<=e.last)return;e.last=t.s;let n={seq:t.s,replayed:t.r===1,...t.p===void 0?{}:{publisher:t.p},...t.u===void 0?{}:{user:t.u}};for(let r of[...e.ev.get(t.e)??[]])B(()=>r(t.d,n));for(let r of[...e.any])B(()=>r({event:t.e,data:t.d,meta:n}));return}case`ack`:{let e=K(t.n);e!==void 0&&Ce(e,{seq:t.s,duplicate:t.dup===!0});return}case`rep`:{let e=K(t.n);e!==void 0&&Ce(e,t.d);return}case`err`:{let r=new e(t.code,t.msg),i=t.c===void 0?void 0:_.get(t.c);if(t.n!==void 0){if(!n&&i?.w?.n===t.n){re.has(t.code)?(Pe(i,!1),z(r)):(i.w=void 0,Z(i,r));return}let e=n||C===`ws`?K(t.n):void 0;if(e!==void 0){W(e,r);return}}z(r);return}case`pres`:{let e=_.get(t.c);if(e===void 0)return;o(e.members,t.op,t.m)&&Ue(e),t.op===`sync`&&e.w!==void 0&&(e.w.ready=!0,e.w.join&&e.w.ver!==e.sv&&Ae(e));return}case`pong`:return}},$=()=>{if(O&&!w){if(Ne(),C===`sse`)Ge();else for(let e=y[0];e!==void 0&&O;e=y[0]){let t=q(e);if(t!==void 0){if(E?.send(t)!==!0)return;Ee(e)}y.shift()}}},Ge=()=>{if(ye||I!==void 0||k===void 0)return;let e=[],t=[],n=0;for(;y.length>0&&e.length<64&&n<256e3;){let r=y.shift();if(r===void 0)break;let i=q(r);i!==void 0&&(e.push(r),t.push(i),n+=i.length)}e.length!==0&&(ye=!0,Ke(e,`{"cid":${JSON.stringify(k)},"frames":[${t.join(`,`)}]}`).then(void 0,z))},Ke=async(t,r)=>{for(let e of t)Ee(e);let i=!1;try{let a=new Headers(await xe());a.set(`content-type`,`application/json`);let o=d.postUrl===void 0?u(l(d.url,!1)):l(d.postUrl,!1),s=await be(o,{method:`POST`,headers:a,body:r,signal:g.signal});if(s.ok){let e=await s.json();if(Array.isArray(e.frames))for(let t of e.frames){let e=n(JSON.stringify(t));e!==void 0&&B(()=>We(e,!0))}L=0}else if(s.status>=500||ie.has(s.status))i=!0;else{let n=await s.json().catch(()=>void 0),r=n?.error?.code??`unavailable`;for(let i of t)b.get(i.n)===i&&b.delete(i.n),W(i,new e(r,n?.error?.message))}}catch{if(g.signal.aborted)return;i=!0}ye=!1;let a=t.filter(e=>(e.kind===`req`||e.kind===`pub`&&e.ack)&&b.get(e.n)===e);for(let e of a)b.delete(e.n);if(i){for(let t of a)t.kind===`req`&&W(t,new e(`unavailable`));De(t.filter(e=>e.kind===`pres`||e.kind===`pub`&&(!e.ack||a.includes(e)))),L+=1,I=setTimeout(()=>{I=void 0,$()},c(L-1,p,m,h))}else for(let t of a)W(t,new e(`unavailable`));$()},qe=()=>y.length>0||[..._.values()].some(J),Je=()=>{T=!1,!w&&(Ne(),E===void 0?F===void 0&&qe()&&Q():C===`sse`&&(Ie()!==fe||[..._.values()].some(e=>J(e)&&e.w===void 0&&e.retry===void 0))?Ve():$())};function Ye(){T||w||(T=!0,queueMicrotask(Je))}function Xe(t){if(w)return;w=!0,clearTimeout(F),clearTimeout(I),F=void 0,I=void 0,Re(),g.abort(),R&&typeof removeEventListener==`function`&&removeEventListener(`online`,Le),R=!1;let n=t??new e(`closed`),r=[...y.splice(0),...b.values()];b.clear();for(let e of r)e.settle===void 0?clearTimeout(e.timer):W(e,n);for(let e of[..._.values()])Z(e);_.clear(),v.clear(),H(`closed`),x.clear(),t!==void 0&&z(t)}let Ze=(t,n)=>{let r={name:t,options:n,ev:/* @__PURE__ */ new Map,any:/* @__PURE__ */ new Set,gl:/* @__PURE__ */ new Set,sl:/* @__PURE__ */ new Set,presence:/* @__PURE__ */ new Set,members:/* @__PURE__ */ new Map,list:void 0,status:`idle`,refs:0,hd:0,last:0,sy:!1,state:n.presence,sv:0,w:void 0,retry:void 0,fails:0,closed:!1,hn:void 0};_.set(t,r),J(r)&&X(r);let o=(e,t,n,i)=>r.closed?()=>void 0:(e.add(t),n||(r.refs+=1,X(r)),()=>{e.delete(t)&&!n&&(--r.refs,i?.(),X(r))}),s=(t,n,o,s,c,ee)=>{let l=`null`,u;if(r.closed)u=new e(`closed`);else if(!i(n)||s!==void 0&&!a(s))u=new e(`bad_frame`);else try{l=JSON.stringify(o??null)??`null`}catch(t){u=new e(`bad_frame`,`not JSON`,{cause:t})}return u===void 0?new Promise((e,i)=>{let a=t===`req`,o=Te(t,r,n,l,{key:a?void 0:s??`${ue}:${++he}`,ack:c,ms:ee,settle:c?(t,n)=>{a&&(--r.hd,X(r)),t?i(t):e(n)}:void 0});a&&(r.hd+=1,X(r));let u=we(o);u===void 0?c||e({seq:0,duplicate:!1}):(o.settle=void 0,a&&--r.hd,i(u))}):Promise.reject(u)},c={name:t,get status(){return r.status},get lastSeq(){return r.last},on(e,t){let n=r.ev.get(e);n===void 0&&(n=/* @__PURE__ */ new Set,r.ev.set(e,n));let i=n;return o(i,t,!1,()=>{i.size===0&&r.ev.get(e)===i&&r.ev.delete(e)})},onAny:e=>o(r.any,e),onGap:e=>o(r.gl,e),onStatus:e=>o(r.sl,e,!0),publish:(e,t,n={})=>s(`pub`,e,t,n.key,n.ack!==!1,0),request:(e,t,n={})=>s(`req`,e,t,void 0,!0,n.timeoutMs??1e4),presence:{members:()=>(r.list??=[...r.members.values()],r.list),set(e){r.closed||(r.state=e,r.sv+=1,X(r))},leave(){r.closed||r.state===void 0||(r.state=void 0,r.sv+=1,X(r))},on:e=>o(r.presence,e)},close:()=>Z(r)};return r.hn=c,c};return{channel(t,n={}){if(w)throw new e(`closed`);if(!r(t))throw new e(`bad_channel`,t);return _.get(t)?.hn??Ze(t,n)},get status(){return S},get connectionId(){return k},onStatus(e){return w||x.add(e),()=>{x.delete(e)}},close:()=>Xe()}}export{d as createRealtime};
1
+ import{RealtimeError as e}from"../errors.js";import{byteLength as t,decodeServerFrame as n,isChannelName as r,isEventName as i,isIdempotencyKey as a}from"../protocol.js";import{applyPresence as o}from"./presence.js";import{openStream as s}from"./sse.js";import{backoff as c,clientId as ee,resolveUrl as l,sendUrl as u}from"./util.js";import{openSocket as te}from"./ws.js";const ne=/* @__PURE__ */ new Set([1002,1008,1009]),re=/* @__PURE__ */ new Set([`unavailable`,`rate_limited`,`timeout`]),ie=/* @__PURE__ */ new Set([408,425,429]);function d(d){let f=d.reconnect??{},p=f.minDelayMs??250,m=f.maxDelayMs??3e4,ae=f.stableMs??5e3,h=f.random??Math.random,oe=d.maxQueued??100,se=d.queueTtlMs??3e4,ce=d.ackTimeoutMs??1e4,le=(d.transport??`auto`)===`auto`,ue=ee(),g=new AbortController,_=/* @__PURE__ */ new Map,v=/* @__PURE__ */ new Set,y=[],b=/* @__PURE__ */ new Map,x=/* @__PURE__ */ new Set,S=`connecting`,C=d.transport===`sse`?`sse`:`ws`,w=!1,T=!1,E,D=0,O=!1,k,de=65536,fe=``,pe,A=0,j=0,me=0,he=0,ge=0,M=!1,N=0,P,F,_e,ve,ye=!1,I,L=0,R=!1,z=e=>{try{d.onError===void 0?console.error(`[realtime]`,e):d.onError(e)}catch{}},B=e=>{try{e()}catch(e){z(e)}},be=(e,t)=>(d.fetch??globalThis.fetch)(e,t),xe=()=>typeof d.headers==`function`?d.headers():d.headers,V=(e,t)=>{for(let n of[...e])B(()=>n(t))},H=e=>{e!==S&&(S=e,d.onStatus!==void 0&&B(()=>d.onStatus?.(e)),V(x,e))},U=(e,t)=>{e.status!==t&&(e.status=t,V(e.sl,t))},Se=(e,t,n)=>{clearTimeout(e.timer);let r=e.settle;e.settle=void 0,r===void 0?t!==void 0&&e.kind===`pub`&&z(t):r(t,n)},W=(e,t)=>Se(e,t),Ce=(e,t)=>Se(e,void 0,t),G=(t,n)=>{clearTimeout(t.timer),t.timer=setTimeout(()=>{let n=y.indexOf(t);n>=0&&y.splice(n,1),b.get(t.n)===t&&b.delete(t.n),W(t,new e(`timeout`))},n)},K=e=>{let t=b.get(e);return t!==void 0&&b.delete(e),t},we=t=>{if(w)return new e(`closed`);let n=O&&C===`ws`;if(t.kind!==`pres`&&!n&&y.length>=oe)return new e(`queue_full`);if(t.kind===`pres`){let e=y.findIndex(e=>e.kind===`pres`&&e.chan===t.chan);e>=0&&y.splice(e,1)}else G(t,se);y.push(t),O?$():Ye()},Te=(e,t,n,r,i)=>({kind:e,chan:t,event:n,data:r,key:i.key,ack:i.ack??!0,ms:i.ms??0,order:++ge,n:0,timer:void 0,settle:i.settle}),q=n=>{let r=JSON.stringify(n.chan.name),i=n.kind===`req`||n.kind===`pub`&&n.ack;n.n=i?++me:0;let a=n.kind===`pres`?`{"t":"pres","c":${r},"s":${n.data}}`:n.kind===`req`?`{"t":"req","n":${n.n},"c":${r},"e":"${n.event}","d":${n.data},"ms":${n.ms}}`:`{"t":"pub","c":${r},"e":"${n.event}","d":${n.data}${i?`,"n":${n.n}`:``},"k":${JSON.stringify(n.key)}}`;if(t(a)>de)W(n,new e(`too_large`));else return a},Ee=e=>{e.kind!==`pres`&&(e.kind===`req`||e.ack?(b.set(e.n,e),G(e,e.kind===`req`?e.ms+1e3:ce)):clearTimeout(e.timer))},De=t=>{t.sort((e,t)=>e.order-t.order);let n=[];for(let r of t)r.kind===`req`?W(r,new e(`closed`)):(r.kind===`pub`&&G(r,se),n.push(r));y.unshift(...n)},J=e=>!e.closed&&(e.refs>0||e.state!==void 0||e.options.watch===!0||e.hd>0&&C===`ws`),Y=e=>e.state!==void 0,Oe=e=>!Y(e)&&(e.presence.size>0||e.options.watch===!0),X=e=>{e.status===`idle`&&J(e)&&U(e,`subscribing`),v.add(e),Ye()},ke=(e,t)=>{let n=Y(e),r=Oe(e),i=e.sy?e.last:e.options.replay===!0?0:void 0;return e.w={n:t,join:n,watch:r,after:i,ver:e.sv,ready:!n},U(e,e.sy?`resuming`:`subscribing`),{fields:{c:e.name,...i===void 0?{}:{after:i},...e.options.echo===!1?{echo:!1}:{},...n?{presence:e.state}:{},...r?{watch:!0}:{}}}},Ae=e=>{let t=e.w;if(t===void 0||e.state===void 0)return;t.ver=e.sv;let n=Te(`pres`,e,``,JSON.stringify(e.state),{});if(C===`ws`){let e=q(n);e!==void 0&&E?.send(e)}else we(n)},je=e=>{e.sy=!1,e.last=0,e.w=void 0,clearTimeout(e.retry),e.retry=void 0,e.fails=0,e.members.size>0&&(e.members.clear(),e.list=void 0),U(e,e.closed?`closed`:`idle`)},Me=e=>{let t=J(e),n=e.w;if(C===`ws`&&O&&(n===void 0||t&&n.join===Y(e)&&n.watch===Oe(e)||(E?.send(`{"t":"unsub","c":${JSON.stringify(e.name)}}`),e.w=void 0),t&&e.w===void 0&&e.retry===void 0)){let t=++me;E?.send(JSON.stringify({t:`sub`,n:t,...ke(e,t).fields}))}if(!t){e.status!==`idle`&&e.status!==`closed`&&je(e);return}let r=e.w;r?.join&&r.ready&&r.ver!==e.sv&&Ae(e)},Ne=()=>{let e=[...v];v.clear();for(let t of e)Me(t)},Z=(e,t)=>{e.closed||(e.closed=!0,_.get(e.name)===e&&_.delete(e.name),e.w!==void 0&&C===`ws`&&O&&E?.send(`{"t":"unsub","c":${JSON.stringify(e.name)}}`),je(e),e.ev.clear(),e.any.clear(),e.gl.clear(),e.presence.clear(),e.sl.clear(),e.refs=0,v.delete(e),t!==void 0&&z(t),Ye())},Pe=(e,t)=>{e.w=void 0,U(e,e.sy?`resuming`:`subscribing`),t?X(e):(e.retry=setTimeout(()=>{e.retry=void 0,X(e)},c(e.fails,p,m,h)),e.fails+=1)},Fe=()=>{let t=[];for(let n of[..._.values()])J(n)&&(t.length>=64?Z(n,new e(`limit`)):t.push(ke(n,t.length+1).fields));return fe=Ie(),t},Ie=()=>{let e=``;for(let t of _.values())J(t)&&(e+=`${t.name}|${t.options.echo===!1?0:1}${+!!Y(t)}${+!!Oe(t)};`);return e},Q=()=>{if(clearTimeout(F),F=void 0,w||E!==void 0)return;D+=1;let t=D;O=!1,M=!1,N=0;let n={rx:()=>{t===D&&(M=!0)},frame:e=>{t===D&&B(()=>We(e,!1))},closed:e=>{t===D&&ze(e)}};try{if(!R&&typeof addEventListener==`function`&&(R=!0,addEventListener(`online`,Le)),C===`sse`){let e=l(d.url,!1);e.searchParams.set(`s`,JSON.stringify(Fe())),E=s(e.toString(),be,xe,n)}else E=te(l(d.url,!0).toString(),d.WebSocket??globalThis.WebSocket,n)}catch(t){D+=1,Xe(new e(`closed`,`cannot open`,{cause:t}));return}P=setTimeout(()=>{t===D&&ze({})},ce)},Le=()=>{F!==void 0&&Q()},Re=()=>{D+=1;let e=E;E=void 0,O=!1,k=void 0,clearTimeout(P),clearTimeout(_e),clearInterval(ve),ve=void 0,e?.close()},ze=t=>{let n=O,r=pe??t.code;if(pe=void 0,Re(),w)return;if(C===`ws`&&b.size>0){let e=[...b.values()];b.clear(),De(e)}for(let e of _.values())e.w=void 0,clearTimeout(e.retry),e.retry=void 0,J(e)&&U(e,e.sy?`resuming`:`subscribing`);let i=t.status!==void 0&&t.status>=400&&t.status<500&&!ie.has(t.status);if((r!==void 0&&ne.has(r)||i)&&f.retryFatal!==!0){let n=r===void 0?`the server answered ${t.status}`:`the server closed the connection with ${r}`;Xe(new e(`closed`,n));return}let a=c(j,p,m,h);j+=1,n?A=0:le&&C===`ws`&&(A+=1,A>=2&&(C=`sse`,a=0)),H(`reconnecting`),F=setTimeout(Q,a)},Be=()=>{if(M)M=!1,N=0;else if(N+=1,N>=2){ze({});return}C===`ws`&&E?.send(`{"t":"ping"}`)},Ve=()=>{Re();for(let e of _.values())e.w=void 0;Q()},He=e=>{if(!O){if(O=!0,k=e.id,de=e.max,A=0,M=!0,N=0,clearTimeout(P),e.hb>0&&(ve=setInterval(Be,e.hb)),_e=setTimeout(()=>{j=0},ae),H(`open`),C===`ws`)for(let e of _.values())v.add(e);$()}},Ue=e=>{let t=[...e.members.values()];e.list=t,V(e.presence,t)},We=(t,n)=>{switch(t.t){case`ready`:He(t);return;case`bye`:pe=t.code;return;case`subbed`:{let e=_.get(t.c),n=e?.w;if(e===void 0||n===void 0||n.n!==t.n)return;(t.reset||n.after===void 0)&&(e.last=t.head);let r={after:n.after??0,head:t.head},i=t.reset?!0:t.gap===!0&&n.after!==void 0&&!(n.after===0&&!e.sy);e.sy=!0,e.fails=0,U(e,`live`),i&&V(e.gl,{...r,reset:t.reset===!0});return}case`unsubbed`:{let n=_.get(t.c);if(n===void 0)return;t.why===`revoked`?(n.w=void 0,Z(n,new e(`forbidden`,`revoked`))):Pe(n,t.why===`gap`||t.why===`reset`);return}case`msg`:{let e=_.get(t.c);if(e===void 0||t.s<=e.last)return;e.last=t.s;let n={seq:t.s,replayed:t.r===1,...t.p===void 0?{}:{publisher:t.p},...t.u===void 0?{}:{user:t.u}};for(let r of[...e.ev.get(t.e)??[]])B(()=>r(t.d,n));for(let r of[...e.any])B(()=>r({event:t.e,data:t.d,meta:n}));return}case`ack`:{let e=K(t.n);e!==void 0&&Ce(e,{seq:t.s,duplicate:t.dup===!0});return}case`rep`:{let e=K(t.n);e!==void 0&&Ce(e,t.d);return}case`err`:{let r=new e(t.code,t.msg),i=t.c===void 0?void 0:_.get(t.c);if(t.n!==void 0){if(!n&&i?.w?.n===t.n){re.has(t.code)?(Pe(i,!1),z(r)):(i.w=void 0,Z(i,r));return}let e=n||C===`ws`?K(t.n):void 0;if(e!==void 0){W(e,r);return}}z(r);return}case`pres`:{let e=_.get(t.c);if(e===void 0)return;o(e.members,t.op,t.m)&&Ue(e),t.op===`sync`&&e.w!==void 0&&(e.w.ready=!0,e.w.join&&e.w.ver!==e.sv&&Ae(e));return}case`pong`:return}},$=()=>{if(O&&!w){if(Ne(),C===`sse`)Ge();else for(let e=y[0];e!==void 0&&O;e=y[0]){let t=q(e);if(t!==void 0){if(E?.send(t)!==!0)return;Ee(e)}y.shift()}}},Ge=()=>{if(ye||I!==void 0||k===void 0)return;let e=[],t=[],n=0;for(;y.length>0&&e.length<64&&n<256e3;){let r=y.shift();if(r===void 0)break;let i=q(r);i!==void 0&&(e.push(r),t.push(i),n+=i.length)}e.length!==0&&(ye=!0,Ke(e,`{"cid":${JSON.stringify(k)},"frames":[${t.join(`,`)}]}`).then(void 0,z))},Ke=async(t,r)=>{for(let e of t)Ee(e);let i=!1;try{let a=new Headers(await xe());a.set(`content-type`,`application/json`);let o=d.postUrl===void 0?u(l(d.url,!1)):l(d.postUrl,!1),s=await be(o,{method:`POST`,headers:a,body:r,signal:g.signal});if(s.ok){let e=await s.json();if(Array.isArray(e.frames))for(let t of e.frames){let e=n(JSON.stringify(t));e!==void 0&&B(()=>We(e,!0))}L=0}else if(s.status>=500||ie.has(s.status))i=!0;else{let n=await s.json().catch(()=>void 0),r=n?.error?.code??`unavailable`;for(let i of t)b.get(i.n)===i&&b.delete(i.n),W(i,new e(r,n?.error?.message))}}catch{if(g.signal.aborted)return;i=!0}ye=!1;let a=t.filter(e=>(e.kind===`req`||e.kind===`pub`&&e.ack)&&b.get(e.n)===e);for(let e of a)b.delete(e.n);if(i){for(let t of a)t.kind===`req`&&W(t,new e(`unavailable`));De(t.filter(e=>e.kind===`pres`||e.kind===`pub`&&(!e.ack||a.includes(e)))),L+=1,I=setTimeout(()=>{I=void 0,$()},c(L-1,p,m,h))}else for(let t of a)W(t,new e(`unavailable`));$()},qe=()=>y.length>0||[..._.values()].some(J),Je=()=>{T=!1,!w&&(Ne(),E===void 0?F===void 0&&qe()&&Q():C===`sse`&&(Ie()!==fe||[..._.values()].some(e=>J(e)&&e.w===void 0&&e.retry===void 0))?Ve():$())};function Ye(){T||w||(T=!0,queueMicrotask(Je))}function Xe(t){if(w)return;w=!0,clearTimeout(F),clearTimeout(I),F=void 0,I=void 0,Re(),g.abort(),R&&typeof removeEventListener==`function`&&removeEventListener(`online`,Le),R=!1;let n=t??new e(`closed`),r=[...y.splice(0),...b.values()];b.clear();for(let e of r)e.settle===void 0?clearTimeout(e.timer):W(e,n);for(let e of[..._.values()])Z(e);_.clear(),v.clear(),H(`closed`),x.clear(),t!==void 0&&z(t)}let Ze=(t,n)=>{let r={name:t,options:n,ev:/* @__PURE__ */ new Map,any:/* @__PURE__ */ new Set,gl:/* @__PURE__ */ new Set,sl:/* @__PURE__ */ new Set,presence:/* @__PURE__ */ new Set,members:/* @__PURE__ */ new Map,list:void 0,status:`idle`,refs:0,hd:0,last:0,sy:!1,state:n.presence,sv:0,w:void 0,retry:void 0,fails:0,closed:!1,hn:void 0};_.set(t,r),J(r)&&X(r);let o=(e,t,n,i)=>r.closed?()=>void 0:(e.add(t),n||(r.refs+=1,X(r)),()=>{e.delete(t)&&!n&&(--r.refs,i?.(),X(r))}),s=(t,n,o,s,c,ee)=>{let l=`null`,u;if(r.closed)u=new e(`closed`);else if(!i(n)||s!==void 0&&!a(s))u=new e(`bad_frame`);else try{l=JSON.stringify(o??null)??`null`}catch(t){u=new e(`bad_frame`,`not JSON`,{cause:t})}return u===void 0?new Promise((e,i)=>{let a=t===`req`,o=Te(t,r,n,l,{key:a?void 0:s??`${ue}:${++he}`,ack:c,ms:ee,settle:c?(t,n)=>{a&&(--r.hd,X(r)),t?i(t):e(n)}:void 0});a&&(r.hd+=1,X(r));let u=we(o);u===void 0?c||e({seq:0,duplicate:!1}):(o.settle=void 0,a&&--r.hd,i(u))}):Promise.reject(u)},c={name:t,get status(){return r.status},get lastSeq(){return r.last},on(e,t){let n=r.ev.get(e);n===void 0&&(n=/* @__PURE__ */ new Set,r.ev.set(e,n));let i=n;return o(i,t,!1,()=>{i.size===0&&r.ev.get(e)===i&&r.ev.delete(e)})},onAny:e=>o(r.any,e),onGap:e=>o(r.gl,e),onStatus:e=>o(r.sl,e,!0),publish:(e,t,n={})=>s(`pub`,e,t,n.key,n.ack!==!1,0),request:(e,t,n={})=>s(`req`,e,t,void 0,!0,n.timeoutMs??1e4),presence:{members:()=>(r.list??=[...r.members.values()],r.list),set(e){r.closed||(r.state=e,r.sv+=1,X(r))},leave(){r.closed||r.state===void 0||(r.state=void 0,r.sv+=1,X(r))},on:e=>o(r.presence,e)},close:()=>Z(r)};return r.hn=c,c};return{channel(t,n={}){if(w)throw new e(`closed`);if(!r(t))throw new e(`bad_channel`,t);return _.get(t)?.hn??Ze(t,n)},get status(){return S},get connectionId(){return k},onStatus(e){return w||x.add(e),()=>{x.delete(e)}},close:()=>Xe()}}export{d as createRealtime};
2
2
  //# sourceMappingURL=core.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"core.js","names":["FATAL","TRANSIENT","RETRYABLE_STATUS","createRealtime","reconnect","options","minDelay","maxDelay","stableMs","random","maxQueued","queueTtl","ackTtl","auto","id","clientId","life","chans","dirty","queue","inflight","statusListeners","status","mode","finished","scheduled","link","gen","ready","connId","maxBytes","streamSig","byeCode","wsFails","attempt","counter","keys","orders","received","silent","connectTimer","reconnectTimer","stableTimer","beatTimer","posting","postTimer","postFails","listening","report","error","guard","run","doFetch","input","init","getHeaders","emit","listener","listeners","value","setStatus","next","setChanStatus","chan","finish","op","settle","fail","succeed","arm","at","RealtimeError","ms","take","n","enqueue","flowing","old","item","flush","schedule","newOp","extra","encode","c","wantsAnswer","text","byteLength","sent","requeue","ops","a","b","again","wants","joins","watches","touch","subscription","join","watch","after","sendPresence","w","goIdle","syncChan","want","current","syncAll","batch","closeChan","resubscribe","now","backoff","declare","entries","signature","sig","connect","g","ev","onFrame","frame","linkClosed","info","onOnline","url","resolveUrl","openStream","openSocket","shutdown","drop","wasReady","code","lost","refused","why","delay","beat","reopen","onReady","notifyPresence","members","gap","meta","handler","viaPost","applyPresence","postNext","texts","bytes","postBatch","headers","sendUrl","response","parsed","decodeServerFrame","refusal","unanswered","needed","closed","pending","makeChannel","channelOptions","name","listen","set","passive","submit","isEventName","event","key","isIdempotencyKey","data","cause","request","kind","ack","reject","resolve","hn","handlers","publishOptions","requestOptions","state","callback","isChannelName"],"sources":["../../../src/client/core.ts"],"sourcesContent":["import { type ErrorCode, RealtimeError } from \"../errors\";\nimport {\n byteLength,\n decodeServerFrame,\n isChannelName,\n isEventName,\n isIdempotencyKey,\n type Json,\n type Member,\n type ServerFrame,\n} from \"../protocol\";\nimport { applyPresence } from \"./presence\";\nimport { type Link, type LinkEvents, openStream } from \"./sse\";\nimport type {\n AnyMessage,\n Channel,\n ChannelDef,\n ChannelOptions,\n ChannelSchema,\n ChannelStatus,\n GapInfo,\n MessageMeta,\n PublishAck,\n Realtime,\n RealtimeOptions,\n Status,\n} from \"./types\";\nimport { backoff, clientId, resolveUrl, sendUrl } from \"./util\";\nimport { openSocket } from \"./ws\";\n\n/** Close codes that mean the client did something the server will not accept again. */\nconst FATAL = new Set([1002, 1008, 1009]);\n/** Refusals that may heal by asking again. */\nconst TRANSIENT = new Set<ErrorCode>([\"unavailable\", \"rate_limited\", \"timeout\"]);\n/** HTTP sl of a stream request that are worth retrying among the 4xx. */\nconst RETRYABLE_STATUS = new Set([408, 425, 429]);\nconst MAX_FRAMES_PER_POST = 64;\nconst MAX_POST_BYTES = 256_000;\nconst MAX_STREAM_CHANNELS = 64;\nconst DEFAULT_REQUEST_MS = 10_000;\n\ntype Handler = (data: Json, meta: MessageMeta) => void;\ntype Timer = ReturnType<typeof setTimeout>;\n\ninterface Wire {\n /** The number the subscription went out with; the server answers with it. */\n readonly n: number;\n readonly join: boolean;\n readonly watch: boolean;\n /** The cursor the subscription asked to resume from. */\n readonly after: number | undefined;\n /** The presence state version the server hd for this connection. */\n ver: number;\n /** False until the server can accept presence changes for this connection (over SSE, until the member list arrived). */\n ready: boolean;\n}\n\ninterface Chan {\n readonly name: string;\n readonly options: ChannelOptions;\n readonly ev: Map<string, Set<Handler>>;\n readonly any: Set<(message: AnyMessage<ChannelDef>) => void>;\n readonly gl: Set<(info: GapInfo) => void>;\n readonly sl: Set<(status: ChannelStatus) => void>;\n readonly presence: Set<(members: readonly Member[]) => void>;\n readonly members: Map<string, Member>;\n list: readonly Member[] | undefined;\n status: ChannelStatus;\n /** Listeners registered; the channel subscribes while this is above zero. */\n refs: number;\n /** Requests in flight; a stateful connection answers a request only on a subscribed channel. */\n hd: number;\n last: number;\n /** True once a `subbed` arrived since the channel last went idle. */\n sy: boolean;\n state: Json | undefined;\n sv: number;\n w: Wire | undefined;\n retry: Timer | undefined;\n fails: number;\n closed: boolean;\n hn: Channel<ChannelDef> | undefined;\n}\n\ninterface Op {\n readonly kind: \"pub\" | \"req\" | \"pres\";\n readonly chan: Chan;\n readonly event: string;\n /** The JSON text of the data (or of the presence state). */\n readonly data: string;\n readonly key: string | undefined;\n readonly ack: boolean;\n readonly ms: number;\n readonly order: number;\n n: number;\n timer: Timer | undefined;\n settle: ((error: RealtimeError | undefined, value?: unknown) => void) | undefined;\n}\n\n/**\n * Creates the realtime client: one transport (WebSocket, falling back to server-sent ev), reconnects with backoff, a\n * bounded offline queue, resume from the last sequence number and typed channels. It connects when the first channel\n * listens or the first message is sent, never earlier.\n *\n * @param options The stream URL and the policy.\n * @returns The client.\n * @example\n * import { createRealtime } from \"@shadow-js/realtime/client\";\n *\n * type Schema = { [name: `chat:${string}`]: { ev: { message: { text: string } } } };\n * const rt = createRealtime<Schema>({ url: \"/rt\" });\n * const lobby = rt.channel(\"chat:lobby\");\n * const stop = lobby.on(\"message\", (data) => console.log(data.text));\n * await lobby.publish(\"message\", { text: \"hello\" });\n * stop();\n * rt.close();\n * @since 1.0.0\n */\nexport function createRealtime<Schema extends ChannelSchema = ChannelSchema>(\n options: RealtimeOptions,\n): Realtime<Schema> {\n const reconnect = options.reconnect ?? {};\n const minDelay = reconnect.minDelayMs ?? 250;\n const maxDelay = reconnect.maxDelayMs ?? 30_000;\n const stableMs = reconnect.stableMs ?? 5000;\n const random = reconnect.random ?? Math.random;\n const maxQueued = options.maxQueued ?? 100;\n const queueTtl = options.queueTtlMs ?? 30_000;\n const ackTtl = options.ackTimeoutMs ?? 10_000;\n const auto = (options.transport ?? \"auto\") === \"auto\";\n const id = clientId();\n const life = new AbortController();\n const chans = new Map<string, Chan>();\n const dirty = new Set<Chan>();\n const queue: Op[] = [];\n const inflight = new Map<number, Op>();\n const statusListeners = new Set<(status: Status) => void>();\n\n let status: Status = \"connecting\";\n let mode: \"ws\" | \"sse\" = options.transport === \"sse\" ? \"sse\" : \"ws\";\n let finished = false;\n let scheduled = false;\n let link: Link | undefined;\n let gen = 0;\n let ready = false;\n let connId: string | undefined;\n let maxBytes = 65_536;\n let streamSig = \"\";\n let byeCode: number | undefined;\n let wsFails = 0;\n let attempt = 0;\n let counter = 0;\n let keys = 0;\n let orders = 0;\n let received = false;\n let silent = 0;\n let connectTimer: Timer | undefined;\n let reconnectTimer: Timer | undefined;\n let stableTimer: Timer | undefined;\n let beatTimer: ReturnType<typeof setInterval> | undefined;\n let posting = false;\n let postTimer: Timer | undefined;\n let postFails = 0;\n let listening = false;\n\n const report = (error: unknown): void => {\n try {\n if (options.onError !== undefined) options.onError(error);\n else console.error(\"[realtime]\", error);\n } catch {\n // A failing reporter must not break the client.\n }\n };\n const guard = (run: () => void): void => {\n try {\n run();\n } catch (error) {\n report(error);\n }\n };\n const doFetch: typeof fetch = (input, init) => (options.fetch ?? globalThis.fetch)(input, init);\n const getHeaders = (): HeadersInit | undefined | Promise<HeadersInit | undefined> =>\n typeof options.headers === \"function\" ? options.headers() : options.headers;\n\n const emit = <T>(listeners: Iterable<(value: T) => void>, value: T): void => {\n for (const listener of [...listeners]) guard(() => listener(value));\n };\n const setStatus = (next: Status): void => {\n if (next === status) return;\n status = next;\n if (options.onStatus !== undefined) guard(() => options.onStatus?.(next));\n emit(statusListeners, next);\n };\n const setChanStatus = (chan: Chan, next: ChannelStatus): void => {\n if (chan.status === next) return;\n chan.status = next;\n emit(chan.sl, next);\n };\n\n // --- operations: publishes and requests, queued while there is no connection --------------------------------------\n\n /** Settles an operation once; an unacknowledged publish that fails is reported instead. */\n const finish = (op: Op, error: RealtimeError | undefined, value?: unknown): void => {\n clearTimeout(op.timer);\n const settle = op.settle;\n op.settle = undefined;\n if (settle !== undefined) settle(error, value);\n else if (error !== undefined && op.kind === \"pub\") report(error);\n };\n const fail = (op: Op, error: RealtimeError): void => finish(op, error);\n const succeed = (op: Op, value: unknown): void => finish(op, undefined, value);\n const arm = (op: Op, ms: number): void => {\n clearTimeout(op.timer);\n op.timer = setTimeout(() => {\n const at = queue.indexOf(op);\n if (at >= 0) queue.splice(at, 1);\n if (inflight.get(op.n) === op) inflight.delete(op.n);\n fail(op, new RealtimeError(\"timeout\"));\n }, ms);\n };\n const take = (n: number): Op | undefined => {\n const op = inflight.get(n);\n if (op !== undefined) inflight.delete(n);\n return op;\n };\n\n const enqueue = (op: Op): RealtimeError | undefined => {\n if (finished) return new RealtimeError(\"closed\");\n const flowing = ready && mode === \"ws\";\n if (op.kind !== \"pres\" && !flowing && queue.length >= maxQueued)\n return new RealtimeError(\"queue_full\");\n if (op.kind === \"pres\") {\n const old = queue.findIndex((item) => item.kind === \"pres\" && item.chan === op.chan);\n if (old >= 0) queue.splice(old, 1);\n } else arm(op, queueTtl);\n queue.push(op);\n if (ready) flush();\n else schedule();\n return undefined;\n };\n\n const newOp = (\n kind: Op[\"kind\"],\n chan: Chan,\n event: string,\n data: string,\n extra: Partial<Pick<Op, \"key\" | \"ack\" | \"ms\" | \"settle\">>,\n ): Op => ({\n kind,\n chan,\n event,\n data,\n key: extra.key,\n ack: extra.ack ?? true,\n ms: extra.ms ?? 0,\n order: ++orders,\n n: 0,\n timer: undefined,\n settle: extra.settle,\n });\n\n /** The frame text of an operation, numbered for an answer. Undefined (and the operation failed) when it is too large. */\n const encode = (op: Op): string | undefined => {\n const c = JSON.stringify(op.chan.name);\n const wantsAnswer = op.kind === \"req\" || (op.kind === \"pub\" && op.ack);\n op.n = wantsAnswer ? ++counter : 0;\n const text =\n op.kind === \"pres\"\n ? `{\"t\":\"pres\",\"c\":${c},\"s\":${op.data}}`\n : op.kind === \"req\"\n ? `{\"t\":\"req\",\"n\":${op.n},\"c\":${c},\"e\":\"${op.event}\",\"d\":${op.data},\"ms\":${op.ms}}`\n : `{\"t\":\"pub\",\"c\":${c},\"e\":\"${op.event}\",\"d\":${op.data}${wantsAnswer ? `,\"n\":${op.n}` : \"\"},\"k\":${JSON.stringify(op.key)}}`;\n if (byteLength(text) > maxBytes) {\n fail(op, new RealtimeError(\"too_large\"));\n return undefined;\n }\n return text;\n };\n\n /** Records that an operation went out: it now waits for an answer, or is done. */\n const sent = (op: Op): void => {\n if (op.kind === \"pres\") return;\n if (op.kind === \"req\" || op.ack) {\n inflight.set(op.n, op);\n arm(op, op.kind === \"req\" ? op.ms + 1000 : ackTtl);\n } else clearTimeout(op.timer);\n };\n\n /** Puts operations that went out on a connection that died back at the head of the queue, in their original order. */\n const requeue = (ops: Op[]): void => {\n ops.sort((a, b) => a.order - b.order);\n const again: Op[] = [];\n for (const op of ops) {\n if (op.kind === \"req\") fail(op, new RealtimeError(\"closed\"));\n else {\n if (op.kind === \"pub\") arm(op, queueTtl);\n again.push(op);\n }\n }\n queue.unshift(...again);\n };\n\n // --- channels -----------------------------------------------------------------------------------------------------\n\n const wants = (chan: Chan): boolean =>\n !chan.closed &&\n (chan.refs > 0 ||\n chan.state !== undefined ||\n chan.options.watch === true ||\n (chan.hd > 0 && mode === \"ws\"));\n const joins = (chan: Chan): boolean => chan.state !== undefined;\n const watches = (chan: Chan): boolean =>\n !joins(chan) && (chan.presence.size > 0 || chan.options.watch === true);\n\n const touch = (chan: Chan): void => {\n if (chan.status === \"idle\" && wants(chan)) setChanStatus(chan, \"subscribing\");\n dirty.add(chan);\n schedule();\n };\n\n /** The fields a subscription goes out with, over a WebSocket as a frame and over SSE as a query entry. */\n const subscription = (chan: Chan, n: number): { fields: Record<string, unknown> } => {\n const join = joins(chan);\n const watch = watches(chan);\n const after = chan.sy ? chan.last : chan.options.replay === true ? 0 : undefined;\n const w: Wire = { n, join, watch, after, ver: chan.sv, ready: !join };\n chan.w = w;\n setChanStatus(chan, chan.sy ? \"resuming\" : \"subscribing\");\n return {\n fields: {\n c: chan.name,\n ...(after === undefined ? {} : { after }),\n ...(chan.options.echo === false ? { echo: false } : {}),\n ...(join ? { presence: chan.state } : {}),\n ...(watch ? { watch: true } : {}),\n },\n };\n };\n\n const sendPresence = (chan: Chan): void => {\n const w = chan.w;\n if (w === undefined || chan.state === undefined) return;\n w.ver = chan.sv;\n const op = newOp(\"pres\", chan, \"\", JSON.stringify(chan.state), {});\n if (mode === \"ws\") {\n const text = encode(op);\n if (text !== undefined) link?.send(text);\n } else enqueue(op);\n };\n\n const goIdle = (chan: Chan): void => {\n chan.sy = false;\n chan.last = 0;\n chan.w = undefined;\n clearTimeout(chan.retry);\n chan.retry = undefined;\n chan.fails = 0;\n if (chan.members.size > 0) {\n chan.members.clear();\n chan.list = undefined;\n }\n setChanStatus(chan, chan.closed ? \"closed\" : \"idle\");\n };\n\n /** Brings the w in line with what a channel wants (WebSocket: subscribe, unsubscribe, presence). */\n const syncChan = (chan: Chan): void => {\n const want = wants(chan);\n const w = chan.w;\n if (mode === \"ws\" && ready) {\n if (w !== undefined && (!want || w.join !== joins(chan) || w.watch !== watches(chan))) {\n link?.send(`{\"t\":\"unsub\",\"c\":${JSON.stringify(chan.name)}}`);\n chan.w = undefined;\n }\n if (want && chan.w === undefined && chan.retry === undefined) {\n const n = ++counter;\n link?.send(JSON.stringify({ t: \"sub\", n, ...subscription(chan, n).fields }));\n }\n }\n if (!want) {\n if (chan.status !== \"idle\" && chan.status !== \"closed\") goIdle(chan);\n return;\n }\n const current = chan.w;\n if (current?.join && current.ready && current.ver !== chan.sv) sendPresence(chan);\n };\n\n const syncAll = (): void => {\n const batch = [...dirty];\n dirty.clear();\n for (const chan of batch) syncChan(chan);\n };\n\n const closeChan = (chan: Chan, error?: RealtimeError): void => {\n if (chan.closed) return;\n chan.closed = true;\n if (chans.get(chan.name) === chan) chans.delete(chan.name);\n if (chan.w !== undefined && mode === \"ws\" && ready)\n link?.send(`{\"t\":\"unsub\",\"c\":${JSON.stringify(chan.name)}}`);\n goIdle(chan);\n chan.ev.clear();\n chan.any.clear();\n chan.gl.clear();\n chan.presence.clear();\n chan.sl.clear();\n chan.refs = 0;\n dirty.delete(chan);\n if (error !== undefined) report(error);\n schedule();\n };\n\n /** Subscribes again after a refusal or a removal the server announced; `now` skips the delay. */\n const resubscribe = (chan: Chan, now: boolean): void => {\n chan.w = undefined;\n setChanStatus(chan, chan.sy ? \"resuming\" : \"subscribing\");\n if (now) {\n touch(chan);\n return;\n }\n chan.retry = setTimeout(\n () => {\n chan.retry = undefined;\n touch(chan);\n },\n backoff(chan.fails, minDelay, maxDelay, random),\n );\n chan.fails += 1;\n };\n\n // --- connection ---------------------------------------------------------------------------------------------------\n\n /** Declares the subscriptions of an SSE stream; returns the query entries. */\n const declare = (): unknown[] => {\n const entries: unknown[] = [];\n for (const chan of [...chans.values()]) {\n if (!wants(chan)) continue;\n if (entries.length >= MAX_STREAM_CHANNELS) {\n closeChan(chan, new RealtimeError(\"limit\"));\n continue;\n }\n entries.push(subscription(chan, entries.length + 1).fields);\n }\n streamSig = signature();\n return entries;\n };\n\n /** What the open stream must be reopened for: the channels it carries and how they join. */\n const signature = (): string => {\n let sig = \"\";\n for (const chan of chans.values())\n if (wants(chan))\n sig += `${chan.name}|${chan.options.echo === false ? 0 : 1}${joins(chan) ? 1 : 0}${watches(chan) ? 1 : 0};`;\n return sig;\n };\n\n const connect = (): void => {\n clearTimeout(reconnectTimer);\n reconnectTimer = undefined;\n if (finished || link !== undefined) return;\n gen += 1;\n const g = gen;\n ready = false;\n received = false;\n silent = 0;\n const ev: LinkEvents = {\n rx: () => {\n if (g === gen) received = true;\n },\n frame: (frame) => {\n if (g === gen) guard(() => onFrame(frame, false));\n },\n closed: (info) => {\n if (g === gen) linkClosed(info);\n },\n };\n try {\n if (!listening && typeof addEventListener === \"function\") {\n listening = true;\n addEventListener(\"online\", onOnline);\n }\n if (mode === \"sse\") {\n const url = resolveUrl(options.url, false);\n url.searchParams.set(\"s\", JSON.stringify(declare()));\n link = openStream(url.toString(), doFetch, getHeaders, ev);\n } else\n link = openSocket(\n resolveUrl(options.url, true).toString(),\n options.WebSocket ?? globalThis.WebSocket,\n ev,\n );\n } catch (error) {\n gen += 1;\n shutdown(new RealtimeError(\"closed\", \"cannot open\", { cause: error }));\n return;\n }\n connectTimer = setTimeout(() => {\n if (g === gen) linkClosed({});\n }, ackTtl);\n };\n\n const onOnline = (): void => {\n if (reconnectTimer !== undefined) connect();\n };\n\n /** Releases the current transport and everything tied to it. */\n const drop = (): void => {\n gen += 1;\n const old = link;\n link = undefined;\n ready = false;\n connId = undefined;\n clearTimeout(connectTimer);\n clearTimeout(stableTimer);\n clearInterval(beatTimer);\n beatTimer = undefined;\n old?.close();\n };\n\n const linkClosed = (info: { readonly code?: number; readonly status?: number }): void => {\n const wasReady = ready;\n const code = byeCode ?? info.code;\n byeCode = undefined;\n drop();\n if (finished) return;\n if (mode === \"ws\" && inflight.size > 0) {\n const lost = [...inflight.values()];\n inflight.clear();\n requeue(lost);\n }\n for (const chan of chans.values()) {\n chan.w = undefined;\n clearTimeout(chan.retry);\n chan.retry = undefined;\n if (wants(chan)) setChanStatus(chan, chan.sy ? \"resuming\" : \"subscribing\");\n }\n const refused =\n info.status !== undefined &&\n info.status >= 400 &&\n info.status < 500 &&\n !RETRYABLE_STATUS.has(info.status);\n if (((code !== undefined && FATAL.has(code)) || refused) && reconnect.retryFatal !== true) {\n const why =\n code !== undefined\n ? `the server closed the connection with ${code}`\n : `the server answered ${info.status}`;\n shutdown(new RealtimeError(\"closed\", why));\n return;\n }\n let delay = backoff(attempt, minDelay, maxDelay, random);\n attempt += 1;\n if (wasReady) wsFails = 0;\n else if (auto && mode === \"ws\") {\n wsFails += 1;\n if (wsFails >= 2) {\n mode = \"sse\";\n delay = 0;\n }\n }\n setStatus(\"reconnecting\");\n reconnectTimer = setTimeout(connect, delay);\n };\n\n /** Heartbeat: every interval sends a ping; two intervals with nothing received declare the connection dead. */\n const beat = (): void => {\n if (received) {\n received = false;\n silent = 0;\n } else {\n silent += 1;\n if (silent >= 2) {\n linkClosed({});\n return;\n }\n }\n if (mode === \"ws\") link?.send('{\"t\":\"ping\"}');\n };\n\n const reopen = (): void => {\n drop();\n for (const chan of chans.values()) chan.w = undefined;\n connect();\n };\n\n const onReady = (frame: Extract<ServerFrame, { t: \"ready\" }>): void => {\n if (ready) return;\n ready = true;\n connId = frame.id;\n maxBytes = frame.max;\n wsFails = 0;\n received = true;\n silent = 0;\n clearTimeout(connectTimer);\n if (frame.hb > 0) beatTimer = setInterval(beat, frame.hb);\n stableTimer = setTimeout(() => {\n attempt = 0;\n }, stableMs);\n setStatus(\"open\");\n if (mode === \"ws\") for (const chan of chans.values()) dirty.add(chan);\n flush();\n };\n\n // --- frames from the server ---------------------------------------------------------------------------------------\n\n const notifyPresence = (chan: Chan): void => {\n const members = [...chan.members.values()];\n chan.list = members;\n emit(chan.presence, members);\n };\n\n const onFrame = (frame: ServerFrame, viaPost: boolean): void => {\n switch (frame.t) {\n case \"ready\":\n onReady(frame);\n return;\n case \"bye\":\n byeCode = frame.code;\n return;\n case \"subbed\": {\n const chan = chans.get(frame.c);\n const w = chan?.w;\n if (chan === undefined || w === undefined || w.n !== frame.n) return;\n if (frame.reset || w.after === undefined) chan.last = frame.head;\n const info = { after: w.after ?? 0, head: frame.head };\n const gap = frame.reset\n ? true\n : frame.gap === true && w.after !== undefined && !(w.after === 0 && !chan.sy);\n chan.sy = true;\n chan.fails = 0;\n setChanStatus(chan, \"live\");\n if (gap) emit(chan.gl, { ...info, reset: frame.reset === true });\n return;\n }\n case \"unsubbed\": {\n const chan = chans.get(frame.c);\n if (chan === undefined) return;\n if (frame.why === \"revoked\") {\n // The hub dropped the subscription: closing must not send an unsub it would answer with not_subscribed.\n chan.w = undefined;\n closeChan(chan, new RealtimeError(\"forbidden\", \"revoked\"));\n } else resubscribe(chan, frame.why === \"gap\" || frame.why === \"reset\");\n return;\n }\n case \"msg\": {\n const chan = chans.get(frame.c);\n if (chan === undefined || frame.s <= chan.last) return;\n chan.last = frame.s;\n const meta: MessageMeta = {\n seq: frame.s,\n replayed: frame.r === 1,\n ...(frame.p === undefined ? {} : { publisher: frame.p }),\n ...(frame.u === undefined ? {} : { user: frame.u }),\n };\n for (const handler of [...(chan.ev.get(frame.e) ?? [])])\n guard(() => handler(frame.d, meta));\n for (const handler of [...chan.any])\n guard(() => handler({ event: frame.e, data: frame.d, meta } as AnyMessage<ChannelDef>));\n return;\n }\n case \"ack\": {\n const op = take(frame.n);\n if (op !== undefined) succeed(op, { seq: frame.s, duplicate: frame.dup === true });\n return;\n }\n case \"rep\": {\n const op = take(frame.n);\n if (op !== undefined) succeed(op, frame.d);\n return;\n }\n case \"err\": {\n const error = new RealtimeError(frame.code, frame.msg);\n const chan = frame.c === undefined ? undefined : chans.get(frame.c);\n if (frame.n !== undefined) {\n if (!viaPost && chan?.w?.n === frame.n) {\n if (TRANSIENT.has(frame.code)) {\n resubscribe(chan, false);\n report(error);\n } else {\n chan.w = undefined;\n closeChan(chan, error);\n }\n return;\n }\n // Over SSE a number on the stream names a subscription; only a POST answer names an operation.\n const op = viaPost || mode === \"ws\" ? take(frame.n) : undefined;\n if (op !== undefined) {\n fail(op, error);\n return;\n }\n }\n report(error);\n return;\n }\n case \"pres\": {\n const chan = chans.get(frame.c);\n if (chan === undefined) return;\n if (applyPresence(chan.members, frame.op, frame.m)) notifyPresence(chan);\n if (frame.op === \"sync\" && chan.w !== undefined) {\n chan.w.ready = true;\n if (chan.w.join && chan.w.ver !== chan.sv) sendPresence(chan);\n }\n return;\n }\n case \"pong\":\n return;\n }\n };\n\n // --- sending ------------------------------------------------------------------------------------------------------\n\n const flush = (): void => {\n if (!ready || finished) return;\n syncAll();\n if (mode === \"sse\") {\n postNext();\n return;\n }\n for (let op = queue[0]; op !== undefined && ready; op = queue[0]) {\n const text = encode(op);\n if (text !== undefined) {\n if (link?.send(text) !== true) return;\n sent(op);\n }\n queue.shift();\n }\n };\n\n const postNext = (): void => {\n if (posting || postTimer !== undefined || connId === undefined) return;\n const ops: Op[] = [];\n const texts: string[] = [];\n let bytes = 0;\n while (queue.length > 0 && ops.length < MAX_FRAMES_PER_POST && bytes < MAX_POST_BYTES) {\n const op = queue.shift();\n if (op === undefined) break;\n const text = encode(op);\n if (text === undefined) continue;\n ops.push(op);\n texts.push(text);\n bytes += text.length;\n }\n if (ops.length === 0) return;\n posting = true;\n postBatch(ops, `{\"cid\":${JSON.stringify(connId)},\"frames\":[${texts.join(\",\")}]}`).then(\n undefined,\n report,\n );\n };\n\n const postBatch = async (ops: Op[], body: string): Promise<void> => {\n for (const op of ops) sent(op);\n let again = false;\n try {\n const headers = new Headers(await getHeaders());\n headers.set(\"content-type\", \"application/json\");\n const url =\n options.postUrl === undefined\n ? sendUrl(resolveUrl(options.url, false))\n : resolveUrl(options.postUrl, false);\n const response = await doFetch(url, { method: \"POST\", headers, body, signal: life.signal });\n if (response.ok) {\n const parsed = (await response.json()) as { frames?: unknown };\n if (Array.isArray(parsed.frames))\n for (const item of parsed.frames as unknown[]) {\n const frame = decodeServerFrame(JSON.stringify(item));\n if (frame !== undefined) guard(() => onFrame(frame, true));\n }\n postFails = 0;\n } else if (response.status >= 500 || RETRYABLE_STATUS.has(response.status)) again = true;\n else {\n const refusal = (await response.json().catch(() => undefined)) as\n | { error?: { code?: ErrorCode; message?: string } }\n | undefined;\n const code: ErrorCode = refusal?.error?.code ?? \"unavailable\";\n for (const op of ops) {\n if (inflight.get(op.n) === op) inflight.delete(op.n);\n fail(op, new RealtimeError(code, refusal?.error?.message));\n }\n }\n } catch {\n if (life.signal.aborted) return;\n again = true;\n }\n posting = false;\n const unanswered = ops.filter(\n (op) => (op.kind === \"req\" || (op.kind === \"pub\" && op.ack)) && inflight.get(op.n) === op,\n );\n for (const op of unanswered) inflight.delete(op.n);\n if (again) {\n for (const op of unanswered)\n if (op.kind === \"req\") fail(op, new RealtimeError(\"unavailable\"));\n requeue(\n ops.filter(\n (op) => op.kind === \"pres\" || (op.kind === \"pub\" && (!op.ack || unanswered.includes(op))),\n ),\n );\n postFails += 1;\n postTimer = setTimeout(\n () => {\n postTimer = undefined;\n flush();\n },\n backoff(postFails - 1, minDelay, maxDelay, random),\n );\n } else for (const op of unanswered) fail(op, new RealtimeError(\"unavailable\"));\n flush();\n };\n\n // --- lifecycle ----------------------------------------------------------------------------------------------------\n\n const needed = (): boolean => queue.length > 0 || [...chans.values()].some(wants);\n\n const run = (): void => {\n scheduled = false;\n if (finished) return;\n syncAll();\n if (link === undefined) {\n if (reconnectTimer === undefined && needed()) connect();\n return;\n }\n if (\n mode === \"sse\" &&\n (signature() !== streamSig ||\n [...chans.values()].some((c) => wants(c) && c.w === undefined && c.retry === undefined))\n )\n reopen();\n else flush();\n };\n\n function schedule(): void {\n if (scheduled || finished) return;\n scheduled = true;\n queueMicrotask(run);\n }\n\n function shutdown(error?: RealtimeError): void {\n if (finished) return;\n finished = true;\n clearTimeout(reconnectTimer);\n clearTimeout(postTimer);\n reconnectTimer = undefined;\n postTimer = undefined;\n drop();\n life.abort();\n if (listening && typeof removeEventListener === \"function\")\n removeEventListener(\"online\", onOnline);\n listening = false;\n const closed = error ?? new RealtimeError(\"closed\");\n const pending = [...queue.splice(0), ...inflight.values()];\n inflight.clear();\n for (const op of pending) {\n if (op.settle === undefined) clearTimeout(op.timer);\n else fail(op, closed);\n }\n for (const chan of [...chans.values()]) closeChan(chan);\n chans.clear();\n dirty.clear();\n setStatus(\"closed\");\n statusListeners.clear();\n if (error !== undefined) report(error);\n }\n\n // --- the public handles -------------------------------------------------------------------------------------------\n\n const makeChannel = (name: string, channelOptions: ChannelOptions): Channel<ChannelDef> => {\n const chan: Chan = {\n name,\n options: channelOptions,\n ev: new Map(),\n any: new Set(),\n gl: new Set(),\n sl: new Set(),\n presence: new Set(),\n members: new Map(),\n list: undefined,\n status: \"idle\",\n refs: 0,\n hd: 0,\n last: 0,\n sy: false,\n state: channelOptions.presence,\n sv: 0,\n w: undefined,\n retry: undefined,\n fails: 0,\n closed: false,\n hn: undefined,\n };\n chans.set(name, chan);\n if (wants(chan)) touch(chan);\n\n /** Registers a listener; unless `passive`, it keeps the channel subscribed until removed. */\n const listen = <T>(\n set: Set<T>,\n item: T,\n passive?: boolean,\n after?: () => void,\n ): (() => void) => {\n if (chan.closed) return () => undefined;\n set.add(item);\n if (!passive) {\n chan.refs += 1;\n touch(chan);\n }\n return () => {\n if (!set.delete(item) || passive) return;\n chan.refs -= 1;\n after?.();\n touch(chan);\n };\n };\n\n /** Validates and queues a publish or a request; the promise settles with its answer. */\n const submit = <T>(\n kind: \"pub\" | \"req\",\n event: string,\n data: unknown,\n key: string | undefined,\n ack: boolean,\n ms: number,\n ): Promise<T> => {\n let text = \"null\";\n let refusal: RealtimeError | undefined;\n if (chan.closed) refusal = new RealtimeError(\"closed\");\n else if (!isEventName(event) || (key !== undefined && !isIdempotencyKey(key)))\n refusal = new RealtimeError(\"bad_frame\");\n else\n try {\n text = JSON.stringify(data ?? null) ?? \"null\";\n } catch (cause) {\n refusal = new RealtimeError(\"bad_frame\", \"not JSON\", { cause });\n }\n if (refusal !== undefined) return Promise.reject(refusal);\n return new Promise<T>((resolve, reject) => {\n const request = kind === \"req\";\n const op = newOp(kind, chan, event, text, {\n key: request ? undefined : (key ?? `${id}:${++keys}`),\n ack,\n ms,\n settle: ack\n ? (error, value) => {\n if (request) {\n chan.hd -= 1;\n touch(chan);\n }\n if (error) reject(error);\n else resolve(value as T);\n }\n : undefined,\n });\n if (request) {\n chan.hd += 1;\n touch(chan);\n }\n const refused = enqueue(op);\n if (refused !== undefined) {\n op.settle = undefined;\n if (request) chan.hd -= 1;\n reject(refused);\n } else if (!ack) resolve({ seq: 0, duplicate: false } as T);\n });\n };\n\n const hn: Channel<ChannelDef> = {\n name,\n get status() {\n return chan.status;\n },\n get lastSeq() {\n return chan.last;\n },\n on(event, handler) {\n let set = chan.ev.get(event);\n if (set === undefined) {\n set = new Set();\n chan.ev.set(event, set);\n }\n const handlers = set;\n return listen(handlers, handler as Handler, false, () => {\n if (handlers.size === 0 && chan.ev.get(event) === handlers) chan.ev.delete(event);\n });\n },\n onAny: (handler) => listen(chan.any, handler as (message: AnyMessage<ChannelDef>) => void),\n onGap: (handler) => listen(chan.gl, handler),\n onStatus: (handler) => listen(chan.sl, handler, true),\n publish: (event, data, publishOptions = {}) =>\n submit<PublishAck>(\"pub\", event, data, publishOptions.key, publishOptions.ack !== false, 0),\n request: (event, data, requestOptions = {}) =>\n submit(\"req\", event, data, undefined, true, requestOptions.timeoutMs ?? DEFAULT_REQUEST_MS),\n presence: {\n members: () => {\n chan.list ??= [...chan.members.values()];\n return chan.list as never;\n },\n set(state) {\n if (chan.closed) return;\n chan.state = state as Json;\n chan.sv += 1;\n touch(chan);\n },\n leave() {\n if (chan.closed || chan.state === undefined) return;\n chan.state = undefined;\n chan.sv += 1;\n touch(chan);\n },\n on: (callback) => listen(chan.presence, callback as (members: readonly Member[]) => void),\n },\n close: () => closeChan(chan),\n };\n chan.hn = hn;\n return hn;\n };\n\n return {\n channel(name, channelOptions = {}) {\n if (finished) throw new RealtimeError(\"closed\");\n if (!isChannelName(name)) throw new RealtimeError(\"bad_channel\", name);\n const live = chans.get(name);\n return (live?.hn ?? makeChannel(name, channelOptions)) as never;\n },\n get status() {\n return status;\n },\n get connectionId() {\n return connId;\n },\n onStatus(handler) {\n if (!finished) statusListeners.add(handler);\n return () => {\n statusListeners.delete(handler);\n };\n },\n close: () => shutdown(),\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"core.js","names":["FATAL","TRANSIENT","RETRYABLE_STATUS","createRealtime","reconnect","options","minDelay","maxDelay","stableMs","random","maxQueued","queueTtl","ackTtl","auto","id","clientId","life","chans","dirty","queue","inflight","statusListeners","status","mode","finished","scheduled","link","gen","ready","connId","maxBytes","streamSig","byeCode","wsFails","attempt","counter","keys","orders","received","silent","connectTimer","reconnectTimer","stableTimer","beatTimer","posting","postTimer","postFails","listening","report","error","guard","run","doFetch","input","init","getHeaders","emit","listener","listeners","value","setStatus","next","setChanStatus","chan","finish","op","settle","fail","succeed","arm","at","RealtimeError","ms","take","n","enqueue","flowing","old","item","flush","schedule","newOp","extra","encode","c","wantsAnswer","text","byteLength","sent","requeue","ops","a","b","again","wants","joins","watches","touch","subscription","join","watch","after","sendPresence","w","goIdle","syncChan","want","current","syncAll","batch","closeChan","resubscribe","now","backoff","declare","entries","signature","sig","connect","g","ev","onFrame","frame","linkClosed","info","onOnline","url","resolveUrl","openStream","openSocket","shutdown","drop","wasReady","code","lost","refused","why","delay","beat","reopen","onReady","notifyPresence","members","gap","meta","handler","viaPost","applyPresence","postNext","texts","bytes","postBatch","headers","sendUrl","response","parsed","decodeServerFrame","refusal","unanswered","needed","closed","pending","makeChannel","channelOptions","name","listen","set","passive","submit","isEventName","event","key","isIdempotencyKey","data","cause","request","kind","ack","reject","resolve","hn","handlers","publishOptions","requestOptions","state","callback","isChannelName"],"sources":["../../../src/client/core.ts"],"sourcesContent":["import { type ErrorCode, RealtimeError } from \"../errors\";\nimport {\n byteLength,\n decodeServerFrame,\n isChannelName,\n isEventName,\n isIdempotencyKey,\n type Json,\n type Member,\n type ServerFrame,\n} from \"../protocol\";\nimport { applyPresence } from \"./presence\";\nimport { type Link, type LinkEvents, openStream } from \"./sse\";\nimport type {\n AnyMessage,\n Channel,\n ChannelDef,\n ChannelOptions,\n ChannelSchema,\n ChannelStatus,\n GapInfo,\n MessageMeta,\n PublishAck,\n Realtime,\n RealtimeOptions,\n Status,\n} from \"./types\";\nimport { backoff, clientId, resolveUrl, sendUrl } from \"./util\";\nimport { openSocket } from \"./ws\";\n\n/** Close codes that mean the client did something the server will not accept again. */\nconst FATAL = new Set([1002, 1008, 1009]);\n/** Refusals that may heal by asking again. */\nconst TRANSIENT = new Set<ErrorCode>([\"unavailable\", \"rate_limited\", \"timeout\"]);\n/** HTTP sl of a stream request that are worth retrying among the 4xx. */\nconst RETRYABLE_STATUS = new Set([408, 425, 429]);\nconst MAX_FRAMES_PER_POST = 64;\nconst MAX_POST_BYTES = 256_000;\nconst MAX_STREAM_CHANNELS = 64;\nconst DEFAULT_REQUEST_MS = 10_000;\n\ntype Handler = (data: Json, meta: MessageMeta) => void;\ntype Timer = ReturnType<typeof setTimeout>;\n\ninterface Wire {\n /** The number the subscription went out with; the server answers with it. */\n readonly n: number;\n readonly join: boolean;\n readonly watch: boolean;\n /** The cursor the subscription asked to resume from. */\n readonly after: number | undefined;\n /** The presence state version the server hd for this connection. */\n ver: number;\n /** False until the server can accept presence changes for this connection (over SSE, until the member list arrived). */\n ready: boolean;\n}\n\ninterface Chan {\n readonly name: string;\n readonly options: ChannelOptions;\n readonly ev: Map<string, Set<Handler>>;\n readonly any: Set<(message: AnyMessage<ChannelDef>) => void>;\n readonly gl: Set<(info: GapInfo) => void>;\n readonly sl: Set<(status: ChannelStatus) => void>;\n readonly presence: Set<(members: readonly Member[]) => void>;\n readonly members: Map<string, Member>;\n list: readonly Member[] | undefined;\n status: ChannelStatus;\n /** Listeners registered; the channel subscribes while this is above zero. */\n refs: number;\n /** Requests in flight; a stateful connection answers a request only on a subscribed channel. */\n hd: number;\n last: number;\n /** True once a `subbed` arrived since the channel last went idle. */\n sy: boolean;\n state: Json | undefined;\n sv: number;\n w: Wire | undefined;\n retry: Timer | undefined;\n fails: number;\n closed: boolean;\n hn: Channel<ChannelDef> | undefined;\n}\n\ninterface Op {\n readonly kind: \"pub\" | \"req\" | \"pres\";\n readonly chan: Chan;\n readonly event: string;\n /** The JSON text of the data (or of the presence state). */\n readonly data: string;\n readonly key: string | undefined;\n readonly ack: boolean;\n readonly ms: number;\n readonly order: number;\n n: number;\n timer: Timer | undefined;\n settle: ((error: RealtimeError | undefined, value?: unknown) => void) | undefined;\n}\n\n/**\n * Creates the realtime client: one transport (WebSocket, falling back to server-sent ev), reconnects with backoff, a\n * bounded offline queue, resume from the last sequence number and typed channels. It connects when the first channel\n * listens or the first message is sent, never earlier.\n *\n * @param options The stream URL and the policy.\n * @returns The client.\n * @example\n * import { createRealtime } from \"@shadow-js/realtime/client\";\n *\n * type Schema = { [name: `chat:${string}`]: { ev: { message: { text: string } } } };\n * const rt = createRealtime<Schema>({ url: \"/rt\" });\n * const lobby = rt.channel(\"chat:lobby\");\n * const stop = lobby.on(\"message\", (data) => console.log(data.text));\n * await lobby.publish(\"message\", { text: \"hello\" });\n * stop();\n * rt.close();\n * @since 1.0.0\n */\nexport function createRealtime<Schema extends ChannelSchema = ChannelSchema>(\n options: RealtimeOptions,\n): Realtime<Schema> {\n const reconnect = options.reconnect ?? {};\n const minDelay = reconnect.minDelayMs ?? 250;\n const maxDelay = reconnect.maxDelayMs ?? 30_000;\n const stableMs = reconnect.stableMs ?? 5000;\n const random = reconnect.random ?? Math.random;\n const maxQueued = options.maxQueued ?? 100;\n const queueTtl = options.queueTtlMs ?? 30_000;\n const ackTtl = options.ackTimeoutMs ?? 10_000;\n const auto = (options.transport ?? \"auto\") === \"auto\";\n const id = clientId();\n const life = new AbortController();\n const chans = new Map<string, Chan>();\n const dirty = new Set<Chan>();\n const queue: Op[] = [];\n const inflight = new Map<number, Op>();\n const statusListeners = new Set<(status: Status) => void>();\n\n let status: Status = \"connecting\";\n let mode: \"ws\" | \"sse\" = options.transport === \"sse\" ? \"sse\" : \"ws\";\n let finished = false;\n let scheduled = false;\n let link: Link | undefined;\n let gen = 0;\n let ready = false;\n let connId: string | undefined;\n let maxBytes = 65_536;\n let streamSig = \"\";\n let byeCode: number | undefined;\n let wsFails = 0;\n let attempt = 0;\n let counter = 0;\n let keys = 0;\n let orders = 0;\n let received = false;\n let silent = 0;\n let connectTimer: Timer | undefined;\n let reconnectTimer: Timer | undefined;\n let stableTimer: Timer | undefined;\n let beatTimer: ReturnType<typeof setInterval> | undefined;\n let posting = false;\n let postTimer: Timer | undefined;\n let postFails = 0;\n let listening = false;\n\n const report = (error: unknown): void => {\n try {\n if (options.onError !== undefined) options.onError(error);\n else console.error(\"[realtime]\", error);\n } catch {\n // A failing reporter must not break the client.\n }\n };\n const guard = (run: () => void): void => {\n try {\n run();\n } catch (error) {\n report(error);\n }\n };\n const doFetch: typeof fetch = (input, init) => (options.fetch ?? globalThis.fetch)(input, init);\n const getHeaders = (): HeadersInit | undefined | Promise<HeadersInit | undefined> =>\n typeof options.headers === \"function\" ? options.headers() : options.headers;\n\n const emit = <T>(listeners: Iterable<(value: T) => void>, value: T): void => {\n for (const listener of [...listeners]) guard(() => listener(value));\n };\n const setStatus = (next: Status): void => {\n if (next === status) return;\n status = next;\n if (options.onStatus !== undefined) guard(() => options.onStatus?.(next));\n emit(statusListeners, next);\n };\n const setChanStatus = (chan: Chan, next: ChannelStatus): void => {\n if (chan.status === next) return;\n chan.status = next;\n emit(chan.sl, next);\n };\n\n // --- operations: publishes and requests, queued while there is no connection --------------------------------------\n\n /** Settles an operation once; an unacknowledged publish that fails is reported instead. */\n const finish = (op: Op, error: RealtimeError | undefined, value?: unknown): void => {\n clearTimeout(op.timer);\n const settle = op.settle;\n op.settle = undefined;\n if (settle !== undefined) settle(error, value);\n else if (error !== undefined && op.kind === \"pub\") report(error);\n };\n const fail = (op: Op, error: RealtimeError): void => finish(op, error);\n const succeed = (op: Op, value: unknown): void => finish(op, undefined, value);\n const arm = (op: Op, ms: number): void => {\n clearTimeout(op.timer);\n op.timer = setTimeout(() => {\n const at = queue.indexOf(op);\n if (at >= 0) queue.splice(at, 1);\n if (inflight.get(op.n) === op) inflight.delete(op.n);\n fail(op, new RealtimeError(\"timeout\"));\n }, ms);\n };\n const take = (n: number): Op | undefined => {\n const op = inflight.get(n);\n if (op !== undefined) inflight.delete(n);\n return op;\n };\n\n const enqueue = (op: Op): RealtimeError | undefined => {\n if (finished) return new RealtimeError(\"closed\");\n const flowing = ready && mode === \"ws\";\n if (op.kind !== \"pres\" && !flowing && queue.length >= maxQueued)\n return new RealtimeError(\"queue_full\");\n if (op.kind === \"pres\") {\n const old = queue.findIndex((item) => item.kind === \"pres\" && item.chan === op.chan);\n if (old >= 0) queue.splice(old, 1);\n } else arm(op, queueTtl);\n queue.push(op);\n if (ready) flush();\n else schedule();\n return undefined;\n };\n\n const newOp = (\n kind: Op[\"kind\"],\n chan: Chan,\n event: string,\n data: string,\n extra: Partial<Pick<Op, \"key\" | \"ack\" | \"ms\" | \"settle\">>,\n ): Op => ({\n kind,\n chan,\n event,\n data,\n key: extra.key,\n ack: extra.ack ?? true,\n ms: extra.ms ?? 0,\n order: ++orders,\n n: 0,\n timer: undefined,\n settle: extra.settle,\n });\n\n /** The frame text of an operation, numbered for an answer. Undefined (and the operation failed) when it is too large. */\n const encode = (op: Op): string | undefined => {\n const c = JSON.stringify(op.chan.name);\n const wantsAnswer = op.kind === \"req\" || (op.kind === \"pub\" && op.ack);\n op.n = wantsAnswer ? ++counter : 0;\n const text =\n op.kind === \"pres\"\n ? `{\"t\":\"pres\",\"c\":${c},\"s\":${op.data}}`\n : op.kind === \"req\"\n ? `{\"t\":\"req\",\"n\":${op.n},\"c\":${c},\"e\":\"${op.event}\",\"d\":${op.data},\"ms\":${op.ms}}`\n : `{\"t\":\"pub\",\"c\":${c},\"e\":\"${op.event}\",\"d\":${op.data}${wantsAnswer ? `,\"n\":${op.n}` : \"\"},\"k\":${JSON.stringify(op.key)}}`;\n if (byteLength(text) > maxBytes) {\n fail(op, new RealtimeError(\"too_large\"));\n return undefined;\n }\n return text;\n };\n\n /** Records that an operation went out: it now waits for an answer, or is done. */\n const sent = (op: Op): void => {\n if (op.kind === \"pres\") return;\n if (op.kind === \"req\" || op.ack) {\n inflight.set(op.n, op);\n arm(op, op.kind === \"req\" ? op.ms + 1000 : ackTtl);\n } else clearTimeout(op.timer);\n };\n\n /** Puts operations that went out on a connection that died back at the head of the queue, in their original order. */\n const requeue = (ops: Op[]): void => {\n ops.sort((a, b) => a.order - b.order);\n const again: Op[] = [];\n for (const op of ops) {\n if (op.kind === \"req\") fail(op, new RealtimeError(\"closed\"));\n else {\n if (op.kind === \"pub\") arm(op, queueTtl);\n again.push(op);\n }\n }\n queue.unshift(...again);\n };\n\n // --- channels -----------------------------------------------------------------------------------------------------\n\n const wants = (chan: Chan): boolean =>\n !chan.closed &&\n (chan.refs > 0 ||\n chan.state !== undefined ||\n chan.options.watch === true ||\n (chan.hd > 0 && mode === \"ws\"));\n const joins = (chan: Chan): boolean => chan.state !== undefined;\n const watches = (chan: Chan): boolean =>\n !joins(chan) && (chan.presence.size > 0 || chan.options.watch === true);\n\n const touch = (chan: Chan): void => {\n if (chan.status === \"idle\" && wants(chan)) setChanStatus(chan, \"subscribing\");\n dirty.add(chan);\n schedule();\n };\n\n /** The fields a subscription goes out with, over a WebSocket as a frame and over SSE as a query entry. */\n const subscription = (chan: Chan, n: number): { fields: Record<string, unknown> } => {\n const join = joins(chan);\n const watch = watches(chan);\n const after = chan.sy ? chan.last : chan.options.replay === true ? 0 : undefined;\n const w: Wire = { n, join, watch, after, ver: chan.sv, ready: !join };\n chan.w = w;\n setChanStatus(chan, chan.sy ? \"resuming\" : \"subscribing\");\n return {\n fields: {\n c: chan.name,\n ...(after === undefined ? {} : { after }),\n ...(chan.options.echo === false ? { echo: false } : {}),\n ...(join ? { presence: chan.state } : {}),\n ...(watch ? { watch: true } : {}),\n },\n };\n };\n\n const sendPresence = (chan: Chan): void => {\n const w = chan.w;\n if (w === undefined || chan.state === undefined) return;\n w.ver = chan.sv;\n const op = newOp(\"pres\", chan, \"\", JSON.stringify(chan.state), {});\n if (mode === \"ws\") {\n const text = encode(op);\n if (text !== undefined) link?.send(text);\n } else enqueue(op);\n };\n\n const goIdle = (chan: Chan): void => {\n chan.sy = false;\n chan.last = 0;\n chan.w = undefined;\n clearTimeout(chan.retry);\n chan.retry = undefined;\n chan.fails = 0;\n if (chan.members.size > 0) {\n chan.members.clear();\n chan.list = undefined;\n }\n setChanStatus(chan, chan.closed ? \"closed\" : \"idle\");\n };\n\n /** Brings the w in line with what a channel wants (WebSocket: subscribe, unsubscribe, presence). */\n const syncChan = (chan: Chan): void => {\n const want = wants(chan);\n const w = chan.w;\n if (mode === \"ws\" && ready) {\n if (w !== undefined && (!want || w.join !== joins(chan) || w.watch !== watches(chan))) {\n link?.send(`{\"t\":\"unsub\",\"c\":${JSON.stringify(chan.name)}}`);\n chan.w = undefined;\n }\n if (want && chan.w === undefined && chan.retry === undefined) {\n const n = ++counter;\n link?.send(JSON.stringify({ t: \"sub\", n, ...subscription(chan, n).fields }));\n }\n }\n if (!want) {\n if (chan.status !== \"idle\" && chan.status !== \"closed\") goIdle(chan);\n return;\n }\n const current = chan.w;\n if (current?.join && current.ready && current.ver !== chan.sv) sendPresence(chan);\n };\n\n const syncAll = (): void => {\n const batch = [...dirty];\n dirty.clear();\n for (const chan of batch) syncChan(chan);\n };\n\n const closeChan = (chan: Chan, error?: RealtimeError): void => {\n if (chan.closed) return;\n chan.closed = true;\n if (chans.get(chan.name) === chan) chans.delete(chan.name);\n if (chan.w !== undefined && mode === \"ws\" && ready)\n link?.send(`{\"t\":\"unsub\",\"c\":${JSON.stringify(chan.name)}}`);\n goIdle(chan);\n chan.ev.clear();\n chan.any.clear();\n chan.gl.clear();\n chan.presence.clear();\n chan.sl.clear();\n chan.refs = 0;\n dirty.delete(chan);\n if (error !== undefined) report(error);\n schedule();\n };\n\n /** Subscribes again after a refusal or a removal the server announced; `now` skips the delay. */\n const resubscribe = (chan: Chan, now: boolean): void => {\n chan.w = undefined;\n setChanStatus(chan, chan.sy ? \"resuming\" : \"subscribing\");\n if (now) {\n touch(chan);\n return;\n }\n chan.retry = setTimeout(\n () => {\n chan.retry = undefined;\n touch(chan);\n },\n backoff(chan.fails, minDelay, maxDelay, random),\n );\n chan.fails += 1;\n };\n\n // --- connection ---------------------------------------------------------------------------------------------------\n\n /** Declares the subscriptions of an SSE stream; returns the query entries. */\n const declare = (): unknown[] => {\n const entries: unknown[] = [];\n for (const chan of [...chans.values()]) {\n if (!wants(chan)) continue;\n if (entries.length >= MAX_STREAM_CHANNELS) {\n closeChan(chan, new RealtimeError(\"limit\"));\n continue;\n }\n entries.push(subscription(chan, entries.length + 1).fields);\n }\n streamSig = signature();\n return entries;\n };\n\n /** What the open stream must be reopened for: the channels it carries and how they join. */\n const signature = (): string => {\n let sig = \"\";\n for (const chan of chans.values())\n if (wants(chan))\n sig += `${chan.name}|${chan.options.echo === false ? 0 : 1}${joins(chan) ? 1 : 0}${watches(chan) ? 1 : 0};`;\n return sig;\n };\n\n const connect = (): void => {\n clearTimeout(reconnectTimer);\n reconnectTimer = undefined;\n if (finished || link !== undefined) return;\n gen += 1;\n const g = gen;\n ready = false;\n received = false;\n silent = 0;\n const ev: LinkEvents = {\n rx: () => {\n if (g === gen) received = true;\n },\n frame: (frame) => {\n if (g === gen) guard(() => onFrame(frame, false));\n },\n closed: (info) => {\n if (g === gen) linkClosed(info);\n },\n };\n try {\n if (!listening && typeof addEventListener === \"function\") {\n listening = true;\n addEventListener(\"online\", onOnline);\n }\n if (mode === \"sse\") {\n const url = resolveUrl(options.url, false);\n url.searchParams.set(\"s\", JSON.stringify(declare()));\n link = openStream(url.toString(), doFetch, getHeaders, ev);\n } else\n link = openSocket(\n resolveUrl(options.url, true).toString(),\n options.WebSocket ?? globalThis.WebSocket,\n ev,\n );\n } catch (error) {\n gen += 1;\n shutdown(new RealtimeError(\"closed\", \"cannot open\", { cause: error }));\n return;\n }\n connectTimer = setTimeout(() => {\n if (g === gen) linkClosed({});\n }, ackTtl);\n };\n\n const onOnline = (): void => {\n if (reconnectTimer !== undefined) connect();\n };\n\n /** Releases the current transport and everything tied to it. */\n const drop = (): void => {\n gen += 1;\n const old = link;\n link = undefined;\n ready = false;\n connId = undefined;\n clearTimeout(connectTimer);\n clearTimeout(stableTimer);\n clearInterval(beatTimer);\n beatTimer = undefined;\n old?.close();\n };\n\n const linkClosed = (info: { readonly code?: number; readonly status?: number }): void => {\n const wasReady = ready;\n const code = byeCode ?? info.code;\n byeCode = undefined;\n drop();\n if (finished) return;\n if (mode === \"ws\" && inflight.size > 0) {\n const lost = [...inflight.values()];\n inflight.clear();\n requeue(lost);\n }\n for (const chan of chans.values()) {\n chan.w = undefined;\n clearTimeout(chan.retry);\n chan.retry = undefined;\n if (wants(chan)) setChanStatus(chan, chan.sy ? \"resuming\" : \"subscribing\");\n }\n const refused =\n info.status !== undefined &&\n info.status >= 400 &&\n info.status < 500 &&\n !RETRYABLE_STATUS.has(info.status);\n if (((code !== undefined && FATAL.has(code)) || refused) && reconnect.retryFatal !== true) {\n const why =\n code !== undefined\n ? `the server closed the connection with ${code}`\n : `the server answered ${info.status}`;\n shutdown(new RealtimeError(\"closed\", why));\n return;\n }\n let delay = backoff(attempt, minDelay, maxDelay, random);\n attempt += 1;\n if (wasReady) wsFails = 0;\n else if (auto && mode === \"ws\") {\n wsFails += 1;\n if (wsFails >= 2) {\n mode = \"sse\";\n delay = 0;\n }\n }\n setStatus(\"reconnecting\");\n reconnectTimer = setTimeout(connect, delay);\n };\n\n /** Heartbeat: every interval sends a ping; two intervals with nothing received declare the connection dead. */\n const beat = (): void => {\n if (received) {\n received = false;\n silent = 0;\n } else {\n silent += 1;\n if (silent >= 2) {\n linkClosed({});\n return;\n }\n }\n if (mode === \"ws\") link?.send('{\"t\":\"ping\"}');\n };\n\n const reopen = (): void => {\n drop();\n for (const chan of chans.values()) chan.w = undefined;\n connect();\n };\n\n const onReady = (frame: Extract<ServerFrame, { t: \"ready\" }>): void => {\n if (ready) return;\n ready = true;\n connId = frame.id;\n maxBytes = frame.max;\n wsFails = 0;\n received = true;\n silent = 0;\n clearTimeout(connectTimer);\n if (frame.hb > 0) beatTimer = setInterval(beat, frame.hb);\n stableTimer = setTimeout(() => {\n attempt = 0;\n }, stableMs);\n setStatus(\"open\");\n if (mode === \"ws\") for (const chan of chans.values()) dirty.add(chan);\n flush();\n };\n\n // --- frames from the server ---------------------------------------------------------------------------------------\n\n const notifyPresence = (chan: Chan): void => {\n const members = [...chan.members.values()];\n chan.list = members;\n emit(chan.presence, members);\n };\n\n const onFrame = (frame: ServerFrame, viaPost: boolean): void => {\n switch (frame.t) {\n case \"ready\":\n onReady(frame);\n return;\n case \"bye\":\n byeCode = frame.code;\n return;\n case \"subbed\": {\n const chan = chans.get(frame.c);\n const w = chan?.w;\n if (chan === undefined || w === undefined || w.n !== frame.n) return;\n if (frame.reset || w.after === undefined) chan.last = frame.head;\n const info = { after: w.after ?? 0, head: frame.head };\n const gap = frame.reset\n ? true\n : frame.gap === true && w.after !== undefined && !(w.after === 0 && !chan.sy);\n chan.sy = true;\n chan.fails = 0;\n setChanStatus(chan, \"live\");\n if (gap) emit(chan.gl, { ...info, reset: frame.reset === true });\n return;\n }\n case \"unsubbed\": {\n const chan = chans.get(frame.c);\n if (chan === undefined) return;\n if (frame.why === \"revoked\") {\n // The hub dropped the subscription: closing must not send an unsub it would answer with not_subscribed.\n chan.w = undefined;\n closeChan(chan, new RealtimeError(\"forbidden\", \"revoked\"));\n } else resubscribe(chan, frame.why === \"gap\" || frame.why === \"reset\");\n return;\n }\n case \"msg\": {\n const chan = chans.get(frame.c);\n if (chan === undefined || frame.s <= chan.last) return;\n chan.last = frame.s;\n const meta: MessageMeta = {\n seq: frame.s,\n replayed: frame.r === 1,\n ...(frame.p === undefined ? {} : { publisher: frame.p }),\n ...(frame.u === undefined ? {} : { user: frame.u }),\n };\n for (const handler of [...(chan.ev.get(frame.e) ?? [])])\n guard(() => handler(frame.d, meta));\n for (const handler of [...chan.any])\n guard(() => handler({ event: frame.e, data: frame.d, meta } as AnyMessage<ChannelDef>));\n return;\n }\n case \"ack\": {\n const op = take(frame.n);\n if (op !== undefined) succeed(op, { seq: frame.s, duplicate: frame.dup === true });\n return;\n }\n case \"rep\": {\n const op = take(frame.n);\n if (op !== undefined) succeed(op, frame.d);\n return;\n }\n case \"err\": {\n const error = new RealtimeError(frame.code, frame.msg);\n const chan = frame.c === undefined ? undefined : chans.get(frame.c);\n if (frame.n !== undefined) {\n if (!viaPost && chan?.w?.n === frame.n) {\n if (TRANSIENT.has(frame.code)) {\n resubscribe(chan, false);\n report(error);\n } else {\n chan.w = undefined;\n closeChan(chan, error);\n }\n return;\n }\n // Over SSE a number on the stream names a subscription; only a POST answer names an operation.\n const op = viaPost || mode === \"ws\" ? take(frame.n) : undefined;\n if (op !== undefined) {\n fail(op, error);\n return;\n }\n }\n report(error);\n return;\n }\n case \"pres\": {\n const chan = chans.get(frame.c);\n if (chan === undefined) return;\n if (applyPresence(chan.members, frame.op, frame.m)) notifyPresence(chan);\n if (frame.op === \"sync\" && chan.w !== undefined) {\n chan.w.ready = true;\n if (chan.w.join && chan.w.ver !== chan.sv) sendPresence(chan);\n }\n return;\n }\n case \"pong\":\n return;\n }\n };\n\n // --- sending ------------------------------------------------------------------------------------------------------\n\n const flush = (): void => {\n if (!ready || finished) return;\n syncAll();\n if (mode === \"sse\") {\n postNext();\n return;\n }\n for (let op = queue[0]; op !== undefined && ready; op = queue[0]) {\n const text = encode(op);\n if (text !== undefined) {\n if (link?.send(text) !== true) return;\n sent(op);\n }\n queue.shift();\n }\n };\n\n const postNext = (): void => {\n if (posting || postTimer !== undefined || connId === undefined) return;\n const ops: Op[] = [];\n const texts: string[] = [];\n let bytes = 0;\n while (queue.length > 0 && ops.length < MAX_FRAMES_PER_POST && bytes < MAX_POST_BYTES) {\n const op = queue.shift();\n if (op === undefined) break;\n const text = encode(op);\n if (text === undefined) continue;\n ops.push(op);\n texts.push(text);\n bytes += text.length;\n }\n if (ops.length === 0) return;\n posting = true;\n postBatch(ops, `{\"cid\":${JSON.stringify(connId)},\"frames\":[${texts.join(\",\")}]}`).then(\n undefined,\n report,\n );\n };\n\n const postBatch = async (ops: Op[], body: string): Promise<void> => {\n for (const op of ops) sent(op);\n let again = false;\n try {\n const headers = new Headers(await getHeaders());\n headers.set(\"content-type\", \"application/json\");\n const url =\n options.postUrl === undefined\n ? sendUrl(resolveUrl(options.url, false))\n : resolveUrl(options.postUrl, false);\n const response = await doFetch(url, { method: \"POST\", headers, body, signal: life.signal });\n if (response.ok) {\n const parsed = (await response.json()) as { frames?: unknown };\n if (Array.isArray(parsed.frames))\n for (const item of parsed.frames as unknown[]) {\n const frame = decodeServerFrame(JSON.stringify(item));\n if (frame !== undefined) guard(() => onFrame(frame, true));\n }\n postFails = 0;\n } else if (response.status >= 500 || RETRYABLE_STATUS.has(response.status)) again = true;\n else {\n const refusal = (await response.json().catch(() => undefined)) as\n | { error?: { code?: ErrorCode; message?: string } }\n | undefined;\n const code: ErrorCode = refusal?.error?.code ?? \"unavailable\";\n for (const op of ops) {\n if (inflight.get(op.n) === op) inflight.delete(op.n);\n fail(op, new RealtimeError(code, refusal?.error?.message));\n }\n }\n } catch {\n if (life.signal.aborted) return;\n again = true;\n }\n posting = false;\n const unanswered = ops.filter(\n (op) => (op.kind === \"req\" || (op.kind === \"pub\" && op.ack)) && inflight.get(op.n) === op,\n );\n for (const op of unanswered) inflight.delete(op.n);\n if (again) {\n for (const op of unanswered)\n if (op.kind === \"req\") fail(op, new RealtimeError(\"unavailable\"));\n requeue(\n ops.filter(\n (op) => op.kind === \"pres\" || (op.kind === \"pub\" && (!op.ack || unanswered.includes(op))),\n ),\n );\n postFails += 1;\n postTimer = setTimeout(\n () => {\n postTimer = undefined;\n flush();\n },\n backoff(postFails - 1, minDelay, maxDelay, random),\n );\n } else for (const op of unanswered) fail(op, new RealtimeError(\"unavailable\"));\n flush();\n };\n\n // --- lifecycle ----------------------------------------------------------------------------------------------------\n\n const needed = (): boolean => queue.length > 0 || [...chans.values()].some(wants);\n\n const run = (): void => {\n scheduled = false;\n if (finished) return;\n syncAll();\n if (link === undefined) {\n if (reconnectTimer === undefined && needed()) connect();\n return;\n }\n if (\n mode === \"sse\" &&\n (signature() !== streamSig ||\n [...chans.values()].some((c) => wants(c) && c.w === undefined && c.retry === undefined))\n )\n reopen();\n else flush();\n };\n\n function schedule(): void {\n if (scheduled || finished) return;\n scheduled = true;\n queueMicrotask(run);\n }\n\n function shutdown(error?: RealtimeError): void {\n if (finished) return;\n finished = true;\n clearTimeout(reconnectTimer);\n clearTimeout(postTimer);\n reconnectTimer = undefined;\n postTimer = undefined;\n drop();\n life.abort();\n if (listening && typeof removeEventListener === \"function\")\n removeEventListener(\"online\", onOnline);\n listening = false;\n const closed = error ?? new RealtimeError(\"closed\");\n const pending = [...queue.splice(0), ...inflight.values()];\n inflight.clear();\n for (const op of pending) {\n if (op.settle === undefined) clearTimeout(op.timer);\n else fail(op, closed);\n }\n for (const chan of [...chans.values()]) closeChan(chan);\n chans.clear();\n dirty.clear();\n setStatus(\"closed\");\n statusListeners.clear();\n if (error !== undefined) report(error);\n }\n\n // --- the public handles -------------------------------------------------------------------------------------------\n\n const makeChannel = (name: string, channelOptions: ChannelOptions): Channel<ChannelDef> => {\n const chan: Chan = {\n name,\n options: channelOptions,\n ev: new Map(),\n any: new Set(),\n gl: new Set(),\n sl: new Set(),\n presence: new Set(),\n members: new Map(),\n list: undefined,\n status: \"idle\",\n refs: 0,\n hd: 0,\n last: 0,\n sy: false,\n state: channelOptions.presence,\n sv: 0,\n w: undefined,\n retry: undefined,\n fails: 0,\n closed: false,\n hn: undefined,\n };\n chans.set(name, chan);\n if (wants(chan)) touch(chan);\n\n /** Registers a listener; unless `passive`, it keeps the channel subscribed until removed. */\n const listen = <T>(\n set: Set<T>,\n item: T,\n passive?: boolean,\n after?: () => void,\n ): (() => void) => {\n if (chan.closed) return () => undefined;\n set.add(item);\n if (!passive) {\n chan.refs += 1;\n touch(chan);\n }\n return () => {\n if (!set.delete(item) || passive) return;\n chan.refs -= 1;\n after?.();\n touch(chan);\n };\n };\n\n /** Validates and queues a publish or a request; the promise settles with its answer. */\n const submit = <T>(\n kind: \"pub\" | \"req\",\n event: string,\n data: unknown,\n key: string | undefined,\n ack: boolean,\n ms: number,\n ): Promise<T> => {\n let text = \"null\";\n let refusal: RealtimeError | undefined;\n if (chan.closed) refusal = new RealtimeError(\"closed\");\n else if (!isEventName(event) || (key !== undefined && !isIdempotencyKey(key)))\n refusal = new RealtimeError(\"bad_frame\");\n else\n try {\n text = JSON.stringify(data ?? null) ?? \"null\";\n } catch (cause) {\n refusal = new RealtimeError(\"bad_frame\", \"not JSON\", { cause });\n }\n if (refusal !== undefined) return Promise.reject(refusal);\n return new Promise<T>((resolve, reject) => {\n const request = kind === \"req\";\n const op = newOp(kind, chan, event, text, {\n key: request ? undefined : (key ?? `${id}:${++keys}`),\n ack,\n ms,\n settle: ack\n ? (error, value) => {\n if (request) {\n chan.hd -= 1;\n touch(chan);\n }\n if (error) reject(error);\n else resolve(value as T);\n }\n : undefined,\n });\n if (request) {\n chan.hd += 1;\n touch(chan);\n }\n const refused = enqueue(op);\n if (refused !== undefined) {\n op.settle = undefined;\n if (request) chan.hd -= 1;\n reject(refused);\n } else if (!ack) resolve({ seq: 0, duplicate: false } as T);\n });\n };\n\n const hn: Channel<ChannelDef> = {\n name,\n get status() {\n return chan.status;\n },\n get lastSeq() {\n return chan.last;\n },\n on(event, handler) {\n let set = chan.ev.get(event);\n if (set === undefined) {\n set = new Set();\n chan.ev.set(event, set);\n }\n const handlers = set;\n return listen(handlers, handler as Handler, false, () => {\n if (handlers.size === 0 && chan.ev.get(event) === handlers) chan.ev.delete(event);\n });\n },\n onAny: (handler) => listen(chan.any, handler as (message: AnyMessage<ChannelDef>) => void),\n onGap: (handler) => listen(chan.gl, handler),\n onStatus: (handler) => listen(chan.sl, handler, true),\n publish: (event, data, publishOptions = {}) =>\n submit<PublishAck>(\"pub\", event, data, publishOptions.key, publishOptions.ack !== false, 0),\n request: (event, data, requestOptions = {}) =>\n submit(\"req\", event, data, undefined, true, requestOptions.timeoutMs ?? DEFAULT_REQUEST_MS),\n presence: {\n members: () => {\n chan.list ??= [...chan.members.values()];\n return chan.list as never;\n },\n set(state) {\n if (chan.closed) return;\n chan.state = state as Json;\n chan.sv += 1;\n touch(chan);\n },\n leave() {\n if (chan.closed || chan.state === undefined) return;\n chan.state = undefined;\n chan.sv += 1;\n touch(chan);\n },\n on: (callback) => listen(chan.presence, callback as (members: readonly Member[]) => void),\n },\n close: () => closeChan(chan),\n };\n chan.hn = hn;\n return hn;\n };\n\n return {\n channel(name, channelOptions = {}) {\n if (finished) throw new RealtimeError(\"closed\");\n if (!isChannelName(name)) throw new RealtimeError(\"bad_channel\", name);\n const live = chans.get(name);\n return (live?.hn ?? makeChannel(name, channelOptions)) as never;\n },\n get status() {\n return status;\n },\n get connectionId() {\n return connId;\n },\n onStatus(handler) {\n if (!finished) statusListeners.add(handler);\n return () => {\n statusListeners.delete(handler);\n };\n },\n close: () => shutdown(),\n };\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shadow-js/realtime",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Typed channels, presence and resumable delivery over WebSocket or server-sent events",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -77,16 +77,16 @@
77
77
  "url": "https://github.com/shadowjs-dev/realtime/issues"
78
78
  },
79
79
  "peerDependencies": {
80
- "@shadow-js/core": "^1.0.0"
80
+ "@shadow-js/core": "^1.0.1"
81
81
  },
82
82
  "devDependencies": {
83
83
  "@biomejs/biome": "2.5.15",
84
84
  "@resvg/resvg-wasm": "2.6.2",
85
- "@shadow-js/core": "^1.0.0",
86
- "@shadow-js/dusk": "^1.0.0",
85
+ "@shadow-js/core": "^1.0.1",
86
+ "@shadow-js/dusk": "^1.0.1",
87
87
  "@shadow-js/i18n": "*",
88
88
  "@shadow-js/router": "*",
89
- "@shadow-js/testing": "^1.0.0",
89
+ "@shadow-js/testing": "^1.0.1",
90
90
  "@testing-library/dom": "10.4.2",
91
91
  "@types/node": "^24.0.0",
92
92
  "fast-check": "^4.10.2",