@use-everywhere/core 0.3.0 → 0.4.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.
- package/dist/index.cjs +973 -0
- package/dist/index.d.cts +445 -0
- package/dist/index.js +24 -3
- package/package.json +21 -10
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,973 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
BroadcastChannelTransport: () => BroadcastChannelTransport,
|
|
24
|
+
CID_PARAM: () => CID_PARAM,
|
|
25
|
+
DEFAULT_NAME: () => DEFAULT_NAME,
|
|
26
|
+
HandshakeTimeoutError: () => HandshakeTimeoutError,
|
|
27
|
+
MemoryHub: () => MemoryHub,
|
|
28
|
+
MemoryTransport: () => MemoryTransport,
|
|
29
|
+
NoopTransport: () => NoopTransport,
|
|
30
|
+
WindowClosedError: () => WindowClosedError,
|
|
31
|
+
connectToOpener: () => connectToOpener,
|
|
32
|
+
createChannel: () => createChannel,
|
|
33
|
+
createLeader: () => createLeader,
|
|
34
|
+
createPresence: () => createPresence,
|
|
35
|
+
createSharedStore: () => createSharedStore,
|
|
36
|
+
defaultTransport: () => defaultTransport,
|
|
37
|
+
enableDebug: () => enableDebug,
|
|
38
|
+
getBusNames: () => getBusNames,
|
|
39
|
+
isBroadcastChannelAvailable: () => isBroadcastChannelAvailable,
|
|
40
|
+
localStorageAdapter: () => localStorageAdapter,
|
|
41
|
+
newer: () => newer,
|
|
42
|
+
observeBus: () => observeBus,
|
|
43
|
+
openWindow: () => openWindow,
|
|
44
|
+
sessionStorageAdapter: () => sessionStorageAdapter,
|
|
45
|
+
webStorageAdapter: () => webStorageAdapter
|
|
46
|
+
});
|
|
47
|
+
module.exports = __toCommonJS(index_exports);
|
|
48
|
+
|
|
49
|
+
// src/defaults.ts
|
|
50
|
+
var DEFAULT_NAME = "use-everywhere";
|
|
51
|
+
|
|
52
|
+
// src/debug.ts
|
|
53
|
+
var observers = /* @__PURE__ */ new Map();
|
|
54
|
+
function emitBusEvent(name, direction, wire) {
|
|
55
|
+
const set = observers.get(name);
|
|
56
|
+
if (!set) return;
|
|
57
|
+
const event = { name, direction, wire };
|
|
58
|
+
for (const fn of set) fn(event);
|
|
59
|
+
}
|
|
60
|
+
function observeBus(name, fn) {
|
|
61
|
+
let set = observers.get(name);
|
|
62
|
+
if (!set) {
|
|
63
|
+
set = /* @__PURE__ */ new Set();
|
|
64
|
+
observers.set(name, set);
|
|
65
|
+
}
|
|
66
|
+
set.add(fn);
|
|
67
|
+
return () => {
|
|
68
|
+
const current = observers.get(name);
|
|
69
|
+
if (!current) return;
|
|
70
|
+
current.delete(fn);
|
|
71
|
+
if (current.size === 0) observers.delete(name);
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function enableDebug(options = {}) {
|
|
75
|
+
const name = options.name ?? DEFAULT_NAME;
|
|
76
|
+
const log = options.log ?? ((...args) => console.log(...args));
|
|
77
|
+
return observeBus(name, ({ direction, wire }) => {
|
|
78
|
+
const arrow = direction === "out" ? "\u2192" : "\u2190";
|
|
79
|
+
log(`[use-everywhere:${name}] ${arrow} ${wire.scope}/${wire.type}`, wire);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// src/ids.ts
|
|
84
|
+
function newClientId() {
|
|
85
|
+
return Math.random().toString(36).slice(2, 8);
|
|
86
|
+
}
|
|
87
|
+
function newMsgId() {
|
|
88
|
+
return Math.random().toString(36).slice(2, 10);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// src/transport/broadcast-channel-transport.ts
|
|
92
|
+
var BroadcastChannelTransport = class {
|
|
93
|
+
constructor(name) {
|
|
94
|
+
this.listeners = /* @__PURE__ */ new Set();
|
|
95
|
+
this.bc = new BroadcastChannel(name);
|
|
96
|
+
this.bc.onmessage = (event) => {
|
|
97
|
+
for (const listener of this.listeners) listener(event.data);
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
post(data) {
|
|
101
|
+
this.bc.postMessage(data);
|
|
102
|
+
}
|
|
103
|
+
subscribe(listener) {
|
|
104
|
+
this.listeners.add(listener);
|
|
105
|
+
return () => this.listeners.delete(listener);
|
|
106
|
+
}
|
|
107
|
+
close() {
|
|
108
|
+
this.listeners.clear();
|
|
109
|
+
this.bc.close();
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
// src/transport/noop-transport.ts
|
|
114
|
+
var NoopTransport = class {
|
|
115
|
+
post() {
|
|
116
|
+
}
|
|
117
|
+
subscribe() {
|
|
118
|
+
return () => {
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
close() {
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
// src/transport/default-transport.ts
|
|
126
|
+
function isBroadcastChannelAvailable() {
|
|
127
|
+
return typeof BroadcastChannel !== "undefined";
|
|
128
|
+
}
|
|
129
|
+
function defaultTransport(name) {
|
|
130
|
+
return isBroadcastChannelAvailable() ? new BroadcastChannelTransport(name) : new NoopTransport();
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// src/bus.ts
|
|
134
|
+
function isBusWire(data) {
|
|
135
|
+
return typeof data === "object" && data !== null && data.v === 1;
|
|
136
|
+
}
|
|
137
|
+
function defaultKind() {
|
|
138
|
+
return typeof document === "undefined" ? "worker" : "tab";
|
|
139
|
+
}
|
|
140
|
+
var registry = /* @__PURE__ */ new Map();
|
|
141
|
+
function createBus(name, options, onShutdown) {
|
|
142
|
+
const transport = (options.transport ?? defaultTransport)(name);
|
|
143
|
+
const clientId = newClientId();
|
|
144
|
+
const kind = options.kind ?? defaultKind();
|
|
145
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
146
|
+
let refs = 0;
|
|
147
|
+
let closed = false;
|
|
148
|
+
const post = (wire) => {
|
|
149
|
+
if (closed) return;
|
|
150
|
+
emitBusEvent(name, "out", wire);
|
|
151
|
+
transport.post(wire);
|
|
152
|
+
};
|
|
153
|
+
const unsubscribe = transport.subscribe((data) => {
|
|
154
|
+
if (!isBusWire(data)) return;
|
|
155
|
+
if (data.clientId === clientId) return;
|
|
156
|
+
emitBusEvent(name, "in", data);
|
|
157
|
+
if (data.scope === "presence" && data.type === "hello") {
|
|
158
|
+
post({ v: 1, scope: "presence", type: "ping", clientId, kind });
|
|
159
|
+
}
|
|
160
|
+
for (const fn of listeners) fn(data);
|
|
161
|
+
});
|
|
162
|
+
post({ v: 1, scope: "presence", type: "hello", clientId, kind });
|
|
163
|
+
const heartbeat = setInterval(
|
|
164
|
+
() => post({ v: 1, scope: "presence", type: "ping", clientId, kind }),
|
|
165
|
+
options.heartbeatMs ?? 2e3
|
|
166
|
+
);
|
|
167
|
+
const sayBye = () => post({ v: 1, scope: "presence", type: "bye", clientId, kind });
|
|
168
|
+
const hasWindow = typeof document !== "undefined" && typeof addEventListener === "function";
|
|
169
|
+
if (hasWindow) addEventListener("pagehide", sayBye);
|
|
170
|
+
return {
|
|
171
|
+
name,
|
|
172
|
+
clientId,
|
|
173
|
+
kind,
|
|
174
|
+
post,
|
|
175
|
+
subscribe(fn) {
|
|
176
|
+
listeners.add(fn);
|
|
177
|
+
return () => listeners.delete(fn);
|
|
178
|
+
},
|
|
179
|
+
acquire() {
|
|
180
|
+
refs++;
|
|
181
|
+
},
|
|
182
|
+
release() {
|
|
183
|
+
refs--;
|
|
184
|
+
if (refs > 0) return;
|
|
185
|
+
sayBye();
|
|
186
|
+
closed = true;
|
|
187
|
+
clearInterval(heartbeat);
|
|
188
|
+
if (hasWindow) removeEventListener("pagehide", sayBye);
|
|
189
|
+
unsubscribe();
|
|
190
|
+
transport.close();
|
|
191
|
+
listeners.clear();
|
|
192
|
+
onShutdown();
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
function getBusNames() {
|
|
197
|
+
return [...registry.keys()];
|
|
198
|
+
}
|
|
199
|
+
function getBus(name, options = {}) {
|
|
200
|
+
if (options.transport) {
|
|
201
|
+
const bus2 = createBus(name, options, () => {
|
|
202
|
+
});
|
|
203
|
+
bus2.acquire();
|
|
204
|
+
return bus2;
|
|
205
|
+
}
|
|
206
|
+
let bus = registry.get(name);
|
|
207
|
+
if (!bus) {
|
|
208
|
+
bus = createBus(name, options, () => registry.delete(name));
|
|
209
|
+
registry.set(name, bus);
|
|
210
|
+
}
|
|
211
|
+
bus.acquire();
|
|
212
|
+
return bus;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// src/channel.ts
|
|
216
|
+
function createChannel(name, options = {}) {
|
|
217
|
+
const bus = getBus(name, options);
|
|
218
|
+
const handlers = /* @__PURE__ */ new Map();
|
|
219
|
+
const unsubscribe = bus.subscribe((wire) => {
|
|
220
|
+
if (wire.scope !== "event") return;
|
|
221
|
+
const set = handlers.get(wire.type);
|
|
222
|
+
if (!set) return;
|
|
223
|
+
const meta = { clientId: wire.clientId, kind: wire.kind, self: false };
|
|
224
|
+
for (const fn of set) fn(wire.payload, meta);
|
|
225
|
+
});
|
|
226
|
+
return {
|
|
227
|
+
name,
|
|
228
|
+
clientId: bus.clientId,
|
|
229
|
+
post(type, payload) {
|
|
230
|
+
bus.post({
|
|
231
|
+
v: 1,
|
|
232
|
+
scope: "event",
|
|
233
|
+
type,
|
|
234
|
+
payload,
|
|
235
|
+
clientId: bus.clientId,
|
|
236
|
+
kind: bus.kind,
|
|
237
|
+
msgId: newMsgId()
|
|
238
|
+
});
|
|
239
|
+
},
|
|
240
|
+
on(type, handler) {
|
|
241
|
+
let set = handlers.get(type);
|
|
242
|
+
if (!set) {
|
|
243
|
+
set = /* @__PURE__ */ new Set();
|
|
244
|
+
handlers.set(type, set);
|
|
245
|
+
}
|
|
246
|
+
set.add(handler);
|
|
247
|
+
return () => set.delete(handler);
|
|
248
|
+
},
|
|
249
|
+
close() {
|
|
250
|
+
unsubscribe();
|
|
251
|
+
handlers.clear();
|
|
252
|
+
bus.release();
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// src/clock.ts
|
|
258
|
+
function newer(a, b) {
|
|
259
|
+
return !b || a[0] > b[0] || a[0] === b[0] && a[1] > b[1];
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// src/dev-freeze.ts
|
|
263
|
+
var inDev = false;
|
|
264
|
+
try {
|
|
265
|
+
inDev = process.env.NODE_ENV !== "production";
|
|
266
|
+
} catch {
|
|
267
|
+
}
|
|
268
|
+
function deepFreeze(value) {
|
|
269
|
+
if (value === null || typeof value !== "object" || Object.isFrozen(value)) return;
|
|
270
|
+
Object.freeze(value);
|
|
271
|
+
for (const key of Object.keys(value)) {
|
|
272
|
+
deepFreeze(value[key]);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
function freezeShared(value) {
|
|
276
|
+
if (inDev) deepFreeze(value);
|
|
277
|
+
return value;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// src/shared-store.ts
|
|
281
|
+
function createSharedStore(name, initial, options = {}) {
|
|
282
|
+
const bus = getBus(name, options);
|
|
283
|
+
const clientId = bus.clientId;
|
|
284
|
+
const accept = options.accept;
|
|
285
|
+
const state = { ...initial };
|
|
286
|
+
const versions = {};
|
|
287
|
+
for (const k in state) {
|
|
288
|
+
versions[k] = [0, clientId];
|
|
289
|
+
freezeShared(state[k]);
|
|
290
|
+
}
|
|
291
|
+
let snapshot = Object.freeze({ ...state });
|
|
292
|
+
let versionsSnapshot = Object.freeze({ ...versions });
|
|
293
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
294
|
+
const keyListeners = /* @__PURE__ */ new Map();
|
|
295
|
+
function notify(key, value, meta) {
|
|
296
|
+
snapshot = Object.freeze({ ...state });
|
|
297
|
+
versionsSnapshot = Object.freeze({ ...versions });
|
|
298
|
+
for (const fn of listeners) fn(key, value, meta);
|
|
299
|
+
const set = keyListeners.get(key);
|
|
300
|
+
if (set) for (const fn of set) fn();
|
|
301
|
+
}
|
|
302
|
+
function applyRemote(key, value, version, meta) {
|
|
303
|
+
if (!newer(version, versions[key])) return;
|
|
304
|
+
versions[key] = version;
|
|
305
|
+
state[key] = freezeShared(value);
|
|
306
|
+
notify(key, value, meta);
|
|
307
|
+
}
|
|
308
|
+
const unsubscribe = bus.subscribe((wire) => {
|
|
309
|
+
if (wire.scope !== "state") return;
|
|
310
|
+
const meta = { clientId: wire.clientId, kind: wire.kind, self: false };
|
|
311
|
+
if (wire.type === "hello") {
|
|
312
|
+
bus.post({
|
|
313
|
+
v: 1,
|
|
314
|
+
scope: "state",
|
|
315
|
+
type: "snapshot",
|
|
316
|
+
clientId,
|
|
317
|
+
kind: bus.kind,
|
|
318
|
+
state: { ...state },
|
|
319
|
+
versions: { ...versions }
|
|
320
|
+
});
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
if (accept && !accept(meta)) return;
|
|
324
|
+
if (wire.type === "patch") {
|
|
325
|
+
applyRemote(wire.key, wire.value, wire.version, meta);
|
|
326
|
+
} else {
|
|
327
|
+
for (const k in wire.state) {
|
|
328
|
+
const version = wire.versions[k];
|
|
329
|
+
if (version) applyRemote(k, wire.state[k], version, meta);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
function setKey(key, value) {
|
|
334
|
+
const version = [(versions[key]?.[0] ?? 0) + 1, clientId];
|
|
335
|
+
versions[key] = version;
|
|
336
|
+
state[key] = freezeShared(value);
|
|
337
|
+
bus.post({
|
|
338
|
+
v: 1,
|
|
339
|
+
scope: "state",
|
|
340
|
+
type: "patch",
|
|
341
|
+
key,
|
|
342
|
+
value,
|
|
343
|
+
version,
|
|
344
|
+
clientId,
|
|
345
|
+
kind: bus.kind
|
|
346
|
+
});
|
|
347
|
+
notify(key, value, { clientId, kind: bus.kind, self: true });
|
|
348
|
+
}
|
|
349
|
+
const proxy = new Proxy(state, {
|
|
350
|
+
set(_target, key, value) {
|
|
351
|
+
if (typeof key !== "string") return false;
|
|
352
|
+
setKey(key, value);
|
|
353
|
+
return true;
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
const persist = options.persist;
|
|
357
|
+
let flushPersist;
|
|
358
|
+
if (persist) {
|
|
359
|
+
const { adapter, keys, debounceMs = 100 } = persist;
|
|
360
|
+
const shouldPersist = (key) => !keys || keys.includes(key);
|
|
361
|
+
const hydrate = (saved2) => {
|
|
362
|
+
if (!saved2) return;
|
|
363
|
+
for (const key in saved2.state) {
|
|
364
|
+
const version = saved2.versions[key];
|
|
365
|
+
if (!version || !shouldPersist(key)) continue;
|
|
366
|
+
applyRemote(key, saved2.state[key], version, { clientId, kind: bus.kind, self: true });
|
|
367
|
+
bus.post({
|
|
368
|
+
v: 1,
|
|
369
|
+
scope: "state",
|
|
370
|
+
type: "patch",
|
|
371
|
+
key,
|
|
372
|
+
value: saved2.state[key],
|
|
373
|
+
version,
|
|
374
|
+
clientId,
|
|
375
|
+
kind: bus.kind
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
};
|
|
379
|
+
const collect = () => {
|
|
380
|
+
const out = { v: 1, state: {}, versions: {} };
|
|
381
|
+
for (const key in versions) {
|
|
382
|
+
const version = versions[key];
|
|
383
|
+
if (!version || version[0] === 0 || !shouldPersist(key)) continue;
|
|
384
|
+
out.state[key] = state[key];
|
|
385
|
+
out.versions[key] = version;
|
|
386
|
+
}
|
|
387
|
+
return out;
|
|
388
|
+
};
|
|
389
|
+
let timer;
|
|
390
|
+
flushPersist = () => {
|
|
391
|
+
clearTimeout(timer);
|
|
392
|
+
timer = void 0;
|
|
393
|
+
void adapter.write(collect());
|
|
394
|
+
};
|
|
395
|
+
const saved = adapter.read();
|
|
396
|
+
if (saved instanceof Promise) {
|
|
397
|
+
void saved.then(hydrate);
|
|
398
|
+
} else {
|
|
399
|
+
hydrate(saved);
|
|
400
|
+
}
|
|
401
|
+
listeners.add(() => {
|
|
402
|
+
if (timer !== void 0) return;
|
|
403
|
+
timer = setTimeout(flushPersist, debounceMs);
|
|
404
|
+
});
|
|
405
|
+
if (typeof document !== "undefined" && typeof addEventListener === "function") {
|
|
406
|
+
addEventListener("pagehide", flushPersist);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
bus.post({ v: 1, scope: "state", type: "hello", clientId, kind: bus.kind });
|
|
410
|
+
return {
|
|
411
|
+
clientId,
|
|
412
|
+
state: proxy,
|
|
413
|
+
getSnapshot: () => snapshot,
|
|
414
|
+
getVersions: () => versionsSnapshot,
|
|
415
|
+
set(key, value) {
|
|
416
|
+
const next = typeof value === "function" ? value(state[key]) : value;
|
|
417
|
+
setKey(key, next);
|
|
418
|
+
},
|
|
419
|
+
subscribe(fn) {
|
|
420
|
+
listeners.add(fn);
|
|
421
|
+
return () => listeners.delete(fn);
|
|
422
|
+
},
|
|
423
|
+
subscribeKey(key, fn) {
|
|
424
|
+
let set = keyListeners.get(key);
|
|
425
|
+
if (!set) {
|
|
426
|
+
set = /* @__PURE__ */ new Set();
|
|
427
|
+
keyListeners.set(key, set);
|
|
428
|
+
}
|
|
429
|
+
set.add(fn);
|
|
430
|
+
return () => set.delete(fn);
|
|
431
|
+
},
|
|
432
|
+
registerKey(key, initialValue) {
|
|
433
|
+
if (key in versions) return;
|
|
434
|
+
versions[key] = [0, clientId];
|
|
435
|
+
state[key] = initialValue;
|
|
436
|
+
snapshot = Object.freeze({ ...state });
|
|
437
|
+
versionsSnapshot = Object.freeze({ ...versions });
|
|
438
|
+
},
|
|
439
|
+
close() {
|
|
440
|
+
if (flushPersist) {
|
|
441
|
+
flushPersist();
|
|
442
|
+
if (typeof document !== "undefined" && typeof removeEventListener === "function") {
|
|
443
|
+
removeEventListener("pagehide", flushPersist);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
unsubscribe();
|
|
447
|
+
listeners.clear();
|
|
448
|
+
keyListeners.clear();
|
|
449
|
+
bus.release();
|
|
450
|
+
}
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
// src/presence.ts
|
|
455
|
+
function createPresence(name, options = {}) {
|
|
456
|
+
const pruneAfterMs = options.pruneAfterMs ?? 5e3;
|
|
457
|
+
const bus = getBus(name, options);
|
|
458
|
+
const peers = /* @__PURE__ */ new Map();
|
|
459
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
460
|
+
let snapshot = [];
|
|
461
|
+
function notify() {
|
|
462
|
+
snapshot = Object.freeze([...peers.values()]);
|
|
463
|
+
for (const fn of listeners) fn();
|
|
464
|
+
}
|
|
465
|
+
const unsubscribe = bus.subscribe((wire) => {
|
|
466
|
+
if (wire.scope === "presence" && wire.type === "bye") {
|
|
467
|
+
if (peers.delete(wire.clientId)) notify();
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
470
|
+
const existing = peers.get(wire.clientId);
|
|
471
|
+
peers.set(wire.clientId, { id: wire.clientId, kind: wire.kind, lastSeen: Date.now() });
|
|
472
|
+
if (!existing) notify();
|
|
473
|
+
});
|
|
474
|
+
const prune = setInterval(
|
|
475
|
+
() => {
|
|
476
|
+
const cutoff = Date.now() - pruneAfterMs;
|
|
477
|
+
let changed = false;
|
|
478
|
+
for (const [id, peer] of peers) {
|
|
479
|
+
if (peer.lastSeen < cutoff) {
|
|
480
|
+
peers.delete(id);
|
|
481
|
+
changed = true;
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
if (changed) notify();
|
|
485
|
+
},
|
|
486
|
+
Math.max(500, Math.floor(pruneAfterMs / 2))
|
|
487
|
+
);
|
|
488
|
+
return {
|
|
489
|
+
clientId: bus.clientId,
|
|
490
|
+
getPeers: () => snapshot,
|
|
491
|
+
subscribe(fn) {
|
|
492
|
+
listeners.add(fn);
|
|
493
|
+
return () => listeners.delete(fn);
|
|
494
|
+
},
|
|
495
|
+
close() {
|
|
496
|
+
clearInterval(prune);
|
|
497
|
+
unsubscribe();
|
|
498
|
+
listeners.clear();
|
|
499
|
+
bus.release();
|
|
500
|
+
}
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
// src/leader.ts
|
|
505
|
+
var NO_LEADER = Object.freeze({ leaderId: null, isLeader: false });
|
|
506
|
+
function createLeader(name, options = {}) {
|
|
507
|
+
const heartbeatMs = options.heartbeatMs ?? 1e3;
|
|
508
|
+
const leaseMs = options.leaseMs ?? 3e3;
|
|
509
|
+
const busOptions = {
|
|
510
|
+
...options.transport ? { transport: options.transport } : {},
|
|
511
|
+
...options.kind ? { kind: options.kind } : {}
|
|
512
|
+
};
|
|
513
|
+
const bus = getBus(name, busOptions);
|
|
514
|
+
const clientId = bus.clientId;
|
|
515
|
+
let eligible = options.eligible ?? true;
|
|
516
|
+
let leaderId = null;
|
|
517
|
+
let term = [0, clientId];
|
|
518
|
+
let snapshot = NO_LEADER;
|
|
519
|
+
let beat;
|
|
520
|
+
let lease;
|
|
521
|
+
let closed = false;
|
|
522
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
523
|
+
function setLeader(id) {
|
|
524
|
+
if (id === leaderId) return;
|
|
525
|
+
leaderId = id;
|
|
526
|
+
snapshot = Object.freeze({ leaderId: id, isLeader: id === clientId });
|
|
527
|
+
for (const fn of listeners) fn();
|
|
528
|
+
}
|
|
529
|
+
function armLease(delay) {
|
|
530
|
+
clearTimeout(lease);
|
|
531
|
+
lease = setTimeout(onLeaseExpired, delay);
|
|
532
|
+
}
|
|
533
|
+
function onLeaseExpired() {
|
|
534
|
+
if (closed) return;
|
|
535
|
+
setLeader(null);
|
|
536
|
+
if (eligible) claim();
|
|
537
|
+
}
|
|
538
|
+
function heartbeat() {
|
|
539
|
+
bus.post({ v: 1, scope: "leader", type: "heartbeat", term, clientId, kind: bus.kind });
|
|
540
|
+
}
|
|
541
|
+
function claim() {
|
|
542
|
+
term = [term[0] + 1, clientId];
|
|
543
|
+
setLeader(clientId);
|
|
544
|
+
bus.post({ v: 1, scope: "leader", type: "claim", term, clientId, kind: bus.kind });
|
|
545
|
+
clearInterval(beat);
|
|
546
|
+
beat = setInterval(heartbeat, heartbeatMs);
|
|
547
|
+
}
|
|
548
|
+
function stepDown(next) {
|
|
549
|
+
clearInterval(beat);
|
|
550
|
+
beat = void 0;
|
|
551
|
+
setLeader(next);
|
|
552
|
+
}
|
|
553
|
+
const unsubscribe = bus.subscribe((wire) => {
|
|
554
|
+
if (wire.scope !== "leader") return;
|
|
555
|
+
if (wire.type === "hello") {
|
|
556
|
+
if (leaderId === clientId) heartbeat();
|
|
557
|
+
return;
|
|
558
|
+
}
|
|
559
|
+
if (wire.type === "resign") {
|
|
560
|
+
if (wire.clientId !== leaderId) return;
|
|
561
|
+
setLeader(null);
|
|
562
|
+
armLease(0);
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
565
|
+
if (newer(wire.term, term)) {
|
|
566
|
+
term = wire.term;
|
|
567
|
+
stepDown(wire.clientId);
|
|
568
|
+
armLease(leaseMs);
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
if (leaderId === clientId) {
|
|
572
|
+
heartbeat();
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
if (wire.clientId === leaderId) armLease(leaseMs);
|
|
576
|
+
});
|
|
577
|
+
function resign() {
|
|
578
|
+
if (leaderId !== clientId) return;
|
|
579
|
+
const resigning = term;
|
|
580
|
+
stepDown(null);
|
|
581
|
+
bus.post({ v: 1, scope: "leader", type: "resign", term: resigning, clientId, kind: bus.kind });
|
|
582
|
+
armLease(leaseMs);
|
|
583
|
+
}
|
|
584
|
+
const hasWindow = typeof document !== "undefined" && typeof addEventListener === "function";
|
|
585
|
+
const onPageHide = () => resign();
|
|
586
|
+
if (hasWindow) addEventListener("pagehide", onPageHide);
|
|
587
|
+
bus.post({ v: 1, scope: "leader", type: "hello", clientId, kind: bus.kind });
|
|
588
|
+
armLease(heartbeatMs);
|
|
589
|
+
return {
|
|
590
|
+
clientId,
|
|
591
|
+
getSnapshot: () => snapshot,
|
|
592
|
+
subscribe(fn) {
|
|
593
|
+
listeners.add(fn);
|
|
594
|
+
return () => listeners.delete(fn);
|
|
595
|
+
},
|
|
596
|
+
resign,
|
|
597
|
+
setEligible(next) {
|
|
598
|
+
if (next === eligible) return;
|
|
599
|
+
eligible = next;
|
|
600
|
+
if (!next) {
|
|
601
|
+
if (leaderId === clientId) resign();
|
|
602
|
+
return;
|
|
603
|
+
}
|
|
604
|
+
if (leaderId === null) armLease(0);
|
|
605
|
+
},
|
|
606
|
+
close() {
|
|
607
|
+
closed = true;
|
|
608
|
+
resign();
|
|
609
|
+
clearInterval(beat);
|
|
610
|
+
clearTimeout(lease);
|
|
611
|
+
if (hasWindow) removeEventListener("pagehide", onPageHide);
|
|
612
|
+
unsubscribe();
|
|
613
|
+
listeners.clear();
|
|
614
|
+
bus.release();
|
|
615
|
+
}
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
// src/persist-web-storage.ts
|
|
620
|
+
function isPersisted(value) {
|
|
621
|
+
if (typeof value !== "object" || value === null) return false;
|
|
622
|
+
const candidate = value;
|
|
623
|
+
return candidate.v === 1 && typeof candidate.state === "object" && typeof candidate.versions === "object";
|
|
624
|
+
}
|
|
625
|
+
function webStorageAdapter(storage, key) {
|
|
626
|
+
const resolve = () => {
|
|
627
|
+
try {
|
|
628
|
+
return typeof storage === "function" ? storage() : storage;
|
|
629
|
+
} catch {
|
|
630
|
+
return void 0;
|
|
631
|
+
}
|
|
632
|
+
};
|
|
633
|
+
return {
|
|
634
|
+
read() {
|
|
635
|
+
try {
|
|
636
|
+
const raw = resolve()?.getItem(key);
|
|
637
|
+
if (!raw) return void 0;
|
|
638
|
+
const parsed = JSON.parse(raw);
|
|
639
|
+
return isPersisted(parsed) ? parsed : void 0;
|
|
640
|
+
} catch {
|
|
641
|
+
return void 0;
|
|
642
|
+
}
|
|
643
|
+
},
|
|
644
|
+
write(snapshot) {
|
|
645
|
+
try {
|
|
646
|
+
resolve()?.setItem(key, JSON.stringify(snapshot));
|
|
647
|
+
} catch {
|
|
648
|
+
}
|
|
649
|
+
},
|
|
650
|
+
remove() {
|
|
651
|
+
try {
|
|
652
|
+
resolve()?.removeItem(key);
|
|
653
|
+
} catch {
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
function localStorageAdapter(key) {
|
|
659
|
+
return webStorageAdapter(() => globalThis.localStorage, key);
|
|
660
|
+
}
|
|
661
|
+
function sessionStorageAdapter(key) {
|
|
662
|
+
return webStorageAdapter(() => globalThis.sessionStorage, key);
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
// src/errors/handshake-timeout-error.ts
|
|
666
|
+
var HandshakeTimeoutError = class extends Error {
|
|
667
|
+
constructor(message = "handshake with the other window timed out") {
|
|
668
|
+
super(message);
|
|
669
|
+
this.name = "HandshakeTimeoutError";
|
|
670
|
+
}
|
|
671
|
+
};
|
|
672
|
+
|
|
673
|
+
// src/errors/window-closed-error.ts
|
|
674
|
+
var WindowClosedError = class extends Error {
|
|
675
|
+
constructor(message = "window closed before a result was delivered") {
|
|
676
|
+
super(message);
|
|
677
|
+
this.name = "WindowClosedError";
|
|
678
|
+
}
|
|
679
|
+
};
|
|
680
|
+
|
|
681
|
+
// src/window-channel.ts
|
|
682
|
+
var CID_PARAM = "ue-cid";
|
|
683
|
+
function isWindowWire(data, cid) {
|
|
684
|
+
return typeof data === "object" && data !== null && data.__ue === 1 && data.cid === cid;
|
|
685
|
+
}
|
|
686
|
+
function validatePeerOrigin(peerOrigin, allowAnyOrigin) {
|
|
687
|
+
if (peerOrigin === "*" && !allowAnyOrigin) {
|
|
688
|
+
throw new Error(
|
|
689
|
+
"peerOrigin '*' is unsafe: any page could read your messages. Pass the exact origin, or set allowAnyOrigin: true (dev only)."
|
|
690
|
+
);
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
function markHandled(promise) {
|
|
694
|
+
promise.catch(() => {
|
|
695
|
+
});
|
|
696
|
+
}
|
|
697
|
+
function openWindow(url, options) {
|
|
698
|
+
const { peerOrigin, allowAnyOrigin } = options;
|
|
699
|
+
validatePeerOrigin(peerOrigin, allowAnyOrigin);
|
|
700
|
+
const base = typeof location !== "undefined" ? location.href : void 0;
|
|
701
|
+
const resolved = new URL(url, base);
|
|
702
|
+
if (!allowAnyOrigin && resolved.origin !== peerOrigin) {
|
|
703
|
+
throw new Error(`url origin ${resolved.origin} does not match peerOrigin ${peerOrigin}`);
|
|
704
|
+
}
|
|
705
|
+
const cid = newMsgId();
|
|
706
|
+
resolved.searchParams.set(CID_PARAM, cid);
|
|
707
|
+
const localWindow = options.localWindow ?? window;
|
|
708
|
+
const openFn = options.openFn ?? ((u, target, features) => window.open(u, target, features));
|
|
709
|
+
const targetOrigin = allowAnyOrigin ? "*" : peerOrigin;
|
|
710
|
+
const handlers = /* @__PURE__ */ new Map();
|
|
711
|
+
const outQueue = [];
|
|
712
|
+
let isReady = false;
|
|
713
|
+
let resultSettled = false;
|
|
714
|
+
let closedSettled = false;
|
|
715
|
+
let resolveReady;
|
|
716
|
+
let rejectReady;
|
|
717
|
+
const ready = new Promise((res, rej) => (resolveReady = res, rejectReady = rej));
|
|
718
|
+
let resolveResult;
|
|
719
|
+
let rejectResult;
|
|
720
|
+
const result = new Promise((res, rej) => (resolveResult = res, rejectResult = rej));
|
|
721
|
+
let resolveClosed;
|
|
722
|
+
const closed = new Promise((res) => resolveClosed = res);
|
|
723
|
+
markHandled(ready);
|
|
724
|
+
markHandled(result);
|
|
725
|
+
const onMessage = (event) => {
|
|
726
|
+
if (!allowAnyOrigin && event.origin !== peerOrigin) return;
|
|
727
|
+
if (!isWindowWire(event.data, cid)) return;
|
|
728
|
+
if (childWindow && event.source !== childWindow) return;
|
|
729
|
+
const wire = event.data;
|
|
730
|
+
if (wire.t === "ready") {
|
|
731
|
+
childWindow?.postMessage({ __ue: 1, cid, t: "ready-ack" }, targetOrigin);
|
|
732
|
+
if (!isReady) {
|
|
733
|
+
isReady = true;
|
|
734
|
+
clearTimeout(readyTimer);
|
|
735
|
+
for (const queued of outQueue.splice(0)) childWindow?.postMessage(queued, targetOrigin);
|
|
736
|
+
resolveReady();
|
|
737
|
+
}
|
|
738
|
+
} else if (wire.t === "msg") {
|
|
739
|
+
const set = handlers.get(wire.type);
|
|
740
|
+
if (set) for (const fn of set) fn(wire.payload);
|
|
741
|
+
} else if (wire.t === "result") {
|
|
742
|
+
if (!resultSettled) {
|
|
743
|
+
resultSettled = true;
|
|
744
|
+
resolveResult(wire.payload);
|
|
745
|
+
}
|
|
746
|
+
} else if (wire.t === "close") {
|
|
747
|
+
settleClosed();
|
|
748
|
+
}
|
|
749
|
+
};
|
|
750
|
+
localWindow.addEventListener("message", onMessage);
|
|
751
|
+
function settleClosed() {
|
|
752
|
+
if (closedSettled) return;
|
|
753
|
+
closedSettled = true;
|
|
754
|
+
clearInterval(closePoller);
|
|
755
|
+
clearTimeout(readyTimer);
|
|
756
|
+
localWindow.removeEventListener("message", onMessage);
|
|
757
|
+
if (!resultSettled) {
|
|
758
|
+
resultSettled = true;
|
|
759
|
+
rejectResult(new WindowClosedError());
|
|
760
|
+
}
|
|
761
|
+
if (!isReady) rejectReady(new WindowClosedError());
|
|
762
|
+
resolveClosed();
|
|
763
|
+
}
|
|
764
|
+
const childWindow = openFn(resolved.toString(), "_blank", options.features);
|
|
765
|
+
if (!childWindow) {
|
|
766
|
+
const err = new Error("popup blocked: window.open returned null");
|
|
767
|
+
localWindow.removeEventListener("message", onMessage);
|
|
768
|
+
rejectReady(err);
|
|
769
|
+
resultSettled = true;
|
|
770
|
+
rejectResult(err);
|
|
771
|
+
return {
|
|
772
|
+
window: null,
|
|
773
|
+
ready,
|
|
774
|
+
post: () => {
|
|
775
|
+
},
|
|
776
|
+
on: () => () => {
|
|
777
|
+
},
|
|
778
|
+
result,
|
|
779
|
+
closed,
|
|
780
|
+
close: () => {
|
|
781
|
+
}
|
|
782
|
+
};
|
|
783
|
+
}
|
|
784
|
+
const closePoller = setInterval(() => {
|
|
785
|
+
if (childWindow.closed) settleClosed();
|
|
786
|
+
}, 400);
|
|
787
|
+
const readyTimer = setTimeout(() => {
|
|
788
|
+
if (isReady || closedSettled) return;
|
|
789
|
+
const err = new HandshakeTimeoutError();
|
|
790
|
+
rejectReady(err);
|
|
791
|
+
if (!resultSettled) {
|
|
792
|
+
resultSettled = true;
|
|
793
|
+
rejectResult(err);
|
|
794
|
+
}
|
|
795
|
+
}, options.readyTimeoutMs ?? 15e3);
|
|
796
|
+
return {
|
|
797
|
+
window: childWindow,
|
|
798
|
+
ready,
|
|
799
|
+
result,
|
|
800
|
+
closed,
|
|
801
|
+
post(type, payload) {
|
|
802
|
+
const wire = { __ue: 1, cid, t: "msg", type, payload, msgId: newMsgId() };
|
|
803
|
+
if (isReady) childWindow.postMessage(wire, targetOrigin);
|
|
804
|
+
else outQueue.push(wire);
|
|
805
|
+
},
|
|
806
|
+
on(type, handler) {
|
|
807
|
+
let set = handlers.get(type);
|
|
808
|
+
if (!set) {
|
|
809
|
+
set = /* @__PURE__ */ new Set();
|
|
810
|
+
handlers.set(type, set);
|
|
811
|
+
}
|
|
812
|
+
set.add(handler);
|
|
813
|
+
return () => set.delete(handler);
|
|
814
|
+
},
|
|
815
|
+
close() {
|
|
816
|
+
childWindow.close?.();
|
|
817
|
+
}
|
|
818
|
+
};
|
|
819
|
+
}
|
|
820
|
+
function connectToOpener(options) {
|
|
821
|
+
const { peerOrigin, allowAnyOrigin } = options;
|
|
822
|
+
validatePeerOrigin(peerOrigin, allowAnyOrigin);
|
|
823
|
+
const opener = options.opener !== void 0 ? options.opener : window.opener ?? null;
|
|
824
|
+
if (!opener) {
|
|
825
|
+
throw new Error("no window.opener \u2014 this page was not opened via openWindow()");
|
|
826
|
+
}
|
|
827
|
+
const cid = options.cid ?? (typeof location !== "undefined" ? new URLSearchParams(location.search).get(CID_PARAM) : null);
|
|
828
|
+
if (!cid) {
|
|
829
|
+
throw new Error(`missing ${CID_PARAM} parameter \u2014 this page was not opened via openWindow()`);
|
|
830
|
+
}
|
|
831
|
+
const localWindow = options.localWindow ?? window;
|
|
832
|
+
const targetOrigin = allowAnyOrigin ? "*" : peerOrigin;
|
|
833
|
+
const handlers = /* @__PURE__ */ new Map();
|
|
834
|
+
const outQueue = [];
|
|
835
|
+
let isReady = false;
|
|
836
|
+
let resolveReady;
|
|
837
|
+
let rejectReady;
|
|
838
|
+
const ready = new Promise((res, rej) => (resolveReady = res, rejectReady = rej));
|
|
839
|
+
markHandled(ready);
|
|
840
|
+
const onMessage = (event) => {
|
|
841
|
+
if (!allowAnyOrigin && event.origin !== peerOrigin) return;
|
|
842
|
+
if (!isWindowWire(event.data, cid)) return;
|
|
843
|
+
const wire = event.data;
|
|
844
|
+
if (wire.t === "ready-ack") {
|
|
845
|
+
if (!isReady) {
|
|
846
|
+
isReady = true;
|
|
847
|
+
clearInterval(retryTimer);
|
|
848
|
+
clearTimeout(giveUpTimer);
|
|
849
|
+
for (const queued of outQueue.splice(0)) opener.postMessage(queued, targetOrigin);
|
|
850
|
+
resolveReady();
|
|
851
|
+
}
|
|
852
|
+
} else if (wire.t === "msg") {
|
|
853
|
+
const set = handlers.get(wire.type);
|
|
854
|
+
if (set) for (const fn of set) fn(wire.payload);
|
|
855
|
+
}
|
|
856
|
+
};
|
|
857
|
+
localWindow.addEventListener("message", onMessage);
|
|
858
|
+
const sayReady = () => opener.postMessage({ __ue: 1, cid, t: "ready" }, targetOrigin);
|
|
859
|
+
sayReady();
|
|
860
|
+
const retryTimer = setInterval(sayReady, 250);
|
|
861
|
+
const giveUpTimer = setTimeout(() => {
|
|
862
|
+
clearInterval(retryTimer);
|
|
863
|
+
localWindow.removeEventListener("message", onMessage);
|
|
864
|
+
rejectReady(new HandshakeTimeoutError());
|
|
865
|
+
}, options.readyTimeoutMs ?? 15e3);
|
|
866
|
+
const sendOrQueue = (wire) => {
|
|
867
|
+
if (isReady) opener.postMessage(wire, targetOrigin);
|
|
868
|
+
else outQueue.push(wire);
|
|
869
|
+
};
|
|
870
|
+
const sayClose = () => opener.postMessage({ __ue: 1, cid, t: "close" }, targetOrigin);
|
|
871
|
+
localWindow.addEventListener("pagehide", sayClose);
|
|
872
|
+
return {
|
|
873
|
+
ready,
|
|
874
|
+
post(type, payload) {
|
|
875
|
+
sendOrQueue({ __ue: 1, cid, t: "msg", type, payload, msgId: newMsgId() });
|
|
876
|
+
},
|
|
877
|
+
on(type, handler) {
|
|
878
|
+
let set = handlers.get(type);
|
|
879
|
+
if (!set) {
|
|
880
|
+
set = /* @__PURE__ */ new Set();
|
|
881
|
+
handlers.set(type, set);
|
|
882
|
+
}
|
|
883
|
+
set.add(handler);
|
|
884
|
+
return () => set.delete(handler);
|
|
885
|
+
},
|
|
886
|
+
finish(value) {
|
|
887
|
+
sendOrQueue({ __ue: 1, cid, t: "result", payload: value });
|
|
888
|
+
},
|
|
889
|
+
close() {
|
|
890
|
+
sayClose();
|
|
891
|
+
localWindow.removeEventListener("message", onMessage);
|
|
892
|
+
localWindow.removeEventListener("pagehide", sayClose);
|
|
893
|
+
if (typeof window !== "undefined" && options.localWindow === void 0) window.close();
|
|
894
|
+
}
|
|
895
|
+
};
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
// src/transport/memory-transport.ts
|
|
899
|
+
var MemoryTransport = class {
|
|
900
|
+
constructor(hub) {
|
|
901
|
+
this.hub = hub;
|
|
902
|
+
this.listeners = /* @__PURE__ */ new Set();
|
|
903
|
+
this.closed = false;
|
|
904
|
+
}
|
|
905
|
+
post(data) {
|
|
906
|
+
if (this.closed) return;
|
|
907
|
+
this.hub.broadcast(this, data);
|
|
908
|
+
}
|
|
909
|
+
subscribe(listener) {
|
|
910
|
+
this.listeners.add(listener);
|
|
911
|
+
return () => this.listeners.delete(listener);
|
|
912
|
+
}
|
|
913
|
+
close() {
|
|
914
|
+
this.closed = true;
|
|
915
|
+
this.listeners.clear();
|
|
916
|
+
this.hub.disconnect(this);
|
|
917
|
+
}
|
|
918
|
+
/** @internal */
|
|
919
|
+
deliver(data) {
|
|
920
|
+
if (this.closed) return;
|
|
921
|
+
for (const listener of this.listeners) listener(data);
|
|
922
|
+
}
|
|
923
|
+
};
|
|
924
|
+
|
|
925
|
+
// src/transport/memory-hub.ts
|
|
926
|
+
var MemoryHub = class {
|
|
927
|
+
constructor() {
|
|
928
|
+
this.transports = /* @__PURE__ */ new Set();
|
|
929
|
+
}
|
|
930
|
+
connect() {
|
|
931
|
+
const transport = new MemoryTransport(this);
|
|
932
|
+
this.transports.add(transport);
|
|
933
|
+
return transport;
|
|
934
|
+
}
|
|
935
|
+
/** @internal */
|
|
936
|
+
broadcast(from, data) {
|
|
937
|
+
for (const transport of this.transports) {
|
|
938
|
+
if (transport !== from) {
|
|
939
|
+
queueMicrotask(() => transport.deliver(data));
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
/** @internal */
|
|
944
|
+
disconnect(transport) {
|
|
945
|
+
this.transports.delete(transport);
|
|
946
|
+
}
|
|
947
|
+
};
|
|
948
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
949
|
+
0 && (module.exports = {
|
|
950
|
+
BroadcastChannelTransport,
|
|
951
|
+
CID_PARAM,
|
|
952
|
+
DEFAULT_NAME,
|
|
953
|
+
HandshakeTimeoutError,
|
|
954
|
+
MemoryHub,
|
|
955
|
+
MemoryTransport,
|
|
956
|
+
NoopTransport,
|
|
957
|
+
WindowClosedError,
|
|
958
|
+
connectToOpener,
|
|
959
|
+
createChannel,
|
|
960
|
+
createLeader,
|
|
961
|
+
createPresence,
|
|
962
|
+
createSharedStore,
|
|
963
|
+
defaultTransport,
|
|
964
|
+
enableDebug,
|
|
965
|
+
getBusNames,
|
|
966
|
+
isBroadcastChannelAvailable,
|
|
967
|
+
localStorageAdapter,
|
|
968
|
+
newer,
|
|
969
|
+
observeBus,
|
|
970
|
+
openWindow,
|
|
971
|
+
sessionStorageAdapter,
|
|
972
|
+
webStorageAdapter
|
|
973
|
+
});
|