cross-tab-worker-databus 0.1.2 → 0.2.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 +64 -0
  2. package/README.md +32 -0
  3. package/README.zh.md +30 -0
  4. package/dist/centrifuge-protocol.d.ts +51 -15
  5. package/dist/centrifuge-protocol.d.ts.map +1 -1
  6. package/dist/centrifuge-session.d.ts +11 -3
  7. package/dist/centrifuge-session.d.ts.map +1 -1
  8. package/dist/centrifuge.d.ts +10 -2
  9. package/dist/centrifuge.d.ts.map +1 -1
  10. package/dist/centrifuge.js +69 -26
  11. package/dist/centrifuge.js.map +2 -2
  12. package/dist/centrifuge.shared.worker.js +73 -25
  13. package/dist/centrifuge.shared.worker.js.map +2 -2
  14. package/dist/centrifuge.worker.js +41 -12
  15. package/dist/centrifuge.worker.js.map +2 -2
  16. package/dist/{chunk-53INHVYO.js → chunk-LBXREMZA.js} +263 -158
  17. package/dist/chunk-LBXREMZA.js.map +7 -0
  18. package/dist/core/cluster.d.ts +49 -4
  19. package/dist/core/cluster.d.ts.map +1 -1
  20. package/dist/core/data-bus.d.ts +19 -2
  21. package/dist/core/data-bus.d.ts.map +1 -1
  22. package/dist/core/environment.d.ts +16 -2
  23. package/dist/core/environment.d.ts.map +1 -1
  24. package/dist/core/hash.d.ts.map +1 -1
  25. package/dist/core/routing.d.ts +5 -2
  26. package/dist/core/routing.d.ts.map +1 -1
  27. package/dist/core/storage-batch.d.ts +12 -0
  28. package/dist/core/storage-batch.d.ts.map +1 -1
  29. package/dist/core/trace.d.ts +16 -1
  30. package/dist/core/trace.d.ts.map +1 -1
  31. package/dist/core/types.d.ts +76 -21
  32. package/dist/core/types.d.ts.map +1 -1
  33. package/dist/index.js +1 -1
  34. package/dist/worker-mode.d.ts +12 -3
  35. package/dist/worker-mode.d.ts.map +1 -1
  36. package/dist/workers/port-reaper.d.ts +21 -6
  37. package/dist/workers/port-reaper.d.ts.map +1 -1
  38. package/docs/README.md +1 -0
  39. package/docs/architecture.md +18 -8
  40. package/docs/getting-started.md +3 -0
  41. package/docs/transports.md +145 -0
  42. package/docs/zh/README.md +1 -0
  43. package/docs/zh/architecture.md +18 -8
  44. package/docs/zh/getting-started.md +3 -0
  45. package/docs/zh/transports.md +133 -0
  46. package/package.json +29 -6
  47. package/dist/chunk-53INHVYO.js.map +0 -7
