@dxos/util 0.8.4-main.ef1bc66f44 → 0.8.4-main.effb148878

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/LICENSE +102 -5
  2. package/dist/lib/browser/index.mjs +313 -180
  3. package/dist/lib/browser/index.mjs.map +4 -4
  4. package/dist/lib/browser/meta.json +1 -1
  5. package/dist/lib/node-esm/index.mjs +313 -180
  6. package/dist/lib/node-esm/index.mjs.map +4 -4
  7. package/dist/lib/node-esm/meta.json +1 -1
  8. package/dist/types/src/array-to-hex.d.ts.map +1 -1
  9. package/dist/types/src/array.d.ts.map +1 -1
  10. package/dist/types/src/binder.d.ts.map +1 -1
  11. package/dist/types/src/bitfield.d.ts.map +1 -1
  12. package/dist/types/src/browser-storage.d.ts +9 -0
  13. package/dist/types/src/browser-storage.d.ts.map +1 -0
  14. package/dist/types/src/callback-collection.d.ts.map +1 -1
  15. package/dist/types/src/callback.d.ts.map +1 -1
  16. package/dist/types/src/case.d.ts.map +1 -1
  17. package/dist/types/src/chunk-array.d.ts.map +1 -1
  18. package/dist/types/src/circular-buffer.d.ts +1 -0
  19. package/dist/types/src/circular-buffer.d.ts.map +1 -1
  20. package/dist/types/src/clear-undefined.d.ts.map +1 -1
  21. package/dist/types/src/complex.d.ts +15 -0
  22. package/dist/types/src/complex.d.ts.map +1 -1
  23. package/dist/types/src/composite-key.d.ts +10 -0
  24. package/dist/types/src/composite-key.d.ts.map +1 -0
  25. package/dist/types/src/composite-key.test.d.ts +2 -0
  26. package/dist/types/src/composite-key.test.d.ts.map +1 -0
  27. package/dist/types/src/deep.d.ts +0 -3
  28. package/dist/types/src/deep.d.ts.map +1 -1
  29. package/dist/types/src/defer-function.d.ts.map +1 -1
  30. package/dist/types/src/defer.d.ts.map +1 -1
  31. package/dist/types/src/di-container.d.ts.map +1 -1
  32. package/dist/types/src/di-key.d.ts +7 -5
  33. package/dist/types/src/di-key.d.ts.map +1 -1
  34. package/dist/types/src/entry.d.ts.map +1 -1
  35. package/dist/types/src/error-format.d.ts.map +1 -1
  36. package/dist/types/src/filename.d.ts.map +1 -1
  37. package/dist/types/src/for-each-async.d.ts.map +1 -1
  38. package/dist/types/src/human-hash.d.ts.map +1 -1
  39. package/dist/types/src/id.d.ts +30 -0
  40. package/dist/types/src/id.d.ts.map +1 -0
  41. package/dist/types/src/id.test.d.ts +2 -0
  42. package/dist/types/src/id.test.d.ts.map +1 -0
  43. package/dist/types/src/index.d.ts +5 -2
  44. package/dist/types/src/index.d.ts.map +1 -1
  45. package/dist/types/src/instance-id.d.ts.map +1 -1
  46. package/dist/types/src/interval.d.ts.map +1 -1
  47. package/dist/types/src/join-tables.d.ts.map +1 -1
  48. package/dist/types/src/json.d.ts.map +1 -1
  49. package/dist/types/src/map-values.d.ts.map +1 -1
  50. package/dist/types/src/map.d.ts.map +1 -1
  51. package/dist/types/src/object.d.ts.map +1 -1
  52. package/dist/types/src/order-keys.d.ts.map +1 -1
  53. package/dist/types/src/order.d.ts.map +1 -1
  54. package/dist/types/src/pick.d.ts.map +1 -1
  55. package/dist/types/src/platform.d.ts +1 -1
  56. package/dist/types/src/platform.d.ts.map +1 -1
  57. package/dist/types/src/position.d.ts +5 -5
  58. package/dist/types/src/position.d.ts.map +1 -1
  59. package/dist/types/src/random.d.ts.map +1 -1
  60. package/dist/types/src/range.d.ts.map +1 -1
  61. package/dist/types/src/reducers.d.ts.map +1 -1
  62. package/dist/types/src/remove-undefined-keys.d.ts.map +1 -1
  63. package/dist/types/src/retry.d.ts.map +1 -1
  64. package/dist/types/src/safe-await.d.ts.map +1 -1
  65. package/dist/types/src/safe-instanceof.d.ts.map +1 -1
  66. package/dist/types/src/safe-parse.d.ts +1 -0
  67. package/dist/types/src/safe-parse.d.ts.map +1 -1
  68. package/dist/types/src/safe-stringify.d.ts +1 -1
  69. package/dist/types/src/safe-stringify.d.ts.map +1 -1
  70. package/dist/types/src/safe-stringify.test.d.ts +2 -0
  71. package/dist/types/src/safe-stringify.test.d.ts.map +1 -0
  72. package/dist/types/src/sliding-window-summary.d.ts.map +1 -1
  73. package/dist/types/src/sort.d.ts.map +1 -1
  74. package/dist/types/src/string.d.ts +12 -0
  75. package/dist/types/src/string.d.ts.map +1 -1
  76. package/dist/types/src/sum.d.ts.map +1 -1
  77. package/dist/types/src/throw-unhandled-error.d.ts.map +1 -1
  78. package/dist/types/src/to-fallback.d.ts +18 -4
  79. package/dist/types/src/to-fallback.d.ts.map +1 -1
  80. package/dist/types/src/tracer.d.ts.map +1 -1
  81. package/dist/types/src/tree.d.ts.map +1 -1
  82. package/dist/types/src/types.d.ts +1 -1
  83. package/dist/types/src/types.d.ts.map +1 -1
  84. package/dist/types/src/uint8array.d.ts +27 -0
  85. package/dist/types/src/uint8array.d.ts.map +1 -1
  86. package/dist/types/src/unit.d.ts.map +1 -1
  87. package/dist/types/src/url.d.ts.map +1 -1
  88. package/dist/types/src/weak.d.ts +15 -0
  89. package/dist/types/src/weak.d.ts.map +1 -1
  90. package/dist/types/tsconfig.tsbuildinfo +1 -1
  91. package/package.json +7 -14
  92. package/src/browser-storage.ts +60 -0
  93. package/src/circular-buffer.test.ts +26 -0
  94. package/src/circular-buffer.ts +5 -0
  95. package/src/complex.ts +32 -0
  96. package/src/composite-key.test.ts +31 -0
  97. package/src/composite-key.ts +16 -0
  98. package/src/deep.ts +0 -6
  99. package/src/di-key.ts +10 -8
  100. package/src/error-format.ts +3 -1
  101. package/src/id.test.ts +109 -0
  102. package/src/id.ts +48 -0
  103. package/src/index.ts +5 -2
  104. package/src/map-values.ts +6 -0
  105. package/src/platform.ts +27 -5
  106. package/src/position.test.ts +38 -44
  107. package/src/position.ts +7 -11
  108. package/src/safe-parse.ts +8 -0
  109. package/src/safe-stringify.test.ts +96 -0
  110. package/src/safe-stringify.ts +15 -8
  111. package/src/string.test.ts +24 -1
  112. package/src/string.ts +22 -2
  113. package/src/to-fallback.ts +39 -156
  114. package/src/types.ts +1 -1
  115. package/src/uint8array.ts +44 -0
  116. package/src/unit.ts +6 -2
  117. package/src/weak.ts +52 -14
