@dxos/util 0.9.1-staging.ee54ba693a → 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.
- package/dist/lib/index.mjs +2575 -0
- package/dist/lib/index.mjs.map +1 -0
- package/dist/types/src/to-fallback.d.ts +13 -0
- package/dist/types/src/to-fallback.d.ts.map +1 -1
- package/dist/types/src/unit.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -11
- package/src/to-fallback.ts +31 -0
- package/src/unit.test.ts +7 -2
- package/src/unit.ts +6 -5
- package/dist/lib/browser/index.mjs +0 -2696
- package/dist/lib/browser/index.mjs.map +0 -7
- package/dist/lib/browser/meta.json +0 -1
- package/dist/lib/node-esm/index.mjs +0 -2696
- package/dist/lib/node-esm/index.mjs.map +0 -7
- package/dist/lib/node-esm/meta.json +0 -1
|
@@ -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
|