@automerge/automerge-repo-react-hooks 2.5.3 → 2.6.0-subduction.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2146,969 +2146,103 @@ const useLocalAwareness = ({
2146
2146
  return [localState, setState];
2147
2147
  };
2148
2148
 
2149
- // Properties of the document root object
2150
- const STATE = Symbol.for("_am_meta"); // symbol used to hide application metadata on automerge objects
2151
- const TRACE = Symbol.for("_am_trace"); // used for debugging
2152
- const OBJECT_ID = Symbol.for("_am_objectId"); // symbol used to hide the object id on automerge objects
2153
- const IS_PROXY = Symbol.for("_am_isProxy"); // symbol used to test if the document is a proxy object
2154
- const CLEAR_CACHE = Symbol.for("_am_clearCache"); // symbol used to tell a proxy object to clear its cache
2155
- const UINT = Symbol.for("_am_uint");
2156
- const INT = Symbol.for("_am_int");
2157
- const F64 = Symbol.for("_am_f64");
2158
- const COUNTER = Symbol.for("_am_counter");
2159
- const IMMUTABLE_STRING = Symbol.for("_am_immutableString");
2149
+ BigInt("9223372036854775807"); // 2n ** 63n - 1n;
2160
2150
 
2161
- /**
2162
- * The most basic CRDT: an integer value that can be changed only by
2163
- * incrementing and decrementing. Since addition of integers is commutative,
2164
- * the value trivially converges.
2165
- */
2166
- class Counter {
2167
- constructor(value) {
2168
- this.value = value || 0;
2169
- Reflect.defineProperty(this, COUNTER, { value: true });
2151
+ let wasm;
2152
+
2153
+ let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
2154
+
2155
+ cachedTextDecoder.decode();
2156
+
2157
+ const cachedTextEncoder = new TextEncoder();
2158
+
2159
+ if (!('encodeInto' in cachedTextEncoder)) {
2160
+ cachedTextEncoder.encodeInto = function (arg, view) {
2161
+ const buf = cachedTextEncoder.encode(arg);
2162
+ view.set(buf);
2163
+ return {
2164
+ read: arg.length,
2165
+ written: buf.length
2166
+ };
2167
+ };
2168
+ }
2169
+
2170
+ function takeFromExternrefTable0(idx) {
2171
+ const value = wasm.__wbindgen_export_4.get(idx);
2172
+ wasm.__externref_table_dealloc(idx);
2173
+ return value;
2174
+ }
2175
+
2176
+ (typeof FinalizationRegistry === 'undefined')
2177
+ ? { }
2178
+ : new FinalizationRegistry(ptr => wasm.__wbg_automerge_free(ptr >>> 0, 1));
2179
+
2180
+ const SyncStateFinalization = (typeof FinalizationRegistry === 'undefined')
2181
+ ? { register: () => {}, unregister: () => {} }
2182
+ : new FinalizationRegistry(ptr => wasm.__wbg_syncstate_free(ptr >>> 0, 1));
2183
+
2184
+ class SyncState {
2185
+
2186
+ static __wrap(ptr) {
2187
+ ptr = ptr >>> 0;
2188
+ const obj = Object.create(SyncState.prototype);
2189
+ obj.__wbg_ptr = ptr;
2190
+ SyncStateFinalization.register(obj, obj.__wbg_ptr, obj);
2191
+ return obj;
2170
2192
  }
2171
- /**
2172
- * A peculiar JavaScript language feature from its early days: if the object
2173
- * `x` has a `valueOf()` method that returns a number, you can use numerical
2174
- * operators on the object `x` directly, such as `x + 1` or `x < 4`.
2175
- * This method is also called when coercing a value to a string by
2176
- * concatenating it with another string, as in `x + ''`.
2177
- * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/valueOf
2178
- */
2179
- valueOf() {
2180
- return this.value;
2193
+
2194
+ __destroy_into_raw() {
2195
+ const ptr = this.__wbg_ptr;
2196
+ this.__wbg_ptr = 0;
2197
+ SyncStateFinalization.unregister(this);
2198
+ return ptr;
2181
2199
  }
2182
- /**
2183
- * Returns the counter value as a decimal string. If `x` is a counter object,
2184
- * this method is called e.g. when you do `['value: ', x].join('')` or when
2185
- * you use string interpolation: `value: ${x}`.
2186
- */
2187
- toString() {
2188
- return this.valueOf().toString();
2200
+
2201
+ free() {
2202
+ const ptr = this.__destroy_into_raw();
2203
+ wasm.__wbg_syncstate_free(ptr, 0);
2189
2204
  }
2190
2205
  /**
2191
- * Returns the counter value, so that a JSON serialization of an Automerge
2192
- * document represents the counter simply as an integer.
2206
+ * @returns {Heads}
2193
2207
  */
2194
- toJSON() {
2195
- return this.value;
2208
+ get sharedHeads() {
2209
+ const ret = wasm.syncstate_sharedHeads(this.__wbg_ptr);
2210
+ return ret;
2196
2211
  }
2197
2212
  /**
2198
- * Increases the value of the counter by `delta`. If `delta` is not given,
2199
- * increases the value of the counter by 1.
2200
- *
2201
- * Will throw an error if used outside of a change callback.
2213
+ * @returns {Heads}
2202
2214
  */
2203
- increment(_delta) {
2204
- throw new Error("Counters should not be incremented outside of a change callback");
2215
+ get lastSentHeads() {
2216
+ const ret = wasm.syncstate_lastSentHeads(this.__wbg_ptr);
2217
+ return ret;
2205
2218
  }
2206
2219
  /**
2207
- * Decreases the value of the counter by `delta`. If `delta` is not given,
2208
- * decreases the value of the counter by 1.
2209
- *
2210
- * Will throw an error if used outside of a change callback.
2220
+ * @param {Heads} heads
2211
2221
  */
2212
- decrement(_delta) {
2213
- throw new Error("Counters should not be decremented outside of a change callback");
2214
- }
2215
- }
2216
- /**
2217
- * An instance of this class is used when a counter is accessed within a change
2218
- * callback.
2219
- */
2220
- class WriteableCounter extends Counter {
2221
- constructor(value, context, path, objectId, key) {
2222
- super(value);
2223
- this.context = context;
2224
- this.path = path;
2225
- this.objectId = objectId;
2226
- this.key = key;
2227
- }
2228
- /**
2229
- * Increases the value of the counter by `delta`. If `delta` is not given,
2230
- * increases the value of the counter by 1.
2231
- */
2232
- increment(delta) {
2233
- delta = typeof delta === "number" ? delta : 1;
2234
- this.context.increment(this.objectId, this.key, delta);
2235
- this.value += delta;
2236
- return this.value;
2222
+ set lastSentHeads(heads) {
2223
+ const ret = wasm.syncstate_set_lastSentHeads(this.__wbg_ptr, heads);
2224
+ if (ret[1]) {
2225
+ throw takeFromExternrefTable0(ret[0]);
2226
+ }
2237
2227
  }
2238
2228
  /**
2239
- * Decreases the value of the counter by `delta`. If `delta` is not given,
2240
- * decreases the value of the counter by 1.
2229
+ * @param {Heads} hashes
2241
2230
  */
2242
- decrement(delta) {
2243
- return this.increment(typeof delta === "number" ? -delta : -1);
2244
- }
2245
- }
2246
- /**
2247
- * Returns an instance of `WriteableCounter` for use in a change callback.
2248
- * `context` is the proxy context that keeps track of the mutations.
2249
- * `objectId` is the ID of the object containing the counter, and `key` is
2250
- * the property name (key in map, or index in list) where the counter is
2251
- * located.
2252
- */
2253
- function getWriteableCounter(value, context, path, objectId, key) {
2254
- return new WriteableCounter(value, context, path, objectId, key);
2255
- }
2256
- //module.exports = { Counter, getWriteableCounter }
2257
-
2258
- var _a;
2259
- class ImmutableString {
2260
- constructor(val) {
2261
- // Used to detect whether a value is a ImmutableString object rather than using an instanceof check
2262
- this[_a] = true;
2263
- this.val = val;
2231
+ set sentHashes(hashes) {
2232
+ const ret = wasm.syncstate_set_sentHashes(this.__wbg_ptr, hashes);
2233
+ if (ret[1]) {
2234
+ throw takeFromExternrefTable0(ret[0]);
2235
+ }
2264
2236
  }
2265
2237
  /**
2266
- * Returns the content of the ImmutableString object as a simple string
2238
+ * @returns {SyncState}
2267
2239
  */
2268
- toString() {
2269
- return this.val;
2270
- }
2271
- toJSON() {
2272
- return this.val;
2240
+ clone() {
2241
+ const ret = wasm.syncstate_clone(this.__wbg_ptr);
2242
+ return SyncState.__wrap(ret);
2273
2243
  }
2274
2244
  }
2275
- _a = IMMUTABLE_STRING;
2276
-
2277
- function parseListIndex(key) {
2278
- if (typeof key === "string" && /^[0-9]+$/.test(key))
2279
- key = parseInt(key, 10);
2280
- if (typeof key !== "number") {
2281
- return key;
2282
- }
2283
- if (key < 0 || isNaN(key) || key === Infinity || key === -Infinity) {
2284
- throw new RangeError("A list index must be positive, but you passed " + key);
2285
- }
2286
- return key;
2287
- }
2288
- function valueAt(target, prop) {
2289
- const { context, objectId, path } = target;
2290
- const value = context.getWithType(objectId, prop);
2291
- if (value === null) {
2292
- return;
2293
- }
2294
- const datatype = value[0];
2295
- const val = value[1];
2296
- switch (datatype) {
2297
- case undefined:
2298
- return;
2299
- case "map":
2300
- return mapProxy(context, val, [...path, prop]);
2301
- case "list":
2302
- return listProxy(context, val, [...path, prop]);
2303
- case "text":
2304
- return context.text(val);
2305
- case "str":
2306
- return new ImmutableString(val);
2307
- case "uint":
2308
- return val;
2309
- case "int":
2310
- return val;
2311
- case "f64":
2312
- return val;
2313
- case "boolean":
2314
- return val;
2315
- case "null":
2316
- return null;
2317
- case "bytes":
2318
- return val;
2319
- case "timestamp":
2320
- return val;
2321
- case "counter": {
2322
- const counter = getWriteableCounter(val, context, path, objectId, prop);
2323
- return counter;
2324
- }
2325
- default:
2326
- throw RangeError(`datatype ${datatype} unimplemented`);
2327
- }
2328
- }
2329
- function import_value(value, path, context) {
2330
- const type = typeof value;
2331
- switch (type) {
2332
- case "object":
2333
- if (value == null) {
2334
- return [null, "null"];
2335
- }
2336
- else if (value[UINT]) {
2337
- return [value.value, "uint"];
2338
- }
2339
- else if (value[INT]) {
2340
- return [value.value, "int"];
2341
- }
2342
- else if (value[F64]) {
2343
- return [value.value, "f64"];
2344
- }
2345
- else if (value[COUNTER]) {
2346
- return [value.value, "counter"];
2347
- }
2348
- else if (value instanceof Date) {
2349
- return [value.getTime(), "timestamp"];
2350
- }
2351
- else if (isImmutableString(value)) {
2352
- return [value.toString(), "str"];
2353
- }
2354
- else if (value instanceof Uint8Array) {
2355
- return [value, "bytes"];
2356
- }
2357
- else if (value instanceof Array) {
2358
- return [value, "list"];
2359
- }
2360
- else if (Object.prototype.toString.call(value) === "[object Object]") {
2361
- return [value, "map"];
2362
- }
2363
- else if (isSameDocument(value, context)) {
2364
- throw new RangeError("Cannot create a reference to an existing document object");
2365
- }
2366
- else {
2367
- throw new RangeError(`Cannot assign unknown object: ${value}`);
2368
- }
2369
- case "boolean":
2370
- return [value, "boolean"];
2371
- case "number":
2372
- if (Number.isInteger(value)) {
2373
- return [value, "int"];
2374
- }
2375
- else {
2376
- return [value, "f64"];
2377
- }
2378
- case "string":
2379
- return [value, "text"];
2380
- case "undefined":
2381
- throw new RangeError([
2382
- `Cannot assign undefined value at ${printPath(path)}, `,
2383
- "because `undefined` is not a valid JSON data type. ",
2384
- "You might consider setting the property's value to `null`, ",
2385
- "or using `delete` to remove it altogether.",
2386
- ].join(""));
2387
- default:
2388
- throw new RangeError([
2389
- `Cannot assign ${type} value at ${printPath(path)}. `,
2390
- `All JSON primitive datatypes (object, array, string, number, boolean, null) `,
2391
- `are supported in an Automerge document; ${type} values are not. `,
2392
- ].join(""));
2393
- }
2394
- }
2395
- // When we assign a value to a property in a proxy we recursively walk through
2396
- // the value we are assigning and copy it into the document. This is generally
2397
- // desirable behaviour. However, a very common bug is to accidentally assign a
2398
- // value which is already in the document to another key within the same
2399
- // document, this often leads to surprising behaviour where users expected to
2400
- // _move_ the object, but it is instead copied. To avoid this we check if the
2401
- // value is from the same document and if it is we throw an error, this means
2402
- // we require an explicit Object.assign call to copy the object, thus avoiding
2403
- // the footgun
2404
- function isSameDocument(val, context) {
2405
- var _b, _c;
2406
- // Date is technically an object, but immutable, so allowing people to assign
2407
- // a date from one place in the document to another place in the document is
2408
- // not likely to be a bug
2409
- if (val instanceof Date) {
2410
- return false;
2411
- }
2412
- // this depends on __wbg_ptr being the wasm pointer
2413
- // a new version of wasm-bindgen will break this
2414
- // but the tests should expose the break
2415
- if (val && ((_c = (_b = val[STATE]) === null || _b === void 0 ? void 0 : _b.handle) === null || _c === void 0 ? void 0 : _c.__wbg_ptr) === context.__wbg_ptr) {
2416
- return true;
2417
- }
2418
- return false;
2419
- }
2420
- const MapHandler = {
2421
- get(target, key) {
2422
- const { context, objectId, cache } = target;
2423
- if (key === Symbol.toStringTag) {
2424
- return target[Symbol.toStringTag];
2425
- }
2426
- if (key === OBJECT_ID)
2427
- return objectId;
2428
- if (key === IS_PROXY)
2429
- return true;
2430
- if (key === TRACE)
2431
- return target.trace;
2432
- if (key === STATE)
2433
- return { handle: context };
2434
- if (!cache[key]) {
2435
- cache[key] = valueAt(target, key);
2436
- }
2437
- return cache[key];
2438
- },
2439
- set(target, key, val) {
2440
- const { context, objectId, path } = target;
2441
- target.cache = {}; // reset cache on set
2442
- if (isSameDocument(val, context)) {
2443
- throw new RangeError("Cannot create a reference to an existing document object");
2444
- }
2445
- if (key === TRACE) {
2446
- target.trace = val;
2447
- return true;
2448
- }
2449
- if (key === CLEAR_CACHE) {
2450
- return true;
2451
- }
2452
- const [value, datatype] = import_value(val, [...path, key], context);
2453
- switch (datatype) {
2454
- case "list": {
2455
- const list = context.putObject(objectId, key, []);
2456
- const proxyList = listProxy(context, list, [...path, key]);
2457
- for (let i = 0; i < value.length; i++) {
2458
- proxyList[i] = value[i];
2459
- }
2460
- break;
2461
- }
2462
- case "text": {
2463
- context.putObject(objectId, key, value);
2464
- break;
2465
- }
2466
- case "map": {
2467
- const map = context.putObject(objectId, key, {});
2468
- const proxyMap = mapProxy(context, map, [...path, key]);
2469
- for (const key in value) {
2470
- proxyMap[key] = value[key];
2471
- }
2472
- break;
2473
- }
2474
- default:
2475
- context.put(objectId, key, value, datatype);
2476
- }
2477
- return true;
2478
- },
2479
- deleteProperty(target, key) {
2480
- const { context, objectId } = target;
2481
- target.cache = {}; // reset cache on delete
2482
- context.delete(objectId, key);
2483
- return true;
2484
- },
2485
- has(target, key) {
2486
- const value = this.get(target, key);
2487
- return value !== undefined;
2488
- },
2489
- getOwnPropertyDescriptor(target, key) {
2490
- // const { context, objectId } = target
2491
- const value = this.get(target, key);
2492
- if (typeof value !== "undefined") {
2493
- return {
2494
- configurable: true,
2495
- enumerable: true,
2496
- value,
2497
- };
2498
- }
2499
- },
2500
- ownKeys(target) {
2501
- const { context, objectId } = target;
2502
- // FIXME - this is a tmp workaround until fix the dupe key bug in keys()
2503
- const keys = context.keys(objectId);
2504
- return [...new Set(keys)];
2505
- },
2506
- };
2507
- const ListHandler = {
2508
- get(target, index) {
2509
- const { context, objectId } = target;
2510
- index = parseListIndex(index);
2511
- if (index === Symbol.hasInstance) {
2512
- return (instance) => {
2513
- return Array.isArray(instance);
2514
- };
2515
- }
2516
- if (index === Symbol.toStringTag) {
2517
- return target[Symbol.toStringTag];
2518
- }
2519
- if (index === OBJECT_ID)
2520
- return objectId;
2521
- if (index === IS_PROXY)
2522
- return true;
2523
- if (index === TRACE)
2524
- return target.trace;
2525
- if (index === STATE)
2526
- return { handle: context };
2527
- if (index === "length")
2528
- return context.length(objectId);
2529
- if (typeof index === "number") {
2530
- return valueAt(target, index);
2531
- }
2532
- else {
2533
- return listMethods(target)[index];
2534
- }
2535
- },
2536
- set(target, index, val) {
2537
- const { context, objectId, path } = target;
2538
- index = parseListIndex(index);
2539
- if (isSameDocument(val, context)) {
2540
- throw new RangeError("Cannot create a reference to an existing document object");
2541
- }
2542
- if (index === CLEAR_CACHE) {
2543
- return true;
2544
- }
2545
- if (index === TRACE) {
2546
- target.trace = val;
2547
- return true;
2548
- }
2549
- if (typeof index == "string") {
2550
- throw new RangeError("list index must be a number");
2551
- }
2552
- const [value, datatype] = import_value(val, [...path, index], context);
2553
- switch (datatype) {
2554
- case "list": {
2555
- let list;
2556
- if (index >= context.length(objectId)) {
2557
- list = context.insertObject(objectId, index, []);
2558
- }
2559
- else {
2560
- list = context.putObject(objectId, index, []);
2561
- }
2562
- const proxyList = listProxy(context, list, [...path, index]);
2563
- proxyList.splice(0, 0, ...value);
2564
- break;
2565
- }
2566
- case "text": {
2567
- if (index >= context.length(objectId)) {
2568
- context.insertObject(objectId, index, value);
2569
- }
2570
- else {
2571
- context.putObject(objectId, index, value);
2572
- }
2573
- break;
2574
- }
2575
- case "map": {
2576
- let map;
2577
- if (index >= context.length(objectId)) {
2578
- map = context.insertObject(objectId, index, {});
2579
- }
2580
- else {
2581
- map = context.putObject(objectId, index, {});
2582
- }
2583
- const proxyMap = mapProxy(context, map, [...path, index]);
2584
- for (const key in value) {
2585
- proxyMap[key] = value[key];
2586
- }
2587
- break;
2588
- }
2589
- default:
2590
- if (index >= context.length(objectId)) {
2591
- context.insert(objectId, index, value, datatype);
2592
- }
2593
- else {
2594
- context.put(objectId, index, value, datatype);
2595
- }
2596
- }
2597
- return true;
2598
- },
2599
- deleteProperty(target, index) {
2600
- const { context, objectId } = target;
2601
- index = parseListIndex(index);
2602
- const elem = context.get(objectId, index);
2603
- if (elem != null && elem[0] == "counter") {
2604
- throw new TypeError("Unsupported operation: deleting a counter from a list");
2605
- }
2606
- context.delete(objectId, index);
2607
- return true;
2608
- },
2609
- has(target, index) {
2610
- const { context, objectId } = target;
2611
- index = parseListIndex(index);
2612
- if (typeof index === "number") {
2613
- return index < context.length(objectId);
2614
- }
2615
- return index === "length";
2616
- },
2617
- getOwnPropertyDescriptor(target, index) {
2618
- const { context, objectId } = target;
2619
- if (index === "length")
2620
- return { writable: true, value: context.length(objectId) };
2621
- if (index === OBJECT_ID)
2622
- return { configurable: false, enumerable: false, value: objectId };
2623
- index = parseListIndex(index);
2624
- const value = valueAt(target, index);
2625
- return { configurable: true, enumerable: true, value };
2626
- },
2627
- getPrototypeOf(target) {
2628
- return Object.getPrototypeOf(target);
2629
- },
2630
- ownKeys( /*target*/) {
2631
- const keys = [];
2632
- // uncommenting this causes assert.deepEqual() to fail when comparing to a pojo array
2633
- // but not uncommenting it causes for (i in list) {} to not enumerate values properly
2634
- //const {context, objectId } = target
2635
- //for (let i = 0; i < target.context.length(objectId); i++) { keys.push(i.toString()) }
2636
- keys.push("length");
2637
- return keys;
2638
- },
2639
- };
2640
- Object.assign({}, ListHandler, {
2641
- get(target, index) {
2642
- const { context, objectId } = target;
2643
- index = parseListIndex(index);
2644
- if (index === Symbol.hasInstance) {
2645
- return (instance) => {
2646
- return Array.isArray(instance);
2647
- };
2648
- }
2649
- if (index === Symbol.toStringTag) {
2650
- return target[Symbol.toStringTag];
2651
- }
2652
- if (index === OBJECT_ID)
2653
- return objectId;
2654
- if (index === IS_PROXY)
2655
- return true;
2656
- if (index === TRACE)
2657
- return target.trace;
2658
- if (index === STATE)
2659
- return { handle: context };
2660
- if (index === "length")
2661
- return context.length(objectId);
2662
- if (typeof index === "number") {
2663
- return valueAt(target, index);
2664
- }
2665
- else {
2666
- return textMethods(target)[index] || listMethods(target)[index];
2667
- }
2668
- },
2669
- getPrototypeOf( /*target*/) {
2670
- return Object.getPrototypeOf(new Text());
2671
- },
2672
- });
2673
- function mapProxy(context, objectId, path) {
2674
- const target = {
2675
- context,
2676
- objectId,
2677
- path: path || [],
2678
- cache: {},
2679
- };
2680
- const proxied = {};
2681
- Object.assign(proxied, target);
2682
- const result = new Proxy(proxied, MapHandler);
2683
- // conversion through unknown is necessary because the types are so different
2684
- return result;
2685
- }
2686
- function listProxy(context, objectId, path) {
2687
- const target = {
2688
- context,
2689
- objectId,
2690
- path: path || [],
2691
- cache: {},
2692
- };
2693
- const proxied = [];
2694
- Object.assign(proxied, target);
2695
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
2696
- // @ts-ignore
2697
- return new Proxy(proxied, ListHandler);
2698
- }
2699
- function listMethods(target) {
2700
- const { context, objectId, path } = target;
2701
- const methods = {
2702
- at(index) {
2703
- return valueAt(target, index);
2704
- },
2705
- deleteAt(index, numDelete) {
2706
- if (typeof numDelete === "number") {
2707
- context.splice(objectId, index, numDelete);
2708
- }
2709
- else {
2710
- context.delete(objectId, index);
2711
- }
2712
- return this;
2713
- },
2714
- fill(val, start, end) {
2715
- const [value, datatype] = import_value(val, [...path, start], context);
2716
- const length = context.length(objectId);
2717
- start = parseListIndex(start || 0);
2718
- end = parseListIndex(end || length);
2719
- for (let i = start; i < Math.min(end, length); i++) {
2720
- if (datatype === "list" || datatype === "map") {
2721
- context.putObject(objectId, i, value);
2722
- }
2723
- else if (datatype === "text") {
2724
- context.putObject(objectId, i, value);
2725
- }
2726
- else {
2727
- context.put(objectId, i, value, datatype);
2728
- }
2729
- }
2730
- return this;
2731
- },
2732
- indexOf(searchElement, start = 0) {
2733
- const length = context.length(objectId);
2734
- for (let i = start; i < length; i++) {
2735
- const valueWithType = context.getWithType(objectId, i);
2736
- if (!valueWithType) {
2737
- continue;
2738
- }
2739
- const [valType, value] = valueWithType;
2740
- // Either the target element is an object, and we return if we have found
2741
- // the same object or it is a primitive value and we return if it matches
2742
- // the current value
2743
- const isObject = ["map", "list", "text"].includes(valType);
2744
- if (!isObject) {
2745
- // If the element is not an object, then check if the value is equal to the target
2746
- if (value === searchElement) {
2747
- return i;
2748
- }
2749
- else {
2750
- continue;
2751
- }
2752
- }
2753
- // if it's an object, but the type of the search element is a string, then we
2754
- // need to check if the object is a text object with the same value as the search element
2755
- if (valType === "text" && typeof searchElement === "string") {
2756
- if (searchElement === valueAt(target, i)) {
2757
- return i;
2758
- }
2759
- }
2760
- // The only possible match now is if the searchElement is an object already in the
2761
- // automerge document with the same object ID as the value
2762
- if (searchElement[OBJECT_ID] === value) {
2763
- return i;
2764
- }
2765
- }
2766
- return -1;
2767
- },
2768
- insertAt(index, ...values) {
2769
- this.splice(index, 0, ...values);
2770
- return this;
2771
- },
2772
- pop() {
2773
- const length = context.length(objectId);
2774
- if (length == 0) {
2775
- return undefined;
2776
- }
2777
- const last = valueAt(target, length - 1);
2778
- context.delete(objectId, length - 1);
2779
- return last;
2780
- },
2781
- push(...values) {
2782
- const len = context.length(objectId);
2783
- this.splice(len, 0, ...values);
2784
- return context.length(objectId);
2785
- },
2786
- shift() {
2787
- if (context.length(objectId) == 0)
2788
- return;
2789
- const first = valueAt(target, 0);
2790
- context.delete(objectId, 0);
2791
- return first;
2792
- },
2793
- splice(index, del, ...vals) {
2794
- index = parseListIndex(index);
2795
- // if del is undefined, delete until the end of the list
2796
- if (typeof del !== "number") {
2797
- del = context.length(objectId) - index;
2798
- }
2799
- del = parseListIndex(del);
2800
- for (const val of vals) {
2801
- if (isSameDocument(val, context)) {
2802
- throw new RangeError("Cannot create a reference to an existing document object");
2803
- }
2804
- }
2805
- const result = [];
2806
- for (let i = 0; i < del; i++) {
2807
- const value = valueAt(target, index);
2808
- if (value !== undefined) {
2809
- result.push(value);
2810
- }
2811
- context.delete(objectId, index);
2812
- }
2813
- const values = vals.map((val, index) => {
2814
- try {
2815
- return import_value(val, [...path], context);
2816
- }
2817
- catch (e) {
2818
- if (e instanceof RangeError) {
2819
- throw new RangeError(`${e.message} (at index ${index} in the input)`);
2820
- }
2821
- else {
2822
- throw e;
2823
- }
2824
- }
2825
- });
2826
- for (const [value, datatype] of values) {
2827
- switch (datatype) {
2828
- case "list": {
2829
- const list = context.insertObject(objectId, index, []);
2830
- const proxyList = listProxy(context, list, [...path, index]);
2831
- proxyList.splice(0, 0, ...value);
2832
- break;
2833
- }
2834
- case "text": {
2835
- context.insertObject(objectId, index, value);
2836
- break;
2837
- }
2838
- case "map": {
2839
- const map = context.insertObject(objectId, index, {});
2840
- const proxyMap = mapProxy(context, map, [...path, index]);
2841
- for (const key in value) {
2842
- proxyMap[key] = value[key];
2843
- }
2844
- break;
2845
- }
2846
- default:
2847
- context.insert(objectId, index, value, datatype);
2848
- }
2849
- index += 1;
2850
- }
2851
- return result;
2852
- },
2853
- unshift(...values) {
2854
- this.splice(0, 0, ...values);
2855
- return context.length(objectId);
2856
- },
2857
- entries() {
2858
- let i = 0;
2859
- const iterator = {
2860
- next: () => {
2861
- const value = valueAt(target, i);
2862
- if (value === undefined) {
2863
- return { value: undefined, done: true };
2864
- }
2865
- else {
2866
- return { value: [i++, value], done: false };
2867
- }
2868
- },
2869
- [Symbol.iterator]() {
2870
- return this;
2871
- },
2872
- };
2873
- return iterator;
2874
- },
2875
- keys() {
2876
- let i = 0;
2877
- const len = context.length(objectId);
2878
- const iterator = {
2879
- next: () => {
2880
- if (i < len) {
2881
- return { value: i++, done: false };
2882
- }
2883
- return { value: undefined, done: true };
2884
- },
2885
- [Symbol.iterator]() {
2886
- return this;
2887
- },
2888
- };
2889
- return iterator;
2890
- },
2891
- values() {
2892
- let i = 0;
2893
- const iterator = {
2894
- next: () => {
2895
- const value = valueAt(target, i++);
2896
- if (value === undefined) {
2897
- return { value: undefined, done: true };
2898
- }
2899
- else {
2900
- return { value, done: false };
2901
- }
2902
- },
2903
- [Symbol.iterator]() {
2904
- return this;
2905
- },
2906
- };
2907
- return iterator;
2908
- },
2909
- toArray() {
2910
- const list = [];
2911
- let value;
2912
- do {
2913
- value = valueAt(target, list.length);
2914
- if (value !== undefined) {
2915
- list.push(value);
2916
- }
2917
- } while (value !== undefined);
2918
- return list;
2919
- },
2920
- map(f) {
2921
- return this.toArray().map(f);
2922
- },
2923
- toString() {
2924
- return this.toArray().toString();
2925
- },
2926
- toLocaleString() {
2927
- return this.toArray().toLocaleString();
2928
- },
2929
- forEach(f) {
2930
- return this.toArray().forEach(f);
2931
- },
2932
- // todo: real concat function is different
2933
- concat(other) {
2934
- return this.toArray().concat(other);
2935
- },
2936
- every(f) {
2937
- return this.toArray().every(f);
2938
- },
2939
- filter(f) {
2940
- return this.toArray().filter(f);
2941
- },
2942
- find(f) {
2943
- let index = 0;
2944
- for (const v of this) {
2945
- if (f(v, index)) {
2946
- return v;
2947
- }
2948
- index += 1;
2949
- }
2950
- },
2951
- findIndex(f) {
2952
- let index = 0;
2953
- for (const v of this) {
2954
- if (f(v, index)) {
2955
- return index;
2956
- }
2957
- index += 1;
2958
- }
2959
- return -1;
2960
- },
2961
- includes(elem) {
2962
- return this.find(e => e === elem) !== undefined;
2963
- },
2964
- join(sep) {
2965
- return this.toArray().join(sep);
2966
- },
2967
- reduce(f, initialValue) {
2968
- return this.toArray().reduce(f, initialValue);
2969
- },
2970
- reduceRight(f, initialValue) {
2971
- return this.toArray().reduceRight(f, initialValue);
2972
- },
2973
- lastIndexOf(search, fromIndex = +Infinity) {
2974
- // this can be faster
2975
- return this.toArray().lastIndexOf(search, fromIndex);
2976
- },
2977
- slice(index, num) {
2978
- return this.toArray().slice(index, num);
2979
- },
2980
- some(f) {
2981
- let index = 0;
2982
- for (const v of this) {
2983
- if (f(v, index)) {
2984
- return true;
2985
- }
2986
- index += 1;
2987
- }
2988
- return false;
2989
- },
2990
- [Symbol.iterator]: function* () {
2991
- let i = 0;
2992
- let value = valueAt(target, i);
2993
- while (value !== undefined) {
2994
- yield value;
2995
- i += 1;
2996
- value = valueAt(target, i);
2997
- }
2998
- },
2999
- };
3000
- return methods;
3001
- }
3002
- function textMethods(target) {
3003
- const { context, objectId } = target;
3004
- const methods = {
3005
- set(index, value) {
3006
- return (this[index] = value);
3007
- },
3008
- get(index) {
3009
- return this[index];
3010
- },
3011
- toString() {
3012
- return context.text(objectId).replace(//g, "");
3013
- },
3014
- toSpans() {
3015
- const spans = [];
3016
- let chars = "";
3017
- const length = context.length(objectId);
3018
- for (let i = 0; i < length; i++) {
3019
- const value = this[i];
3020
- if (typeof value === "string") {
3021
- chars += value;
3022
- }
3023
- else {
3024
- if (chars.length > 0) {
3025
- spans.push(chars);
3026
- chars = "";
3027
- }
3028
- spans.push(value);
3029
- }
3030
- }
3031
- if (chars.length > 0) {
3032
- spans.push(chars);
3033
- }
3034
- return spans;
3035
- },
3036
- toJSON() {
3037
- return this.toString();
3038
- },
3039
- indexOf(o, start = 0) {
3040
- const text = context.text(objectId);
3041
- return text.indexOf(o, start);
3042
- },
3043
- insertAt(index, ...values) {
3044
- if (values.every(v => typeof v === "string")) {
3045
- context.splice(objectId, index, 0, values.join(""));
3046
- }
3047
- else {
3048
- listMethods(target).insertAt(index, ...values);
3049
- }
3050
- },
3051
- };
3052
- return methods;
3053
- }
3054
- function printPath(path) {
3055
- // print the path as a json pointer
3056
- const jsonPointerComponents = path.map(component => {
3057
- // if its a number just turn it into a string
3058
- if (typeof component === "number") {
3059
- return component.toString();
3060
- }
3061
- else if (typeof component === "string") {
3062
- // otherwise we have to escape `/` and `~` characters
3063
- return component.replace(/~/g, "~0").replace(/\//g, "~1");
3064
- }
3065
- });
3066
- if (path.length === 0) {
3067
- return "";
3068
- }
3069
- else {
3070
- return "/" + jsonPointerComponents.join("/");
3071
- }
3072
- }
3073
- /*
3074
- * Check if an object is a {@link ImmutableString}
3075
- */
3076
- function isImmutableString(obj) {
3077
- // We used to determine whether something was a ImmutableString by doing an instanceof check, but
3078
- // this doesn't work if the automerge module is loaded twice somehow. Instead, use the presence
3079
- // of a symbol to determine if something is a ImmutableString
3080
- return (typeof obj === "object" &&
3081
- obj !== null &&
3082
- Object.prototype.hasOwnProperty.call(obj, IMMUTABLE_STRING));
3083
- }
3084
-
3085
- let wasm;
3086
-
3087
- const cachedTextEncoder = (typeof TextEncoder !== 'undefined' ? new TextEncoder('utf-8') : { encode: () => { throw Error('TextEncoder not available') } } );
3088
-
3089
- (typeof cachedTextEncoder.encodeInto === 'function'
3090
- ? function (arg, view) {
3091
- return cachedTextEncoder.encodeInto(arg, view);
3092
- }
3093
- : function (arg, view) {
3094
- const buf = cachedTextEncoder.encode(arg);
3095
- view.set(buf);
3096
- return {
3097
- read: arg.length,
3098
- written: buf.length
3099
- };
3100
- });
3101
-
3102
- const cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } );
3103
-
3104
- if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); }
3105
- (typeof FinalizationRegistry === 'undefined')
3106
- ? { }
3107
- : new FinalizationRegistry(ptr => wasm.__wbg_automerge_free(ptr >>> 0, 1));
3108
-
3109
- (typeof FinalizationRegistry === 'undefined')
3110
- ? { }
3111
- : new FinalizationRegistry(ptr => wasm.__wbg_syncstate_free(ptr >>> 0, 1));
2245
+ if (Symbol.dispose) SyncState.prototype[Symbol.dispose] = SyncState.prototype.free;
3112
2246
 
3113
2247
  (undefined && undefined.__rest) || function (s, e) {
3114
2248
  var t = {};
@@ -6241,13 +5375,6 @@ const REUSE_BUFFER_MODE = 512;
6241
5375
  const RESET_BUFFER_MODE = 1024;
6242
5376
  const THROW_ON_ITERABLE = 2048;
6243
5377
 
6244
- /**
6245
- * FinalizationRegistry for automatic cleanup of Ref instances.
6246
- * This ensures subscriptions are cleaned up when Refs are garbage collected,
6247
- * even if dispose() is never called.
6248
- */
6249
- new FinalizationRegistry(cleanup => cleanup());
6250
-
6251
5378
  var sha256$1 = {exports: {}};
6252
5379
 
6253
5380
  var sha256 = sha256$1.exports;
@@ -6692,67 +5819,139 @@ const DEFAULT_HEARTBEAT_INTERVAL_MS = 15_000;
6692
5819
  const DEFAULT_PEER_TTL_MS = 3 * DEFAULT_HEARTBEAT_INTERVAL_MS;
6693
5820
  const PRESENCE_MESSAGE_MARKER = "__presence";
6694
5821
 
6695
- /**
6696
- * A grouped view of peer states.
6697
- */
5822
+ function unique(items) {
5823
+ return Array.from(new Set(items));
5824
+ }
5825
+
6698
5826
  class PeerStateView {
6699
5827
  value;
6700
5828
  constructor(value) {
6701
5829
  this.value = value;
6702
5830
  }
6703
5831
  /**
6704
- * Get the presence state of all peers. By default, each peer is its own
6705
- * group, but presence activity can be aggregated by arbitrary criteria.
5832
+ * Get all users.
5833
+ *
5834
+ * @returns Array of user presence {@link State}s
5835
+ */
5836
+ get users() {
5837
+ const userIds = unique(Object.values(this.value).map(peerState => peerState.userId));
5838
+ return userIds.map(u => this.getUserState(u));
5839
+ }
5840
+ /**
5841
+ * Get all devices.
5842
+ *
5843
+ * @returns Array of device presence {@link State}s
5844
+ */
5845
+ get devices() {
5846
+ const deviceIds = unique(Object.values(this.value).map(peerState => peerState.deviceId));
5847
+ return deviceIds.map(d => this.getDeviceState(d));
5848
+ }
5849
+ /**
5850
+ * Get all peers.
5851
+ *
5852
+ * @returns Array of peer presence {@link State}s
5853
+ */
5854
+ get peers() {
5855
+ return Object.values(this.value);
5856
+ }
5857
+ /**
5858
+ * Get all peer ids for this user.
5859
+ *
5860
+ * @param userId
5861
+ * @returns Array of peer ids for this user
5862
+ */
5863
+ getUserPeers(userId) {
5864
+ return Object.values(this.value)
5865
+ .filter(peerState => peerState.userId === userId)
5866
+ .map(peerState => peerState.peerId);
5867
+ }
5868
+ /**
5869
+ * Get all peers for this device.
5870
+ *
5871
+ * @param deviceId
5872
+ * @returns Array of peer ids for this device
5873
+ */
5874
+ getDevicePeers(deviceId) {
5875
+ return Object.values(this.value)
5876
+ .filter(peerState => peerState.deviceId === deviceId)
5877
+ .map(peerState => peerState.peerId);
5878
+ }
5879
+ /**
5880
+ * Return the most-recently-seen peer from this group.
6706
5881
  *
6707
- * @param opts
6708
- * @returns presence state for all groups
5882
+ * @param peers
5883
+ * @returns id of most recently seen peer
6709
5884
  */
6710
- getStates(opts) {
6711
- const groupingFn = opts?.groupingFn ?? peerIdentity;
6712
- const summaryFn = opts?.summaryFn ??
6713
- getLastActivePeer;
6714
- const statesByKey = Object.values(this.value).reduce((byKey, curr) => {
6715
- const key = groupingFn(curr);
6716
- if (!(key in byKey)) {
6717
- byKey[key] = [];
5885
+ getLastSeenPeer(peers) {
5886
+ let freshestLastSeenAt;
5887
+ return peers.reduce((freshest, curr) => {
5888
+ const lastSeenAt = this.value[curr]?.lastActiveAt;
5889
+ if (!lastSeenAt) {
5890
+ return freshest;
6718
5891
  }
6719
- byKey[key].push(curr);
6720
- return byKey;
6721
- }, {});
6722
- return Object.entries(statesByKey).reduce((result, [key, states]) => {
6723
- result[key] = summaryFn(states);
6724
- return result;
6725
- }, {});
5892
+ if (!freshest || lastSeenAt > freshestLastSeenAt) {
5893
+ freshestLastSeenAt = lastSeenAt;
5894
+ return curr;
5895
+ }
5896
+ return freshest;
5897
+ }, undefined);
6726
5898
  }
6727
- }
6728
- /**
6729
- * Get the peerId of this peer.
6730
- *
6731
- * @param peer
6732
- * @returns peer id
6733
- */
6734
- function peerIdentity(peer) {
6735
- return peer.peerId;
6736
- }
6737
- /**
6738
- * Find the peer that most recently sent a state update.
6739
- *
6740
- * @param peers
6741
- * @returns id of most recently active peer
6742
- */
6743
- function getLastActivePeer(peers) {
6744
- let freshestLastActiveAt;
6745
- return peers.reduce((freshest, curr) => {
6746
- const lastActiveAt = curr.lastActiveAt;
6747
- if (!lastActiveAt) {
5899
+ /**
5900
+ * Return the peer from this group that sent a state update most recently
5901
+ *
5902
+ * @param peers
5903
+ * @returns id of most recently seen peer
5904
+ */
5905
+ getLastActivePeer(peers) {
5906
+ let freshestLastActiveAt;
5907
+ return peers.reduce((freshest, curr) => {
5908
+ const lastActiveAt = this.value[curr]?.lastActiveAt;
5909
+ if (!lastActiveAt) {
5910
+ return freshest;
5911
+ }
5912
+ if (!freshest || lastActiveAt > freshestLastActiveAt) {
5913
+ freshestLastActiveAt = lastActiveAt;
5914
+ return curr;
5915
+ }
6748
5916
  return freshest;
5917
+ }, undefined);
5918
+ }
5919
+ /**
5920
+ * Get current ephemeral state value for this user's most-recently-active
5921
+ * peer.
5922
+ *
5923
+ * @param userId
5924
+ * @returns user's {@link State}
5925
+ */
5926
+ getUserState(userId) {
5927
+ const peers = this.getUserPeers(userId);
5928
+ if (!peers) {
5929
+ return undefined;
6749
5930
  }
6750
- if (!freshest || lastActiveAt > freshestLastActiveAt) {
6751
- freshestLastActiveAt = lastActiveAt;
6752
- return curr;
5931
+ const peer = this.getLastActivePeer(peers);
5932
+ if (!peer) {
5933
+ return undefined;
6753
5934
  }
6754
- return freshest;
6755
- }, undefined);
5935
+ return this.value[peer];
5936
+ }
5937
+ /**
5938
+ * Get current ephemeral state value for this device's most-recently-active
5939
+ * peer.
5940
+ *
5941
+ * @param deviceId
5942
+ * @returns device's {@link State}
5943
+ */
5944
+ getDeviceState(deviceId) {
5945
+ const peers = this.getDevicePeers(deviceId);
5946
+ if (!peers) {
5947
+ return undefined;
5948
+ }
5949
+ const peer = this.getLastActivePeer(peers);
5950
+ if (!peer) {
5951
+ return undefined;
5952
+ }
5953
+ return this.value[peer];
5954
+ }
6756
5955
  }
6757
5956
 
6758
5957
  class PeerPresenceInfo {
@@ -6776,15 +5975,11 @@ class PeerPresenceInfo {
6776
5975
  * @param peerId
6777
5976
  */
6778
5977
  markSeen(peerId) {
6779
- if (!(peerId in this.#peerStates.value)) {
6780
- // Ignore heartbeats from peers we have not seen before: they will send a snapshot
6781
- return;
6782
- }
6783
5978
  this.#peerStates = new PeerStateView({
6784
5979
  ...this.#peerStates.value,
6785
5980
  [peerId]: {
6786
5981
  ...this.#peerStates.value[peerId],
6787
- lastSeenAt: Date.now(),
5982
+ lastSeen: Date.now(),
6788
5983
  },
6789
5984
  });
6790
5985
  }
@@ -6795,7 +5990,7 @@ class PeerPresenceInfo {
6795
5990
  * @param peerId
6796
5991
  * @param value
6797
5992
  */
6798
- update({ peerId, value }) {
5993
+ update({ peerId, deviceId, userId, value, }) {
6799
5994
  const peerState = this.#peerStates.value[peerId];
6800
5995
  const existingState = peerState?.value ?? {};
6801
5996
  const now = Date.now();
@@ -6803,8 +5998,10 @@ class PeerPresenceInfo {
6803
5998
  ...this.#peerStates.value,
6804
5999
  [peerId]: {
6805
6000
  peerId,
6806
- lastSeenAt: now,
6001
+ deviceId,
6002
+ userId,
6807
6003
  lastActiveAt: now,
6004
+ lastUpdateAt: now,
6808
6005
  value: {
6809
6006
  ...existingState,
6810
6007
  ...value,
@@ -6828,15 +6025,9 @@ class PeerPresenceInfo {
6828
6025
  */
6829
6026
  prune() {
6830
6027
  const threshold = Date.now() - this.ttl;
6831
- const pruned = [];
6832
- this.#peerStates = new PeerStateView(Object.fromEntries(Object.entries(this.#peerStates.value).filter(([id, state]) => {
6833
- const keep = state.lastSeenAt >= threshold;
6834
- if (!keep) {
6835
- pruned.push(id);
6836
- }
6837
- return keep;
6028
+ this.#peerStates = new PeerStateView(Object.fromEntries(Object.entries(this.#peerStates).filter(([, state]) => {
6029
+ return state.lastActiveAt >= threshold;
6838
6030
  })));
6839
- return pruned;
6840
6031
  }
6841
6032
  /**
6842
6033
  * Get a snapshot of the current peer states
@@ -6859,6 +6050,8 @@ class PeerPresenceInfo {
6859
6050
  */
6860
6051
  class Presence extends EventEmitter {
6861
6052
  #handle;
6053
+ deviceId;
6054
+ userId;
6862
6055
  #peers;
6863
6056
  #localState;
6864
6057
  #heartbeatMs;
@@ -6873,11 +6066,13 @@ class Presence extends EventEmitter {
6873
6066
  * @param config see {@link PresenceConfig}
6874
6067
  * @returns
6875
6068
  */
6876
- constructor({ handle }) {
6069
+ constructor({ handle, deviceId, userId, }) {
6877
6070
  super();
6878
6071
  this.#handle = handle;
6879
6072
  this.#peers = new PeerPresenceInfo(DEFAULT_PEER_TTL_MS);
6880
6073
  this.#localState = {};
6074
+ this.userId = userId;
6075
+ this.deviceId = deviceId;
6881
6076
  }
6882
6077
  /**
6883
6078
  * Start listening to ephemeral messages on the handle, broadcast initial
@@ -6901,6 +6096,7 @@ class Presence extends EventEmitter {
6901
6096
  return;
6902
6097
  }
6903
6098
  const message = envelope[PRESENCE_MESSAGE_MARKER];
6099
+ const { deviceId, userId } = message;
6904
6100
  if (!this.#peers.has(peerId)) {
6905
6101
  this.announce();
6906
6102
  }
@@ -6916,11 +6112,15 @@ class Presence extends EventEmitter {
6916
6112
  case "update":
6917
6113
  this.#peers.update({
6918
6114
  peerId,
6115
+ deviceId,
6116
+ userId,
6919
6117
  value: { [message.channel]: message.value },
6920
6118
  });
6921
6119
  this.emit("update", {
6922
6120
  type: "update",
6923
6121
  peerId,
6122
+ deviceId,
6123
+ userId,
6924
6124
  channel: message.channel,
6925
6125
  value: message.value,
6926
6126
  });
@@ -6928,11 +6128,15 @@ class Presence extends EventEmitter {
6928
6128
  case "snapshot":
6929
6129
  this.#peers.update({
6930
6130
  peerId,
6131
+ deviceId,
6132
+ userId,
6931
6133
  value: message.state,
6932
6134
  });
6933
6135
  this.emit("snapshot", {
6934
6136
  type: "snapshot",
6935
6137
  peerId,
6138
+ deviceId,
6139
+ userId,
6936
6140
  state: message.state,
6937
6141
  });
6938
6142
  break;
@@ -7027,6 +6231,8 @@ class Presence extends EventEmitter {
7027
6231
  }
7028
6232
  doBroadcast(type, extra) {
7029
6233
  this.send({
6234
+ userId: this.userId,
6235
+ deviceId: this.deviceId,
7030
6236
  type,
7031
6237
  ...extra,
7032
6238
  });
@@ -7062,10 +6268,7 @@ class Presence extends EventEmitter {
7062
6268
  // to minimize variance between peer expiration, since the heartbeat frequency
7063
6269
  // is expected to be several times higher.
7064
6270
  this.#pruningInterval = setInterval(() => {
7065
- const pruned = this.#peers.prune();
7066
- if (pruned.length > 0) {
7067
- this.emit("pruning", { pruned });
7068
- }
6271
+ this.#peers.prune();
7069
6272
  }, this.#heartbeatMs);
7070
6273
  }
7071
6274
  stopPruningPeers() {
@@ -7079,6 +6282,8 @@ class Presence extends EventEmitter {
7079
6282
 
7080
6283
  function usePresence({
7081
6284
  handle,
6285
+ userId,
6286
+ deviceId,
7082
6287
  initialState,
7083
6288
  heartbeatMs,
7084
6289
  peerTtlMs
@@ -7090,7 +6295,9 @@ function usePresence({
7090
6295
  peerTtlMs
7091
6296
  });
7092
6297
  const firstInitialState = useRef(initialState);
7093
- const [presence] = useState(() => new Presence({ handle }));
6298
+ const [presence] = useState(
6299
+ () => new Presence({ handle, userId, deviceId })
6300
+ );
7094
6301
  useEffect(() => {
7095
6302
  presence.start({
7096
6303
  initialState: firstInitialState.current,
@@ -7100,26 +6307,10 @@ function usePresence({
7100
6307
  presence.on("snapshot", () => setPeerStates(presence.getPeerStates()));
7101
6308
  presence.on("update", () => setPeerStates(presence.getPeerStates()));
7102
6309
  presence.on("goodbye", () => setPeerStates(presence.getPeerStates()));
7103
- presence.on("pruning", () => setPeerStates(presence.getPeerStates()));
7104
6310
  return () => {
7105
6311
  presence.stop();
7106
6312
  };
7107
- }, [presence, firstInitialState, firstOpts]);
7108
- const start = useCallback(
7109
- (config) => {
7110
- const initialState2 = config?.initialState ?? presence.getLocalState();
7111
- const opts = {
7112
- ...firstOpts.current,
7113
- ...config,
7114
- initialState: initialState2
7115
- };
7116
- presence.start(opts);
7117
- },
7118
- [presence, firstOpts]
7119
- );
7120
- const stop = useCallback(() => {
7121
- presence.stop();
7122
- }, [presence]);
6313
+ }, [presence, userId, deviceId, firstInitialState, firstOpts]);
7123
6314
  const update = useCallback(
7124
6315
  (channel, msg) => {
7125
6316
  presence.broadcast(channel, msg);
@@ -7131,9 +6322,7 @@ function usePresence({
7131
6322
  return {
7132
6323
  peerStates,
7133
6324
  localState,
7134
- update,
7135
- start,
7136
- stop
6325
+ update
7137
6326
  };
7138
6327
  }
7139
6328