@dxos/util 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2575 @@
1
+ import { inspect, promisify } from "@dxos/node-std/util";
2
+ import { invariant } from "@dxos/invariant";
3
+ import { inspectObject, raise, truncateKey } from "@dxos/debug";
4
+ import "@hazae41/symbol-dispose-polyfill";
5
+ import { PublicKey } from "@dxos/keys";
6
+ //#region \0rolldown/runtime.js
7
+ var __defProp = Object.defineProperty;
8
+ var __exportAll = (all, no_symbols) => {
9
+ let target = {};
10
+ for (var name in all) __defProp(target, name, {
11
+ get: all[name],
12
+ enumerable: true
13
+ });
14
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
15
+ return target;
16
+ };
17
+ //#endregion
18
+ //#region src/array-to-hex.ts
19
+ var byteToHex = [];
20
+ for (let n = 0; n <= 255; ++n) {
21
+ const hexOctet = n.toString(16).padStart(2, "0");
22
+ byteToHex.push(hexOctet);
23
+ }
24
+ var arrayToHex = (buf) => {
25
+ const buff = new Uint8Array(buf);
26
+ const hexOctets = [];
27
+ for (let i = 0; i < buff.length; ++i) hexOctets.push(byteToHex[buff[i]]);
28
+ return hexOctets.join("");
29
+ };
30
+ //#endregion
31
+ //#region src/array.ts
32
+ /**
33
+ * Compute diff between two arrays.
34
+ * @param previous
35
+ * @param next
36
+ * @param comparator
37
+ */
38
+ var diff = (previous, next, comparator) => {
39
+ const remaining = [...previous];
40
+ const result = {
41
+ added: [],
42
+ updated: [],
43
+ removed: remaining
44
+ };
45
+ for (const object of next) {
46
+ const index = remaining.findIndex((item) => comparator(item, object));
47
+ if (index === -1) result.added.push(object);
48
+ else {
49
+ result.updated.push(object);
50
+ remaining.splice(index, 1);
51
+ }
52
+ }
53
+ return result;
54
+ };
55
+ var intersection = (a, b, comparator) => a.filter((a) => b.find((b) => comparator(a, b)) !== void 0);
56
+ /**
57
+ * Returns a new array with only the first instance of each unique item
58
+ * based on a specified property.
59
+ *
60
+ * @typeProp T - The type of items in the input array.
61
+ * @param array - The array to filter for distinct items.
62
+ * @param key - The property key to determine uniqueness for each item.
63
+ * @returns A new array with only distinct items based on the specified property.
64
+ */
65
+ var distinctBy = (array, selector) => {
66
+ const seenKeys = /* @__PURE__ */ new Set();
67
+ return array.filter((item) => {
68
+ const key = selector(item);
69
+ if (seenKeys.has(key)) return false;
70
+ seenKeys.add(key);
71
+ return true;
72
+ });
73
+ };
74
+ /**
75
+ * Remove elements from array.
76
+ * @param array
77
+ * @param test
78
+ * @returns removed elements.
79
+ */
80
+ var removeBy = (array, test) => {
81
+ const removed = [];
82
+ for (let i = array.length - 1; i >= 0; i--) if (test(array[i], i)) removed.push(...array.splice(i, 1));
83
+ return removed;
84
+ };
85
+ /**
86
+ * Splits an array based on a type guard predicate function.
87
+ * Infers the output tuple types from the guard function.
88
+ */
89
+ var partition = (array, guard) => {
90
+ return array.reduce(([accepted, rejected], item, index, array) => guard(item, index, array) ? [[...accepted, item], rejected] : [accepted, [...rejected, item]], [[], []]);
91
+ };
92
+ /**
93
+ * Returns elements that exist in all provided arrays based on a selector function.
94
+ *
95
+ * @param arrays - Arrays to intersect.
96
+ * @param selector - Function to extract the comparison value from each element.
97
+ * @returns Array containing elements from the first array that exist in all other arrays.
98
+ */
99
+ var intersectBy = (arrays, selector) => {
100
+ if (arrays.length === 0) return [];
101
+ if (arrays.length === 1) return [...arrays[0]];
102
+ const [first, ...rest] = arrays;
103
+ const lookups = rest.map((array) => {
104
+ const map = /* @__PURE__ */ new Map();
105
+ for (const item of array) map.set(selector(item), item);
106
+ return map;
107
+ });
108
+ return first.filter((item) => {
109
+ const key = selector(item);
110
+ return lookups.every((lookup) => lookup.has(key));
111
+ });
112
+ };
113
+ var coerceArray = (arr) => {
114
+ if (arr === void 0) return [];
115
+ return Array.isArray(arr) ? arr : [arr];
116
+ };
117
+ //#endregion
118
+ //#region src/assume.ts
119
+ /**
120
+ * Assumes the type of the value.
121
+ *
122
+ * @param value - The value to assume the type of.
123
+ *
124
+ * @example
125
+ * ```ts
126
+ * const value: unknown = 1;
127
+ * assumeType<number>(value);
128
+ *
129
+ * // value is now of type number
130
+ * ```
131
+ */
132
+ function assumeType(value) {}
133
+ //#endregion
134
+ //#region src/binder.ts
135
+ /**
136
+ * Function binder replaces pify.
137
+ */
138
+ var createBinder = (obj) => ({
139
+ fn: (fn) => fn.bind(obj),
140
+ async: (fn) => promisify(fn.bind(obj))
141
+ });
142
+ //#endregion
143
+ //#region src/bitfield.ts
144
+ var __dxlog_file$4 = "/__w/dxos/dxos/packages/common/util/src/bitfield.ts";
145
+ /**
146
+ * Bitfield encodes indices from MSB to LSB.
147
+ * Index 0 is the MSB of the first byte.
148
+ *
149
+ *
150
+ * #0 #1 #2 #3
151
+ * 01010101 11110000 00001111 01010101
152
+ * ^ ^
153
+ * MSB LSB
154
+ */
155
+ var BitField = class BitField {
156
+ static get(data, idx) {
157
+ return !!(data[idx >> 3] >> 7 - idx % 8 & 1);
158
+ }
159
+ static set(data, idx, value) {
160
+ if (value) data[idx >> 3] = data[idx >> 3] | 1 << 7 - idx % 8;
161
+ else data[idx >> 3] = data[idx >> 3] & ~(1 << 7 - idx % 8);
162
+ }
163
+ /**
164
+ * [start; end)
165
+ */
166
+ static count(data, begin, end) {
167
+ let count = 0;
168
+ for (let i = begin; i < end; i++) {
169
+ const bit = data[i >> 3] >> 7 - i % 8 & 1;
170
+ count += bit;
171
+ }
172
+ return count;
173
+ }
174
+ static invert(data) {
175
+ const result = new Uint8Array(data.length);
176
+ for (let i = 0; i < data.length; i++) result[i] = ~data[i];
177
+ return result;
178
+ }
179
+ static and(first, second) {
180
+ invariant(first.length === second.length, "Bitfields must be of the same length", {
181
+ "~LogMeta": "~LogMeta",
182
+ F: __dxlog_file$4,
183
+ L: 52,
184
+ S: this,
185
+ A: ["first.length === second.length", "'Bitfields must be of the same length'"]
186
+ });
187
+ const result = new Uint8Array(first.length);
188
+ for (let i = 0; i < first.length; i++) result[i] = first[i] & second[i];
189
+ return result;
190
+ }
191
+ static findIndexes(data, opts = {}) {
192
+ const { start = 0, end = data.length * 8, value = true } = opts;
193
+ const result = [];
194
+ for (let i = start; i < end; i++) if (BitField.get(data, i) === value) result.push(i);
195
+ return result;
196
+ }
197
+ static ones(count) {
198
+ const res = new Uint8Array(Math.ceil(Math.ceil(count) / 8)).fill(255);
199
+ const bitInLastByte = Math.ceil(count % 8);
200
+ res[res.length - 1] = 255 << 8 - bitInLastByte;
201
+ return res;
202
+ }
203
+ static zeros(count) {
204
+ return new Uint8Array(Math.ceil(Math.ceil(count) / 8)).fill(0);
205
+ }
206
+ };
207
+ //#endregion
208
+ //#region src/browser-storage.ts
209
+ /** Delete all IndexedDB databases for this origin. */
210
+ var clearIndexedDB = async () => {
211
+ const dbs = await indexedDB.databases();
212
+ const failures = (await Promise.allSettled(dbs.filter((db) => db.name != null).map((db) => new Promise((resolve, reject) => {
213
+ const request = indexedDB.deleteDatabase(db.name);
214
+ request.onsuccess = () => resolve();
215
+ request.onerror = () => reject(request.error);
216
+ request.onblocked = () => reject(/* @__PURE__ */ new Error(`IndexedDB deletion blocked: ${db.name}`));
217
+ })))).filter((r) => r.status === "rejected");
218
+ if (failures.length > 0) throw new AggregateError(failures.map((r) => r.reason), "Failed to delete some IndexedDB databases");
219
+ };
220
+ /** Remove all entries from the Origin Private File System. */
221
+ var clearOPFS = async () => {
222
+ const root = await navigator.storage.getDirectory();
223
+ const errors = [];
224
+ for await (const [name] of root.entries()) try {
225
+ await root.removeEntry(name, { recursive: true });
226
+ } catch (err) {
227
+ errors.push(err);
228
+ }
229
+ if (errors.length > 0) throw new AggregateError(errors, "Failed to remove some OPFS entries");
230
+ };
231
+ /** Unregister all service workers for this origin. */
232
+ var clearServiceWorkers = async () => {
233
+ const regs = await navigator.serviceWorker.getRegistrations();
234
+ for (const reg of regs) await reg.unregister();
235
+ };
236
+ /** Delete all HTTP caches for this origin. */
237
+ var clearCaches = async () => {
238
+ const keys = await caches.keys();
239
+ for (const key of keys) await caches.delete(key);
240
+ };
241
+ //#endregion
242
+ //#region src/callback-collection.ts
243
+ /**
244
+ * A collection of async functions.
245
+ */
246
+ var CallbackCollection = class {
247
+ #callbacks = [];
248
+ append(callback) {
249
+ this.#callbacks.push(callback);
250
+ }
251
+ prepend(callback) {
252
+ this.#callbacks.unshift(callback);
253
+ }
254
+ remove(callback) {
255
+ this.#callbacks = this.#callbacks.filter((c) => c !== callback);
256
+ }
257
+ callParallel(...args) {
258
+ return Promise.all(this.#callbacks.map((callback) => callback(...args)));
259
+ }
260
+ async callSerial(...args) {
261
+ const results = [];
262
+ for (const callback of this.#callbacks) results.push(await callback(...args));
263
+ return results;
264
+ }
265
+ };
266
+ //#endregion
267
+ //#region src/callback.ts
268
+ var __dxlog_file$3 = "/__w/dxos/dxos/packages/common/util/src/callback.ts";
269
+ /**
270
+ * Represents a callback that can be set once.
271
+ *
272
+ * Common usage is dependency injection.
273
+ * In contrast to events, callbacks can only have one handler,
274
+ * are executed synchronously,
275
+ * and can return results.
276
+ */
277
+ var Callback = class {
278
+ _callback;
279
+ call(...args) {
280
+ invariant(this._callback, "Callback not set", {
281
+ "~LogMeta": "~LogMeta",
282
+ F: __dxlog_file$3,
283
+ L: 20,
284
+ S: this,
285
+ A: ["this._callback", "'Callback not set'"]
286
+ });
287
+ return this._callback(...args);
288
+ }
289
+ callIfSet(...args) {
290
+ return this._callback?.(...args);
291
+ }
292
+ set(callback) {
293
+ invariant(!this._callback, "Callback already set", {
294
+ "~LogMeta": "~LogMeta",
295
+ F: __dxlog_file$3,
296
+ L: 29,
297
+ S: this,
298
+ A: ["!this._callback", "'Callback already set'"]
299
+ });
300
+ this._callback = callback;
301
+ }
302
+ isSet() {
303
+ return !!this._callback;
304
+ }
305
+ };
306
+ /**
307
+ * Create a fan-out callback handler.
308
+ * NOTE: Methods cannot return values.
309
+ */
310
+ var createSetDispatch = ({ handlers }) => {
311
+ return new Proxy({ handlers }, { get: (target, prop) => {
312
+ return (...args) => {
313
+ handlers.forEach((handler) => {
314
+ const method = handler[prop];
315
+ if (method) method.apply(handler, args);
316
+ });
317
+ };
318
+ } });
319
+ };
320
+ //#endregion
321
+ //#region src/case.ts
322
+ var LOW_DASH = "_".codePointAt(0);
323
+ var HI_DASH = "-".codePointAt(0);
324
+ var SMALL_A = "a".codePointAt(0);
325
+ var CAPITAL_A = "A".codePointAt(0);
326
+ var SMALL_Z = "z".codePointAt(0);
327
+ var CAPITAL_Z = "Z".codePointAt(0);
328
+ var isLower = (char) => char >= SMALL_A && char <= SMALL_Z;
329
+ var isUpper = (char) => char >= CAPITAL_A && char <= CAPITAL_Z;
330
+ var toLower = (char) => char + 32;
331
+ /**
332
+ * NOTE: Removed `xcase` due to CF dependency conflicts.
333
+ */
334
+ var changeCase = (str, delim) => {
335
+ if (!isLower(str.charCodeAt(0))) return str;
336
+ const length = str.length;
337
+ let changed = false;
338
+ const out = [];
339
+ for (let i = 0; i < length; ++i) {
340
+ const c = str.charCodeAt(i);
341
+ if (isUpper(c)) {
342
+ out.push(delim);
343
+ out.push(toLower(c));
344
+ changed = true;
345
+ } else out.push(c);
346
+ }
347
+ return changed ? String.fromCharCode.apply(void 0, out) : str;
348
+ };
349
+ var decamelize = (str) => changeCase(str, LOW_DASH);
350
+ var hyphenize = (str) => changeCase(str, HI_DASH);
351
+ //#endregion
352
+ //#region src/chunk-array.ts
353
+ var chunkArray = (array, size) => {
354
+ const result = [];
355
+ for (let i = 0; i < array.length; i += size) result.push(array.slice(i, i + size));
356
+ return result;
357
+ };
358
+ //#endregion
359
+ //#region src/circular-buffer.ts
360
+ var __dxlog_file$2 = "/__w/dxos/dxos/packages/common/util/src/circular-buffer.ts";
361
+ var CircularBuffer = class {
362
+ _buffer;
363
+ _nextIndex = 0;
364
+ _elementCount = 0;
365
+ constructor(size) {
366
+ invariant(size >= 1, void 0, {
367
+ "~LogMeta": "~LogMeta",
368
+ F: __dxlog_file$2,
369
+ L: 13,
370
+ S: this,
371
+ A: ["size >= 1", ""]
372
+ });
373
+ this._buffer = new Array(size);
374
+ }
375
+ push(element) {
376
+ const evicted = this._elementCount === this._buffer.length ? this._buffer[this._nextIndex] : void 0;
377
+ this._buffer[this._nextIndex] = element;
378
+ this._nextIndex = (this._nextIndex + 1) % this._buffer.length;
379
+ this._elementCount = Math.min(this._buffer.length, this._elementCount + 1);
380
+ return evicted;
381
+ }
382
+ get elementCount() {
383
+ return this._elementCount;
384
+ }
385
+ clear() {
386
+ this._nextIndex = 0;
387
+ this._elementCount = 0;
388
+ }
389
+ getLast() {
390
+ if (this._elementCount === 0) return;
391
+ if (this._nextIndex === 0) return this._buffer[this._buffer.length - 1];
392
+ return this._buffer[this._nextIndex - 1];
393
+ }
394
+ [Symbol.iterator]() {
395
+ return this.values();
396
+ }
397
+ *values() {
398
+ if (this._elementCount === 0) return;
399
+ if (this._elementCount < this._buffer.length) {
400
+ for (let i = 0; i < this._elementCount; i++) yield this._buffer[i];
401
+ return;
402
+ }
403
+ for (let i = this._nextIndex; i < this._buffer.length; i++) yield this._buffer[i];
404
+ for (let i = 0; i < this._nextIndex; i++) yield this._buffer[i];
405
+ }
406
+ };
407
+ //#endregion
408
+ //#region src/clear-undefined.ts
409
+ /**
410
+ * Remove undefined values from an object.
411
+ */
412
+ var clearUndefined = (obj) => {
413
+ for (const key of [...Object.getOwnPropertyNames(obj), ...Object.getOwnPropertySymbols(obj)]) if (obj[key] === void 0) delete obj[key];
414
+ return obj;
415
+ };
416
+ //#endregion
417
+ //#region src/complex.ts
418
+ var MAX_SERIALIZATION_LENGTH = 10;
419
+ /**
420
+ * A set implementation that can hold complex values (like Buffer).
421
+ *
422
+ * The user must provide a projection function which returns a primitive
423
+ * representation of the complex value. This function must be 1-to-1 mapping.
424
+ *
425
+ * Look at `../complex.test.ts` for usage examples.
426
+ */
427
+ var ComplexSet = class {
428
+ _projection;
429
+ _values = /* @__PURE__ */ new Map();
430
+ constructor(_projection, values) {
431
+ this._projection = _projection;
432
+ if (values) for (const value of values) this.add(value);
433
+ }
434
+ toString() {
435
+ return inspectObject(this);
436
+ }
437
+ toJSON() {
438
+ return this._values.size > MAX_SERIALIZATION_LENGTH ? { size: this._values.size } : Array.from(this._values.values());
439
+ }
440
+ [inspect.custom]() {
441
+ return inspectObject(this);
442
+ }
443
+ add(value) {
444
+ this._values.set(this._projection(value), value);
445
+ return this;
446
+ }
447
+ clear() {
448
+ this._values.clear();
449
+ }
450
+ delete(value) {
451
+ return this._values.delete(this._projection(value));
452
+ }
453
+ forEach(callbackfn, thisArg) {
454
+ if (thisArg) callbackfn = callbackfn.bind(thisArg);
455
+ this._values.forEach((value) => callbackfn(value, value, this));
456
+ }
457
+ has(value) {
458
+ return this._values.has(this._projection(value));
459
+ }
460
+ get size() {
461
+ return this._values.size;
462
+ }
463
+ [Symbol.iterator]() {
464
+ return this._values.values();
465
+ }
466
+ *entries() {
467
+ for (const value of this._values.values()) yield [value, value];
468
+ }
469
+ keys() {
470
+ return this[Symbol.iterator]();
471
+ }
472
+ values() {
473
+ return this[Symbol.iterator]();
474
+ }
475
+ get [Symbol.toStringTag]() {
476
+ return "ComplexSet";
477
+ }
478
+ union(other) {
479
+ throw new Error("Method not implemented.");
480
+ }
481
+ intersection(other) {
482
+ throw new Error("Method not implemented.");
483
+ }
484
+ difference(other) {
485
+ throw new Error("Method not implemented.");
486
+ }
487
+ symmetricDifference(other) {
488
+ throw new Error("Method not implemented.");
489
+ }
490
+ isSubsetOf(other) {
491
+ throw new Error("Method not implemented.");
492
+ }
493
+ isSupersetOf(other) {
494
+ throw new Error("Method not implemented.");
495
+ }
496
+ isDisjointFrom(other) {
497
+ throw new Error("Method not implemented.");
498
+ }
499
+ };
500
+ /**
501
+ * Create a subclass of ComplexSet with predefined projection function.
502
+ */
503
+ var makeSet = (projection) => {
504
+ return class BoundComplexSet extends ComplexSet {
505
+ constructor(values) {
506
+ super(projection, values);
507
+ }
508
+ };
509
+ };
510
+ /**
511
+ * A map implementation that can hold complex values (like Buffer) as keys.
512
+ * The user must provide a projection function for map keys which returns a primitive
513
+ * representation of the complex value. This function must be 1-to-1 mapping.
514
+ * Look at `../complex.test.ts` for usage examples.
515
+ */
516
+ var ComplexMap = class ComplexMap {
517
+ _keyProjection;
518
+ _keys = /* @__PURE__ */ new Map();
519
+ _values = /* @__PURE__ */ new Map();
520
+ constructor(_keyProjection, entries) {
521
+ this._keyProjection = _keyProjection;
522
+ if (entries) for (const [key, value] of entries) this.set(key, value);
523
+ }
524
+ toString() {
525
+ return inspectObject(this);
526
+ }
527
+ toJSON() {
528
+ return this._values.size > MAX_SERIALIZATION_LENGTH ? { size: this._values.size } : Array.from(this._values.values());
529
+ }
530
+ [inspect.custom]() {
531
+ return inspectObject(this);
532
+ }
533
+ clear() {
534
+ this._keys.clear();
535
+ this._values.clear();
536
+ }
537
+ delete(key) {
538
+ const keyDeleted = this._keys.delete(this._keyProjection(key));
539
+ const valueDeleted = this._values.delete(this._keyProjection(key));
540
+ return keyDeleted || valueDeleted;
541
+ }
542
+ forEach(callbackfn, thisArg) {
543
+ if (thisArg) callbackfn = callbackfn.bind(thisArg);
544
+ this._keys.forEach((key, primitive) => callbackfn(this._values.get(primitive) ?? raise(/* @__PURE__ */ new Error("Map corrupted.")), key, this));
545
+ }
546
+ get(key) {
547
+ return this._values.get(this._keyProjection(key));
548
+ }
549
+ has(key) {
550
+ return this._keys.has(this._keyProjection(key));
551
+ }
552
+ set(key, value) {
553
+ const primitive = this._keyProjection(key);
554
+ this._keys.set(primitive, key);
555
+ this._values.set(primitive, value);
556
+ return this;
557
+ }
558
+ /**
559
+ * Returns the value for the given key if present, otherwise inserts and returns the default value.
560
+ * @param key - The key to look up or insert.
561
+ * @param defaultValue - The value to insert if the key is not present.
562
+ * @returns The existing or newly inserted value.
563
+ */
564
+ getOrInsert(key, defaultValue) {
565
+ const primitive = this._keyProjection(key);
566
+ if (this._values.has(primitive)) return this._values.get(primitive);
567
+ this.set(key, defaultValue);
568
+ return defaultValue;
569
+ }
570
+ /**
571
+ * Returns the value for the given key if present, otherwise computes, inserts, and returns a new value.
572
+ * The callback is only invoked when the key is missing.
573
+ * @param key - The key to look up or insert.
574
+ * @param callbackfn - Function to compute the value if the key is not present.
575
+ * @returns The existing or newly computed value.
576
+ */
577
+ getOrInsertComputed(key, callbackfn) {
578
+ const primitive = this._keyProjection(key);
579
+ if (this._values.has(primitive)) return this._values.get(primitive);
580
+ const value = callbackfn(key);
581
+ this.set(key, value);
582
+ return value;
583
+ }
584
+ get size() {
585
+ return this._keys.size;
586
+ }
587
+ *[Symbol.iterator]() {
588
+ for (const [primitive, key] of this._keys) yield [key, this._values.get(primitive) ?? raise(/* @__PURE__ */ new Error("Map corrupted."))];
589
+ }
590
+ entries() {
591
+ return this[Symbol.iterator]();
592
+ }
593
+ keys() {
594
+ return this._keys.values();
595
+ }
596
+ values() {
597
+ return this._values.values();
598
+ }
599
+ mapValues(mapper) {
600
+ return new ComplexMap(this._keyProjection, [...this.entries()].map(([key, value]) => [key, mapper(value, key)]));
601
+ }
602
+ get [Symbol.toStringTag]() {
603
+ return "ComplexMap";
604
+ }
605
+ };
606
+ /**
607
+ * Create a subclass of ComplexMap with predefined key projection function.
608
+ */
609
+ var makeMap = (keyProjection) => class BoundComplexMap extends ComplexMap {
610
+ constructor(entries) {
611
+ super(keyProjection, entries);
612
+ }
613
+ };
614
+ //#endregion
615
+ //#region src/composite-key.ts
616
+ var SEPARATOR = ":";
617
+ /**
618
+ * Build a composite key from string parts joined by a colon separator.
619
+ * Parts must not contain the separator character.
620
+ */
621
+ var compositeKey = (...parts) => parts.join(SEPARATOR);
622
+ /**
623
+ * Split a composite key back into its parts.
624
+ */
625
+ var splitCompositeKey = (key) => key.split(SEPARATOR);
626
+ //#endregion
627
+ //#region src/deep.ts
628
+ var __dxlog_file$1 = "/__w/dxos/dxos/packages/common/util/src/deep.ts";
629
+ /**
630
+ * Initialize a deeply nested object.
631
+ * @returns The value of the prop after assignment.
632
+ */
633
+ var setDeep = (obj, path, value) => {
634
+ invariant(path.length > 0, void 0, {
635
+ "~LogMeta": "~LogMeta",
636
+ F: __dxlog_file$1,
637
+ L: 12,
638
+ S: void 0,
639
+ A: ["path.length > 0", ""]
640
+ });
641
+ let parent = obj;
642
+ for (const key of path.slice(0, -1)) {
643
+ if (parent[key] === void 0) {
644
+ const isArrayIndex = !isNaN(Number(key));
645
+ parent[key] = isArrayIndex ? [] : {};
646
+ }
647
+ parent = parent[key];
648
+ }
649
+ parent[path.at(-1)] = value;
650
+ return obj;
651
+ };
652
+ /**
653
+ * Gets a value from a deeply nested object.
654
+ * @returns The value of the prop if it exists, otherwise undefined.
655
+ */
656
+ var getDeep = (obj, path) => {
657
+ let parent = obj;
658
+ for (const key of path) parent = parent?.[key];
659
+ return parent;
660
+ };
661
+ //#endregion
662
+ //#region src/defer-function.ts
663
+ /**
664
+ * Wraps a function provider in a function that will defer the execution of the provided function.
665
+ *
666
+ * Example:
667
+ *
668
+ * ```typescript
669
+ * const fn = deferFunction(() => impl);
670
+ *
671
+ * // Impl can be defined after the usage.
672
+ * const impl = () => {
673
+ * console.log('Hello World!')
674
+ * }
675
+ * ```
676
+ */
677
+ var deferFunction = (fnProvider) => (...args) => fnProvider()(...args);
678
+ //#endregion
679
+ //#region src/defer.ts
680
+ /**
681
+ * Run function on scope exit. Go style.
682
+ *
683
+ * @example
684
+ * ```ts
685
+ * {
686
+ * using _ = defer(() => console.log('exiting'));
687
+ *
688
+ * ...
689
+ * }
690
+ */
691
+ var defer = (fn) => new DeferGuard(fn);
692
+ var DeferGuard = class {
693
+ _fn;
694
+ /**
695
+ * @internal
696
+ */
697
+ constructor(_fn) {
698
+ this._fn = _fn;
699
+ }
700
+ [Symbol.dispose]() {
701
+ if (this._fn() instanceof Promise) throw new Error("Async functions in defer are not supported. Use deferAsync instead.");
702
+ }
703
+ };
704
+ /**
705
+ * Run async function on scope exit. Go style.
706
+ *
707
+ * @example
708
+ * ```ts
709
+ * {
710
+ * await using _ = deferAsync(async () => console.log('exiting'));
711
+ *
712
+ * ...
713
+ * }
714
+ */
715
+ var deferAsync = (fn) => new DeferAsyncGuard(fn);
716
+ var DeferAsyncGuard = class {
717
+ _fn;
718
+ /**
719
+ * @internal
720
+ */
721
+ constructor(_fn) {
722
+ this._fn = _fn;
723
+ }
724
+ async [Symbol.asyncDispose]() {
725
+ await this._fn();
726
+ }
727
+ };
728
+ //#endregion
729
+ //#region src/entry.ts
730
+ /**
731
+ * Inspired by https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.entry
732
+ */
733
+ var entry = (map, key) => new MapEntry(map, key);
734
+ var MapEntry = class {
735
+ _map;
736
+ _key;
737
+ /**
738
+ * @internal
739
+ */
740
+ constructor(_map, _key) {
741
+ this._map = _map;
742
+ this._key = _key;
743
+ }
744
+ get key() {
745
+ return this._key;
746
+ }
747
+ get value() {
748
+ return this._map.get(this._key);
749
+ }
750
+ orInsert(value) {
751
+ if (!this._map.has(this._key)) this._map.set(this._key, value);
752
+ return this;
753
+ }
754
+ deep(key) {
755
+ return entry(this.value, key);
756
+ }
757
+ };
758
+ //#endregion
759
+ //#region src/error-format.ts
760
+ /**
761
+ * Formats an error with its cause chain.
762
+ */
763
+ var formatErrorWithCauses = (error) => {
764
+ const lines = [];
765
+ let current = error;
766
+ let level = 0;
767
+ while (current) {
768
+ const prefix = level === 0 ? "" : `Caused by: `;
769
+ lines.push(prefix + (current.stack ?? String(current)));
770
+ if (!(current.cause instanceof Error)) break;
771
+ current = current.cause;
772
+ level += 1;
773
+ }
774
+ return lines.join("\n\n");
775
+ };
776
+ //#endregion
777
+ //#region src/filename.ts
778
+ /**
779
+ * Creates a unique filename.
780
+ */
781
+ var createFilename = ({ parts = [], ext, date = /* @__PURE__ */ new Date() }) => [date.toISOString().replace(/[:.]/g, "-"), ...parts].join("_") + (ext ? `.${ext}` : "");
782
+ //#endregion
783
+ //#region src/for-each-async.ts
784
+ var forEachAsync = (items, fn) => Promise.all(items.map(fn));
785
+ //#endregion
786
+ //#region src/human-hash.ts
787
+ var DEFAULT_WORDLIST = [
788
+ "ack",
789
+ "alabama",
790
+ "alanine",
791
+ "alaska",
792
+ "alpha",
793
+ "angel",
794
+ "apart",
795
+ "april",
796
+ "arizona",
797
+ "arkansas",
798
+ "artist",
799
+ "asparagus",
800
+ "aspen",
801
+ "august",
802
+ "autumn",
803
+ "avocado",
804
+ "bacon",
805
+ "bakerloo",
806
+ "batman",
807
+ "beer",
808
+ "berlin",
809
+ "beryllium",
810
+ "black",
811
+ "blossom",
812
+ "blue",
813
+ "bluebird",
814
+ "bravo",
815
+ "bulldog",
816
+ "burger",
817
+ "butter",
818
+ "california",
819
+ "carbon",
820
+ "cardinal",
821
+ "carolina",
822
+ "carpet",
823
+ "cat",
824
+ "ceiling",
825
+ "charlie",
826
+ "chicken",
827
+ "coffee",
828
+ "cola",
829
+ "cold",
830
+ "colorado",
831
+ "comet",
832
+ "connecticut",
833
+ "crazy",
834
+ "cup",
835
+ "dakota",
836
+ "december",
837
+ "delaware",
838
+ "delta",
839
+ "diet",
840
+ "don",
841
+ "double",
842
+ "early",
843
+ "earth",
844
+ "east",
845
+ "echo",
846
+ "edward",
847
+ "eight",
848
+ "eighteen",
849
+ "eleven",
850
+ "emma",
851
+ "enemy",
852
+ "equal",
853
+ "failed",
854
+ "fanta",
855
+ "fifteen",
856
+ "fillet",
857
+ "finch",
858
+ "fish",
859
+ "five",
860
+ "fix",
861
+ "floor",
862
+ "florida",
863
+ "football",
864
+ "four",
865
+ "fourteen",
866
+ "foxtrot",
867
+ "freddie",
868
+ "friend",
869
+ "fruit",
870
+ "gee",
871
+ "georgia",
872
+ "glucose",
873
+ "golf",
874
+ "green",
875
+ "grey",
876
+ "hamper",
877
+ "happy",
878
+ "harry",
879
+ "hawaii",
880
+ "helium",
881
+ "high",
882
+ "hot",
883
+ "hotel",
884
+ "hydrogen",
885
+ "idaho",
886
+ "illinois",
887
+ "india",
888
+ "indigo",
889
+ "ink",
890
+ "iowa",
891
+ "island",
892
+ "item",
893
+ "jersey",
894
+ "jig",
895
+ "johnny",
896
+ "juliet",
897
+ "july",
898
+ "jupiter",
899
+ "kansas",
900
+ "kentucky",
901
+ "kilo",
902
+ "king",
903
+ "kitten",
904
+ "lactose",
905
+ "lake",
906
+ "lamp",
907
+ "lemon",
908
+ "leopard",
909
+ "lima",
910
+ "lion",
911
+ "lithium",
912
+ "london",
913
+ "louisiana",
914
+ "low",
915
+ "magazine",
916
+ "magnesium",
917
+ "maine",
918
+ "mango",
919
+ "march",
920
+ "mars",
921
+ "maryland",
922
+ "massachusetts",
923
+ "may",
924
+ "mexico",
925
+ "michigan",
926
+ "mike",
927
+ "minnesota",
928
+ "mirror",
929
+ "mississippi",
930
+ "missouri",
931
+ "mobile",
932
+ "mockingbird",
933
+ "monkey",
934
+ "montana",
935
+ "moon",
936
+ "mountain",
937
+ "muppet",
938
+ "music",
939
+ "nebraska",
940
+ "neptune",
941
+ "network",
942
+ "nevada",
943
+ "nine",
944
+ "nineteen",
945
+ "nitrogen",
946
+ "north",
947
+ "november",
948
+ "nuts",
949
+ "october",
950
+ "ohio",
951
+ "oklahoma",
952
+ "one",
953
+ "orange",
954
+ "oranges",
955
+ "oregon",
956
+ "oscar",
957
+ "oven",
958
+ "oxygen",
959
+ "papa",
960
+ "paris",
961
+ "pasta",
962
+ "pennsylvania",
963
+ "pip",
964
+ "pizza",
965
+ "pluto",
966
+ "potato",
967
+ "princess",
968
+ "purple",
969
+ "quebec",
970
+ "queen",
971
+ "quiet",
972
+ "red",
973
+ "river",
974
+ "robert",
975
+ "robin",
976
+ "romeo",
977
+ "rugby",
978
+ "sad",
979
+ "salami",
980
+ "saturn",
981
+ "september",
982
+ "seven",
983
+ "seventeen",
984
+ "shade",
985
+ "sierra",
986
+ "single",
987
+ "sink",
988
+ "six",
989
+ "sixteen",
990
+ "skylark",
991
+ "snake",
992
+ "social",
993
+ "sodium",
994
+ "solar",
995
+ "south",
996
+ "spaghetti",
997
+ "speaker",
998
+ "spring",
999
+ "stairway",
1000
+ "steak",
1001
+ "stream",
1002
+ "summer",
1003
+ "sweet",
1004
+ "table",
1005
+ "tango",
1006
+ "ten",
1007
+ "tennessee",
1008
+ "tennis",
1009
+ "texas",
1010
+ "thirteen",
1011
+ "three",
1012
+ "timing",
1013
+ "triple",
1014
+ "twelve",
1015
+ "twenty",
1016
+ "two",
1017
+ "uncle",
1018
+ "undress",
1019
+ "uniform",
1020
+ "uranus",
1021
+ "utah",
1022
+ "vegan",
1023
+ "venus",
1024
+ "vermont",
1025
+ "victor",
1026
+ "video",
1027
+ "violet",
1028
+ "virginia",
1029
+ "washington",
1030
+ "west",
1031
+ "whiskey",
1032
+ "white",
1033
+ "william",
1034
+ "winner",
1035
+ "winter",
1036
+ "wisconsin",
1037
+ "wolfram",
1038
+ "wyoming",
1039
+ "xray",
1040
+ "yankee",
1041
+ "yellow",
1042
+ "zebra",
1043
+ "zulu"
1044
+ ];
1045
+ /**
1046
+ * humanhash: Human-readable representations of digests.
1047
+ */
1048
+ var HumanHasher = class {
1049
+ wordlist;
1050
+ /**
1051
+ * Transforms hex digests to human-readable strings.
1052
+ *
1053
+ * The format of these strings will look something like:
1054
+ * `victor-bacon-zulu-lima`. The output is obtained by compressing the input
1055
+ * digest to a fixed number of bytes, then mapping those bytes to one of 256
1056
+ * words. A default wordlist is provided, but you can override this if you
1057
+ * prefer.
1058
+ * As long as you use the same wordlist, the output will be consistent (i.e.
1059
+ * the same digest will always render the same representation).
1060
+ *
1061
+ * @param wordlist A list of exactly 256 words to choose from
1062
+ */
1063
+ constructor(wordlist = DEFAULT_WORDLIST) {
1064
+ this.wordlist = wordlist;
1065
+ if (wordlist.length !== 256) throw new Error("Wordlist must have exactly 256 items");
1066
+ this.wordlist = wordlist;
1067
+ }
1068
+ /**
1069
+ * Humanize a given hexadecimal digest.
1070
+ *
1071
+ * Change the number of words output by specifying `words`. Change the
1072
+ * word separator with `separator`.
1073
+ *
1074
+ * @param hexdigest A string of hexadecimal characters to humanize
1075
+ * @param words How many words to output (more = safer)
1076
+ * @param separator The string used to seperate the words
1077
+ */
1078
+ humanize(hexdigest, words = 4, separator = "-") {
1079
+ const pairs = hexdigest.match(/(..?)/g);
1080
+ if (!pairs) throw new Error("");
1081
+ const bytes = pairs.map((x) => parseInt(x, 16));
1082
+ return this._compress(bytes, words).map((x) => this.wordlist[x]).join(separator);
1083
+ }
1084
+ /**
1085
+ * Compress a list of byte values to a fixed target length.
1086
+ *
1087
+ * @param bytes A list of bytes (numbers from 0-254)
1088
+ * @param target The number of bytes to return / compress to
1089
+ */
1090
+ _compress(bytes, target) {
1091
+ const length = bytes.length;
1092
+ if (target > length) throw new Error("Fewer input bytes than requested output");
1093
+ const segSize = length / target >> 0;
1094
+ const segments = [];
1095
+ for (let i = 0; i < segSize * target; i += segSize) segments.push(bytes.slice(i, i + segSize));
1096
+ segments[segments.length - 1] = segments[segments.length - 1].concat(bytes.slice(target * segSize));
1097
+ return segments.map((x) => x.reduce((acc, curr) => acc ^ curr));
1098
+ }
1099
+ };
1100
+ var hasher = new HumanHasher();
1101
+ var humanize = (value) => {
1102
+ if (value instanceof Buffer || value instanceof Uint8Array || value instanceof ArrayBuffer) value = PublicKey.stringify(value);
1103
+ else if (value instanceof PublicKey) value = value.toHex();
1104
+ return hasher.humanize(value);
1105
+ };
1106
+ //#endregion
1107
+ //#region src/id.ts
1108
+ var PART = /^[a-zA-Z][a-zA-Z0-9]{0,62}$/;
1109
+ var ID = /^[a-zA-Z]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(\.[a-zA-Z]([a-zA-Z0-9]{0,62})?)$/;
1110
+ /**
1111
+ * Tagged template literal that constructs a well-formed, dot-delimited id string.
1112
+ * Throws if the resulting string is not well-formed.
1113
+ *
1114
+ * Follows the AT Protocol NSID convention (https://atproto.com/specs/nsid)
1115
+ * Full NSID: authority segments (hyphens allowed) + dot + name segment (no hyphens).
1116
+ * - Authority segments: at most 253 characters (including periods), and must contain at least two segments.
1117
+ * - Name segment: starts with alpha, alphanumeric only (no hyphens), max 63 chars.
1118
+ *
1119
+ * @example
1120
+ * id`org.dxos.plugin.deck` // 'org.dxos.plugin.deck'
1121
+ * id`${ns}.${plugin}.deck` // joins interpolated values
1122
+ */
1123
+ function id(strings, ...values) {
1124
+ const raw = strings.reduce((out, str, i) => out + str + (i < values.length ? String(values[i]) : ""), "");
1125
+ if (!ID.test(raw)) throw new Error(`Invalid id (expected AT Protocol NSID): ${JSON.stringify(raw)}`);
1126
+ return raw;
1127
+ }
1128
+ /**
1129
+ * Returns true if the given string is a well-formed NSID.
1130
+ */
1131
+ var isWellFormedId = (value) => ID.test(value);
1132
+ /**
1133
+ * Returns true if the given string is a well-formed NSID name segment:
1134
+ * `/^[a-zA-Z][a-zA-Z0-9]{0,62}$/` (starts with alpha, alphanumeric only, no dots or hyphens).
1135
+ */
1136
+ var isWellFormedIdPart = (value) => PART.test(value);
1137
+ //#endregion
1138
+ //#region src/map.ts
1139
+ /**
1140
+ * Get or set map value.
1141
+ */
1142
+ var defaultMap = (map, key, def) => {
1143
+ let value = map.get(key);
1144
+ if (value === void 0) {
1145
+ value = typeof def === "function" ? def() : def;
1146
+ map.set(key, value);
1147
+ }
1148
+ return value;
1149
+ };
1150
+ //#endregion
1151
+ //#region src/instance-id.ts
1152
+ var symbol = Symbol.for("dxos.instance-contexts");
1153
+ var instanceContexts = globalThis[symbol] ??= /* @__PURE__ */ new WeakMap();
1154
+ /**
1155
+ * Returns a unique instance id for a given object.
1156
+ * Ids are generated as incrementing numbers.
1157
+ * Ids are only unique within the scope of a given prototype.
1158
+ * Instances of different classes may have the same id.
1159
+ */
1160
+ var getPrototypeSpecificInstanceId = (instance) => {
1161
+ const instanceCtx = defaultMap(instanceContexts, Object.getPrototypeOf(instance), () => ({
1162
+ nextId: 0,
1163
+ instanceIds: /* @__PURE__ */ new WeakMap()
1164
+ }));
1165
+ let id = instanceCtx.instanceIds.get(instance);
1166
+ if (id === void 0) {
1167
+ id = instanceCtx.nextId++;
1168
+ instanceCtx.instanceIds.set(instance, id);
1169
+ }
1170
+ return id;
1171
+ };
1172
+ var getDebugName = (instance) => {
1173
+ if (instance == null) return "null";
1174
+ return `${Object.getPrototypeOf(instance).constructor?.name ?? "Object"}#${getPrototypeSpecificInstanceId(instance)}`;
1175
+ };
1176
+ //#endregion
1177
+ //#region src/interval.ts
1178
+ /**
1179
+ * Runs the callback in an exponentially increasing interval.
1180
+ * @returns Callback to clear the interval.
1181
+ */
1182
+ var exponentialBackoffInterval = (cb, initialInterval) => {
1183
+ let interval = initialInterval;
1184
+ const repeat = () => {
1185
+ cb();
1186
+ interval *= 2;
1187
+ timeoutId = setTimeout(repeat, interval);
1188
+ };
1189
+ let timeoutId = setTimeout(repeat, interval);
1190
+ return () => clearTimeout(timeoutId);
1191
+ };
1192
+ //#endregion
1193
+ //#region src/join-tables.ts
1194
+ /**
1195
+ * Joins two untyped tables on the given columns.
1196
+ * @param leftColumn The column to join on in the first table.
1197
+ * @param rightColumn The column to join on in the second table.
1198
+ */
1199
+ var joinTables = (leftColumn, rightColumn, left, right) => {
1200
+ const map = /* @__PURE__ */ new Map();
1201
+ const used = /* @__PURE__ */ new Set();
1202
+ for (const row of right) map.set(row[rightColumn], row);
1203
+ const result = [];
1204
+ for (const row of left) {
1205
+ const right = map.get(row[leftColumn]);
1206
+ used.add(right);
1207
+ result.push(Object.assign(right ?? {}, row));
1208
+ }
1209
+ for (const row of right) if (!used.has(row)) result.push(row);
1210
+ return result;
1211
+ };
1212
+ //#endregion
1213
+ //#region src/uint8array.ts
1214
+ var arraysEqual = (a, b) => {
1215
+ if (a.length !== b.length) return false;
1216
+ for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
1217
+ return true;
1218
+ };
1219
+ /**
1220
+ * Non-copying conversion of Uint8Array to Buffer.
1221
+ * The resulting buffer will share the same allocated memory as the Uint8Array.
1222
+ */
1223
+ var arrayToBuffer = (array) => {
1224
+ return Buffer.from(array.buffer, array.byteOffset, array.byteLength);
1225
+ };
1226
+ /**
1227
+ * Non-copying conversion of Buffer to Uint8Array.
1228
+ * The resulting Uint8Array will share the same allocated memory as the Buffer.
1229
+ */
1230
+ var bufferToArray = (buffer) => {
1231
+ return new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
1232
+ };
1233
+ var stringToArray = (string) => bufferToArray(Buffer.from(string, "hex"));
1234
+ var arrayToString = (array) => arrayToBuffer(array).toString("hex");
1235
+ var toUnpaddedBase64 = (bytes) => arrayToBuffer(bytes).toString("base64").replace(/=+$/, "");
1236
+ /**
1237
+ * Encode a `Uint8Array` as the DAG-JSON bytes form `{ '/': { bytes: '<base64-no-padding>' } }`.
1238
+ */
1239
+ var encodeUint8ArrayToJson = (bytes) => ({ "/": { bytes: toUnpaddedBase64(bytes) } });
1240
+ /**
1241
+ * Type-guard that returns true iff `value` is the DAG-JSON bytes form produced by
1242
+ * {@link encodeUint8ArrayToJson} — an object with exactly one key `'/'` whose value is an
1243
+ * object with exactly one string key `bytes`.
1244
+ */
1245
+ var isEncodedUint8Array = (value) => {
1246
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
1247
+ if (Object.keys(value).length !== 1) return false;
1248
+ const inner = value["/"];
1249
+ if (typeof inner !== "object" || inner === null || Array.isArray(inner)) return false;
1250
+ return Object.keys(inner).length === 1 && typeof inner.bytes === "string";
1251
+ };
1252
+ /**
1253
+ * Decode a DAG-JSON bytes form (as produced by {@link encodeUint8ArrayToJson}) back to a
1254
+ * `Uint8Array`. The base64 string is tolerated with or without padding.
1255
+ */
1256
+ var decodeUint8ArrayFromJson = (encoded) => bufferToArray(Buffer.from(encoded["/"].bytes, "base64"));
1257
+ //#endregion
1258
+ //#region src/json.ts
1259
+ var MAX_DEPTH = 5;
1260
+ var LOG_MAX_DEPTH = 7;
1261
+ /**
1262
+ * JSON.stringify replacer.
1263
+ */
1264
+ var jsonReplacer = (key, value) => {
1265
+ if (value !== null && typeof value === "object" && typeof value[inspect.custom] === "function") return value[inspect.custom]();
1266
+ if (value !== null && typeof value === "object" && value.type === "Buffer" && Array.isArray(value.data)) if (value.data.length === 32) {
1267
+ const key = Buffer.from(value.data);
1268
+ return `[${humanize(key)}]:[${PublicKey.stringify(key)}]`;
1269
+ } else return Buffer.from(value.data).toString("hex");
1270
+ return value;
1271
+ };
1272
+ /**
1273
+ * Recursively converts an object into a JSON-compatible object.
1274
+ */
1275
+ var jsonify = (value, depth = 0, visitedObjects = /* @__PURE__ */ new WeakSet()) => {
1276
+ if (depth > MAX_DEPTH) return null;
1277
+ else if (typeof value === "function") return null;
1278
+ else if (typeof value === "object" && value !== null) {
1279
+ if (visitedObjects.has(value)) return null;
1280
+ visitedObjects.add(value);
1281
+ try {
1282
+ if (value instanceof Uint8Array) return arrayToBuffer(value).toString("hex");
1283
+ else if (Array.isArray(value)) return value.map((x) => jsonify(x, depth + 1, visitedObjects));
1284
+ else if (typeof value.toJSON === "function") return value.toJSON();
1285
+ else {
1286
+ const res = {};
1287
+ for (const key of Object.keys(value)) res[key] = jsonify(value[key], depth + 1, visitedObjects);
1288
+ return res;
1289
+ }
1290
+ } finally {
1291
+ visitedObjects.delete(value);
1292
+ }
1293
+ } else return value;
1294
+ };
1295
+ /**
1296
+ * Recursively converts an object into a JSON-compatible object appropriate for logging.
1297
+ */
1298
+ var jsonlogify = (value, depth = 0, visitedObjects = /* @__PURE__ */ new WeakSet()) => {
1299
+ if (depth > LOG_MAX_DEPTH) return null;
1300
+ else if (typeof value === "function") return null;
1301
+ else if (typeof value === "object" && value !== null) {
1302
+ if (visitedObjects.has(value)) return null;
1303
+ visitedObjects.add(value);
1304
+ try {
1305
+ if (value instanceof Uint8Array) return arrayToBuffer(value).toString("hex");
1306
+ else if (Array.isArray(value)) return value.map((x) => jsonlogify(x, depth + 1, visitedObjects));
1307
+ else if (typeof value.toJSONL === "function") return value.toJSONL();
1308
+ else if (typeof value.toJSON === "function") return value.toJSON();
1309
+ else {
1310
+ const res = {};
1311
+ for (const key of Object.keys(value)) res[key] = jsonlogify(value[key], depth + 1, visitedObjects);
1312
+ return res;
1313
+ }
1314
+ } finally {
1315
+ visitedObjects.delete(value);
1316
+ }
1317
+ } else return value;
1318
+ };
1319
+ var jsonKeyReplacer = (options = {}) => (key, value) => {
1320
+ if (typeof value === "string") {
1321
+ const key = PublicKey.fromHex(value);
1322
+ if (key.toHex() === value) return options.humanize ? humanize(key) : options.truncate ? key.truncate() : key.toHex();
1323
+ }
1324
+ return value;
1325
+ };
1326
+ //#endregion
1327
+ //#region src/map-values.ts
1328
+ var mapValues = (obj, fn) => {
1329
+ const result = {};
1330
+ Object.keys(obj).forEach((key) => {
1331
+ result[key] = fn(obj[key], key);
1332
+ });
1333
+ return result;
1334
+ };
1335
+ /**
1336
+ * Recursively maps values traversing arrays and objects.
1337
+ * @param fn Function to apply to each value. Second argument is a function to recurse into the value.
1338
+ */
1339
+ var deepMapValues = (value, fn) => {
1340
+ return new DeepMapper(fn).map(value);
1341
+ };
1342
+ var DeepMapper = class {
1343
+ _fn;
1344
+ _cyclic = /* @__PURE__ */ new Map();
1345
+ constructor(_fn) {
1346
+ this._fn = _fn;
1347
+ }
1348
+ map(value) {
1349
+ return this._map(value, void 0);
1350
+ }
1351
+ _map(value, key) {
1352
+ if (this._cyclic.has(value)) return this._cyclic.get(value);
1353
+ return this._fn(value, this._recurse, key);
1354
+ }
1355
+ _recurse = (value) => {
1356
+ if (this._cyclic.has(value)) return this._cyclic.get(value);
1357
+ if (Array.isArray(value)) {
1358
+ const res = new Array(value.length);
1359
+ this._cyclic.set(value, res);
1360
+ for (let i = 0; i < value.length; i++) res[i] = this._map(value[i], i);
1361
+ return res;
1362
+ } else if (ArrayBuffer.isView(value)) return value;
1363
+ else if (value !== null && typeof value === "object") {
1364
+ const res = {};
1365
+ this._cyclic.set(value, res);
1366
+ for (const key in value) res[key] = this._map(value[key], key);
1367
+ return res;
1368
+ } else return value;
1369
+ };
1370
+ };
1371
+ /**
1372
+ * Recursively maps values traversing arrays and objects.
1373
+ * @param fn Function to apply to each value. Second argument is a function to recurse into the value.
1374
+ * Async version.
1375
+ */
1376
+ var deepMapValuesAsync = (value, fn) => {
1377
+ return new DeepMapperAsync(fn).map(value);
1378
+ };
1379
+ var DeepMapperAsync = class {
1380
+ _fn;
1381
+ _cyclic = /* @__PURE__ */ new Map();
1382
+ constructor(_fn) {
1383
+ this._fn = _fn;
1384
+ }
1385
+ map(value) {
1386
+ return this._map(value, void 0);
1387
+ }
1388
+ _map(value, key) {
1389
+ if (this._cyclic.has(value)) return this._cyclic.get(value);
1390
+ return this._fn(value, this._recurse, key);
1391
+ }
1392
+ _recurse = async (value) => {
1393
+ if (this._cyclic.has(value)) return this._cyclic.get(value);
1394
+ if (Array.isArray(value)) {
1395
+ const res = new Array(value.length);
1396
+ this._cyclic.set(value, res);
1397
+ for (let i = 0; i < value.length; i++) res[i] = await this._map(value[i], i);
1398
+ return res;
1399
+ } else if (ArrayBuffer.isView(value)) return value;
1400
+ else if (value !== null && typeof value === "object") {
1401
+ const res = {};
1402
+ this._cyclic.set(value, res);
1403
+ for (const key in value) res[key] = await this._map(value[key], key);
1404
+ return res;
1405
+ } else return value;
1406
+ };
1407
+ };
1408
+ /**
1409
+ * Visits all values on an object or every item in an array.
1410
+ * No-op if the value is not an object or array.
1411
+ */
1412
+ var visitValues = (object, visitor) => {
1413
+ if (Array.isArray(object)) object.forEach((item, index) => visitor(item, index));
1414
+ else if (typeof object === "object" && object !== null) for (const [key, value] of Object.entries(object)) visitor(value, key);
1415
+ };
1416
+ //#endregion
1417
+ //#region src/object.ts
1418
+ /**
1419
+ * @deprecated Use `Struct.keys` from effect.
1420
+ */
1421
+ var keys = (obj) => Object.keys(obj);
1422
+ var entries = (obj) => Object.entries(obj);
1423
+ //#endregion
1424
+ //#region src/order-keys.ts
1425
+ var orderKeys = (obj, order) => {
1426
+ const ordered = {};
1427
+ for (const key of order) if (key in obj) ordered[key] = obj[key];
1428
+ for (const key in obj) if (!(key in ordered)) ordered[key] = obj[key];
1429
+ return ordered;
1430
+ };
1431
+ //#endregion
1432
+ //#region src/order.ts
1433
+ /**
1434
+ * Uses an array of string id’s to order a map of objects, returning an array of those objects. Objects not listed by
1435
+ * the array of id’s occur later in the resulting array of objects based on the map’s key order.
1436
+ * @param objectMap
1437
+ * @param order
1438
+ */
1439
+ var inferObjectOrder = (objectMap, order = []) => {
1440
+ const orderedObjects = order.reduce((acc, id) => {
1441
+ if (id in objectMap) {
1442
+ acc.objects.push(objectMap[id]);
1443
+ acc.ids.add(id);
1444
+ }
1445
+ return acc;
1446
+ }, {
1447
+ objects: [],
1448
+ ids: /* @__PURE__ */ new Set()
1449
+ });
1450
+ const { objects } = Object.keys(objectMap).reduce((acc, id) => {
1451
+ if (!acc.ids.has(id)) acc.objects.push(objectMap[id]);
1452
+ return acc;
1453
+ }, orderedObjects);
1454
+ return objects;
1455
+ };
1456
+ /**
1457
+ * Uses an array of string id’s to order a map of objects, returning a new map with the keys in the prescribed order.
1458
+ * Objects not listed by the array of id’s occur later in the resulting array of objects based on the map’s key order.
1459
+ * @param objectMap
1460
+ * @param order
1461
+ */
1462
+ var inferRecordOrder = (objectMap, order = []) => {
1463
+ return Object.assign(order.filter((id) => id in objectMap).reduce((acc, id) => {
1464
+ acc[id] = null;
1465
+ return acc;
1466
+ }, {}), objectMap);
1467
+ };
1468
+ //#endregion
1469
+ //#region src/pick.ts
1470
+ /**
1471
+ * Creates an object composed of the object properties predicate returns truthy for.
1472
+ */
1473
+ var pick = (obj, keys) => {
1474
+ return keys.reduce((result, key) => {
1475
+ if (obj && key in obj) result[key] = obj[key];
1476
+ return result;
1477
+ }, {});
1478
+ };
1479
+ /**
1480
+ * Creates an object composed of the object properties predicate returns truthy for.
1481
+ */
1482
+ var pickBy = (obj, predicate) => {
1483
+ const result = {};
1484
+ for (const key in obj) if (predicate(obj[key])) result[key] = obj[key];
1485
+ return result;
1486
+ };
1487
+ /**
1488
+ * Omit given props.
1489
+ * @param obj
1490
+ * @param keys
1491
+ */
1492
+ var omit = (obj, keys) => {
1493
+ const result = { ...obj };
1494
+ keys.forEach((key) => {
1495
+ delete result[key];
1496
+ });
1497
+ return result;
1498
+ };
1499
+ //#endregion
1500
+ //#region src/platform.ts
1501
+ var isNode = () => typeof process !== "undefined" && process.versions != null && process.versions.node != null;
1502
+ var isBun = () => globalThis.Bun !== void 0;
1503
+ var isTauri = () => !!globalThis.__TAURI__;
1504
+ var isMobile = () => {
1505
+ let check = false;
1506
+ (function(a) {
1507
+ if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4))) check = true;
1508
+ })(navigator.userAgent || navigator.vendor || window.opera);
1509
+ return check;
1510
+ };
1511
+ var isMobileOrTablet = () => {
1512
+ let check = false;
1513
+ ((a) => {
1514
+ if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4))) check = true;
1515
+ })(navigator.userAgent || navigator.vendor || window.opera);
1516
+ return check;
1517
+ };
1518
+ var iosCheck = () => {
1519
+ return [
1520
+ "iPad Simulator",
1521
+ "iPhone Simulator",
1522
+ "iPod Simulator",
1523
+ "iPad",
1524
+ "iPhone",
1525
+ "iPod"
1526
+ ].includes(navigator.platform) || navigator.userAgent.includes("Mac") && "ontouchend" in document;
1527
+ };
1528
+ var safariCheck = () => typeof navigator !== "undefined" && /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
1529
+ /**
1530
+ * Retrieve the host platform in a best-effort way with normalized output.
1531
+ */
1532
+ var getHostPlatform = () => {
1533
+ if (!("navigator" in globalThis)) return "unknown";
1534
+ const platform = (navigator.userAgentData?.platform || navigator.platform)?.toLowerCase();
1535
+ if (platform.startsWith("win")) return "windows";
1536
+ else if (platform.startsWith("mac")) return "macos";
1537
+ else if (platform.startsWith("ipad") || platform.startsWith("iphone") || platform.startsWith("ipod")) return "ios";
1538
+ else if (platform.startsWith("linux")) return "linux";
1539
+ else return "unknown";
1540
+ };
1541
+ //#endregion
1542
+ //#region src/Position.ts
1543
+ var Position_exports = /* @__PURE__ */ __exportAll({
1544
+ compare: () => compare,
1545
+ first: () => first,
1546
+ last: () => last
1547
+ });
1548
+ var first = -Infinity;
1549
+ var last = Infinity;
1550
+ /**
1551
+ * Comparator for sorting by position.
1552
+ */
1553
+ var compare = ({ position: a }, { position: b }) => {
1554
+ const aVal = a ?? 0;
1555
+ const bVal = b ?? 0;
1556
+ if (aVal === bVal) return 0;
1557
+ return aVal < bVal ? -1 : 1;
1558
+ };
1559
+ //#endregion
1560
+ //#region src/random.ts
1561
+ var randomInt = (max, min = 0) => {
1562
+ min = Math.ceil(min);
1563
+ max = Math.floor(max);
1564
+ return Math.floor(Math.random() * (max - min + 1)) + min;
1565
+ };
1566
+ //#endregion
1567
+ //#region src/range.ts
1568
+ var range = (n = 0, mapper) => {
1569
+ const range = Array.from(Array(n).keys());
1570
+ return mapper == null ? range : range.map(mapper);
1571
+ };
1572
+ var rangeFromTo = (from, to, mapper) => {
1573
+ return mapper == null ? range(to - from, (i) => i + from) : range(to - from, (i) => mapper(i + from));
1574
+ };
1575
+ /**
1576
+ * Clamps a value between a minimum and maximum value.
1577
+ */
1578
+ var clamp = (value, min, max) => {
1579
+ return Math.min(Math.max(value, min), max);
1580
+ };
1581
+ //#endregion
1582
+ //#region src/reducers.ts
1583
+ var accessBy = (value, accessor) => typeof accessor === "function" ? accessor(value) : value[accessor];
1584
+ var median = (values) => {
1585
+ const mid = Math.floor(values.length / 2);
1586
+ if (values.length % 2 === 1) return values[mid];
1587
+ else return (values[mid - 1] + values[mid]) / 2;
1588
+ };
1589
+ /**
1590
+ * Returns an array of unique values.
1591
+ */
1592
+ var numericalValues = (values, accessor) => {
1593
+ const result = {
1594
+ total: 0,
1595
+ count: 0
1596
+ };
1597
+ const sorted = values.map((value) => {
1598
+ const v = accessBy(value, accessor);
1599
+ if (v === void 0 || isNaN(v)) return;
1600
+ result.total += v;
1601
+ if (result.min === void 0 || v < result.min) result.min = v;
1602
+ if (result.max === void 0 || v > result.max) result.max = v;
1603
+ return v;
1604
+ }).filter((value) => value !== void 0).sort((a, b) => a - b);
1605
+ if (sorted.length) Object.assign(result, {
1606
+ count: sorted.length,
1607
+ mean: result.total / sorted.length,
1608
+ median: median(sorted)
1609
+ });
1610
+ return result;
1611
+ };
1612
+ /**
1613
+ * Returns an array of unique values.
1614
+ */
1615
+ var reduceSet = (values, accessor) => {
1616
+ return values.reduce((values, value) => {
1617
+ const v = accessBy(value, accessor);
1618
+ values.add(v);
1619
+ return values;
1620
+ }, /* @__PURE__ */ new Set());
1621
+ };
1622
+ /**
1623
+ * Returns an object containing values grouped by the given key accessor.
1624
+ */
1625
+ var reduceGroupBy = (values, accessor) => {
1626
+ return values.reduce((values, value) => {
1627
+ defaultMap(values, accessBy(value, accessor), []).push(value);
1628
+ return values;
1629
+ }, /* @__PURE__ */ new Map());
1630
+ };
1631
+ /**
1632
+ * Applies the reducer to the array of values.
1633
+ */
1634
+ var reduceSeries = (reducer, events) => {
1635
+ const state = reducer.initialState();
1636
+ for (const event of events) reducer.reduce(state, event);
1637
+ return state;
1638
+ };
1639
+ /**
1640
+ * Reducer to group values.
1641
+ */
1642
+ var createGroupReducer = (groupBy, sub) => ({
1643
+ initialState: () => ({}),
1644
+ reduce: (state, event) => {
1645
+ const key = groupBy(event);
1646
+ state[key] = sub.reduce(state[key] ?? sub.initialState(), event);
1647
+ return state;
1648
+ }
1649
+ });
1650
+ var getDate = (value) => value instanceof Date ? value : new Date(value);
1651
+ /**
1652
+ * Reducer to group by time period.
1653
+ */
1654
+ var createBucketReducer = (period) => ({
1655
+ initialState: () => [],
1656
+ reduce: (series, event) => {
1657
+ const timestamp = getDate(event.timestamp);
1658
+ let bucket = series[series.length - 1];
1659
+ if (!bucket || bucket.start + period < timestamp.getTime()) {
1660
+ bucket = {
1661
+ start: timestamp.getTime(),
1662
+ period,
1663
+ count: 0
1664
+ };
1665
+ series.push(bucket);
1666
+ }
1667
+ bucket.count++;
1668
+ return series;
1669
+ }
1670
+ });
1671
+ //#endregion
1672
+ //#region src/remove-undefined-keys.ts
1673
+ var removeUndefinedProperties = (object) => {
1674
+ for (const prop of [...Object.getOwnPropertyNames(object), ...Object.getOwnPropertySymbols(object)]) if (object[prop] === void 0) delete object[prop];
1675
+ return object;
1676
+ };
1677
+ /**
1678
+ * Recursively remove properties from the object, returning the modified object.
1679
+ */
1680
+ var removeProperties = (root, condition) => {
1681
+ if (!root || typeof root !== "object") return root;
1682
+ if (Array.isArray(root)) return root.map((item) => removeProperties(item, condition));
1683
+ const result = { ...root };
1684
+ if (typeof condition === "function") {
1685
+ for (const [key, value] of Object.entries(result)) if (condition(key, value)) delete result[key];
1686
+ } else for (const key of condition) delete result[key];
1687
+ for (const [key, value] of Object.entries(result)) if (typeof value === "object") result[key] = removeProperties(value, condition);
1688
+ return result;
1689
+ };
1690
+ //#endregion
1691
+ //#region src/retry.ts
1692
+ var DEFAULT_RETRY_OPTIONS = {
1693
+ count: 3,
1694
+ delayMs: 100,
1695
+ exponent: 2,
1696
+ retryOnError: async () => true,
1697
+ retryOnValue: async () => false
1698
+ };
1699
+ /**
1700
+ * Retries the operation a number of times.
1701
+ * @returns The result of the succesfull invocation
1702
+ * @throws Last error if all retries failed
1703
+ */
1704
+ var retry = async (options, cb) => {
1705
+ const fullOptions = {
1706
+ ...DEFAULT_RETRY_OPTIONS,
1707
+ ...options
1708
+ };
1709
+ let numRetries = 0, currentDelay = fullOptions.delayMs;
1710
+ while (true) {
1711
+ let result;
1712
+ try {
1713
+ result = await cb();
1714
+ } catch (err) {
1715
+ if (numRetries > fullOptions.count || !await fullOptions.retryOnError(err)) throw err;
1716
+ await new Promise((resolve) => setTimeout(resolve, currentDelay));
1717
+ currentDelay *= fullOptions.exponent;
1718
+ numRetries++;
1719
+ continue;
1720
+ }
1721
+ if (!await fullOptions.retryOnValue(result)) return result;
1722
+ await new Promise((resolve) => setTimeout(resolve, currentDelay));
1723
+ currentDelay *= fullOptions.exponent;
1724
+ numRetries++;
1725
+ continue;
1726
+ }
1727
+ };
1728
+ //#endregion
1729
+ //#region src/safe-await.ts
1730
+ /**
1731
+ * A utility for safely performing an asynchronous action on every item from source.
1732
+ * @param source elements passed to taskFactory.
1733
+ * @param taskFactory a function that converts an elements into an async task.
1734
+ * @param onError if provided will be called for every failed task.
1735
+ * @returns elements for which task execution failed.
1736
+ */
1737
+ var safeAwaitAll = async (source, taskFactory, onError) => {
1738
+ const failedItems = [];
1739
+ await Promise.all([...source].map(async (item, idx) => {
1740
+ try {
1741
+ await taskFactory(item);
1742
+ } catch (err) {
1743
+ if (onError) onError(err, item, idx);
1744
+ failedItems.push(item);
1745
+ }
1746
+ }));
1747
+ return failedItems;
1748
+ };
1749
+ //#endregion
1750
+ //#region src/safe-instanceof.ts
1751
+ var instanceTag = Symbol("instanceTag");
1752
+ /**
1753
+ * Makes instanceof work correctly even if the class definition was duplicated (e.g. when bundling).
1754
+ * The comparison is done by comparing the tag passed to this function.
1755
+ *
1756
+ * Example:
1757
+ *
1758
+ * ```typescript
1759
+ * @safeInstanceof('Tagged')
1760
+ * class Tagged {}
1761
+ * ```
1762
+ */
1763
+ var safeInstanceof = (tag) => (target) => {
1764
+ target.prototype[instanceTag] = tag;
1765
+ Object.defineProperty(target.prototype, Symbol.hasInstance, { value: (instance) => instance?.[instanceTag] === tag });
1766
+ Object.defineProperty(target, Symbol.hasInstance, { value: (instance) => instance?.[instanceTag] === tag });
1767
+ };
1768
+ //#endregion
1769
+ //#region src/safe-parse.ts
1770
+ function safeParseInt(str, defaultValue) {
1771
+ try {
1772
+ const value = parseInt(str ?? "");
1773
+ return isNaN(value) ? defaultValue : value;
1774
+ } catch {
1775
+ return defaultValue;
1776
+ }
1777
+ }
1778
+ function safeParseFloat(str, defaultValue) {
1779
+ try {
1780
+ const value = parseFloat(str ?? "");
1781
+ return isNaN(value) ? defaultValue : value;
1782
+ } catch {
1783
+ return defaultValue;
1784
+ }
1785
+ }
1786
+ var safeParseJson = (str, defaultValue) => {
1787
+ if (str && str.length > 0) try {
1788
+ return JSON.parse(str);
1789
+ } catch {}
1790
+ return defaultValue;
1791
+ };
1792
+ var safeUrl = (str) => {
1793
+ try {
1794
+ return new URL(str ?? "");
1795
+ } catch {
1796
+ return;
1797
+ }
1798
+ };
1799
+ //#endregion
1800
+ //#region src/safe-stringify.ts
1801
+ var SKIP = Object.freeze({});
1802
+ /**
1803
+ * Safely stringifies an object.
1804
+ */
1805
+ function safeStringify(obj, filter = defaultFilter, indent = 2) {
1806
+ const seen = /* @__PURE__ */ new WeakMap();
1807
+ function replacer(key, value) {
1808
+ try {
1809
+ let path = key;
1810
+ if (!key) {
1811
+ path = "$";
1812
+ if (value != null && typeof value === "object") seen.set(value, path);
1813
+ return value;
1814
+ } else if (this) {
1815
+ const parentPath = seen.get(this);
1816
+ path = parentPath ? `${parentPath}.${key}` : key;
1817
+ }
1818
+ if (value == null) return value;
1819
+ if (typeof value === "function") return;
1820
+ if (typeof value === "object" && Object.getPrototypeOf(value) !== Object.prototype && !Array.isArray(value)) return;
1821
+ if (typeof value === "object" && value !== null) {
1822
+ const exists = seen.get(value);
1823
+ if (exists) return `[${path} => ${exists}]`;
1824
+ seen.set(value, path);
1825
+ }
1826
+ if (filter) {
1827
+ const filteredValue = filter?.(key, value);
1828
+ if (filteredValue !== void 0) return filteredValue === SKIP ? void 0 : filteredValue;
1829
+ }
1830
+ return value;
1831
+ } catch (error) {
1832
+ return `ERROR: ${error.message}`;
1833
+ }
1834
+ }
1835
+ try {
1836
+ return JSON.stringify(obj, replacer, indent);
1837
+ } catch (error) {
1838
+ return `ERROR: ${error.message}`;
1839
+ }
1840
+ }
1841
+ /**
1842
+ * Construct JSON.stringify replacer.
1843
+ */
1844
+ var createReplacer = ({ omit, parse, maxDepth, maxArrayLen, maxStringLen } = {}) => {
1845
+ let currentDepth = 0;
1846
+ const depthMap = /* @__PURE__ */ new WeakMap();
1847
+ return function(key, value) {
1848
+ if (key === "") currentDepth = 0;
1849
+ else if (this && typeof this === "object") currentDepth = (depthMap.get(this) ?? 0) + 1;
1850
+ if (typeof value === "function") return SKIP;
1851
+ if (maxArrayLen != null && Array.isArray(value) && value.length > maxArrayLen) return `[length: ${value.length}]`;
1852
+ if (value && typeof value === "object") {
1853
+ depthMap.set(value, currentDepth);
1854
+ if (maxDepth != null && currentDepth >= maxDepth) return Array.isArray(value) ? `[{ length: ${value.length} }]` : `{ keys: ${Object.keys(value).length} }`;
1855
+ }
1856
+ if (omit?.includes(key)) return SKIP;
1857
+ if (parse?.includes(key) && typeof value === "string") try {
1858
+ return JSON.parse(value);
1859
+ } catch {
1860
+ return value;
1861
+ }
1862
+ if (maxStringLen != null && typeof value === "string" && value.length > maxStringLen) return value.slice(0, maxStringLen) + "...";
1863
+ return value;
1864
+ };
1865
+ };
1866
+ var defaultFilter = createReplacer();
1867
+ //#endregion
1868
+ //#region src/sliding-window-summary.ts
1869
+ var __dxlog_file = "/__w/dxos/dxos/packages/common/util/src/sliding-window-summary.ts";
1870
+ var SlidingWindowSummary = class {
1871
+ _buffer;
1872
+ _sum = 0;
1873
+ _precision;
1874
+ constructor(options) {
1875
+ this._buffer = new CircularBuffer(options.dataPoints);
1876
+ if (options.precision != null) {
1877
+ invariant(options.precision >= 0, void 0, {
1878
+ "~LogMeta": "~LogMeta",
1879
+ F: __dxlog_file,
1880
+ L: 26,
1881
+ S: this,
1882
+ A: ["options.precision >= 0", ""]
1883
+ });
1884
+ this._precision = Math.pow(10, options.precision);
1885
+ }
1886
+ }
1887
+ record(value) {
1888
+ const evicted = this._buffer.push(value);
1889
+ this._sum += value - (evicted ?? 0);
1890
+ }
1891
+ average() {
1892
+ return this._buffer.elementCount === 0 ? 0 : this._withPrecision(this._sum / this._buffer.elementCount);
1893
+ }
1894
+ computeWindowSummary() {
1895
+ const mean = this.average();
1896
+ const sortedElements = [...this._buffer].sort();
1897
+ const median = this._withPrecision(sortedElements.length % 2 === 0 ? (sortedElements[sortedElements.length / 2] + sortedElements[sortedElements.length / 2 - 1]) / 2 : sortedElements[sortedElements.length / 2]);
1898
+ const p90 = this._withPrecision(sortedElements[Math.round(sortedElements.length * .9)]);
1899
+ const variance = sortedElements.reduce((acc, v) => acc + Math.pow(v - mean, 2)) / sortedElements.length;
1900
+ return {
1901
+ mean,
1902
+ median,
1903
+ p90,
1904
+ stdDev: this._withPrecision(Math.sqrt(variance)),
1905
+ histogram: sortedElements.reduce((acc, v) => {
1906
+ acc[v] += 1;
1907
+ return acc;
1908
+ }, {})
1909
+ };
1910
+ }
1911
+ _withPrecision(value) {
1912
+ if (this._precision == null) return value;
1913
+ return Math.round(value * this._precision) / this._precision;
1914
+ }
1915
+ };
1916
+ //#endregion
1917
+ //#region src/sort.ts
1918
+ var compareScalar = (inc = true) => (a, b) => (inc ? 1 : -1) * (a < b ? -1 : a > b ? 1 : 0);
1919
+ var compareString = (inc = true, caseInsensitive = true) => (a, b) => {
1920
+ if (caseInsensitive) {
1921
+ a = a?.toLowerCase();
1922
+ b = b?.toLowerCase();
1923
+ }
1924
+ return (inc ? 1 : -1) * (a < b ? -1 : a > b ? 1 : 0);
1925
+ };
1926
+ var compareObject = (prop, sorter, inc = true) => (a, b) => (inc ? 1 : -1) * sorter(a[prop], b[prop]);
1927
+ var compareMulti = (sorters) => (a, b) => {
1928
+ const sort = (i = 0) => {
1929
+ const s = sorters[i](a, b);
1930
+ if (s === 0 && i < sorters.length - 1) return sort(i + 1);
1931
+ else return s;
1932
+ };
1933
+ return sort();
1934
+ };
1935
+ //#endregion
1936
+ //#region src/string.ts
1937
+ /**
1938
+ * Capitalizes the first letter of a string.
1939
+ */
1940
+ var capitalize = (str) => {
1941
+ if (str.length === 0) return "";
1942
+ return str.charAt(0).toUpperCase() + str.slice(1);
1943
+ };
1944
+ /**
1945
+ * Collapse a multi-line tagged template literal to a single space-separated string.
1946
+ * Useful for statically concatenating long lists of class names across multiple lines:
1947
+ *
1948
+ * ```ts
1949
+ * const cls = inline`
1950
+ * rounded-xs outline-none
1951
+ * data-[focused]:bg-accent-bg
1952
+ * `;
1953
+ * ```
1954
+ */
1955
+ function inline(strings, ...values) {
1956
+ return strings.reduce((out, str, i) => out + str + (i < values.length ? String(values[i]) : ""), "").replace(/\s+/g, " ").trim();
1957
+ }
1958
+ /**
1959
+ * Remove leading space from multi-line strings.
1960
+ */
1961
+ function trim(strings, ...values) {
1962
+ const lines = strings.reduce((out, str, i) => {
1963
+ out += str;
1964
+ if (i < values.length) {
1965
+ const match = str.match(/(^|\n)([ \t]*)$/);
1966
+ const baseIndent = match ? match[2] : "";
1967
+ const val = String(values[i]).replace(/\r?\n/g, "\n" + baseIndent);
1968
+ out += val;
1969
+ }
1970
+ return out;
1971
+ }, "").split("\n");
1972
+ while (lines.length && !lines[0].trim()) lines.shift();
1973
+ while (lines.length && !lines[lines.length - 1].trim()) lines.pop();
1974
+ const minIndent = Math.min(...lines.filter((l) => l.trim()).map((l) => l.match(/^[ \t]*/)?.[0].length ?? 0));
1975
+ return lines.map((l) => l.slice(minIndent)).join("\n");
1976
+ }
1977
+ /**
1978
+ * Converts a string to kebab case.
1979
+ */
1980
+ var kebabize = (str) => str.replace(/[A-Z]+(?![a-z])|[A-Z]/g, ($, ofs) => (ofs ? "-" : "") + $.toLowerCase());
1981
+ //#endregion
1982
+ //#region src/sum.ts
1983
+ var sum = (values) => values.reduce((a, b) => a + b, 0);
1984
+ //#endregion
1985
+ //#region src/throw-unhandled-error.ts
1986
+ /**
1987
+ * Throws an unhandled error for the runtime to catch.
1988
+ * Does not cause stack unwinding.
1989
+ * Error will be thrown in the next microtask.
1990
+ */
1991
+ var throwUnhandledError = (error) => {
1992
+ queueMicrotask(() => {
1993
+ throw error;
1994
+ });
1995
+ };
1996
+ //#endregion
1997
+ //#region src/to-fallback.ts
1998
+ /**
1999
+ * When changing this set, please check the result in a console or e.g. RunKit (https://runkit.com/thure/642214441dd6ae000855a8de)
2000
+ * Emoji sometimes use a combination of code points, and some code points aren't visible on their own, so by adding or deleting you may unintentionally create non-visible items.
2001
+ * This set was chosen from the characters in Unicode Emoji v15.0 based on the following criteria:
2002
+ * – not people or isolated anthropomorphic faces
2003
+ * – not flags
2004
+ * – more concrete than abstract
2005
+ * – less culturally specific
2006
+ * – less easily confused with another emoji in the set
2007
+ * – requires less special knowledge to identify
2008
+ * – less likely to evoke negative feelings (no meat, no drugs, no weapons, etc)
2009
+ * – less common as a signifier in UX
2010
+ * NOTE that this is intentionally an array of strings because of the way emoji graphemes work.
2011
+ */
2012
+ var idEmoji = [
2013
+ "👻",
2014
+ "👹",
2015
+ "👽",
2016
+ "🤖",
2017
+ "🎃",
2018
+ "🦾",
2019
+ "🦿",
2020
+ "🦷",
2021
+ "👣",
2022
+ "👁️",
2023
+ "🧶",
2024
+ "👑",
2025
+ "🐒",
2026
+ "🦆",
2027
+ "🦉",
2028
+ "🐴",
2029
+ "🦄",
2030
+ "🐝",
2031
+ "🦋",
2032
+ "🐞",
2033
+ "🪲",
2034
+ "🐢",
2035
+ "🦎",
2036
+ "🦕",
2037
+ "🦑",
2038
+ "🦀",
2039
+ "🐠",
2040
+ "🐬",
2041
+ "🐋",
2042
+ "🦭",
2043
+ "🐅",
2044
+ "🐆",
2045
+ "🦓",
2046
+ "🦍",
2047
+ "🦧",
2048
+ "🐘",
2049
+ "🐫",
2050
+ "🦒",
2051
+ "🦘",
2052
+ "🦬",
2053
+ "🐖",
2054
+ "🐏",
2055
+ "🦌",
2056
+ "🐕",
2057
+ "🐈",
2058
+ "🐓",
2059
+ "🦚",
2060
+ "🦜",
2061
+ "🦢",
2062
+ "🦩",
2063
+ "🦦",
2064
+ "🐁",
2065
+ "🐿️",
2066
+ "🌵",
2067
+ "🌲",
2068
+ "🌳",
2069
+ "🪵",
2070
+ "🌱",
2071
+ "🍁",
2072
+ "🪺",
2073
+ "🍄",
2074
+ "🐚",
2075
+ "🪸",
2076
+ "🪨",
2077
+ "🌾",
2078
+ "🌷",
2079
+ "🌻",
2080
+ "☀️",
2081
+ "🌙",
2082
+ "🪐",
2083
+ "⭐️",
2084
+ "⚡️",
2085
+ "☄️",
2086
+ "🔥",
2087
+ "🌈",
2088
+ "☁️",
2089
+ "💧",
2090
+ "⛱️",
2091
+ "🌊",
2092
+ "🍎",
2093
+ "🍋",
2094
+ "🍉",
2095
+ "🍇",
2096
+ "🫐",
2097
+ "🍈",
2098
+ "🍒",
2099
+ "🍑",
2100
+ "🥭",
2101
+ "🍍",
2102
+ "🥥",
2103
+ "🥝",
2104
+ "🥑",
2105
+ "🌶️",
2106
+ "🌽",
2107
+ "🥕",
2108
+ "🍬",
2109
+ "🥜",
2110
+ "🫖",
2111
+ "☕️",
2112
+ "🍵",
2113
+ "🧊",
2114
+ "🧂",
2115
+ "🏔️",
2116
+ "⚓️",
2117
+ "🛟",
2118
+ "🏝️",
2119
+ "🛶",
2120
+ "🚀",
2121
+ "🛰️",
2122
+ "⛲️",
2123
+ "🏰",
2124
+ "🚲",
2125
+ "⛺️",
2126
+ "🎙️",
2127
+ "🧲",
2128
+ "⚙️",
2129
+ "🔩",
2130
+ "🔮",
2131
+ "🔭",
2132
+ "🔬",
2133
+ "🧬",
2134
+ "🌡️",
2135
+ "🧺",
2136
+ "🛎️",
2137
+ "🔑",
2138
+ "🪑",
2139
+ "🧸",
2140
+ "🎈",
2141
+ "🎀",
2142
+ "🎊",
2143
+ "♻️",
2144
+ "🎵"
2145
+ ];
2146
+ var idHue = [
2147
+ "red",
2148
+ "orange",
2149
+ "amber",
2150
+ "yellow",
2151
+ "lime",
2152
+ "green",
2153
+ "emerald",
2154
+ "teal",
2155
+ "cyan",
2156
+ "violet",
2157
+ "purple",
2158
+ "fuchsia",
2159
+ "pink",
2160
+ "rose"
2161
+ ];
2162
+ /** FNV-1a hash of an arbitrary string, as an unsigned 32-bit integer. */
2163
+ var fnv1a = (id) => {
2164
+ let hash = 2166136261;
2165
+ for (let index = 0; index < id.length; index++) {
2166
+ hash ^= id.charCodeAt(index);
2167
+ hash = Math.imul(hash, 16777619);
2168
+ }
2169
+ return Math.abs(hash);
2170
+ };
2171
+ /**
2172
+ * Deterministic palette hue for an arbitrary id string that isn't hex-parseable (e.g. an identity
2173
+ * DID). Seeds the shared {@link idHue} palette via FNV-1a so the same id always maps to the same hue,
2174
+ * matching the colouring used for avatars/tags elsewhere. Prefer {@link hexToHue} when a hex
2175
+ * identity key is available (it aligns with the awareness-cursor palette).
2176
+ */
2177
+ var stringToHue = (id) => idHue[fnv1a(id) % idHue.length];
2178
+ /**
2179
+ * Deterministic avatar fallback (emoji + hue) for an arbitrary id string (e.g. an identity DID).
2180
+ * Shares {@link stringToHue}'s FNV-1a seed, so `stringToFallback(id).hue === stringToHue(id)` — an
2181
+ * avatar seeded from an id and a tag coloured by {@link stringToHue} for the same id agree.
2182
+ */
2183
+ var stringToFallback = (id) => {
2184
+ const hash = fnv1a(id);
2185
+ return {
2186
+ emoji: idEmoji[Math.floor(hash / idHue.length) % idEmoji.length],
2187
+ hue: idHue[hash % idHue.length]
2188
+ };
2189
+ };
2190
+ var keyToEmoji = (key) => keyToFallback(key).emoji;
2191
+ var hexToEmoji = (hex) => hexToFallback(hex).emoji;
2192
+ var toEmoji = (hash) => toFallback(hash).emoji;
2193
+ var keyToHue = (key) => keyToFallback(key).hue;
2194
+ var hexToHue = (hex) => hexToFallback(hex).hue;
2195
+ var toHue = (hash) => toFallback(hash).hue;
2196
+ var keyToFallback = (key) => hexToFallback(key.toHex());
2197
+ var hexToFallback = (hex) => toFallback(parseInt(hex, 16));
2198
+ var toFallback = (hash) => {
2199
+ const combinationIndex = hash % (idEmoji.length * idHue.length);
2200
+ const emojiIndex = Math.floor(combinationIndex / idHue.length);
2201
+ const hueIndex = combinationIndex % idHue.length;
2202
+ return {
2203
+ emoji: idEmoji[emojiIndex],
2204
+ hue: idHue[hueIndex]
2205
+ };
2206
+ };
2207
+ //#endregion
2208
+ //#region src/tracer.ts
2209
+ /**
2210
+ * Event sink.
2211
+ */
2212
+ var Tracer = class {
2213
+ _events = /* @__PURE__ */ new Map();
2214
+ _recording = false;
2215
+ get recording() {
2216
+ return this._recording;
2217
+ }
2218
+ keys() {
2219
+ return Array.from(this._events.keys());
2220
+ }
2221
+ get(id, filter) {
2222
+ const events = this._events.get(id);
2223
+ if (filter) return events?.filter((event) => Object.entries(filter).every(([key, value]) => event?.value[key] === value));
2224
+ return events;
2225
+ }
2226
+ clear() {
2227
+ this._events.clear();
2228
+ }
2229
+ start() {
2230
+ this._recording = true;
2231
+ return this;
2232
+ }
2233
+ stop() {
2234
+ this._recording = false;
2235
+ return this;
2236
+ }
2237
+ emit(id, value) {
2238
+ this._post(this._createEvent(id, value));
2239
+ }
2240
+ mark(id, value) {
2241
+ const event = this._createEvent(id, value);
2242
+ const start = performance.now();
2243
+ return {
2244
+ start,
2245
+ end: () => {
2246
+ event.duration = performance.now() - start;
2247
+ this._post(event);
2248
+ }
2249
+ };
2250
+ }
2251
+ _createEvent(id, value) {
2252
+ const event = {
2253
+ id,
2254
+ timestamp: Date.now()
2255
+ };
2256
+ if (value !== void 0) event.value = value;
2257
+ return event;
2258
+ }
2259
+ _post(event) {
2260
+ if (this._recording) defaultMap(this._events, event.id, []).push(event);
2261
+ }
2262
+ };
2263
+ var tracer = new Tracer();
2264
+ //#endregion
2265
+ //#region src/tree.ts
2266
+ /**
2267
+ * Create tree using depth first traversal.
2268
+ * https://waylonwalker.com/drawing-ascii-boxes/#connectors
2269
+ */
2270
+ var stringifyTree = (node, ancestors = [], rows = []) => {
2271
+ if (node.children?.length) node.children.forEach((child, i) => {
2272
+ stringifyTree(child, [...ancestors, [node, i]], rows);
2273
+ });
2274
+ else {
2275
+ const keyLen = 8;
2276
+ const name = (node) => truncateKey(node.id, keyLen);
2277
+ const parts = [];
2278
+ ancestors.forEach(([node, i], j) => {
2279
+ const first = ancestors.slice(j).every(([_, i]) => i === 0);
2280
+ parts.push(j === 0 ? first ? "├" : " " : "");
2281
+ parts.push(first ? `─(${name(node)})─` : "".padEnd(12));
2282
+ if (node.children) if (first) parts.push(node.children.length > 1 ? "┬" : "─");
2283
+ else {
2284
+ const childFirst = ancestors.slice(j + 1).every(([_, i]) => i === 0);
2285
+ if (node.children.length - 1 === i) parts.push(childFirst ? "╰" : " ");
2286
+ else parts.push(childFirst ? "├" : "│");
2287
+ }
2288
+ });
2289
+ parts.push(`─(${name(node)})`);
2290
+ rows.push(parts.join(""));
2291
+ }
2292
+ return rows;
2293
+ };
2294
+ //#endregion
2295
+ //#region src/types.ts
2296
+ /**
2297
+ * Use with filter chaining instead of filter(Boolean) to preserve type.
2298
+ * NOTE: To filter by type:
2299
+ * items.filter((item: any): item is RangeSet<Decoration> => item instanceof RangeSet)
2300
+ */
2301
+ var isTruthy = (value) => !!value;
2302
+ var isNonNullable = (value) => value != null;
2303
+ var doAsync = async (fn) => fn();
2304
+ /**
2305
+ * Get value from a provider.
2306
+ */
2307
+ var getProviderValue = (provider, arg) => {
2308
+ return typeof provider === "function" ? provider(arg) : provider;
2309
+ };
2310
+ /**
2311
+ * Get value from a provider, which may be async.
2312
+ */
2313
+ var getAsyncProviderValue = (provider, arg) => {
2314
+ return getProviderValue(provider, arg);
2315
+ };
2316
+ /**
2317
+ * Remove keys with undefined values.
2318
+ */
2319
+ var stripUndefined = (obj) => {
2320
+ if (typeof obj === "object") Object.keys(obj).forEach((key) => {
2321
+ const value = obj[key];
2322
+ if (value === void 0) delete obj[key];
2323
+ else if (value !== null && typeof value === "object") stripUndefined(value);
2324
+ });
2325
+ return obj;
2326
+ };
2327
+ /**
2328
+ * Return new object with sorted keys.
2329
+ */
2330
+ var sortKeys = (obj) => Object.keys(obj).sort().reduce((sorted, key) => {
2331
+ sorted[key] = obj[key];
2332
+ return sorted;
2333
+ }, {});
2334
+ /**
2335
+ * Move element within array.
2336
+ */
2337
+ var arrayMove = (array, from, to) => {
2338
+ array.splice(to < 0 ? array.length + to : to, 0, array.splice(from, 1)[0]);
2339
+ return array;
2340
+ };
2341
+ /**
2342
+ * Swap position of element within array.
2343
+ */
2344
+ function arraySwap(array, from, to) {
2345
+ const current = array[from];
2346
+ array[from] = array[to];
2347
+ array[to] = current;
2348
+ return array;
2349
+ }
2350
+ //#endregion
2351
+ //#region src/unit.ts
2352
+ var createFormat = (unit) => {
2353
+ return (n, precision = unit.precision ?? 0) => {
2354
+ const value = n / unit.quotient;
2355
+ const formattedValue = value.toLocaleString("en-US", {
2356
+ minimumFractionDigits: precision,
2357
+ maximumFractionDigits: precision
2358
+ });
2359
+ return {
2360
+ unit,
2361
+ value,
2362
+ formattedValue,
2363
+ toString: () => `${formattedValue}${unit.symbol}`
2364
+ };
2365
+ };
2366
+ };
2367
+ var MS_SECONDS = 1e3;
2368
+ var MS_MINUTES = 60 * MS_SECONDS;
2369
+ var MS_HOURS = 60 * MS_MINUTES;
2370
+ var Unit = {
2371
+ Percent: createFormat({
2372
+ symbol: "%",
2373
+ quotient: 1 / 100,
2374
+ precision: 1
2375
+ }),
2376
+ Thousand: createFormat({
2377
+ symbol: "k",
2378
+ quotient: 1e3,
2379
+ precision: 1
2380
+ }),
2381
+ Million: createFormat({
2382
+ symbol: "M",
2383
+ quotient: 1e6,
2384
+ precision: 1
2385
+ }),
2386
+ Gigabyte: createFormat({
2387
+ symbol: "GB",
2388
+ quotient: 1e3 * 1e3 * 1e3,
2389
+ precision: 1
2390
+ }),
2391
+ Megabyte: createFormat({
2392
+ symbol: "MB",
2393
+ quotient: 1e3 * 1e3,
2394
+ precision: 1
2395
+ }),
2396
+ Kilobyte: createFormat({
2397
+ symbol: "KB",
2398
+ quotient: 1e3,
2399
+ precision: 1
2400
+ }),
2401
+ Byte: createFormat({
2402
+ symbol: "B",
2403
+ quotient: 1
2404
+ }),
2405
+ Hour: createFormat({
2406
+ symbol: "h",
2407
+ quotient: MS_HOURS
2408
+ }),
2409
+ Minute: createFormat({
2410
+ symbol: "m",
2411
+ quotient: MS_MINUTES
2412
+ }),
2413
+ Second: createFormat({
2414
+ symbol: "s",
2415
+ quotient: MS_SECONDS,
2416
+ precision: 1
2417
+ }),
2418
+ Millisecond: createFormat({
2419
+ symbol: "ms",
2420
+ quotient: 1
2421
+ }),
2422
+ Duration: (n) => {
2423
+ const hours = Math.floor(n / MS_HOURS);
2424
+ const minutes = Math.floor(n % MS_HOURS / MS_MINUTES);
2425
+ if (hours) {
2426
+ const formattedValue = minutes ? `${hours}h ${minutes}m` : `${hours}h`;
2427
+ return {
2428
+ unit: {
2429
+ symbol: "h",
2430
+ quotient: MS_HOURS
2431
+ },
2432
+ value: hours,
2433
+ formattedValue,
2434
+ toString: () => formattedValue
2435
+ };
2436
+ }
2437
+ if (minutes) {
2438
+ const seconds = (n - MS_MINUTES * minutes) / MS_SECONDS;
2439
+ const formattedValue = seconds ? `${minutes}m ${Math.round(seconds)}s` : `${minutes}m`;
2440
+ return {
2441
+ unit: {
2442
+ symbol: "m",
2443
+ quotient: MS_MINUTES
2444
+ },
2445
+ value: minutes,
2446
+ formattedValue,
2447
+ toString: () => formattedValue
2448
+ };
2449
+ }
2450
+ if (n >= MS_SECONDS) return Unit.Second(n);
2451
+ return Unit.Millisecond(n);
2452
+ }
2453
+ };
2454
+ //#endregion
2455
+ //#region src/url.ts
2456
+ /**
2457
+ * Normalize construction of URLs.
2458
+ */
2459
+ var createUrl = (url, search) => {
2460
+ const base = typeof url === "string" ? new URL(url) : url;
2461
+ if (search) base.search = new URLSearchParams(Object.entries(search).filter(([_, value]) => value != null)).toString();
2462
+ return base;
2463
+ };
2464
+ //#endregion
2465
+ //#region src/weak.ts
2466
+ /**
2467
+ * Weak dictionary. It is a map that holds weak references to its values and allows garbage collection of values and keys.
2468
+ */
2469
+ var WeakDictionary = class {
2470
+ _internal = /* @__PURE__ */ new Map();
2471
+ _finalization = new FinalizationRegistry(({ key, ref }) => {
2472
+ if (this._internal.get(key) === ref) this._internal.delete(key);
2473
+ });
2474
+ constructor(entries) {
2475
+ if (entries) for (const [key, value] of entries) {
2476
+ const ref = new WeakRef(value);
2477
+ this._internal.set(key, ref);
2478
+ this._register(key, value, ref);
2479
+ }
2480
+ }
2481
+ *entries() {
2482
+ for (const [key, value] of this._internal) yield [key, value.deref()];
2483
+ }
2484
+ keys() {
2485
+ return this._internal.keys();
2486
+ }
2487
+ *values() {
2488
+ for (const value of this._internal.values()) {
2489
+ const deref = value.deref();
2490
+ if (!deref) continue;
2491
+ yield deref;
2492
+ }
2493
+ }
2494
+ *[Symbol.iterator]() {
2495
+ for (const [key, value] of this._internal) yield [key, value.deref()];
2496
+ }
2497
+ get [Symbol.toStringTag]() {
2498
+ return "WeakDictionary";
2499
+ }
2500
+ get size() {
2501
+ return this._internal.size;
2502
+ }
2503
+ get(key) {
2504
+ return this._internal.get(key)?.deref();
2505
+ }
2506
+ set(key, value) {
2507
+ const previous = this._internal.get(key)?.deref();
2508
+ if (previous) this._unregister(previous);
2509
+ const ref = new WeakRef(value);
2510
+ this._internal.set(key, ref);
2511
+ this._register(key, value, ref);
2512
+ return this;
2513
+ }
2514
+ /**
2515
+ * Returns the value for the given key if present, otherwise inserts and returns the default value.
2516
+ * @param key - The key to look up or insert.
2517
+ * @param defaultValue - The value to insert if the key is not present.
2518
+ * @returns The existing or newly inserted value.
2519
+ */
2520
+ getOrInsert(key, defaultValue) {
2521
+ const existing = this.get(key);
2522
+ if (existing !== void 0) return existing;
2523
+ this.set(key, defaultValue);
2524
+ return defaultValue;
2525
+ }
2526
+ /**
2527
+ * Returns the value for the given key if present, otherwise computes, inserts, and returns a new value.
2528
+ * The callback is only invoked when the key is missing.
2529
+ * @param key - The key to look up or insert.
2530
+ * @param callbackfn - Function to compute the value if the key is not present.
2531
+ * @returns The existing or newly computed value.
2532
+ */
2533
+ getOrInsertComputed(key, callbackfn) {
2534
+ const existing = this.get(key);
2535
+ if (existing !== void 0) return existing;
2536
+ const value = callbackfn(key);
2537
+ this.set(key, value);
2538
+ return value;
2539
+ }
2540
+ has(key) {
2541
+ return this._internal.has(key) && this._internal.get(key).deref() !== void 0;
2542
+ }
2543
+ delete(key) {
2544
+ const value = this._internal.get(key)?.deref();
2545
+ if (value) this._unregister(value);
2546
+ return this._internal.delete(key);
2547
+ }
2548
+ clear() {
2549
+ this._internal.forEach((value) => {
2550
+ const v = value.deref();
2551
+ if (v) this._unregister(v);
2552
+ });
2553
+ this._internal.clear();
2554
+ }
2555
+ forEach(callbackfn, thisArg) {
2556
+ if (thisArg) callbackfn = callbackfn.bind(thisArg);
2557
+ this._internal.forEach((value, key) => {
2558
+ const v = value.deref();
2559
+ if (v) callbackfn(v, key, this);
2560
+ });
2561
+ }
2562
+ _register(key, value, ref) {
2563
+ this._finalization.register(value, {
2564
+ key,
2565
+ ref
2566
+ }, value);
2567
+ }
2568
+ _unregister(value) {
2569
+ this._finalization.unregister(value);
2570
+ }
2571
+ };
2572
+ //#endregion
2573
+ export { BitField, Callback, CallbackCollection, CircularBuffer, ComplexMap, ComplexSet, HumanHasher, MapEntry, Position_exports as Position, SKIP, SlidingWindowSummary, Tracer, Unit, WeakDictionary, accessBy, arrayMove, arraySwap, arrayToBuffer, arrayToHex, arrayToString, arraysEqual, assumeType, bufferToArray, capitalize, chunkArray, clamp, clearCaches, clearIndexedDB, clearOPFS, clearServiceWorkers, clearUndefined, coerceArray, compareMulti, compareObject, compareScalar, compareString, compositeKey, createBinder, createBucketReducer, createFilename, createGroupReducer, createReplacer, createSetDispatch, createUrl, decamelize, decodeUint8ArrayFromJson, deepMapValues, deepMapValuesAsync, defaultFilter, defaultMap, defer, deferAsync, deferFunction, diff, distinctBy, doAsync, encodeUint8ArrayToJson, entries, entry, exponentialBackoffInterval, forEachAsync, formatErrorWithCauses, getAsyncProviderValue, getDate, getDebugName, getDeep, getHostPlatform, getPrototypeSpecificInstanceId, getProviderValue, hexToEmoji, hexToFallback, hexToHue, humanize, hyphenize, id, idEmoji, idHue, inferObjectOrder, inferRecordOrder, inline, intersectBy, intersection, iosCheck, isBun, isEncodedUint8Array, isMobile, isMobileOrTablet, isNode, isNonNullable, isTauri, isTruthy, isWellFormedId, isWellFormedIdPart, joinTables, jsonKeyReplacer, jsonReplacer, jsonify, jsonlogify, kebabize, keyToEmoji, keyToFallback, keyToHue, keys, makeMap, makeSet, mapValues, median, numericalValues, omit, orderKeys, partition, pick, pickBy, randomInt, range, rangeFromTo, reduceGroupBy, reduceSeries, reduceSet, removeBy, removeProperties, removeUndefinedProperties, retry, safariCheck, safeAwaitAll, safeInstanceof, safeParseFloat, safeParseInt, safeParseJson, safeStringify, safeUrl, setDeep, sortKeys, splitCompositeKey, stringToArray, stringToFallback, stringToHue, stringifyTree, stripUndefined, sum, throwUnhandledError, toEmoji, toFallback, toHue, tracer, trim, visitValues };
2574
+
2575
+ //# sourceMappingURL=index.mjs.map