@@ -119,7 +119,6 @@ var createBinder = (obj) => ({
119
119
 
120
120
  // src/bitfield.ts
121
121
  import { invariant } from "@dxos/invariant";
122
- var __dxlog_file = "/__w/dxos/dxos/packages/common/util/src/bitfield.ts";
123
122
  var BitField = class _BitField {
124
123
  static get(data, idx) {
125
124
  const bit = data[idx >> 3] >> 7 - idx % 8 & 1;
@@ -151,15 +150,7 @@ var BitField = class _BitField {
151
150
  return result;
152
151
  }
153
152
  static and(first, second) {
154
- invariant(first.length === second.length, "Bitfields must be of the same length", {
155
- F: __dxlog_file,
156
- L: 52,
157
- S: this,
158
- A: [
159
- "first.length === second.length",
160
- "'Bitfields must be of the same length'"
161
- ]
162
- });
153
+ invariant(first.length === second.length, "Bitfields must be of the same length");
163
154
  const result = new Uint8Array(first.length);
164
155
  for (let i = 0; i < first.length; i++) {
165
156
  result[i] = first[i] & second[i];
@@ -187,6 +178,49 @@ var BitField = class _BitField {
187
178
  }
188
179
  };
189
180
 
181
+ // src/browser-storage.ts
182
+ var clearIndexedDB = async () => {
183
+ const dbs = await indexedDB.databases();
184
+ const results = await Promise.allSettled(dbs.filter((db) => db.name != null).map((db) => new Promise((resolve, reject) => {
185
+ const request = indexedDB.deleteDatabase(db.name);
186
+ request.onsuccess = () => resolve();
187
+ request.onerror = () => reject(request.error);
188
+ request.onblocked = () => reject(new Error(`IndexedDB deletion blocked: ${db.name}`));
189
+ })));
190
+ const failures = results.filter((r) => r.status === "rejected");
191
+ if (failures.length > 0) {
192
+ throw new AggregateError(failures.map((r) => r.reason), "Failed to delete some IndexedDB databases");
193
+ }
194
+ };
195
+ var clearOPFS = async () => {
196
+ const root = await navigator.storage.getDirectory();
197
+ const errors = [];
198
+ for await (const [name] of root.entries()) {
199
+ try {
200
+ await root.removeEntry(name, {
201
+ recursive: true
202
+ });
203
+ } catch (err) {
204
+ errors.push(err);
205
+ }
206
+ }
207
+ if (errors.length > 0) {
208
+ throw new AggregateError(errors, "Failed to remove some OPFS entries");
209
+ }
210
+ };
211
+ var clearServiceWorkers = async () => {
212
+ const regs = await navigator.serviceWorker.getRegistrations();
213
+ for (const reg of regs) {
214
+ await reg.unregister();
215
+ }
216
+ };
217
+ var clearCaches = async () => {
218
+ const keys2 = await caches.keys();
219
+ for (const key of keys2) {
220
+ await caches.delete(key);
221
+ }
222
+ };
223
+
190
224
  // src/callback-collection.ts
191
225
  var CallbackCollection = class {
192
226
  #callbacks = [];
@@ -213,34 +247,17 @@ var CallbackCollection = class {
213
247
 
214
248
  // src/callback.ts
215
249
  import { invariant as invariant2 } from "@dxos/invariant";
216
- var __dxlog_file2 = "/__w/dxos/dxos/packages/common/util/src/callback.ts";
217
250
  var Callback = class {
218
251
  _callback;
219
252
  call(...args) {
220
- invariant2(this._callback, "Callback not set", {
221
- F: __dxlog_file2,
222
- L: 20,
223
- S: this,
224
- A: [
225
- "this._callback",
226
- "'Callback not set'"
227
- ]
228
- });
253
+ invariant2(this._callback, "Callback not set");
229
254
  return this._callback(...args);
230
255
  }
231
256
  callIfSet(...args) {
232
257
  return this._callback?.(...args);
233
258
  }
234
259
  set(callback) {
235
- invariant2(!this._callback, "Callback already set", {
236
- F: __dxlog_file2,
237
- L: 29,
238
- S: this,
239
- A: [
240
- "!this._callback",
241
- "'Callback already set'"
242
- ]
243
- });
260
+ invariant2(!this._callback, "Callback already set");
244
261
  this._callback = callback;
245
262
  }
246
263
  isSet() {
@@ -308,21 +325,12 @@ var chunkArray = (array, size) => {
308
325
 
309
326
  // src/circular-buffer.ts
310
327
  import { invariant as invariant3 } from "@dxos/invariant";
311
- var __dxlog_file3 = "/__w/dxos/dxos/packages/common/util/src/circular-buffer.ts";
312
328
  var CircularBuffer = class {
313
329
  _buffer;
314
330
  _nextIndex = 0;
315
331
  _elementCount = 0;
316
332
  constructor(size) {
317
- invariant3(size >= 1, void 0, {
318
- F: __dxlog_file3,
319
- L: 13,
320
- S: this,
321
- A: [
322
- "size >= 1",
323
- ""
324
- ]
325
- });
333
+ invariant3(size >= 1);
326
334
  this._buffer = new Array(size);
327
335
  }
328
336
  push(element) {
@@ -335,6 +343,10 @@ var CircularBuffer = class {
335
343
  get elementCount() {
336
344
  return this._elementCount;
337
345
  }
346
+ clear() {
347
+ this._nextIndex = 0;
348
+ this._elementCount = 0;
349
+ }
338
350
  getLast() {
339
351
  if (this._elementCount === 0) {
340
352
  return void 0;
@@ -528,6 +540,36 @@ var ComplexMap = class _ComplexMap {
528
540
  this._values.set(primitive, value);
529
541
  return this;
530
542
  }
543
+ /**
544
+ * Returns the value for the given key if present, otherwise inserts and returns the default value.
545
+ * @param key - The key to look up or insert.
546
+ * @param defaultValue - The value to insert if the key is not present.
547
+ * @returns The existing or newly inserted value.
548
+ */
549
+ getOrInsert(key, defaultValue) {
550
+ const primitive = this._keyProjection(key);
551
+ if (this._values.has(primitive)) {
552
+ return this._values.get(primitive);
553
+ }
554
+ this.set(key, defaultValue);
555
+ return defaultValue;
556
+ }
557
+ /**
558
+ * Returns the value for the given key if present, otherwise computes, inserts, and returns a new value.
559
+ * The callback is only invoked when the key is missing.
560
+ * @param key - The key to look up or insert.
561
+ * @param callbackfn - Function to compute the value if the key is not present.
562
+ * @returns The existing or newly computed value.
563
+ */
564
+ getOrInsertComputed(key, callbackfn) {
565
+ const primitive = this._keyProjection(key);
566
+ if (this._values.has(primitive)) {
567
+ return this._values.get(primitive);
568
+ }
569
+ const value = callbackfn(key);
570
+ this.set(key, value);
571
+ return value;
572
+ }
531
573
  get size() {
532
574
  return this._keys.size;
533
575
  }
@@ -567,21 +609,15 @@ var makeMap = (keyProjection) => class BoundComplexMap extends ComplexMap {
567
609
  }
568
610
  };
569
611
 
612
+ // src/composite-key.ts
613
+ var SEPARATOR = ":";
614
+ var compositeKey = (...parts) => parts.join(SEPARATOR);
615
+ var splitCompositeKey = (key) => key.split(SEPARATOR);
616
+
570
617
  // src/deep.ts
571
- import get from "lodash.get";
572
- import set from "lodash.set";
573
618
  import { invariant as invariant4 } from "@dxos/invariant";
574
- var __dxlog_file4 = "/__w/dxos/dxos/packages/common/util/src/deep.ts";
575
619
  var setDeep = (obj, path, value) => {
576
- invariant4(path.length > 0, void 0, {
577
- F: __dxlog_file4,
578
- L: 18,
579
- S: void 0,
580
- A: [
581
- "path.length > 0",
582
- ""
583
- ]
584
- });
620
+ invariant4(path.length > 0);
585
621
  let parent = obj;
586
622
  for (const key of path.slice(0, -1)) {
587
623
  if (parent[key] === void 0) {
@@ -666,6 +702,23 @@ var MapEntry = class {
666
702
  }
667
703
  };
668
704
 
705
+ // src/error-format.ts
706
+ var formatErrorWithCauses = (error) => {
707
+ const lines = [];
708
+ let current = error;
709
+ let level = 0;
710
+ while (current) {
711
+ const prefix = level === 0 ? "" : `Caused by: `;
712
+ lines.push(prefix + (current.stack ?? String(current)));
713
+ if (!(current.cause instanceof Error)) {
714
+ break;
715
+ }
716
+ current = current.cause;
717
+ level += 1;
718
+ }
719
+ return lines.join("\n\n");
720
+ };
721
+
669
722
  // src/filename.ts
670
723
  var createFilename = ({ parts = [], ext, date = /* @__PURE__ */ new Date() }) => [
671
724
  date.toISOString().replace(/[:.]/g, "-"),
@@ -1007,6 +1060,19 @@ var humanize = (value) => {
1007
1060
  return hasher.humanize(value);
1008
1061
  };
1009
1062
 
1063
+ // src/id.ts
1064
+ var PART = /^[a-zA-Z][a-zA-Z0-9]{0,62}$/;
1065
+ 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})?)$/;
1066
+ function id(strings, ...values) {
1067
+ const raw = strings.reduce((out, str, i) => out + str + (i < values.length ? String(values[i]) : ""), "");
1068
+ if (!ID.test(raw)) {
1069
+ throw new Error(`Invalid id (expected AT Protocol NSID): ${JSON.stringify(raw)}`);
1070
+ }
1071
+ return raw;
1072
+ }
1073
+ var isWellFormedId = (value) => ID.test(value);
1074
+ var isWellFormedIdPart = (value) => PART.test(value);
1075
+
1010
1076
  // src/map.ts
1011
1077
  var defaultMap = (map, key, def) => {
1012
1078
  let value = map.get(key);
@@ -1018,7 +1084,7 @@ var defaultMap = (map, key, def) => {
1018
1084
  };
1019
1085
 
1020
1086
  // src/instance-id.ts
1021
- var symbol = Symbol.for("dxos.instance-contexts");
1087
+ var symbol = /* @__PURE__ */ Symbol.for("dxos.instance-contexts");
1022
1088
  var instanceContexts = globalThis[symbol] ??= /* @__PURE__ */ new WeakMap();
1023
1089
  var getPrototypeSpecificInstanceId = (instance) => {
1024
1090
  const prototype = Object.getPrototypeOf(instance);
@@ -1026,12 +1092,12 @@ var getPrototypeSpecificInstanceId = (instance) => {
1026
1092
  nextId: 0,
1027
1093
  instanceIds: /* @__PURE__ */ new WeakMap()
1028
1094
  }));
1029
- let id = instanceCtx.instanceIds.get(instance);
1030
- if (id === void 0) {
1031
- id = instanceCtx.nextId++;
1032
- instanceCtx.instanceIds.set(instance, id);
1095
+ let id2 = instanceCtx.instanceIds.get(instance);
1096
+ if (id2 === void 0) {
1097
+ id2 = instanceCtx.nextId++;
1098
+ instanceCtx.instanceIds.set(instance, id2);
1033
1099
  }
1034
- return id;
1100
+ return id2;
1035
1101
  };
1036
1102
  var getDebugName = (instance) => {
1037
1103
  if (instance == null) {
@@ -1098,6 +1164,26 @@ var bufferToArray = (buffer) => {
1098
1164
  };
1099
1165
  var stringToArray = (string) => bufferToArray(Buffer.from(string, "hex"));
1100
1166
  var arrayToString = (array) => arrayToBuffer(array).toString("hex");
1167
+ var toUnpaddedBase64 = (bytes) => arrayToBuffer(bytes).toString("base64").replace(/=+$/, "");
1168
+ var encodeUint8ArrayToJson = (bytes) => ({
1169
+ "/": {
1170
+ bytes: toUnpaddedBase64(bytes)
1171
+ }
1172
+ });
1173
+ var isEncodedUint8Array = (value) => {
1174
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
1175
+ return false;
1176
+ }
1177
+ if (Object.keys(value).length !== 1) {
1178
+ return false;
1179
+ }
1180
+ const inner = value["/"];
1181
+ if (typeof inner !== "object" || inner === null || Array.isArray(inner)) {
1182
+ return false;
1183
+ }
1184
+ return Object.keys(inner).length === 1 && typeof inner.bytes === "string";
1185
+ };
1186
+ var decodeUint8ArrayFromJson = (encoded) => bufferToArray(Buffer.from(encoded["/"].bytes, "base64"));
1101
1187
 
1102
1188
  // src/json.ts
1103
1189
  var MAX_DEPTH = 5;
@@ -1227,6 +1313,8 @@ var DeepMapper = class {
1227
1313
  res[i] = this._map(value[i], i);
1228
1314
  }
1229
1315
  return res;
1316
+ } else if (ArrayBuffer.isView(value)) {
1317
+ return value;
1230
1318
  } else if (value !== null && typeof value === "object") {
1231
1319
  const res = {};
1232
1320
  this._cyclic.set(value, res);
@@ -1268,6 +1356,8 @@ var DeepMapperAsync = class {
1268
1356
  res[i] = await this._map(value[i], i);
1269
1357
  }
1270
1358
  return res;
1359
+ } else if (ArrayBuffer.isView(value)) {
1360
+ return value;
1271
1361
  } else if (value !== null && typeof value === "object") {
1272
1362
  const res = {};
1273
1363
  this._cyclic.set(value, res);
@@ -1312,27 +1402,27 @@ var orderKeys = (obj, order) => {
1312
1402
 
1313
1403
  // src/order.ts
1314
1404
  var inferObjectOrder = (objectMap, order = []) => {
1315
- const orderedObjects = order.reduce((acc, id) => {
1316
- if (id in objectMap) {
1317
- acc.objects.push(objectMap[id]);
1318
- acc.ids.add(id);
1405
+ const orderedObjects = order.reduce((acc, id2) => {
1406
+ if (id2 in objectMap) {
1407
+ acc.objects.push(objectMap[id2]);
1408
+ acc.ids.add(id2);
1319
1409
  }
1320
1410
  return acc;
1321
1411
  }, {
1322
1412
  objects: [],
1323
1413
  ids: /* @__PURE__ */ new Set()
1324
1414
  });
1325
- const { objects } = Object.keys(objectMap).reduce((acc, id) => {
1326
- if (!acc.ids.has(id)) {
1327
- acc.objects.push(objectMap[id]);
1415
+ const { objects } = Object.keys(objectMap).reduce((acc, id2) => {
1416
+ if (!acc.ids.has(id2)) {
1417
+ acc.objects.push(objectMap[id2]);
1328
1418
  }
1329
1419
  return acc;
1330
1420
  }, orderedObjects);
1331
1421
  return objects;
1332
1422
  };
1333
1423
  var inferRecordOrder = (objectMap, order = []) => {
1334
- return Object.assign(order.filter((id) => id in objectMap).reduce((acc, id) => {
1335
- acc[id] = null;
1424
+ return Object.assign(order.filter((id2) => id2 in objectMap).reduce((acc, id2) => {
1425
+ acc[id2] = null;
1336
1426
  return acc;
1337
1427
  }, {}), objectMap);
1338
1428
  };
@@ -1418,12 +1508,12 @@ var getHostPlatform = () => {
1418
1508
  };
1419
1509
 
1420
1510
  // src/position.ts
1421
- var byPosition = ({ position: a = "static" }, { position: b = "static" }) => {
1511
+ var byPosition = ({ position: a }, { position: b }) => {
1422
1512
  if (a === b) {
1423
1513
  return 0;
1424
- } else if (a === "hoist" || b === "fallback") {
1514
+ } else if (a === "first" || b === "last") {
1425
1515
  return -1;
1426
- } else if (b === "hoist" || a === "fallback") {
1516
+ } else if (b === "first" || a === "last") {
1427
1517
  return 1;
1428
1518
  } else {
1429
1519
  return 0;
@@ -1576,6 +1666,43 @@ var removeProperties = (root, condition) => {
1576
1666
  return result;
1577
1667
  };
1578
1668
 
1669
+ // src/retry.ts
1670
+ var DEFAULT_RETRY_OPTIONS = {
1671
+ count: 3,
1672
+ delayMs: 100,
1673
+ exponent: 2,
1674
+ retryOnError: async () => true,
1675
+ retryOnValue: async () => false
1676
+ };
1677
+ var retry = async (options, cb) => {
1678
+ const fullOptions = {
1679
+ ...DEFAULT_RETRY_OPTIONS,
1680
+ ...options
1681
+ };
1682
+ let numRetries = 0, currentDelay = fullOptions.delayMs;
1683
+ while (true) {
1684
+ let result;
1685
+ try {
1686
+ result = await cb();
1687
+ } catch (err) {
1688
+ if (numRetries > fullOptions.count || !await fullOptions.retryOnError(err)) {
1689
+ throw err;
1690
+ }
1691
+ await new Promise((resolve) => setTimeout(resolve, currentDelay));
1692
+ currentDelay *= fullOptions.exponent;
1693
+ numRetries++;
1694
+ continue;
1695
+ }
1696
+ if (!await fullOptions.retryOnValue(result)) {
1697
+ return result;
1698
+ }
1699
+ await new Promise((resolve) => setTimeout(resolve, currentDelay));
1700
+ currentDelay *= fullOptions.exponent;
1701
+ numRetries++;
1702
+ continue;
1703
+ }
1704
+ };
1705
+
1579
1706
  // src/safe-await.ts
1580
1707
  var safeAwaitAll = async (source, taskFactory, onError) => {
1581
1708
  const failedItems = [];
@@ -1595,7 +1722,7 @@ var safeAwaitAll = async (source, taskFactory, onError) => {
1595
1722
  };
1596
1723
 
1597
1724
  // src/safe-instanceof.ts
1598
- var instanceTag = Symbol("instanceTag");
1725
+ var instanceTag = /* @__PURE__ */ Symbol("instanceTag");
1599
1726
  var safeInstanceof = (tag) => (target) => {
1600
1727
  target.prototype[instanceTag] = tag;
1601
1728
  Object.defineProperty(target.prototype, Symbol.hasInstance, {
@@ -1632,6 +1759,13 @@ var safeParseJson = (str, defaultValue) => {
1632
1759
  }
1633
1760
  return defaultValue;
1634
1761
  };
1762
+ var safeUrl = (str) => {
1763
+ try {
1764
+ return new URL(str ?? "");
1765
+ } catch {
1766
+ return void 0;
1767
+ }
1768
+ };
1635
1769
 
1636
1770
  // src/safe-stringify.ts
1637
1771
  var SKIP = Object.freeze({});
@@ -1642,6 +1776,9 @@ function safeStringify(obj, filter = defaultFilter, indent = 2) {
1642
1776
  let path = key;
1643
1777
  if (!key) {
1644
1778
  path = "$";
1779
+ if (value != null && typeof value === "object") {
1780
+ seen.set(value, path);
1781
+ }
1645
1782
  return value;
1646
1783
  } else if (this) {
1647
1784
  const parentPath = seen.get(this);
@@ -1653,7 +1790,7 @@ function safeStringify(obj, filter = defaultFilter, indent = 2) {
1653
1790
  if (typeof value === "function") {
1654
1791
  return void 0;
1655
1792
  }
1656
- if (typeof value === "object" && Object.getPrototypeOf(value) !== Object.prototype) {
1793
+ if (typeof value === "object" && Object.getPrototypeOf(value) !== Object.prototype && !Array.isArray(value)) {
1657
1794
  return void 0;
1658
1795
  }
1659
1796
  if (typeof value === "object" && value !== null) {
@@ -1674,7 +1811,11 @@ function safeStringify(obj, filter = defaultFilter, indent = 2) {
1674
1811
  return `ERROR: ${error.message}`;
1675
1812
  }
1676
1813
  }
1677
- return JSON.stringify(obj, replacer, indent);
1814
+ try {
1815
+ return JSON.stringify(obj, replacer, indent);
1816
+ } catch (error) {
1817
+ return `ERROR: ${error.message}`;
1818
+ }
1678
1819
  }
1679
1820
  var createReplacer = ({ omit: omit2, parse, maxDepth, maxArrayLen, maxStringLen } = {}) => {
1680
1821
  let currentDepth = 0;
@@ -1689,6 +1830,9 @@ var createReplacer = ({ omit: omit2, parse, maxDepth, maxArrayLen, maxStringLen
1689
1830
  if (typeof value === "function") {
1690
1831
  return SKIP;
1691
1832
  }
1833
+ if (maxArrayLen != null && Array.isArray(value) && value.length > maxArrayLen) {
1834
+ return `[length: ${value.length}]`;
1835
+ }
1692
1836
  if (value && typeof value === "object") {
1693
1837
  depthMap.set(value, currentDepth);
1694
1838
  if (maxDepth != null && currentDepth >= maxDepth) {
@@ -1705,9 +1849,6 @@ var createReplacer = ({ omit: omit2, parse, maxDepth, maxArrayLen, maxStringLen
1705
1849
  return value;
1706
1850
  }
1707
1851
  }
1708
- if (maxArrayLen != null && Array.isArray(value) && value.length > maxArrayLen) {
1709
- return `[length: ${value.length}]`;
1710
- }
1711
1852
  if (maxStringLen != null && typeof value === "string" && value.length > maxStringLen) {
1712
1853
  return value.slice(0, maxStringLen) + "...";
1713
1854
  }
@@ -1718,7 +1859,6 @@ var defaultFilter = createReplacer();
1718
1859
 
1719
1860
  // src/sliding-window-summary.ts
1720
1861
  import { invariant as invariant5 } from "@dxos/invariant";
1721
- var __dxlog_file5 = "/__w/dxos/dxos/packages/common/util/src/sliding-window-summary.ts";
1722
1862
  var SlidingWindowSummary = class {
1723
1863
  _buffer;
1724
1864
  _sum = 0;
@@ -1726,15 +1866,7 @@ var SlidingWindowSummary = class {
1726
1866
  constructor(options) {
1727
1867
  this._buffer = new CircularBuffer(options.dataPoints);
1728
1868
  if (options.precision != null) {
1729
- invariant5(options.precision >= 0, void 0, {
1730
- F: __dxlog_file5,
1731
- L: 26,
1732
- S: this,
1733
- A: [
1734
- "options.precision >= 0",
1735
- ""
1736
- ]
1737
- });
1869
+ invariant5(options.precision >= 0);
1738
1870
  this._precision = Math.pow(10, options.precision);
1739
1871
  }
1740
1872
  }
@@ -1803,6 +1935,10 @@ var capitalize = (str) => {
1803
1935
  }
1804
1936
  return str.charAt(0).toUpperCase() + str.slice(1);
1805
1937
  };
1938
+ function inline(strings, ...values) {
1939
+ const raw = strings.reduce((out, str, i) => out + str + (i < values.length ? String(values[i]) : ""), "");
1940
+ return raw.replace(/\s+/g, " ").trim();
1941
+ }
1806
1942
  function trim(strings, ...values) {
1807
1943
  const raw = strings.reduce((out, str, i) => {
1808
1944
  out += str;
@@ -1815,8 +1951,12 @@ function trim(strings, ...values) {
1815
1951
  return out;
1816
1952
  }, "");
1817
1953
  const lines = raw.split("\n");
1818
- while (lines.length && !lines[0].trim()) lines.shift();
1819
- while (lines.length && !lines[lines.length - 1].trim()) lines.pop();
1954
+ while (lines.length && !lines[0].trim()) {
1955
+ lines.shift();
1956
+ }
1957
+ while (lines.length && !lines[lines.length - 1].trim()) {
1958
+ lines.pop();
1959
+ }
1820
1960
  const minIndent = Math.min(...lines.filter((l) => l.trim()).map((l) => l.match(/^[ \t]*/)?.[0].length ?? 0));
1821
1961
  return lines.map((l) => l.slice(minIndent)).join("\n");
1822
1962
  }
@@ -1834,18 +1974,6 @@ var throwUnhandledError = (error) => {
1834
1974
 
1835
1975
  // src/to-fallback.ts
1836
1976
  var idEmoji = [
1837
- // When changing this set, please check the result in a console or e.g. RunKit (https://runkit.com/thure/642214441dd6ae000855a8de)
1838
- // 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.
1839
- // This set was chosen from the characters in Unicode Emoji v15.0 based on the following criteria:
1840
- // – not people or isolated anthropomorphic faces
1841
- // – not flags
1842
- // – more concrete than abstract
1843
- // – less culturally specific
1844
- // – less easily confused with another emoji in the set
1845
- // – requires less special knowledge to identify
1846
- // – less likely to evoke negative feelings (no meat, no drugs, no weapons, etc)
1847
- // – less common as a signifier in UX
1848
- // NOTE that this is intentionally an array of strings because of the way emoji graphemes work.
1849
1977
  "\u{1F47B}",
1850
1978
  "\u{1F479}",
1851
1979
  "\u{1F47D}",
@@ -1981,17 +2109,18 @@ var idEmoji = [
1981
2109
  ];
1982
2110
  var idHue = [
1983
2111
  "red",
1984
- // 'orange' as const, /* More shades in these palettes are considered “ugly” */
2112
+ "orange",
1985
2113
  "amber",
1986
- // 'yellow' as const, /* More shades in these palettes are considered “ugly” */
2114
+ "yellow",
1987
2115
  "lime",
1988
2116
  "green",
1989
2117
  "emerald",
1990
2118
  "teal",
1991
2119
  "cyan",
1992
- // 'sky' as const, /* Omitted since it is quite similar to the primary accent palette */
1993
- // 'blue' as const, /* Omitted since it is quite similar to the primary accent palette */
1994
- // 'indigo' as const, /* Omitted since it is quite similar to the primary accent palette */
2120
+ // Omit colors similar to primary accent.
2121
+ // 'sky' as const,
2122
+ // 'blue' as const,
2123
+ // 'indigo' as const,
1995
2124
  "violet",
1996
2125
  "purple",
1997
2126
  "fuchsia",
@@ -2030,8 +2159,8 @@ var Tracer = class {
2030
2159
  keys() {
2031
2160
  return Array.from(this._events.keys());
2032
2161
  }
2033
- get(id, filter) {
2034
- const events = this._events.get(id);
2162
+ get(id2, filter) {
2163
+ const events = this._events.get(id2);
2035
2164
  if (filter) {
2036
2165
  return events?.filter((event) => Object.entries(filter).every(([key, value]) => event?.value[key] === value));
2037
2166
  }
@@ -2048,11 +2177,11 @@ var Tracer = class {
2048
2177
  this._recording = false;
2049
2178
  return this;
2050
2179
  }
2051
- emit(id, value) {
2052
- this._post(this._createEvent(id, value));
2180
+ emit(id2, value) {
2181
+ this._post(this._createEvent(id2, value));
2053
2182
  }
2054
- mark(id, value) {
2055
- const event = this._createEvent(id, value);
2183
+ mark(id2, value) {
2184
+ const event = this._createEvent(id2, value);
2056
2185
  const start = performance.now();
2057
2186
  return {
2058
2187
  start,
@@ -2062,9 +2191,9 @@ var Tracer = class {
2062
2191
  }
2063
2192
  };
2064
2193
  }
2065
- _createEvent(id, value) {
2194
+ _createEvent(id2, value) {
2066
2195
  const event = {
2067
- id,
2196
+ id: id2,
2068
2197
  timestamp: Date.now()
2069
2198
  };
2070
2199
  if (value !== void 0) {
@@ -2162,11 +2291,15 @@ function arraySwap(array, from, to) {
2162
2291
  var createFormat = (unit) => {
2163
2292
  return (n, precision = unit.precision ?? 0) => {
2164
2293
  const value = n / unit.quotient;
2294
+ const formattedValue = value.toLocaleString("en-US", {
2295
+ minimumFractionDigits: precision,
2296
+ maximumFractionDigits: precision
2297
+ });
2165
2298
  return {
2166
2299
  unit,
2167
2300
  value,
2168
- formattedValue: value.toFixed(precision),
2169
- toString: () => `${value.toFixed(precision)}${unit.symbol}`
2301
+ formattedValue,
2302
+ toString: () => `${formattedValue}${unit.symbol}`
2170
2303
  };
2171
2304
  };
2172
2305
  };
@@ -2271,15 +2404,19 @@ var createUrl = (url, search) => {
2271
2404
  // src/weak.ts
2272
2405
  var WeakDictionary = class {
2273
2406
  _internal = /* @__PURE__ */ new Map();
2274
- _finalization = new FinalizationRegistry((cleanUpCallback) => {
2275
- cleanUpCallback();
2407
+ _finalization = new FinalizationRegistry(({ key, ref }) => {
2408
+ if (this._internal.get(key) === ref) {
2409
+ this._internal.delete(key);
2410
+ }
2276
2411
  });
2277
2412
  constructor(entries2) {
2278
- this._internal = new Map(entries2?.map(([key, value]) => [
2279
- key,
2280
- new WeakRef(value)
2281
- ]));
2282
- entries2?.forEach(([key, value]) => this._register(key, value));
2413
+ if (entries2) {
2414
+ for (const [key, value] of entries2) {
2415
+ const ref = new WeakRef(value);
2416
+ this._internal.set(key, ref);
2417
+ this._register(key, value, ref);
2418
+ }
2419
+ }
2283
2420
  }
2284
2421
  *entries() {
2285
2422
  for (const [key, value] of this._internal) {
@@ -2319,10 +2456,45 @@ var WeakDictionary = class {
2319
2456
  return this._internal.get(key)?.deref();
2320
2457
  }
2321
2458
  set(key, value) {
2322
- this._internal.set(key, new WeakRef(value));
2323
- this._register(key, value);
2459
+ const previous = this._internal.get(key)?.deref();
2460
+ if (previous) {
2461
+ this._unregister(previous);
2462
+ }
2463
+ const ref = new WeakRef(value);
2464
+ this._internal.set(key, ref);
2465
+ this._register(key, value, ref);
2324
2466
  return this;
2325
2467
  }
2468
+ /**
2469
+ * Returns the value for the given key if present, otherwise inserts and returns the default value.
2470
+ * @param key - The key to look up or insert.
2471
+ * @param defaultValue - The value to insert if the key is not present.
2472
+ * @returns The existing or newly inserted value.
2473
+ */
2474
+ getOrInsert(key, defaultValue) {
2475
+ const existing = this.get(key);
2476
+ if (existing !== void 0) {
2477
+ return existing;
2478
+ }
2479
+ this.set(key, defaultValue);
2480
+ return defaultValue;
2481
+ }
2482
+ /**
2483
+ * Returns the value for the given key if present, otherwise computes, inserts, and returns a new value.
2484
+ * The callback is only invoked when the key is missing.
2485
+ * @param key - The key to look up or insert.
2486
+ * @param callbackfn - Function to compute the value if the key is not present.
2487
+ * @returns The existing or newly computed value.
2488
+ */
2489
+ getOrInsertComputed(key, callbackfn) {
2490
+ const existing = this.get(key);
2491
+ if (existing !== void 0) {
2492
+ return existing;
2493
+ }
2494
+ const value = callbackfn(key);
2495
+ this.set(key, value);
2496
+ return value;
2497
+ }
2326
2498
  has(key) {
2327
2499
  return this._internal.has(key) && this._internal.get(key).deref() !== void 0;
2328
2500
  }
@@ -2353,67 +2525,16 @@ var WeakDictionary = class {
2353
2525
  }
2354
2526
  });
2355
2527
  }
2356
- _register(key, value) {
2357
- this._finalization.register(value, () => {
2358
- this._internal.delete(key);
2528
+ _register(key, value, ref) {
2529
+ this._finalization.register(value, {
2530
+ key,
2531
+ ref
2359
2532
  }, value);
2360
2533
  }
2361
2534
  _unregister(value) {
2362
2535
  this._finalization.unregister(value);
2363
2536
  }
2364
2537
  };
2365
-
2366
- // src/error-format.ts
2367
- var formatErrorWithCauses = (error) => {
2368
- const lines = [];
2369
- let current = error;
2370
- let level = 0;
2371
- while (current) {
2372
- const prefix = level === 0 ? "" : `Caused by: `;
2373
- lines.push(prefix + (current.stack ?? String(current)));
2374
- if (!(current.cause instanceof Error)) break;
2375
- current = current.cause;
2376
- level += 1;
2377
- }
2378
- return lines.join("\n\n");
2379
- };
2380
-
2381
- // src/retry.ts
2382
- var DEFAULT_RETRY_OPTIONS = {
2383
- count: 3,
2384
- delayMs: 100,
2385
- exponent: 2,
2386
- retryOnError: async () => true,
2387
- retryOnValue: async () => false
2388
- };
2389
- var retry = async (options, cb) => {
2390
- const fullOptions = {
2391
- ...DEFAULT_RETRY_OPTIONS,
2392
- ...options
2393
- };
2394
- let numRetries = 0, currentDelay = fullOptions.delayMs;
2395
- while (true) {
2396
- let result;
2397
- try {
2398
- result = await cb();
2399
- } catch (err) {
2400
- if (numRetries > fullOptions.count || !await fullOptions.retryOnError(err)) {
2401
- throw err;
2402
- }
2403
- await new Promise((resolve) => setTimeout(resolve, currentDelay));
2404
- currentDelay *= fullOptions.exponent;
2405
- numRetries++;
2406
- continue;
2407
- }
2408
- if (!await fullOptions.retryOnValue(result)) {
2409
- return result;
2410
- }
2411
- await new Promise((resolve) => setTimeout(resolve, currentDelay));
2412
- currentDelay *= fullOptions.exponent;
2413
- numRetries++;
2414
- continue;
2415
- }
2416
- };
2417
2538
  export {
2418
2539
  BitField,
2419
2540
  Callback,
@@ -2441,12 +2562,17 @@ export {
2441
2562
  capitalize,
2442
2563
  chunkArray,
2443
2564
  clamp,
2565
+ clearCaches,
2566
+ clearIndexedDB,
2567
+ clearOPFS,
2568
+ clearServiceWorkers,
2444
2569
  clearUndefined,
2445
2570
  coerceArray,
2446
2571
  compareMulti,
2447
2572
  compareObject,
2448
2573
  compareScalar,
2449
2574
  compareString,
2575
+ compositeKey,
2450
2576
  createBinder,
2451
2577
  createBucketReducer,
2452
2578
  createFilename,
@@ -2455,6 +2581,7 @@ export {
2455
2581
  createSetDispatch,
2456
2582
  createUrl,
2457
2583
  decamelize,
2584
+ decodeUint8ArrayFromJson,
2458
2585
  deepMapValues,
2459
2586
  deepMapValuesAsync,
2460
2587
  defaultFilter,
@@ -2465,12 +2592,12 @@ export {
2465
2592
  diff,
2466
2593
  distinctBy,
2467
2594
  doAsync,
2595
+ encodeUint8ArrayToJson,
2468
2596
  entries,
2469
2597
  entry,
2470
2598
  exponentialBackoffInterval,
2471
2599
  forEachAsync,
2472
2600
  formatErrorWithCauses,
2473
- get,
2474
2601
  getAsyncProviderValue,
2475
2602
  getDate,
2476
2603
  getDebugName,
@@ -2483,20 +2610,25 @@ export {
2483
2610
  hexToHue,
2484
2611
  humanize,
2485
2612
  hyphenize,
2613
+ id,
2486
2614
  idEmoji,
2487
2615
  idHue,
2488
2616
  inferObjectOrder,
2489
2617
  inferRecordOrder,
2618
+ inline,
2490
2619
  intersectBy,
2491
2620
  intersection,
2492
2621
  iosCheck,
2493
2622
  isBun,
2623
+ isEncodedUint8Array,
2494
2624
  isMobile,
2495
2625
  isMobileOrTablet,
2496
2626
  isNode,
2497
2627
  isNonNullable,
2498
2628
  isTauri,
2499
2629
  isTruthy,
2630
+ isWellFormedId,
2631
+ isWellFormedIdPart,
2500
2632
  joinTables,
2501
2633
  jsonKeyReplacer,
2502
2634
  jsonReplacer,
@@ -2534,9 +2666,10 @@ export {
2534
2666
  safeParseInt,
2535
2667
  safeParseJson,
2536
2668
  safeStringify,
2537
- set,
2669
+ safeUrl,
2538
2670
  setDeep,
2539
2671
  sortKeys,
2672
+ splitCompositeKey,
2540
2673
  stringToArray,
2541
2674
  stringifyTree,
2542
2675
  stripUndefined,