@@ -28,21 +28,33 @@ export interface ClusterChannel {
28
28
  * Tests inject a fake environment to control timing, storage, and lifecycle.
29
29
  */
30
30
  export interface ClusterEnvironment {
31
- /** localStorage (or null if unavailable). */
31
+ /** localStorage (or null if unavailable). Wrapped by BatchingStorageWriter. */
32
32
  storage: StorageLike | null;
33
33
  /** sessionStorage (or null if unavailable). Used for stable tab IDs. */
34
34
  sessionStorage: StorageLike | null;
35
+ /** Monotonic clock; injected so tests can control time. */
35
36
  now: () => number;
37
+ /** Generates a random ID (UUID when crypto is available, else Math.random). */
36
38
  randomId: () => string;
39
+ /** Creates a BroadcastChannel by name, or null if unsupported. */
37
40
  createChannel: (name: string) => ClusterChannel | null;
41
+ /** Sets an interval; returns a handle for clearInterval. */
38
42
  setInterval: (callback: () => void, intervalMs: number) => unknown;
43
+ /** Clears a handle from setInterval. */
39
44
  clearInterval: (handle: unknown) => void;
45
+ /** Current tab visibility ('visible' or 'hidden'). */
40
46
  getVisibilityState: () => TabVisibilityState;
47
+ /** Register a listener for visibilitychange events. */
41
48
  addVisibilityChangeListener: (listener: () => void) => void;
49
+ /** Remove a previously-added visibilitychange listener. */
42
50
  removeVisibilityChangeListener: (listener: () => void) => void;
51
+ /** Register a listener for pagehide (BFCache entry). */
43
52
  addPageHideListener: (listener: () => void) => void;
53
+ /** Remove a previously-added pagehide listener. */
44
54
  removePageHideListener: (listener: () => void) => void;
55
+ /** Register a listener for pageshow (BFCache exit / restore). */
45
56
  addPageShowListener: (listener: () => void) => void;
57
+ /** Remove a previously-added pageshow listener. */
46
58
  removePageShowListener: (listener: () => void) => void;
47
59
  }
48
60
  /**
@@ -54,7 +66,9 @@ export declare function createBrowserEnvironment(): ClusterEnvironment;
54
66
  /**
55
67
  * Probe a storage instance with a write-read-delete round-trip.
56
68
  * Returns a type guard so the caller can narrow the type after a successful check.
57
- * Catches quota errors, disabled-storage, or opaque exceptions.
69
+ * Catches quota errors, disabled-storage (Safari private mode), or opaque
70
+ * exceptions — any of which means the storage is not usable for coordination
71
+ * and the Runtime must degrade to local mode.
58
72
  */
59
73
  export declare function canUseStorage(storage: StorageLike | null, probeKey: string): storage is StorageLike;
60
74
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"environment.d.ts","sourceRoot":"","sources":["../../src/core/environment.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAExE,qFAAqF;AACrF,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,KAAK,IAAI,IAAI,CAAC;IACd,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACpC,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAClC,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3C;AAED,sGAAsG;AACtG,MAAM,WAAW,cAAc;IAC7B,gBAAgB,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,CAAC,oBAAoB,CAAC,KAAK,IAAI,GAAG,IAAI,CAAC;IACvG,mBAAmB,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,CAAC,oBAAoB,CAAC,KAAK,IAAI,GAAG,IAAI,CAAC;IAC1G,WAAW,CAAC,OAAO,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACjD,KAAK,IAAI,IAAI,CAAC;CACf;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,6CAA6C;IAC7C,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5B,wEAAwE;IACxE,cAAc,EAAE,WAAW,GAAG,IAAI,CAAC;IACnC,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,MAAM,CAAC;IACvB,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,cAAc,GAAG,IAAI,CAAC;IACvD,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC;IACnE,aAAa,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;IAC7C,2BAA2B,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;IAC5D,8BAA8B,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;IAC/D,mBAAmB,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;IACpD,sBAAsB,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;IACvD,mBAAmB,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;IACpD,sBAAsB,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;CACxD;AAuBD;;;;GAIG;AACH,wBAAgB,wBAAwB,IAAI,kBAAkB,CAoC7D;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,IAAI,WAAW,CASnG;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,kBAAkB,EAC/B,GAAG,SAAoC,GACtC,MAAM,CAqBR"}
1
+ {"version":3,"file":"environment.d.ts","sourceRoot":"","sources":["../../src/core/environment.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAExE,qFAAqF;AACrF,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,KAAK,IAAI,IAAI,CAAC;IACd,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACpC,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAClC,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3C;AAED,sGAAsG;AACtG,MAAM,WAAW,cAAc;IAC7B,gBAAgB,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,CAAC,oBAAoB,CAAC,KAAK,IAAI,GAAG,IAAI,CAAC;IACvG,mBAAmB,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,CAAC,oBAAoB,CAAC,KAAK,IAAI,GAAG,IAAI,CAAC;IAC1G,WAAW,CAAC,OAAO,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACjD,KAAK,IAAI,IAAI,CAAC;CACf;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,+EAA+E;IAC/E,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5B,wEAAwE;IACxE,cAAc,EAAE,WAAW,GAAG,IAAI,CAAC;IACnC,2DAA2D;IAC3D,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,+EAA+E;IAC/E,QAAQ,EAAE,MAAM,MAAM,CAAC;IACvB,kEAAkE;IAClE,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,cAAc,GAAG,IAAI,CAAC;IACvD,4DAA4D;IAC5D,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC;IACnE,wCAAwC;IACxC,aAAa,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,sDAAsD;IACtD,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;IAC7C,uDAAuD;IACvD,2BAA2B,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;IAC5D,2DAA2D;IAC3D,8BAA8B,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;IAC/D,wDAAwD;IACxD,mBAAmB,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;IACpD,mDAAmD;IACnD,sBAAsB,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;IACvD,iEAAiE;IACjE,mBAAmB,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;IACpD,mDAAmD;IACnD,sBAAsB,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;CACxD;AA2BD;;;;GAIG;AACH,wBAAgB,wBAAwB,IAAI,kBAAkB,CAoC7D;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,IAAI,WAAW,CASnG;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,kBAAkB,EAC/B,GAAG,SAAoC,GACtC,MAAM,CAqBR"}
@@ -1 +1 @@
1
- {"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/core/hash.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAyBrD"}
1
+ {"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/core/hash.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CA+BrD"}
@@ -6,13 +6,16 @@
6
6
  * them straightforward to test and reason about.
7
7
  */
8
8
  import type { WorkerRecord, WorkerRoute } from './types';
9
- /** Default cap on the number of Workers that can own topics concurrently. */
9
+ /** Default cap on the number of Workers that can own topics concurrently.
10
+ * Limits fan-out breadth: only N workers are eligible to be new-route
11
+ * owners, so a cluster of 20 tabs still concentrates ownership on a few. */
10
12
  export declare const DEFAULT_MAX_ACTIVE_WORKERS = 3;
11
13
  /**
12
14
  * Pick the Worker with the fewest owned topics, optionally preferring a
13
15
  * specific sticky owner when it is still in the candidate set.
14
16
  * Uses a single reduce pass instead of a full sort — O(n) — and breaks
15
- * load ties by workerId for deterministic routing across tabs.
17
+ * load ties by workerId for deterministic routing across tabs (the
18
+ * comparison is code-unit based, not locale-based, for cross-host stability).
16
19
  */
17
20
  export declare function selectLeastLoadedWorker(workers: readonly WorkerRecord[], preferredWorkerId?: string): WorkerRecord | undefined;
18
21
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"routing.d.ts","sourceRoot":"","sources":["../../src/core/routing.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEzD,6EAA6E;AAC7E,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAE5C;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,SAAS,YAAY,EAAE,EAChC,iBAAiB,CAAC,EAAE,MAAM,GACzB,YAAY,GAAG,SAAS,CAS1B;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,SAAS,YAAY,EAAE,EAChC,gBAAgB,SAA6B,GAC5C,YAAY,EAAE,CAWhB;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,SAAS,YAAY,EAAE,EAChC,eAAe,EAAE,MAAM,GACtB,YAAY,GAAG,IAAI,CAYrB;AAED,iFAAiF;AACjF,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,EAAE,OAAO,EAAE,SAAS,YAAY,EAAE,GAAG,OAAO,CAEnG"}
1
+ {"version":3,"file":"routing.d.ts","sourceRoot":"","sources":["../../src/core/routing.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEzD;;4EAE4E;AAC5E,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAE5C;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,SAAS,YAAY,EAAE,EAChC,iBAAiB,CAAC,EAAE,MAAM,GACzB,YAAY,GAAG,SAAS,CAY1B;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,SAAS,YAAY,EAAE,EAChC,gBAAgB,SAA6B,GAC5C,YAAY,EAAE,CAYhB;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,SAAS,YAAY,EAAE,EAChC,eAAe,EAAE,MAAM,GACtB,YAAY,GAAG,IAAI,CAYrB;AAED,iFAAiF;AACjF,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,EAAE,OAAO,EAAE,SAAS,YAAY,EAAE,GAAG,OAAO,CAEnG"}
@@ -10,6 +10,15 @@ import type { StorageLike } from './environment';
10
10
  * Coalesces synchronous storage writes and applies them in one pass, with
11
11
  * exponential backoff when the underlying storage rejects a write.
12
12
  */
13
+ /**
14
+ * Coalesces synchronous storage writes and applies them in one pass, with
15
+ * exponential backoff when the underlying storage rejects a write.
16
+ *
17
+ * Wraps a {@link StorageLike} so callers (WorkerClusterRuntime) see a normal
18
+ * storage interface; reads transparently see pending writes before they flush.
19
+ * The coalescing window is one microtask, so a burst of heartbeat + route +
20
+ * subscriber writes in the same task becomes a single localStorage flush.
21
+ */
13
22
  export declare class BatchingStorageWriter implements StorageLike {
14
23
  private readonly storage;
15
24
  /** Coalesced write set. A `null` value represents a pending delete. */
@@ -20,6 +29,9 @@ export declare class BatchingStorageWriter implements StorageLike {
20
29
  private retryHandle;
21
30
  private retryDelayMs;
22
31
  constructor(storage: StorageLike);
32
+ /** Number of writes queued in memory but not yet flushed to storage.
33
+ * Used by tests to assert the coalescing window and by flush() to detect
34
+ * the all-drained state. */
23
35
  get pendingSize(): number;
24
36
  get length(): number;
25
37
  clear(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"storage-batch.d.ts","sourceRoot":"","sources":["../../src/core/storage-batch.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AASjD;;;GAGG;AACH,qBAAa,qBAAsB,YAAW,WAAW;IAS3C,OAAO,CAAC,QAAQ,CAAC,OAAO;IARpC,uEAAuE;IACvE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoC;IAC5D,0DAA0D;IAC1D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA6B;IACxD,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,WAAW,CAA8C;IACjE,OAAO,CAAC,YAAY,CAA0B;gBAEjB,OAAO,EAAE,WAAW;IAEjD,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,KAAK,IAAI,IAAI;IAab,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAKnC,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAIjC,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAK7B,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAKzC,KAAK,IAAI,IAAI;IAsCb,yEAAyE;IACzE,OAAO,CAAC,IAAI;IAeZ,OAAO,CAAC,aAAa;IAWrB,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,WAAW;CAMpB"}
1
+ {"version":3,"file":"storage-batch.d.ts","sourceRoot":"","sources":["../../src/core/storage-batch.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAYjD;;;GAGG;AACH;;;;;;;;GAQG;AACH,qBAAa,qBAAsB,YAAW,WAAW;IAS3C,OAAO,CAAC,QAAQ,CAAC,OAAO;IARpC,uEAAuE;IACvE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoC;IAC5D,0DAA0D;IAC1D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA6B;IACxD,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,WAAW,CAA8C;IACjE,OAAO,CAAC,YAAY,CAA0B;gBAEjB,OAAO,EAAE,WAAW;IAEjD;;gCAE4B;IAC5B,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,KAAK,IAAI,IAAI;IAab,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAKnC,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAIjC,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAK7B,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAKzC,KAAK,IAAI,IAAI;IA6Cb,yEAAyE;IACzE,OAAO,CAAC,IAAI;IAiBZ,OAAO,CAAC,aAAa;IAcrB,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,WAAW;CAMpB"}
@@ -8,6 +8,10 @@
8
8
  */
9
9
  import type { WorkerStatus } from './types';
10
10
  /** Trace reporting mode: record only events, only metrics, or both. */
11
+ /** Selects which trace categories the reporter emits.
12
+ * - `events` — lifecycle/status/subscription/coordination/error events only.
13
+ * - `metrics` — periodic `message_metrics` snapshots only.
14
+ * - `all` — both event streams and metrics snapshots. */
11
15
  export type DataBusTraceMode = 'events' | 'metrics' | 'all';
12
16
  /** Emitted when the DataBus starts, stops, suspends, or resumes. */
13
17
  export interface DataBusLifecycleTraceEvent {
@@ -65,10 +69,16 @@ export interface DataBusMetricsTraceEvent {
65
69
  export type DataBusTraceEvent = DataBusLifecycleTraceEvent | DataBusStatusTraceEvent | DataBusSubscriptionTraceEvent | DataBusCoordinationTraceEvent | DataBusErrorTraceEvent | DataBusMetricsTraceEvent;
66
70
  /** Distributive-conditional type: given a trace event union, derive the same shape minus `timestamp`. */
67
71
  type DataBusTraceEventInput = DataBusTraceEvent extends infer TEvent ? TEvent extends DataBusTraceEvent ? Omit<TEvent, 'timestamp'> : never : never;
72
+ /** Configuration for {@link DataBusTraceReporter}. `sink` receives every
73
+ * emitted event (filtered by `mode`); all other fields are optional. */
68
74
  export interface DataBusTraceOptions {
75
+ /** When `false`, the reporter is inert (no events emitted). Default `true`. */
69
76
  enabled?: boolean;
77
+ /** Which event categories to emit. Default `all`. */
70
78
  mode?: DataBusTraceMode;
79
+ /** Aggregation window for `message_metrics` events. Default 5 s. */
71
80
  metricsIntervalMs?: number;
81
+ /** Callback invoked for each emitted trace event. */
72
82
  sink: (event: DataBusTraceEvent) => void;
73
83
  }
74
84
  /**
@@ -94,7 +104,8 @@ export declare class DataBusTraceReporter {
94
104
  private readonly latencyBuckets;
95
105
  private latencySumMs;
96
106
  constructor(options?: DataBusTraceOptions, now?: () => number);
97
- /** Start the periodic metrics flush interval. No-op when mode is 'events'. */
107
+ /** Start the periodic metrics flush interval. No-op when mode is 'events'
108
+ * (no metrics to emit), when disabled, or when already running. */
98
109
  start(): void;
99
110
  /** Pause the metrics interval and reset accumulated counters. */
100
111
  pause(): void;
@@ -116,6 +127,10 @@ export declare class DataBusTraceReporter {
116
127
  * as dispatched but do not produce a latency sample.
117
128
  */
118
129
  recordDispatched(topic: string): void;
130
+ /** True when metrics recording is active: enabled and mode includes metrics.
131
+ * Extracted so the four record / flush methods share one guard expression
132
+ * instead of repeating `!this.enabled || this.mode === 'events'` at each. */
133
+ private get metricsActive();
119
134
  /** Emit the accumulated metrics snapshot if the interval is active. */
120
135
  flush(): void;
121
136
  private flushNow;
@@ -1 +1 @@
1
- {"version":3,"file":"trace.d.ts","sourceRoot":"","sources":["../../src/core/trace.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"trace.d.ts","sourceRoot":"","sources":["../../src/core/trace.ts"],"names":[],"mappings":"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"}
@@ -5,31 +5,40 @@
5
5
  * transport interfaces, trace events, and all supporting types used across
6
6
  * the cluster coordination, DataBus public API, and diagnostics layers.
7
7
  */
8
- /** Convenience alias for values that may be synchronously returned or Promise. */
8
+ /** Convenience alias for values that may be synchronously returned or as a
9
+ * Promise. Used by the DataBusTransport contract so implementations can be
10
+ * either sync or async without changing the call signature. */
9
11
  export type MaybePromise<T> = T | Promise<T>;
10
- /** Whether this Worker can act as a Topic owner. */
12
+ /** Whether this Worker can act as a Topic owner. `active` workers are eligible
13
+ * for new topic assignments; `standby` workers hold existing assignments but
14
+ * are not selected for new ones (e.g. a hidden tab that already owns topics). */
11
15
  export type WorkerRole = 'active' | 'standby';
12
- /** Connection-level status of the transport. */
16
+ /** Connection-level status of the transport. `error` triggers auto-recovery
17
+ * (subject to a cooldown); `disconnected` is a clean or suspend state. */
13
18
  export type WorkerStatus = 'connecting' | 'connected' | 'disconnected' | 'error';
14
- /** Control-plane actions routed between Workers via BroadcastChannel. */
19
+ /** Control-plane actions routed between Workers via BroadcastChannel.
20
+ * These are the three operations a subscriber asks the owning worker to perform. */
15
21
  export type WorkerControlAction = 'SUBSCRIBE' | 'UNSUBSCRIBE' | 'PUBLISH';
16
- /** Whether the tab is currently visible to the user. */
22
+ /** Whether the tab is currently visible to the user. Only influences placement
23
+ * of NEW topic routes; existing routes are sticky and never migrated on hide. */
17
24
  export type TabVisibilityState = 'visible' | 'hidden';
18
25
  /**
19
26
  * A Worker's self-published registration record, written to localStorage
20
27
  * so sibling tabs can discover and route to it.
21
28
  */
22
29
  export interface WorkerRecord {
30
+ /** Stable identity of this runtime instance. Random-suffixed; survives refresh. */
23
31
  workerId: string;
32
+ /** Identity of the browser tab hosting this worker. Survives refresh. */
24
33
  tabId: string;
25
- /** Number of topics this Worker owns. Not a CPU load. */
34
+ /** Number of topics this Worker owns. NOT a CPU load metric. */
26
35
  load: number;
27
36
  role: WorkerRole;
28
37
  status: WorkerStatus;
29
38
  visibilityState: TabVisibilityState;
30
- /** Last heartbeat write timestamp (ms). */
39
+ /** Last heartbeat write timestamp (ms). Workers past `workerTtlMs` are pruned. */
31
40
  heartbeatAt: number;
32
- /** First registration timestamp (ms). Used for deterministic ordering. */
41
+ /** First registration timestamp (ms). Used for deterministic ordering in owner selection. */
33
42
  registeredAt: number;
34
43
  }
35
44
  /**
@@ -38,45 +47,71 @@ export interface WorkerRecord {
38
47
  * the SUBSCRIBE control message.
39
48
  */
40
49
  export interface WorkerRoute {
50
+ /** Opaque 128-bit hash of the topic name (never the plaintext). */
41
51
  topicKey: string;
52
+ /** The workerId that owns this topic's transport subscription. */
42
53
  workerId: string;
54
+ /** The tabId of the owning worker. */
43
55
  tabId: string;
56
+ /** Timestamp (ms) of the last route write. Used for orphan-TTL cleanup. */
44
57
  updatedAt: number;
45
- /** Monotonic route generation; handoff acknowledgements must match it. */
58
+ /** Monotonic route generation; handoff acknowledgements must match it to
59
+ * prevent a stale ACK from authorizing a superseded owner. */
46
60
  generation: number;
47
- /** Previous owner must release its transport subscription before takeover. */
61
+ /** Previous owner that must release its transport subscription before the
62
+ * new owner takes over (graceful handoff only). */
48
63
  handoffFromWorkerId?: string;
49
- /** Set by the owner when it has processed the SUBSCRIBE. Absent → subscriber will retry. */
64
+ /** Set by the owner when it has processed the SUBSCRIBE. Absent → the
65
+ * subscriber will retry the control message to recover from channel loss. */
50
66
  confirmedAt?: number;
51
67
  }
52
- /** Per-tab-per-topic marker stored in localStorage so the cluster knows which tabs still need a topic. */
68
+ /** Per-tab-per-topic marker stored in localStorage so the cluster knows which
69
+ * tabs still need a topic. Each tab writes its own record independently,
70
+ * avoiding read-modify-write contention on a shared array. */
53
71
  export interface TopicSubscriberRecord {
72
+ /** The tab that holds this subscription. */
54
73
  tabId: string;
74
+ /** Timestamp (ms) of the last subscriber write. */
55
75
  updatedAt: number;
56
76
  }
57
77
  /**
58
- * Messages exchanged over the BroadcastChannel. Three types:
59
- * - CONTROL: direct peer-to-peer actions (SUBSCRIBE / UNSUBSCRIBE / PUBLISH)
78
+ * Messages exchanged over the BroadcastChannel. Four types:
79
+ * - CONTROL: point-to-point action (SUBSCRIBE / UNSUBSCRIBE / PUBLISH)
60
80
  * - EVENT: fan-out publications from the owning Worker to all tabs
61
- * - REGISTRY: heartbeat signal that triggers reconciliation on other tabs
81
+ * - REGISTRY: nudge every tab to reconcile immediately
82
+ * - ROUTE_RELEASED: ACK a graceful handoff (only matching generation acts)
62
83
  */
63
- export type WorkerClusterMessage<TEvent = unknown> = {
84
+ export type WorkerClusterMessage<TEvent = unknown> =
85
+ /** A subscriber asks the target worker to perform an action on a topic.
86
+ * Carries the plaintext topic (for transport calls) and the opaque key
87
+ * (for storage/route bookkeeping). */
88
+ {
64
89
  type: 'CONTROL';
65
90
  sourceWorkerId: string;
66
91
  targetWorkerId: string;
67
92
  action: WorkerControlAction;
68
93
  topic: string;
69
94
  topicKey: string;
95
+ /** Present only for PUBLISH actions; the publication payload. */
70
96
  data?: unknown;
71
- } | {
97
+ }
98
+ /** The owning worker fans out a publication to every tab. `eventType`
99
+ * distinguishes databus publications from future event types. */
100
+ | {
72
101
  type: 'EVENT';
73
102
  sourceWorkerId: string;
74
103
  eventType: string;
75
104
  payload: TEvent;
76
- } | {
105
+ }
106
+ /** Nudge peers to reconcile immediately after a registry/route/subscriber
107
+ * write, instead of waiting for the next heartbeat (3 s default). */
108
+ | {
77
109
  type: 'REGISTRY';
78
110
  sourceWorkerId: string;
79
- } | {
111
+ }
112
+ /** The old owner acknowledges it released the transport subscription.
113
+ * Only the new owner whose route `generation` matches may act on this. */
114
+ | {
80
115
  type: 'ROUTE_RELEASED';
81
116
  sourceWorkerId: string;
82
117
  targetWorkerId: string;
@@ -84,29 +119,49 @@ export type WorkerClusterMessage<TEvent = unknown> = {
84
119
  topicKey: string;
85
120
  generation: number;
86
121
  };
122
+ /** A publication delivered to a topic handler: the topic name and the
123
+ * structured-clone-safe payload. */
87
124
  export interface DataBusMessage<TData = unknown> {
88
125
  topic: string;
89
126
  data: TData;
90
127
  }
91
- /** Callbacks the transport calls to notify the DataBus of events. */
128
+ /** Callbacks the transport calls to notify the DataBus of events.
129
+ * The DataBus wires these once during `start()`; the transport must hold
130
+ * the reference and call them for the lifetime of the connection. */
92
131
  export interface DataBusTransportHandlers<TData = unknown> {
132
+ /** A publication arrived from the server for a topic this worker owns. */
93
133
  onMessage: (message: DataBusMessage<TData>) => void;
134
+ /** The connection status changed. `error` triggers auto-recovery. */
94
135
  onStatus: (status: WorkerStatus) => void;
136
+ /** A non-fatal transport error occurred. Does not imply disconnection. */
95
137
  onError: (error: unknown) => void;
96
138
  }
97
139
  /**
98
140
  * Transport abstraction that the DataBus delegates to for real I/O.
99
141
  * Implementations may wrap a WebSocket library, a Worker, or a mock.
100
- * subscribe / unsubscribe MUST be idempotent.
142
+ *
143
+ * Contract requirements:
144
+ * - `subscribe` / `unsubscribe` MUST be idempotent (called on reconnect).
145
+ * - `start` is called once per lifecycle; `stop` is idempotent.
146
+ * - `publish` may be called before `start` settles (queued by the DataBus).
101
147
  */
102
148
  export interface DataBusTransport<TConfig = unknown, TData = unknown> {
149
+ /** Open the connection with `config`. Report status changes via `handlers.onStatus`.
150
+ * May return a Promise that resolves on connect or rejects on failure. */
103
151
  start(config: TConfig, handlers: DataBusTransportHandlers<TData>): MaybePromise<void>;
152
+ /** Subscribe to a topic. Idempotent: re-subscribing an active topic is a no-op. */
104
153
  subscribe(topic: string): MaybePromise<void>;
154
+ /** Unsubscribe from a topic. Idempotent: unsubscribing a non-subscribed topic is a no-op. */
105
155
  unsubscribe(topic: string): MaybePromise<void>;
156
+ /** Publish `data` to `topic` via the server. */
106
157
  publish(topic: string, data: unknown): MaybePromise<void>;
158
+ /** Close the connection and release all resources. Safe to call multiple times. */
107
159
  stop(): MaybePromise<void>;
108
160
  }
161
+ /** Callback invoked for each publication delivered to a subscribed topic. */
109
162
  export type DataBusMessageHandler<TData = unknown> = (message: DataBusMessage<TData>) => void;
163
+ /** Callback invoked on every transport status change. */
110
164
  export type DataBusStatusHandler = (status: WorkerStatus) => void;
165
+ /** Callback invoked when the transport or an operation reports an error. */
111
166
  export type DataBusErrorHandler = (error: unknown) => void;
112
167
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  selectLeastLoadedWorker,
11
11
  selectRebalanceTarget,
12
12
  selectWorkerBackend
13
- } from "./chunk-53INHVYO.js";
13
+ } from "./chunk-LBXREMZA.js";
14
14
  export {
15
15
  CrossTabDataBus,
16
16
  DEFAULT_MAX_ACTIVE_WORKERS,
@@ -5,13 +5,21 @@
5
5
  * that resolves the preference against browser capability to pick the actual
6
6
  * backend (dedicated, shared, or local fallback).
7
7
  */
8
- /** Preferred Worker mode: 'dedicated' → try Dedicated Worker first, 'shared'/'auto' → try SharedWorker first. */
8
+ /** Preferred Worker mode.
9
+ * - `dedicated` → try Dedicated Worker first (one WebSocket per tab).
10
+ * - `shared` → try SharedWorker first (one process, per-port connections).
11
+ * - `auto` → same as `shared` (alias for forward compatibility). */
9
12
  export type WorkerMode = 'dedicated' | 'shared' | 'auto';
10
- /** Resolved backend that was actually created. */
13
+ /** Resolved backend that was actually created. `local` means the session
14
+ * runs on the main thread (fallback when no Worker API is available). */
11
15
  export type WorkerBackend = 'dedicated' | 'shared' | 'local';
12
- /** Override Worker availability for testing or environments where feature detection is unreliable. */
16
+ /** Override Worker availability for testing or environments where feature
17
+ * detection is unreliable (e.g. sandboxed iframes). When a field is omitted,
18
+ * the global `typeof Worker` / `typeof SharedWorker` check is used. */
13
19
  export interface WorkerAvailability {
20
+ /** When provided, overrides `typeof Worker !== 'undefined'`. */
14
21
  worker?: boolean;
22
+ /** When provided, overrides `typeof SharedWorker !== 'undefined'`. */
15
23
  sharedWorker?: boolean;
16
24
  }
17
25
  /**
@@ -20,6 +28,7 @@ export interface WorkerAvailability {
20
28
  *
21
29
  * - `dedicated` prefers Dedicated Worker, then SharedWorker, then local mode.
22
30
  * - `shared` and `auto` prefer SharedWorker, then Dedicated Worker, then local.
31
+ * Returns `'local'` when neither Worker API is available (main-thread fallback).
23
32
  */
24
33
  export declare function selectWorkerBackend(mode: WorkerMode, availability?: WorkerAvailability): WorkerBackend;
25
34
  //# sourceMappingURL=worker-mode.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"worker-mode.d.ts","sourceRoot":"","sources":["../src/worker-mode.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,iHAAiH;AACjH,MAAM,MAAM,UAAU,GAAG,WAAW,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEzD,kDAAkD;AAClD,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE7D,sGAAsG;AACtG,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,UAAU,EAChB,YAAY,GAAE,kBAAuB,GACpC,aAAa,CAOf"}
1
+ {"version":3,"file":"worker-mode.d.ts","sourceRoot":"","sources":["../src/worker-mode.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;oEAGoE;AACpE,MAAM,MAAM,UAAU,GAAG,WAAW,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEzD;yEACyE;AACzE,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE7D;;uEAEuE;AACvE,MAAM,WAAW,kBAAkB;IACjC,gEAAgE;IAChE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,sEAAsE;IACtE,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,UAAU,EAChB,YAAY,GAAE,kBAAuB,GACpC,aAAa,CAOf"}
@@ -32,23 +32,38 @@ export declare class PortReaper {
32
32
  private readonly setTimer;
33
33
  private readonly clearTimer;
34
34
  /** Track a newly connected port and its session. The default timeout applies
35
- * until the port sends an INIT with its own heartbeat config. */
35
+ * until the port sends an INIT with its own heartbeat config, at which point
36
+ * setTimeout() overrides it. register() always calls schedule() so the
37
+ * reaper interval starts as soon as the first port connects. */
36
38
  register(port: MessagePort, target: ReapTarget): void;
37
- /** Record activity on a port (any incoming message). No-op for untracked ports. */
39
+ /** Record activity on a port (any incoming message). No-op for untracked
40
+ * ports — a late PING from a port that was already removed/STOP'd must not
41
+ * resurrect it in the reaper's tracking maps. */
38
42
  touch(port: MessagePort): void;
39
43
  /** Override a port's session timeout from its INIT heartbeat config.
40
44
  * A non-finite or non-positive value falls back to the default so a bad
41
- * payload cannot degenerate the reaper into a busy loop or silence it. */
45
+ * payload cannot degenerate the reaper into a busy loop or silence it.
46
+ * No-op for untracked ports (e.g. setTimeout arrives after remove/STOP). */
42
47
  setTimeout(port: MessagePort, heartbeatIntervalMs: number): void;
43
48
  /** Remove a port (STOP message). The caller is responsible for closing the
44
- * port and stopping the session. */
49
+ * port and stopping the session. No-op for untracked ports so a duplicate
50
+ * STOP or a STOP-after-reap cannot corrupt the reaper's bookkeeping. */
45
51
  remove(port: MessagePort): void;
46
52
  /** Clear all state and stop the reaper. Closes and stops every tracked
47
53
  * session so the SharedWorker does not leak WebSockets on shutdown. */
48
54
  dispose(): void;
49
- /** Recompute the reaper cadence, or stop it entirely when no ports remain. */
55
+ /** Recompute the reaper cadence, or stop it entirely when no ports remain.
56
+ * Idempotent: if the interval is already running at the correct cadence,
57
+ * no new timer is created. This guards against register/remove/setTimeout
58
+ * each spawning redundant timers when the cadence hasn't changed. */
50
59
  private schedule;
51
- /** Close sessions whose port has been silent longer than its timeout. */
60
+ /** Smallest heartbeat interval among active ports, derived from each port's
61
+ * configured session timeout. Exposed as a method so the cadence logic can
62
+ * be unit-tested in isolation from the timer plumbing. */
63
+ private computeMinHeartbeat;
64
+ /** Close sessions whose port has been silent longer than its timeout.
65
+ * Iterates a snapshot so closing a target (which mutates `targets`) during
66
+ * the loop cannot skip a subsequent entry or visit one twice. */
52
67
  private reap;
53
68
  }
54
69
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"port-reaper.d.ts","sourceRoot":"","sources":["../../src/workers/port-reaper.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,4EAA4E;AAC5E,MAAM,WAAW,UAAU;IACzB,KAAK,IAAI,IAAI,CAAC;IACd,IAAI,IAAI,IAAI,CAAC;CACd;AAED,KAAK,QAAQ,GAAG,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC;AAC7D,KAAK,UAAU,GAAG,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;AAE3C,qBAAa,UAAU;IAQnB,OAAO,CAAC,QAAQ,CAAC,GAAG;IAPtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsC;IAC9D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAkC;IAC7D,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAkC;IACnE,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,UAAU,CAAiC;gBAGhC,GAAG,GAAE,MAAM,MAAiB,EAC7C,QAAQ,GAAE,QAA2E,EACrF,UAAU,GAAE,UAA4C;IAM1D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAW;IACpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;IAExC;qEACiE;IACjE,QAAQ,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI;IAOrD,mFAAmF;IACnF,KAAK,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI;IAK9B;;8EAE0E;IAC1E,UAAU,CAAC,IAAI,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,GAAG,IAAI;IAShE;wCACoC;IACpC,MAAM,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI;IAQ/B;2EACuE;IACvE,OAAO,IAAI,IAAI;IAgBf,8EAA8E;IAC9E,OAAO,CAAC,QAAQ;IAiBhB,yEAAyE;IACzE,OAAO,CAAC,IAAI;CA4Bb"}
1
+ {"version":3,"file":"port-reaper.d.ts","sourceRoot":"","sources":["../../src/workers/port-reaper.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAQH,4EAA4E;AAC5E,MAAM,WAAW,UAAU;IACzB,KAAK,IAAI,IAAI,CAAC;IACd,IAAI,IAAI,IAAI,CAAC;CACd;AAED,KAAK,QAAQ,GAAG,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC;AAC7D,KAAK,UAAU,GAAG,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;AAE3C,qBAAa,UAAU;IAQnB,OAAO,CAAC,QAAQ,CAAC,GAAG;IAPtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsC;IAC9D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAkC;IAC7D,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAkC;IACnE,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,UAAU,CAAiC;gBAGhC,GAAG,GAAE,MAAM,MAAiB,EAC7C,QAAQ,GAAE,QAA2E,EACrF,UAAU,GAAE,UAA4C;IAM1D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAW;IACpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;IAExC;;;oEAGgE;IAChE,QAAQ,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI;IAOrD;;qDAEiD;IACjD,KAAK,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI;IAK9B;;;gFAG4E;IAC5E,UAAU,CAAC,IAAI,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,GAAG,IAAI;IAShE;;4EAEwE;IACxE,MAAM,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI;IAQ/B;2EACuE;IACvE,OAAO,IAAI,IAAI;IAgBf;;;yEAGqE;IACrE,OAAO,CAAC,QAAQ;IAahB;;8DAE0D;IAC1D,OAAO,CAAC,mBAAmB;IAQ3B;;qEAEiE;IACjE,OAAO,CAAC,IAAI;CA0Bb"}
package/docs/README.md CHANGED
@@ -6,6 +6,7 @@
6
6
  |---|---|
7
7
  | [Getting Started](./getting-started.md) | Installation, creating instances, subscribing, publishing, and destroying |
8
8
  | [Configuration](./configuration.md) | Core configuration, Centrifuge configuration, defaults, and constraints |
9
+ | [Transports](./transports.md) | The `DataBusTransport` contract, worker protocol, and third-party backend guide |
9
10
  | [API Reference](./api.md) | Public API, types, methods, return values, and behavior |
10
11
  | [Architecture](./architecture.md) | Worker cluster, routing, storage, migration, and degradation design |
11
12
  | [Capabilities Matrix](./capabilities.md) | Implemented, not implemented, and planned capabilities matrix |
@@ -10,23 +10,33 @@ graph TB
10
10
  subgraph TabA["Tab A"]
11
11
  AppA["Business Module"] --> BusA["CrossTabDataBus"]
12
12
  BusA --> RuntimeA["WorkerClusterRuntime"]
13
- BusA --> WorkerA["Dedicated / Shared Worker A"]
13
+ BusA --> TransportA["CentrifugeWorkerTransport"]
14
+ TransportA --> WorkerA["Dedicated / Shared Worker A"]
14
15
  end
15
16
  subgraph TabB["Tab B"]
16
17
  AppB["Business Module"] --> BusB["CrossTabDataBus"]
17
18
  BusB --> RuntimeB["WorkerClusterRuntime"]
18
- BusB --> WorkerB["Dedicated / Shared Worker B"]
19
+ BusB --> TransportB["CentrifugeWorkerTransport"]
20
+ TransportB --> WorkerB["Dedicated / Shared Worker B"]
19
21
  end
20
22
  end
21
23
 
22
24
  RuntimeA <--> Channel["BroadcastChannel Control Plane"]
23
25
  RuntimeB <--> Channel
24
- RuntimeA <--> Registry["localStorage Worker Registration"]
25
- RuntimeB <--> Registry
26
- RuntimeA <--> Routes["localStorage Topic Routes"]
27
- RuntimeB <--> Routes
28
- WorkerA --> Server["Centrifuge / realtime server"]
29
- WorkerB --> Server
26
+ RuntimeA --> BatchA["BatchingStorageWriter"]
27
+ RuntimeB --> BatchB["BatchingStorageWriter"]
28
+ BatchA <--> Registry["localStorage Worker Registration"]
29
+ BatchB <--> Registry
30
+ BatchA <--> Routes["localStorage Topic Routes"]
31
+ BatchB <--> Routes
32
+ WorkerA --> SessionA["CentrifugeSession"]
33
+ WorkerB --> SessionB["CentrifugeSession"]
34
+ SessionA --> Server["Centrifuge / realtime server"]
35
+ SessionB --> Server
36
+ subgraph SW["SharedWorker process (when backend = shared)"]
37
+ Reaper["PortReaper"] -.-> SessionA
38
+ Reaper -.-> SessionB
39
+ end
30
40
  ```
31
41
 
32
42
  By default, when `workerMode: 'dedicated'`, each Tab has its own dedicated transport Worker. When configured as `shared` or `auto` and the browser supports SharedWorker, same-origin tabs share the same SharedWorker; each connection port within the SharedWorker creates its own independent `CentrifugeSession`, so one Tab refreshing or stopping does not affect other Tabs. The `auto` mode degrades in order of **SharedWorker → Dedicated Worker → Local mode**, while the `dedicated` mode degrades in order of **Dedicated Worker → SharedWorker → Local mode**. `BroadcastChannel` is only responsible for control messages and real-time publication forwarding; localStorage is only responsible for eventually-consistent coordination metadata.
@@ -12,8 +12,11 @@ The package provides the following entry points:
12
12
 
13
13
  - `cross-tab-worker-databus`: the core DataBus and transport interfaces
14
14
  - `cross-tab-worker-databus/centrifuge`: the built-in Centrifuge Worker transport
15
+ - `cross-tab-worker-databus/centrifuge.worker`: the Dedicated Worker build artifact, loaded by default by the built-in factory; typically no need to reference it directly
15
16
  - `cross-tab-worker-databus/centrifuge.shared.worker`: the SharedWorker build artifact, loaded by default by the built-in factory; typically no need to reference it directly
16
17
 
18
+ The `cross-tab-worker-databus/centrifuge` entry point relies on the optional peer dependency `centrifuge` (^5.5.3). Install it alongside this package when using the built-in Centrifuge transport: `pnpm add centrifuge`.
19
+
17
20
  ## 2. Creating an Instance
18
21
 
19
22
  It is recommended to create an instance in the application's infrastructure layer and have other modules import it directly. This way, business modules within the same Tab share the Worker, connection, and Topic references.