@esposter/shared 4.3.2 → 4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -3,47 +3,42 @@ import { ResultAsync, fromThrowable } from "neverthrow";
3
3
  import { parse } from "node-html-parser";
4
4
  import mimeDatabase from "mime-db/db.json" with { type: "json" };
5
5
  import { defaultTreeAdapter, html as html$1, parseFragment } from "parse5";
6
- //#region src/models/error/ForbiddenError.ts
6
+ // src/models/error/ForbiddenError.ts
7
7
  var ForbiddenError = class extends Error {
8
8
  constructor(message) {
9
9
  super(message);
10
10
  this.name = "ForbiddenError";
11
11
  }
12
12
  };
13
- //#endregion
14
- //#region src/models/error/InvalidOperationError.ts
13
+ // src/models/error/InvalidOperationError.ts
15
14
  var InvalidOperationError = class extends Error {
16
15
  constructor(operation, name, message) {
17
16
  super(`Invalid operation: ${operation}, name: ${name}, ${message}`);
18
17
  this.name = "InvalidOperationError";
19
18
  }
20
19
  };
21
- //#endregion
22
- //#region src/models/error/NotFoundError.ts
20
+ // src/models/error/NotFoundError.ts
23
21
  var NotFoundError = class extends Error {
24
22
  constructor(name, id) {
25
23
  super(`${name} is not found for id: ${id}`);
26
24
  this.name = "NotFoundError";
27
25
  }
28
26
  };
29
- //#endregion
30
- //#region src/models/error/NotInitializedError.ts
27
+ // src/models/error/NotInitializedError.ts
31
28
  var NotInitializedError = class extends Error {
32
29
  constructor(name) {
33
30
  super(`${name} is not initialized`);
34
31
  this.name = "NotInitializedError";
35
32
  }
36
33
  };
37
- //#endregion
38
- //#region src/models/error/WordFilteredError.ts
34
+ // src/models/error/WordFilteredError.ts
39
35
  var WordFilteredError = class extends Error {
40
36
  constructor(message) {
41
37
  super(message);
42
38
  this.name = "WordFilteredError";
43
39
  }
44
40
  };
45
- //#endregion
46
- //#region src/models/shared/Operation.ts
41
+ // src/models/shared/Operation.ts
47
42
  let Operation = /* @__PURE__ */ function(Operation) {
48
43
  Operation["Create"] = "Create";
49
44
  Operation["Delete"] = "Delete";
@@ -53,8 +48,7 @@ let Operation = /* @__PURE__ */ function(Operation) {
53
48
  Operation["Update"] = "Update";
54
49
  return Operation;
55
50
  }({});
56
- //#endregion
57
- //#region src/models/eventEmitter/TypedEventEmitter.ts
51
+ // src/models/eventEmitter/TypedEventEmitter.ts
58
52
  var TypedEventEmitter = class {
59
53
  #entriesMap = /* @__PURE__ */ new Map();
60
54
  emit(event, ...args) {
@@ -89,8 +83,7 @@ var TypedEventEmitter = class {
89
83
  else this.#entriesMap.set(event, entries);
90
84
  }
91
85
  };
92
- //#endregion
93
- //#region src/models/jsonPatch/JsonPatchOperationType.ts
86
+ // src/models/jsonPatch/JsonPatchOperationType.ts
94
87
  let JsonPatchOperationType = /* @__PURE__ */ function(JsonPatchOperationType) {
95
88
  JsonPatchOperationType["Add"] = "add";
96
89
  JsonPatchOperationType["Copy"] = "copy";
@@ -100,28 +93,24 @@ let JsonPatchOperationType = /* @__PURE__ */ function(JsonPatchOperationType) {
100
93
  JsonPatchOperationType["Test"] = "test";
101
94
  return JsonPatchOperationType;
102
95
  }({});
103
- //#endregion
104
- //#region src/models/message/MentionType.ts
96
+ // src/models/message/MentionType.ts
105
97
  let MentionType = /* @__PURE__ */ function(MentionType) {
106
98
  MentionType["Role"] = "role";
107
99
  MentionType["User"] = "user";
108
100
  return MentionType;
109
101
  }({});
110
- //#endregion
111
- //#region src/models/object/ObjectMethod.ts
102
+ // src/models/object/ObjectMethod.ts
112
103
  let ObjectMethod = /* @__PURE__ */ function(ObjectMethod) {
113
104
  ObjectMethod["ToString"] = "toString";
114
105
  ObjectMethod["ValueOf"] = "valueOf";
115
106
  return ObjectMethod;
116
107
  }({});
117
- //#endregion
118
- //#region src/services/app/constants.ts
108
+ // src/services/app/constants.ts
119
109
  const MAX_READ_LIMIT = 1e3;
120
110
  const SITE_NAME = "Esposter";
121
111
  const KIBIBYTE = 1024;
122
112
  const GIBIBYTE = KIBIBYTE ** 2 * KIBIBYTE;
123
- //#endregion
124
- //#region src/models/router/RoutePath.ts
113
+ // src/models/router/RoutePath.ts
125
114
  const RoutePath = {
126
115
  About: "/about",
127
116
  Achievements: "/achievements",
@@ -160,24 +149,24 @@ const RoutePath = {
160
149
  UserSettings: "/user/settings",
161
150
  View: (type, id) => `/view/${type}/${id}`
162
151
  };
163
- //#endregion
164
- //#region src/models/shared/ItemEntityType.ts
152
+ // src/models/shared/ItemEntityType.ts
165
153
  const createItemEntityTypeSchema = (schema) => z.object({ type: schema });
166
- //#endregion
167
- //#region src/models/shared/ItemMetadata.ts
154
+ // src/models/shared/ItemMetadata.ts
168
155
  var ItemMetadata = class {
169
156
  createdAt = /* @__PURE__ */ new Date();
170
157
  deletedAt = null;
171
158
  updatedAt = /* @__PURE__ */ new Date();
172
159
  };
173
- //#endregion
174
- //#region src/util/reactivity/getRawData.ts
160
+ // src/util/object/getPropertyNames.ts
161
+ const getPropertyNames = () => new Proxy({}, { get: (_target, property) => property });
162
+ // src/models/shared/ItemMetadataPropertyNames.ts
163
+ const ItemMetadataPropertyNames = getPropertyNames();
164
+ // src/util/reactivity/getRawData.ts
175
165
  const getRawData = (data) => {
176
166
  const raw = data && data.__v_raw;
177
167
  return raw ? getRawData(raw) : data;
178
168
  };
179
- //#endregion
180
- //#region src/util/reactivity/toRawDeep.ts
169
+ // src/util/reactivity/toRawDeep.ts
181
170
  const toRawDeep = (data) => {
182
171
  const rawData = getRawData(data);
183
172
  for (const key in rawData) if (Object.hasOwn(rawData, key)) {
@@ -186,28 +175,23 @@ const toRawDeep = (data) => {
186
175
  }
187
176
  return rawData;
188
177
  };
189
- //#endregion
190
- //#region src/models/shared/Serializable.ts
178
+ // src/models/shared/Serializable.ts
191
179
  var Serializable = class {
192
180
  toJSON() {
193
181
  return structuredClone(toRawDeep(this));
194
182
  }
195
183
  };
196
- //#endregion
197
- //#region src/services/error/toAppError.ts
184
+ // src/services/error/toAppError.ts
198
185
  const toAppError = (error) => {
199
186
  if (error instanceof Error) return error;
200
187
  else if (typeof error === "object" && error !== null && "message" in error && typeof error.message === "string") return new Error(error.message, { cause: error });
201
188
  else return new Error(String(error), { cause: error });
202
189
  };
203
- //#endregion
204
- //#region src/services/error/getResult.ts
190
+ // src/services/error/getResult.ts
205
191
  const getResult = (callback) => fromThrowable(callback, toAppError)();
206
- //#endregion
207
- //#region src/services/error/getResultAsync.ts
192
+ // src/services/error/getResultAsync.ts
208
193
  const getResultAsync = (callback) => ResultAsync.fromThrowable(callback, toAppError)();
209
- //#endregion
210
- //#region src/services/error/reportFinalizerError.ts
194
+ // src/services/error/reportFinalizerError.ts
211
195
  const reportFinalizerError = (callbackResult, finalizerError) => {
212
196
  callbackResult.match(() => {
213
197
  throw finalizerError;
@@ -215,11 +199,9 @@ const reportFinalizerError = (callbackResult, finalizerError) => {
215
199
  console.error(finalizerError);
216
200
  });
217
201
  };
218
- //#endregion
219
- //#region src/util/function/noop.ts
202
+ // src/util/function/noop.ts
220
203
  const noop = () => {};
221
- //#endregion
222
- //#region src/services/error/withFinalizer.ts
204
+ // src/services/error/withFinalizer.ts
223
205
  const withFinalizer = (callback, finalizer) => {
224
206
  const callbackResult = getResult(callback);
225
207
  if (finalizer) getResult(finalizer).match(noop, (error) => {
@@ -229,26 +211,27 @@ const withFinalizer = (callback, finalizer) => {
229
211
  throw error;
230
212
  });
231
213
  };
232
- //#endregion
233
- //#region src/services/error/withFinalizerAsync.ts
214
+ // src/services/error/withFinalizerAsync.ts
234
215
  const withFinalizerAsync = async (callback, finalizer) => {
235
- const callbackResult = await getResultAsync(async () => callback());
236
- if (finalizer) await getResultAsync(async () => finalizer()).match(noop, (error) => {
216
+ const callbackResult = await getResultAsync(async () => {
217
+ return await callback();
218
+ });
219
+ if (finalizer) await getResultAsync(async () => {
220
+ await finalizer();
221
+ }).match(noop, (error) => {
237
222
  reportFinalizerError(callbackResult, error);
238
223
  });
239
224
  return callbackResult.match((value) => value, (error) => {
240
225
  throw error;
241
226
  });
242
227
  };
243
- //#endregion
244
- //#region src/services/history/createHistory.ts
228
+ // src/services/history/createHistory.ts
245
229
  const createHistory = (limit) => ({
246
230
  future: [],
247
231
  limit,
248
232
  past: []
249
233
  });
250
- //#endregion
251
- //#region src/services/history/pushHistory.ts
234
+ // src/services/history/pushHistory.ts
252
235
  const pushHistory = (history, entry) => {
253
236
  const past = [...history.past, entry];
254
237
  return {
@@ -257,8 +240,7 @@ const pushHistory = (history, entry) => {
257
240
  past: past.slice(Math.max(past.length - history.limit, 0))
258
241
  };
259
242
  };
260
- //#endregion
261
- //#region src/services/history/redoHistory.ts
243
+ // src/services/history/redoHistory.ts
262
244
  const redoHistory = (history) => {
263
245
  const [entry] = history.future;
264
246
  if (entry === void 0) return { history };
@@ -270,8 +252,7 @@ const redoHistory = (history) => {
270
252
  }
271
253
  };
272
254
  };
273
- //#endregion
274
- //#region src/services/history/undoHistory.ts
255
+ // src/services/history/undoHistory.ts
275
256
  const undoHistory = (history) => {
276
257
  const entry = history.past.at(-1);
277
258
  if (entry === void 0) return { history };
@@ -284,11 +265,9 @@ const undoHistory = (history) => {
284
265
  }
285
266
  };
286
267
  };
287
- //#endregion
288
- //#region src/services/indexedDb/getRequestError.ts
268
+ // src/services/indexedDb/getRequestError.ts
289
269
  const getRequestError = (request) => request.error ?? new DOMException("The request failed without an error", "UnknownError");
290
- //#endregion
291
- //#region src/services/indexedDb/getTransactionDone.ts
270
+ // src/services/indexedDb/getTransactionDone.ts
292
271
  const getTransactionDone = (transaction) => new Promise((resolve, reject) => {
293
272
  transaction.addEventListener("complete", () => {
294
273
  resolve();
@@ -297,8 +276,7 @@ const getTransactionDone = (transaction) => new Promise((resolve, reject) => {
297
276
  reject(transaction.error ?? new DOMException("The transaction was aborted", "AbortError"));
298
277
  });
299
278
  });
300
- //#endregion
301
- //#region src/services/indexedDb/requestToPromise.ts
279
+ // src/services/indexedDb/requestToPromise.ts
302
280
  const requestToPromise = (request) => new Promise((resolve, reject) => {
303
281
  request.addEventListener("success", () => {
304
282
  resolve(request.result);
@@ -307,14 +285,12 @@ const requestToPromise = (request) => new Promise((resolve, reject) => {
307
285
  reject(getRequestError(request));
308
286
  });
309
287
  });
310
- //#endregion
311
- //#region src/services/indexedDb/wrapIndex.ts
288
+ // src/services/indexedDb/wrapIndex.ts
312
289
  const wrapIndex = (index) => ({
313
290
  getAll: (query, count) => requestToPromise(index.getAll(query, count)),
314
291
  getAllKeys: (query, count) => requestToPromise(index.getAllKeys(query, count))
315
292
  });
316
- //#endregion
317
- //#region src/services/indexedDb/wrapObjectStore.ts
293
+ // src/services/indexedDb/wrapObjectStore.ts
318
294
  const wrapObjectStore = (objectStore) => {
319
295
  const reader = {
320
296
  get: (key) => requestToPromise(objectStore.get(key)),
@@ -335,17 +311,14 @@ const wrapObjectStore = (objectStore) => {
335
311
  ...creator
336
312
  };
337
313
  };
338
- //#endregion
339
- //#region src/services/indexedDb/getTransactionObjectStore.ts
314
+ // src/services/indexedDb/getTransactionObjectStore.ts
340
315
  const getTransactionObjectStore = (transaction) => (name) => wrapObjectStore(transaction.objectStore(name));
341
- //#endregion
342
- //#region src/services/indexedDb/wrapTransaction.ts
316
+ // src/services/indexedDb/wrapTransaction.ts
343
317
  const wrapTransaction = (transaction) => ({
344
318
  done: getTransactionDone(transaction),
345
319
  objectStore: getTransactionObjectStore(transaction)
346
320
  });
347
- //#endregion
348
- //#region src/services/indexedDb/wrapDatabase.ts
321
+ // src/services/indexedDb/wrapDatabase.ts
349
322
  const wrapDatabase = (database) => {
350
323
  const getReadonlyObjectStore = (storeName) => wrapObjectStore(database.transaction(storeName, "readonly").objectStore(storeName));
351
324
  const getReadwriteObjectStore = (storeName) => wrapObjectStore(database.transaction(storeName, "readwrite").objectStore(storeName));
@@ -366,19 +339,28 @@ const wrapDatabase = (database) => {
366
339
  transaction
367
340
  };
368
341
  };
369
- //#endregion
370
- //#region src/services/indexedDb/wrapUpgradeDatabase.ts
342
+ // src/services/indexedDb/wrapUpgradeDatabase.ts
371
343
  const wrapUpgradeDatabase = (database) => ({
372
344
  ...wrapDatabase(database),
373
345
  createObjectStore: (name, options) => wrapObjectStore(database.createObjectStore(name, options))
374
346
  });
375
- //#endregion
376
- //#region src/services/indexedDb/wrapUpgradeTransaction.ts
347
+ // src/util/function/getSynchronizedFunction.ts
348
+ const pendingPromises = /* @__PURE__ */ new Set();
349
+ const getSynchronizedFunction = (asyncFunction) => (...args) => {
350
+ const promise = withFinalizerAsync(() => asyncFunction(...args), () => {
351
+ pendingPromises.delete(promise);
352
+ });
353
+ pendingPromises.add(promise);
354
+ };
355
+ const waitForSynchronizedFunctions = async () => {
356
+ await Promise.allSettled(pendingPromises);
357
+ };
358
+ // src/services/indexedDb/wrapUpgradeTransaction.ts
377
359
  const wrapUpgradeTransaction = (transaction) => {
378
360
  const done = getTransactionDone(transaction);
379
- getResultAsync(() => done).match(noop, (error) => {
361
+ getSynchronizedFunction(() => getResultAsync(() => done).match(noop, (error) => {
380
362
  if (transaction.error) console.error(error);
381
- });
363
+ }))();
382
364
  return {
383
365
  get done() {
384
366
  return done;
@@ -386,8 +368,7 @@ const wrapUpgradeTransaction = (transaction) => {
386
368
  objectStore: getTransactionObjectStore(transaction)
387
369
  };
388
370
  };
389
- //#endregion
390
- //#region src/services/indexedDb/openDatabase.ts
371
+ // src/services/indexedDb/openDatabase.ts
391
372
  const openDatabase = (name, version, options = {}) => new Promise((resolve, reject) => {
392
373
  const request = indexedDB.open(name, version);
393
374
  request.addEventListener("blocked", (event) => {
@@ -415,36 +396,30 @@ const openDatabase = (name, version, options = {}) => new Promise((resolve, reje
415
396
  reject(getRequestError(request));
416
397
  });
417
398
  });
418
- //#endregion
419
- //#region src/services/jsonPatch/constants.ts
399
+ // src/services/jsonPatch/constants.ts
420
400
  const APPEND_SEGMENT = "-";
421
401
  const JSON_POINTER_REGEX = /^(?:\/(?:[^/~]|~[01])*)*$/u;
422
- //#endregion
423
- //#region src/services/jsonPatch/parseArrayIndex.ts
402
+ // src/services/jsonPatch/parseArrayIndex.ts
424
403
  const ARRAY_INDEX_REGEX = /^(?:0|[1-9]\d*)$/u;
425
404
  const parseArrayIndex = (segment, maxIndex) => {
426
405
  const index = Number(segment);
427
406
  return ARRAY_INDEX_REGEX.test(segment) && index <= maxIndex ? index : void 0;
428
407
  };
429
- //#endregion
430
- //#region src/services/jsonPatch/parseJsonPointer.ts
408
+ // src/services/jsonPatch/parseJsonPointer.ts
431
409
  const parseJsonPointer = (pointer) => {
432
410
  if (pointer === "") return [];
433
411
  else if (!JSON_POINTER_REGEX.test(pointer)) throw new InvalidOperationError("Read", pointer, "not a JSON Pointer");
434
412
  return pointer.slice(1).split("/").map((segment) => segment.replaceAll("~1", "/").replaceAll("~0", "~"));
435
413
  };
436
- //#endregion
437
- //#region src/services/jsonPatch/toJsonPointer.ts
414
+ // src/services/jsonPatch/toJsonPointer.ts
438
415
  const toJsonPointer = (segments) => segments.map((segment) => `/${segment.replaceAll("~", "~0").replaceAll("/", "~1")}`).join("");
439
- //#endregion
440
- //#region src/util/object/checkIsPlainObject.ts
416
+ // src/util/object/checkIsPlainObject.ts
441
417
  const checkIsPlainObject = (data) => {
442
418
  if (typeof data !== "object" || data === null) return false;
443
419
  const prototype = Object.getPrototypeOf(data);
444
420
  return prototype === null || prototype === Object.prototype;
445
421
  };
446
- //#endregion
447
- //#region src/services/jsonPatch/readJsonValue.ts
422
+ // src/services/jsonPatch/readJsonValue.ts
448
423
  const readJsonValue = (document, segments) => {
449
424
  let value = document;
450
425
  for (const segment of segments) {
@@ -455,8 +430,7 @@ const readJsonValue = (document, segments) => {
455
430
  }
456
431
  return value;
457
432
  };
458
- //#endregion
459
- //#region src/services/jsonPatch/updateJsonValue.ts
433
+ // src/services/jsonPatch/updateJsonValue.ts
460
434
  const updateJsonValue = (document, segments, update) => {
461
435
  const [segment, ...restSegments] = segments;
462
436
  if (segment === void 0) return update(document);
@@ -468,8 +442,7 @@ const updateJsonValue = (document, segments, update) => {
468
442
  };
469
443
  else throw new InvalidOperationError("Update", toJsonPointer(segments), "no such member");
470
444
  };
471
- //#endregion
472
- //#region src/services/jsonPatch/addJsonValue.ts
445
+ // src/services/jsonPatch/addJsonValue.ts
473
446
  const addJsonValue = (document, path, value) => {
474
447
  const segments = parseJsonPointer(path);
475
448
  const parentSegments = segments.slice(0, -1);
@@ -509,8 +482,7 @@ const addJsonValue = (document, path, value) => {
509
482
  };
510
483
  else throw new InvalidOperationError("Update", path, "its parent holds no members");
511
484
  };
512
- //#endregion
513
- //#region src/services/jsonPatch/removeJsonValue.ts
485
+ // src/services/jsonPatch/removeJsonValue.ts
514
486
  const removeJsonValue = (document, path) => {
515
487
  const segments = parseJsonPointer(path);
516
488
  const parentSegments = segments.slice(0, -1);
@@ -538,28 +510,23 @@ const removeJsonValue = (document, path) => {
538
510
  };
539
511
  } else throw new InvalidOperationError("Delete", path, "no such member");
540
512
  };
541
- //#endregion
542
- //#region src/util/object/checkIsCustomMethod.ts
513
+ // src/util/object/checkIsCustomMethod.ts
543
514
  const checkIsCustomMethod = (value, methodName) => {
544
515
  const method = Reflect.get(value, methodName);
545
516
  return typeof method === "function" && method !== Object.prototype[methodName];
546
517
  };
547
- //#endregion
548
- //#region src/util/object/checkIsSameBytes.ts
518
+ // src/util/object/checkIsSameBytes.ts
549
519
  const toBytes = (view) => ArrayBuffer.isView(view) ? new Uint8Array(view.buffer, view.byteOffset, view.byteLength) : new Uint8Array(view);
550
520
  const checkIsSameBytes = (first, second) => {
551
521
  const firstBytes = toBytes(first);
552
522
  const secondBytes = toBytes(second);
553
523
  return firstBytes.length === secondBytes.length && firstBytes.every((byte, index) => byte === secondBytes[index]);
554
524
  };
555
- //#endregion
556
- //#region src/util/object/checkIsSameValueZero.ts
525
+ // src/util/object/checkIsSameValueZero.ts
557
526
  const checkIsSameValueZero = (first, second) => first === second || Number.isNaN(first) && Number.isNaN(second);
558
- //#endregion
559
- //#region src/util/object/getEnumerableKeys.ts
527
+ // src/util/object/getEnumerableKeys.ts
560
528
  const getEnumerableKeys = (value) => Reflect.ownKeys(value).filter((key) => Object.prototype.propertyIsEnumerable.call(value, key));
561
- //#endregion
562
- //#region src/util/object/checkIsDeepEqual.ts
529
+ // src/util/object/checkIsDeepEqual.ts
563
530
  const checkIsBinary = (value) => ArrayBuffer.isView(value) || value instanceof ArrayBuffer || typeof SharedArrayBuffer !== "undefined" && value instanceof SharedArrayBuffer;
564
531
  const checkIsDeepEqual = (first, second) => {
565
532
  if (first === second) return true;
@@ -589,13 +556,11 @@ const checkIsDeepEqual = (first, second) => {
589
556
  if (firstKeys.length !== getEnumerableKeys(second).length) return false;
590
557
  return firstKeys.every((key) => Object.prototype.propertyIsEnumerable.call(second, key) && checkIsDeepEqual(Reflect.get(first, key), Reflect.get(second, key)));
591
558
  };
592
- //#endregion
593
- //#region src/util/validation/exhaustiveGuard.ts
559
+ // src/util/validation/exhaustiveGuard.ts
594
560
  const exhaustiveGuard = (value) => {
595
561
  throw new InvalidOperationError("Read", exhaustiveGuard.name, JSON.stringify(value));
596
562
  };
597
- //#endregion
598
- //#region src/services/jsonPatch/applyPatch.ts
563
+ // src/services/jsonPatch/applyPatch.ts
599
564
  const applyPatch = (document, operation) => {
600
565
  switch (operation.op) {
601
566
  case "add": return addJsonValue(document, operation.path, operation.value);
@@ -637,8 +602,7 @@ const applyPatch = (document, operation) => {
637
602
  default: return exhaustiveGuard(operation);
638
603
  }
639
604
  };
640
- //#endregion
641
- //#region src/services/jsonPatch/applyPatches.ts
605
+ // src/services/jsonPatch/applyPatches.ts
642
606
  const applyPatches = (document, operations) => {
643
607
  let patchedDocument = document;
644
608
  const inverseGroups = [];
@@ -652,8 +616,7 @@ const applyPatches = (document, operations) => {
652
616
  inverses: inverseGroups.toReversed().flat()
653
617
  };
654
618
  };
655
- //#endregion
656
- //#region src/services/message/constants.ts
619
+ // src/services/message/constants.ts
657
620
  const MENTION_ID_ATTRIBUTE = "data-id";
658
621
  const MENTION_ITEM_TYPE_ATTRIBUTE = "data-mention-type";
659
622
  const MENTION_LABEL_ATTRIBUTE = "data-label";
@@ -666,11 +629,13 @@ const CUSTOM_EMOJI_ID_ATTRIBUTE = "data-custom-emoji-id";
666
629
  const CUSTOM_EMOJI_NAME_ATTRIBUTE = "data-custom-emoji-name";
667
630
  const SPOILER_ATTRIBUTE = "data-spoiler";
668
631
  const SPOILER_SELECTOR = `span[${SPOILER_ATTRIBUTE}]`;
669
- //#endregion
670
- //#region src/services/message/getMentions.ts
632
+ // src/services/message/emoji/checkIsOnlyReactor.ts
633
+ const checkIsOnlyReactor = (userIds, userId) => userIds.length === 1 && userIds[0] === userId;
634
+ // src/services/message/emoji/getUpdatedUserIds.ts
635
+ const getUpdatedUserIds = (userIds, newUserId) => userIds.includes(newUserId) ? userIds.filter((id) => id !== newUserId) : [...userIds, newUserId];
636
+ // src/services/message/getMentions.ts
671
637
  const getMentions = (message) => parse(message).querySelectorAll(MENTION_SELECTOR);
672
- //#endregion
673
- //#region src/services/mime/constants.ts
638
+ // src/services/mime/constants.ts
674
639
  const MEDIA_TYPE_REGEX = /^\s*(?<mediaType>[^;\s]*)(?:;|\s|$)/u;
675
640
  const PATH_SEPARATOR_REGEX = /[/\\]/u;
676
641
  const TEXT_MEDIA_TYPE_REGEX = /^text\//iu;
@@ -696,26 +661,22 @@ const TypeScoreMap = /* @__PURE__ */ new Map([
696
661
  ["video", 3]
697
662
  ]);
698
663
  const DEFAULT_TYPE_SCORE = 0;
699
- //#endregion
700
- //#region src/services/mime/getMediaType.ts
664
+ // src/services/mime/getMediaType.ts
701
665
  const getMediaType = (value) => MEDIA_TYPE_REGEX.exec(value)?.groups?.mediaType ?? "";
702
- //#endregion
703
- //#region src/services/mime/getMimeTypeEntryMap.ts
666
+ // src/services/mime/getMimeTypeEntryMap.ts
704
667
  let mimeTypeEntryMap;
705
668
  const getMimeTypeEntryMap = () => {
706
669
  mimeTypeEntryMap ??= new Map(Object.entries(mimeDatabase));
707
670
  return mimeTypeEntryMap;
708
671
  };
709
- //#endregion
710
- //#region src/services/mime/charset.ts
672
+ // src/services/mime/charset.ts
711
673
  const charset = (type) => {
712
674
  const mediaType = getMediaType(type);
713
675
  const dataCharset = getMimeTypeEntryMap().get(mediaType.toLowerCase())?.charset;
714
676
  if (dataCharset) return dataCharset;
715
677
  return TEXT_MEDIA_TYPE_REGEX.test(mediaType) ? DEFAULT_TEXT_CHARSET : false;
716
678
  };
717
- //#endregion
718
- //#region src/services/mime/getMimeScore.ts
679
+ // src/services/mime/getMimeScore.ts
719
680
  const getMimeScore = (mimeType, source = "") => {
720
681
  if (mimeType === "application/octet-stream") return 0;
721
682
  const [type = "", subtype = ""] = mimeType.split("/");
@@ -726,8 +687,7 @@ const getMimeScore = (mimeType, source = "") => {
726
687
  const lengthScore = 1 - mimeType.length / 100;
727
688
  return facetScore + sourceScore + typeScore + lengthScore;
728
689
  };
729
- //#endregion
730
- //#region src/services/mime/getExtensionMimeTypeMap.ts
690
+ // src/services/mime/getExtensionMimeTypeMap.ts
731
691
  let extensionMimeTypeMap;
732
692
  const getPreferredMimeType = (currentMimeType, candidateMimeType) => {
733
693
  if (currentMimeType === void 0) return candidateMimeType;
@@ -742,8 +702,7 @@ const getExtensionMimeTypeMap = () => {
742
702
  }
743
703
  return extensionMimeTypeMap;
744
704
  };
745
- //#endregion
746
- //#region src/services/mime/lookup.ts
705
+ // src/services/mime/lookup.ts
747
706
  const getExtension = (path) => {
748
707
  const name = path.split(PATH_SEPARATOR_REGEX).at(-1) ?? "";
749
708
  const dotIndex = name.lastIndexOf(".");
@@ -755,8 +714,7 @@ const lookup = (path) => {
755
714
  if (!extension) return false;
756
715
  return getExtensionMimeTypeMap().get(extension) ?? false;
757
716
  };
758
- //#endregion
759
- //#region src/services/mime/contentType.ts
717
+ // src/services/mime/contentType.ts
760
718
  const contentType = (value) => {
761
719
  const mediaType = value.includes("/") ? value : lookup(value);
762
720
  if (!mediaType) return false;
@@ -764,17 +722,13 @@ const contentType = (value) => {
764
722
  const mediaCharset = charset(mediaType);
765
723
  return mediaCharset ? `${mediaType}; charset=${mediaCharset.toLowerCase()}` : mediaType;
766
724
  };
767
- //#endregion
768
- //#region src/services/mime/extension.ts
725
+ // src/services/mime/extension.ts
769
726
  const extension = (type) => getMimeTypeEntryMap().get(getMediaType(type).toLowerCase())?.extensions?.[0] ?? false;
770
- //#endregion
771
- //#region src/services/prettier/css.ts
727
+ // src/services/prettier/css.ts
772
728
  const css = String.raw;
773
- //#endregion
774
- //#region src/services/prettier/html.ts
729
+ // src/services/prettier/html.ts
775
730
  const html = String.raw;
776
- //#endregion
777
- //#region src/services/profanity/englishProfaneWords.ts
731
+ // src/services/profanity/englishProfaneWords.ts
778
732
  const englishProfaneWords = [
779
733
  "4r5e",
780
734
  "5h1t",
@@ -1226,8 +1180,7 @@ const englishProfaneWords = [
1226
1180
  "willies",
1227
1181
  "willy"
1228
1182
  ];
1229
- //#endregion
1230
- //#region src/services/profanity/checkContainsProfanity.ts
1183
+ // src/services/profanity/checkContainsProfanity.ts
1231
1184
  const WORD_CHARACTER_CLASS = String.raw`\p{L}\p{N}\p{M}`;
1232
1185
  const PROFANE_WORD_ALTERNATION = englishProfaneWords.map((word) => word.replaceAll(/[.*+?^${}()|[\]\\]/gu, String.raw`\$&`)).join("|");
1233
1186
  const WHOLE_WORD_PROFANITY_REGEX = new RegExp(`(?<![${WORD_CHARACTER_CLASS}])(?:${PROFANE_WORD_ALTERNATION})(?![${WORD_CHARACTER_CLASS}])`, "iu");
@@ -1236,11 +1189,9 @@ const checkContainsProfanity = (text, { isWholeWord = true } = {}) => {
1236
1189
  if (typeof text !== "string") return false;
1237
1190
  return (isWholeWord ? WHOLE_WORD_PROFANITY_REGEX : SUBSTRING_PROFANITY_REGEX).test(text);
1238
1191
  };
1239
- //#endregion
1240
- //#region src/services/sanitizeHtml/checkIsWhitespaceCharacter.ts
1192
+ // src/services/sanitizeHtml/checkIsWhitespaceCharacter.ts
1241
1193
  const checkIsWhitespaceCharacter = (character) => character.trim() === "";
1242
- //#endregion
1243
- //#region src/services/sanitizeHtml/checkIsUnsafeUrlCharacter.ts
1194
+ // src/services/sanitizeHtml/checkIsUnsafeUrlCharacter.ts
1244
1195
  const FIRST_PRINTABLE_CODE_POINT = 32;
1245
1196
  const DELETE_CODE_POINT = 127;
1246
1197
  const LAST_C1_CONTROL_CODE_POINT = 159;
@@ -1249,13 +1200,11 @@ const checkIsUnsafeUrlCharacter = (character) => {
1249
1200
  const codePoint = character.codePointAt(0) ?? 0;
1250
1201
  return checkIsWhitespaceCharacter(character) || codePoint < FIRST_PRINTABLE_CODE_POINT || codePoint >= DELETE_CODE_POINT && codePoint <= LAST_C1_CONTROL_CODE_POINT || character === GRAVE_ACCENT;
1251
1202
  };
1252
- //#endregion
1253
- //#region src/util/array/takeOne.ts
1203
+ // src/util/array/takeOne.ts
1254
1204
  const takeOne = (values, index = 0) => {
1255
1205
  return values[index];
1256
1206
  };
1257
- //#endregion
1258
- //#region src/services/sanitizeHtml/checkIsAllowedUrl.ts
1207
+ // src/services/sanitizeHtml/checkIsAllowedUrl.ts
1259
1208
  const PATH_DELIMITER_REGEX = /[/?#]/u;
1260
1209
  const NON_SCHEME_CHARACTERS_REGEX = /[^a-z\d+.-]/giu;
1261
1210
  const SCHEME_SEPARATOR = ":";
@@ -1267,8 +1216,18 @@ const checkIsAllowedUrl = (url, allowedSchemes) => {
1267
1216
  const scheme = beforePath.slice(0, separatorIndex).replaceAll(NON_SCHEME_CHARACTERS_REGEX, "").toLowerCase();
1268
1217
  return allowedSchemes.includes(scheme);
1269
1218
  };
1270
- //#endregion
1271
- //#region src/services/sanitizeHtml/constants.ts
1219
+ // src/services/sanitizeHtml/getTagPolicy.ts
1220
+ const getTagPolicy = (tagPolicies, tagName) => Object.hasOwn(tagPolicies, tagName) ? tagPolicies[tagName] : void 0;
1221
+ // src/services/sanitizeHtml/checkIsSourceAllowed.ts
1222
+ const checkIsSourceAllowed = (element, allowedSources) => {
1223
+ const sourceRules = getTagPolicy(allowedSources, element.tagName);
1224
+ if (!sourceRules) return true;
1225
+ return Object.entries(sourceRules).every(([name, patterns]) => {
1226
+ const attribute = element.attrs.find((attr) => attr.name === name);
1227
+ return attribute !== void 0 && patterns.some((pattern) => pattern.test(attribute.value));
1228
+ });
1229
+ };
1230
+ // src/services/sanitizeHtml/constants.ts
1272
1231
  const HTML_NAMESPACE = html$1.NS.HTML;
1273
1232
  const DEFAULT_ALLOWED_TAGS = [
1274
1233
  "address",
@@ -1402,23 +1361,19 @@ const MAX_NESTING_DEPTH = 256;
1402
1361
  const SRCSET_DESCRIPTOR_REGEX = /^(?:\d+w|\d*\.?\d+x|\d+h)$/u;
1403
1362
  const ESCAPED_TEXT_CHARACTERS_REGEX = /[&<>]/gu;
1404
1363
  const ESCAPED_ATTRIBUTE_CHARACTERS_REGEX = /[&"<>]/gu;
1405
- const SANITIZER_ADVISORY_WATCH_SINCE = "2026-10-21";
1406
- //#endregion
1407
- //#region src/services/sanitizeHtml/getChildNodes.ts
1364
+ const SANITIZER_ADVISORY_WATCH_SINCE = "2026-10-23";
1365
+ // src/services/sanitizeHtml/getChildNodes.ts
1408
1366
  const getChildNodes = (element) => "content" in element ? element.content.childNodes : element.childNodes;
1409
- //#endregion
1410
- //#region src/services/sanitizeHtml/collectText.ts
1367
+ // src/services/sanitizeHtml/collectText.ts
1411
1368
  const collectText = (nodes, depth) => depth > 256 ? "" : nodes.map((node) => {
1412
1369
  if ("value" in node) return node.value;
1413
1370
  if (!("tagName" in node) || NON_TEXT_TAGS.includes(node.tagName)) return "";
1414
1371
  return collectText(getChildNodes(node), depth + 1);
1415
1372
  }).join("");
1416
- //#endregion
1417
- //#region src/services/sanitizeHtml/escapeCharacters.ts
1373
+ // src/services/sanitizeHtml/escapeCharacters.ts
1418
1374
  const NON_BREAKING_SPACE = String.fromCodePoint(160);
1419
1375
  const escapeCharacters = (value, charactersRegex, entities) => value.replace(charactersRegex, (character) => entities[character] ?? character).replaceAll(NON_BREAKING_SPACE, "&nbsp;");
1420
- //#endregion
1421
- //#region src/services/sanitizeHtml/escapeAttribute.ts
1376
+ // src/services/sanitizeHtml/escapeAttribute.ts
1422
1377
  const ESCAPED_ATTRIBUTE_CHARACTERS = {
1423
1378
  "\"": "&quot;",
1424
1379
  "&": "&amp;",
@@ -1426,26 +1381,22 @@ const ESCAPED_ATTRIBUTE_CHARACTERS = {
1426
1381
  ">": "&gt;"
1427
1382
  };
1428
1383
  const escapeAttribute = (value) => escapeCharacters(value, ESCAPED_ATTRIBUTE_CHARACTERS_REGEX, ESCAPED_ATTRIBUTE_CHARACTERS);
1429
- //#endregion
1430
- //#region src/services/sanitizeHtml/escapeText.ts
1384
+ // src/services/sanitizeHtml/escapeText.ts
1431
1385
  const ESCAPED_TEXT_CHARACTERS = {
1432
1386
  "&": "&amp;",
1433
1387
  "<": "&lt;",
1434
1388
  ">": "&gt;"
1435
1389
  };
1436
1390
  const escapeText = (text) => escapeCharacters(text, ESCAPED_TEXT_CHARACTERS_REGEX, ESCAPED_TEXT_CHARACTERS);
1437
- //#endregion
1438
- //#region src/services/sanitizeHtml/matchesClassPattern.ts
1391
+ // src/services/sanitizeHtml/matchesClassPattern.ts
1439
1392
  const matchesClassPattern = (className, pattern) => pattern.endsWith("*") ? className.startsWith(pattern.slice(0, -1)) : className === pattern;
1440
- //#endregion
1441
- //#region src/services/sanitizeHtml/filterClasses.ts
1393
+ // src/services/sanitizeHtml/filterClasses.ts
1442
1394
  const filterClasses = (value, patterns) => {
1443
1395
  if (!patterns) return void 0;
1444
1396
  const classNames = value.split(/\s+/u).filter((className) => className && patterns.some((pattern) => matchesClassPattern(className, pattern)));
1445
1397
  return classNames.length > 0 ? classNames.join(" ") : void 0;
1446
1398
  };
1447
- //#endregion
1448
- //#region src/services/sanitizeHtml/filterSrcset.ts
1399
+ // src/services/sanitizeHtml/filterSrcset.ts
1449
1400
  const COMMA = ",";
1450
1401
  const OPENING_PARENTHESIS = "(";
1451
1402
  const CLOSING_PARENTHESIS = ")";
@@ -1477,8 +1428,7 @@ const filterSrcset = (value, allowedSchemes) => {
1477
1428
  }
1478
1429
  return candidates.length > 0 ? candidates.join(", ") : void 0;
1479
1430
  };
1480
- //#endregion
1481
- //#region src/services/sanitizeHtml/filterStyle.ts
1431
+ // src/services/sanitizeHtml/filterStyle.ts
1482
1432
  const DECLARATION_SEPARATOR = ";";
1483
1433
  const PROPERTY_SEPARATOR = ":";
1484
1434
  const IMPORTANT_SUFFIX = "!important";
@@ -1503,9 +1453,7 @@ const filterStyle = (value, rules) => {
1503
1453
  if (declarations.size === 0) return void 0;
1504
1454
  return Array.from(declarations, ([property, { important, propertyValue }]) => `${property}${PROPERTY_SEPARATOR}${propertyValue}${important ? IMPORTANT_SUFFIX : ""}`).join(DECLARATION_SEPARATOR);
1505
1455
  };
1506
- //#endregion
1507
- //#region src/services/sanitizeHtml/filterAttributes.ts
1508
- const getTagPolicy = (tagPolicies, tagName) => Object.hasOwn(tagPolicies, tagName) ? tagPolicies[tagName] : void 0;
1456
+ // src/services/sanitizeHtml/filterAttributes.ts
1509
1457
  const checkIsMetaRefresh = (tagName, attributes) => tagName === "meta" && attributes["http-equiv"]?.trim().toLowerCase() === "refresh";
1510
1458
  const filterAttributes = (element, policy) => {
1511
1459
  const { tagName } = element;
@@ -1530,28 +1478,25 @@ const filterValue = (tagName, name, value, policy) => {
1530
1478
  if (URL_ATTRIBUTES.includes(name)) return checkIsAllowedUrl(value, policy.allowedSchemes) ? value : void 0;
1531
1479
  return value;
1532
1480
  };
1533
- //#endregion
1534
- //#region src/services/sanitizeHtml/renderNode.ts
1481
+ // src/services/sanitizeHtml/renderNode.ts
1535
1482
  const renderNode = (node, policy, depth) => {
1536
1483
  if (node.nodeName === "#text") return escapeText(node.value);
1537
1484
  if (!("tagName" in node) || depth > 256) return "";
1538
1485
  const element = node;
1539
1486
  const children = getChildNodes(element).map((child) => renderNode(child, policy, depth + 1)).join("");
1540
- if (!(element.namespaceURI === HTML_NAMESPACE && !NON_TEXT_TAGS.includes(element.tagName) && policy.allowedTags.includes(element.tagName))) return NON_TEXT_TAGS.includes(element.tagName) ? "" : children;
1487
+ if (!(element.namespaceURI === HTML_NAMESPACE && !NON_TEXT_TAGS.includes(element.tagName) && policy.allowedTags.includes(element.tagName) && checkIsSourceAllowed(element, policy.allowedSources))) return NON_TEXT_TAGS.includes(element.tagName) ? "" : children;
1541
1488
  const attributes = Object.entries(filterAttributes(element, policy)).map(([name, value]) => ` ${name}="${escapeAttribute(value)}"`).join("");
1542
1489
  const opening = `<${element.tagName}${attributes}>`;
1543
1490
  return VOID_TAGS.includes(element.tagName) ? opening : `${opening}${children}</${element.tagName}>`;
1544
1491
  };
1545
- //#endregion
1546
- //#region src/services/sanitizeHtml/filterHtml.ts
1492
+ // src/services/sanitizeHtml/filterHtml.ts
1547
1493
  const filterHtml = (html, policy) => {
1548
1494
  const context = defaultTreeAdapter.createElement("body", HTML_NAMESPACE, []);
1549
1495
  const childNodes = parseFragment(context, html, {}).childNodes;
1550
1496
  const output = childNodes.map((node) => renderNode(node, policy, 0)).join("");
1551
1497
  return parseFragment(context, output, {}).childNodes.map((node) => renderNode(node, policy, 0)).join("") === output ? output : escapeText(collectText(childNodes, 0));
1552
1498
  };
1553
- //#endregion
1554
- //#region src/services/sanitizeHtml/sanitizeHtml.ts
1499
+ // src/services/sanitizeHtml/sanitizeHtml.ts
1555
1500
  const appendStyle = (style, declarations) => style ? `${style}; ${declarations}` : declarations;
1556
1501
  const transformCellAlign = ({ align, ...attributes }) => align ? {
1557
1502
  ...attributes,
@@ -1590,6 +1535,7 @@ const sanitizeHtml = (html, options) => filterHtml(html, {
1590
1535
  },
1591
1536
  allowedClasses: options?.allowedClasses ?? {},
1592
1537
  allowedSchemes: DEFAULT_ALLOWED_SCHEMES,
1538
+ allowedSources: options?.allowedSources ?? {},
1593
1539
  allowedStyles: {
1594
1540
  ...options?.allowedStyles,
1595
1541
  ...TABLE_ALLOWED_STYLES
@@ -1603,87 +1549,85 @@ const sanitizeHtml = (html, options) => filterHtml(html, {
1603
1549
  th: transformCellAlign
1604
1550
  }
1605
1551
  });
1606
- //#endregion
1607
- //#region src/services/sanitizeHtml/sanitizeTextHtml.ts
1552
+ // src/services/sanitizeHtml/sanitizeTextHtml.ts
1608
1553
  const COLOR_REGEXES = [
1609
1554
  /^#[\da-fA-F]{3,8}$/u,
1610
1555
  /^rgba?\(\d{1,3},\s*\d{1,3},\s*\d{1,3}(?:,\s*[\d.]+)?\)$/u,
1611
1556
  /^[a-z]+$/iu
1612
1557
  ];
1613
- const sanitizeTextHtml = (html) => sanitizeHtml(html, {
1614
- allowedAttributes: {
1615
- input: [
1616
- "checked",
1617
- "disabled",
1618
- "type"
1619
- ],
1620
- li: ["data-checked", "data-type"],
1621
- span: [
1622
- CUSTOM_EMOJI_ID_ATTRIBUTE,
1623
- CUSTOM_EMOJI_NAME_ATTRIBUTE,
1624
- MENTION_ID_ATTRIBUTE,
1625
- MENTION_ITEM_TYPE_ATTRIBUTE,
1626
- MENTION_LABEL_ATTRIBUTE,
1627
- MENTION_TYPE_ATTRIBUTE,
1628
- SPOILER_ATTRIBUTE,
1629
- "style"
1630
- ],
1631
- ul: ["data-type"]
1632
- },
1633
- allowedClasses: {
1634
- code: ["language-*"],
1635
- pre: ["language-*"],
1636
- span: ["hljs*"]
1637
- },
1638
- allowedStyles: { span: {
1639
- "background-color": COLOR_REGEXES,
1640
- "border-radius": [/^[\d.]+(?<unit>px|em|rem|%)$/u],
1641
- color: COLOR_REGEXES
1642
- } },
1643
- allowedTags: [
1644
- ...DEFAULT_ALLOWED_TAGS,
1645
- "input",
1646
- "label"
1558
+ const KIT_ALLOWED_ATTRIBUTES = {
1559
+ input: [
1560
+ "checked",
1561
+ "disabled",
1562
+ "type"
1647
1563
  ],
1648
- transformAttributes: { input: ({ checked }) => ({
1649
- ...checked === void 0 ? {} : { checked },
1650
- disabled: "",
1651
- type: "checkbox"
1652
- }) }
1653
- });
1654
- //#endregion
1655
- //#region src/services/shared/applyItemMetadataMixin.ts
1564
+ li: ["data-checked", "data-type"],
1565
+ span: [
1566
+ CUSTOM_EMOJI_ID_ATTRIBUTE,
1567
+ CUSTOM_EMOJI_NAME_ATTRIBUTE,
1568
+ MENTION_ID_ATTRIBUTE,
1569
+ MENTION_ITEM_TYPE_ATTRIBUTE,
1570
+ MENTION_LABEL_ATTRIBUTE,
1571
+ MENTION_TYPE_ATTRIBUTE,
1572
+ SPOILER_ATTRIBUTE,
1573
+ "style"
1574
+ ],
1575
+ ul: ["data-type"]
1576
+ };
1577
+ const sanitizeTextHtml = (html, allowance = {}) => {
1578
+ const allowedAttributes = { ...KIT_ALLOWED_ATTRIBUTES };
1579
+ for (const [tagName, attributes] of Object.entries(allowance.allowedAttributes ?? {})) allowedAttributes[tagName] = [.../* @__PURE__ */ new Set([...allowedAttributes[tagName] ?? [], ...attributes])];
1580
+ return sanitizeHtml(html, {
1581
+ allowedAttributes,
1582
+ allowedClasses: {
1583
+ code: ["language-*"],
1584
+ pre: ["language-*"],
1585
+ span: ["hljs*"]
1586
+ },
1587
+ allowedSources: allowance.allowedSources,
1588
+ allowedStyles: { span: {
1589
+ "background-color": COLOR_REGEXES,
1590
+ "border-radius": [/^[\d.]+(?<unit>px|em|rem|%)$/u],
1591
+ color: COLOR_REGEXES
1592
+ } },
1593
+ allowedTags: [
1594
+ ...DEFAULT_ALLOWED_TAGS,
1595
+ "input",
1596
+ "label",
1597
+ ...allowance.allowedTags ?? []
1598
+ ],
1599
+ transformAttributes: { input: ({ checked }) => ({
1600
+ ...checked === void 0 ? {} : { checked },
1601
+ disabled: "",
1602
+ type: "checkbox"
1603
+ }) }
1604
+ });
1605
+ };
1606
+ // src/services/shared/applyItemMetadataMixin.ts
1656
1607
  const applyItemMetadataMixin = (Base) => class ItemWithMetadata extends Base {
1657
1608
  createdAt = /* @__PURE__ */ new Date();
1658
1609
  deletedAt = null;
1659
1610
  updatedAt = /* @__PURE__ */ new Date();
1660
1611
  };
1661
- //#endregion
1662
- //#region src/util/text/normalizeString.ts
1612
+ // src/util/text/normalizeString.ts
1663
1613
  const normalizeString = (value) => value?.trim() ?? "";
1664
- //#endregion
1665
- //#region src/services/zod/createNormalizedStringSchema.ts
1614
+ // src/services/zod/createNormalizedStringSchema.ts
1666
1615
  const createNormalizedStringSchema = (maxLength, schema = z.string()) => schema.transform(normalizeString).pipe(z.string().max(maxLength));
1667
- //#endregion
1668
- //#region src/util/id/constants.ts
1616
+ // src/util/id/constants.ts
1669
1617
  const ID_SEPARATOR = "|";
1670
- //#endregion
1671
- //#region src/services/zod/createUniqueArraySchema.ts
1618
+ // src/services/zod/createUniqueArraySchema.ts
1672
1619
  const getItemKey = (item, key) => {
1673
1620
  const record = item;
1674
1621
  return typeof key === "string" ? record[key] : key.map((part) => record[part]).join("|");
1675
1622
  };
1676
1623
  const createUniqueArraySchema = (schema, key) => schema.array().refine((array) => new Set(key === void 0 ? array : array.map((item) => getItemKey(item, key))).size === array.length, { error: "Array items must be unique" });
1677
- //#endregion
1678
- //#region src/services/zstd/constants.ts
1624
+ // src/services/zstd/constants.ts
1679
1625
  const DEFAULT_COMPRESSION_LEVEL = 12;
1680
1626
  const MIN_WINDOW_LOG = 10;
1681
1627
  const MAX_WINDOW_LOG = 27;
1682
- //#endregion
1683
- //#region src/services/zstd/getWindowLog.ts
1628
+ // src/services/zstd/getWindowLog.ts
1684
1629
  const getWindowLog = (dictionaryByteCount, inputByteCount) => Math.min(27, Math.max(10, Math.ceil(Math.log2(dictionaryByteCount + inputByteCount + 1))));
1685
- //#endregion
1686
- //#region src/test/constants.ts
1630
+ // src/test/constants.ts
1687
1631
  const ALL_SPECIAL_VALUES = [
1688
1632
  {
1689
1633
  isPlainObject: true,
@@ -1730,15 +1674,13 @@ const ALL_SPECIAL_VALUES = [
1730
1674
  value: /(?:)/u
1731
1675
  }
1732
1676
  ];
1733
- //#endregion
1734
- //#region src/util/array/chunk.ts
1677
+ // src/util/array/chunk.ts
1735
1678
  const chunk = (array, size) => {
1736
1679
  const chunks = [];
1737
1680
  for (let index = 0; index < array.length; index += size) chunks.push(array.slice(index, index + size));
1738
1681
  return chunks;
1739
1682
  };
1740
- //#endregion
1741
- //#region src/util/array/chunkBySerializedSize.ts
1683
+ // src/util/array/chunkBySerializedSize.ts
1742
1684
  const ARRAY_SERIALIZATION_BYTES = 1;
1743
1685
  const chunkBySerializedSize = (items, maxBytes, maxCount) => {
1744
1686
  const textEncoder = new TextEncoder();
@@ -1758,17 +1700,13 @@ const chunkBySerializedSize = (items, maxBytes, maxCount) => {
1758
1700
  if (currentChunk.length > 0) chunks.push(currentChunk);
1759
1701
  return chunks;
1760
1702
  };
1761
- //#endregion
1762
- //#region src/util/array/takeRandom.ts
1703
+ // src/util/array/takeRandom.ts
1763
1704
  const takeRandom = (values, random) => takeOne(values, Math.floor(random() * values.length));
1764
- //#endregion
1765
- //#region src/util/date/getZonedDateTime.ts
1705
+ // src/util/date/getZonedDateTime.ts
1766
1706
  const getZonedDateTime = (date) => Temporal.Instant.fromEpochMilliseconds(date.getTime()).toZonedDateTimeISO(Temporal.Now.timeZoneId());
1767
- //#endregion
1768
- //#region src/util/date/getEndOfDay.ts
1707
+ // src/util/date/getEndOfDay.ts
1769
1708
  const getEndOfDay = (date) => /* @__PURE__ */ new Date(getZonedDateTime(date).startOfDay().add({ days: 1 }).epochMilliseconds - 1);
1770
- //#endregion
1771
- //#region src/util/dom/checkIsNestedControl.ts
1709
+ // src/util/dom/checkIsNestedControl.ts
1772
1710
  const NESTED_INTERACTION_SELECTOR = [
1773
1711
  "a[href]",
1774
1712
  "button",
@@ -1798,19 +1736,16 @@ const checkIsNestedControl = (event) => {
1798
1736
  const interactiveElement = target.closest(NESTED_INTERACTION_SELECTOR);
1799
1737
  return Boolean(interactiveElement && interactiveElement !== currentTarget && currentTarget.contains(interactiveElement));
1800
1738
  };
1801
- //#endregion
1802
- //#region src/util/dom/checkIsNestedInteraction.ts
1739
+ // src/util/dom/checkIsNestedInteraction.ts
1803
1740
  const checkIsNestedInteraction = (event) => checkIsNestedControl(event) || Boolean(window.getSelection()?.toString());
1804
- //#endregion
1805
- //#region src/util/dom/downloadUrl.ts
1741
+ // src/util/dom/downloadUrl.ts
1806
1742
  const downloadUrl = (url, filename) => {
1807
1743
  const anchor = window.document.createElement("a");
1808
1744
  anchor.href = url;
1809
1745
  anchor.download = filename;
1810
1746
  anchor.click();
1811
1747
  };
1812
- //#endregion
1813
- //#region src/util/dom/downloadFile.ts
1748
+ // src/util/dom/downloadFile.ts
1814
1749
  const downloadFile = (filename, blobPart, type) => {
1815
1750
  const url = URL.createObjectURL(new Blob([blobPart], { type }));
1816
1751
  downloadUrl(url, filename);
@@ -1818,34 +1753,18 @@ const downloadFile = (filename, blobPart, type) => {
1818
1753
  URL.revokeObjectURL(url);
1819
1754
  }, 0);
1820
1755
  };
1821
- //#endregion
1822
- //#region src/util/environment/checkIsServer.ts
1756
+ // src/util/environment/checkIsServer.ts
1823
1757
  const checkIsServer = () => typeof window === "undefined";
1824
- //#endregion
1825
- //#region src/util/function/getSynchronizedFunction.ts
1826
- const pendingPromises = /* @__PURE__ */ new Set();
1827
- const getSynchronizedFunction = (asyncFunction) => (...args) => {
1828
- const promise = asyncFunction(...args).finally(() => {
1829
- pendingPromises.delete(promise);
1830
- });
1831
- pendingPromises.add(promise);
1832
- };
1833
- const waitForSynchronizedFunctions = async () => {
1834
- await Promise.allSettled(pendingPromises);
1835
- };
1836
- //#endregion
1837
- //#region src/util/id/uuid/constants.ts
1758
+ // src/util/id/uuid/constants.ts
1838
1759
  const UUIDV4_REGEX = /^[0-9A-F]{8}-[0-9A-F]{4}-[4][0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/iu;
1839
- //#endregion
1840
- //#region src/util/map/getOrCreate.ts
1760
+ // src/util/map/getOrCreate.ts
1841
1761
  const getOrCreate = (map, key, create) => {
1842
1762
  if (map.has(key)) return map.get(key);
1843
1763
  const value = create();
1844
1764
  map.set(key, value);
1845
1765
  return value;
1846
1766
  };
1847
- //#endregion
1848
- //#region src/util/object/clonePlainDeep.ts
1767
+ // src/util/object/clonePlainDeep.ts
1849
1768
  const clone = (data, copies) => {
1850
1769
  if (!Array.isArray(data) && !checkIsPlainObject(data)) return data;
1851
1770
  else if (copies.has(data)) return copies.get(data);
@@ -1862,11 +1781,7 @@ const clone = (data, copies) => {
1862
1781
  }
1863
1782
  };
1864
1783
  const clonePlainDeep = (data) => clone(data, /* @__PURE__ */ new WeakMap());
1865
- //#endregion
1866
- //#region src/util/object/getPropertyNames.ts
1867
- const getPropertyNames = () => new Proxy({}, { get: (_target, property) => property });
1868
- //#endregion
1869
- //#region src/util/object/jsonDateParse.ts
1784
+ // src/util/object/jsonDateParse.ts
1870
1785
  const ISO_DATE_REGEX = /^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})T(?<hours>\d{2}):(?<minutes>\d{2}):(?<seconds>\d{2}(?:\.{0,1}\d*))(?:Z|(?<sign>\+|-)(?<offset>[\d|:]*))?$/u;
1871
1786
  const MS_AJAX_DATE_REGEX = /^\/Date\((?<timestamp>-?\d+(?:[-+]\d+)?)\)[/\\]$/u;
1872
1787
  const jsonDateParse = (text) => JSON.parse(text, (_key, value) => {
@@ -1877,11 +1792,9 @@ const jsonDateParse = (text) => JSON.parse(text, (_key, value) => {
1877
1792
  const timestampParts = takeOne(msAjaxDateMatch, 1).split(/[-+,.]/u);
1878
1793
  return new Date(timestampParts[0] ? Number(timestampParts[0]) : 0 - Number(timestampParts[1]));
1879
1794
  });
1880
- //#endregion
1881
- //#region src/util/object/mergeObjectsStrict.ts
1795
+ // src/util/object/mergeObjectsStrict.ts
1882
1796
  const mergeObjectsStrict = (...objects) => Object.assign({}, ...objects);
1883
- //#endregion
1884
- //#region src/util/object/omitDeep.ts
1797
+ // src/util/object/omitDeep.ts
1885
1798
  const checkIsWalkable = (value) => Object.prototype.toString.call(value) === "[object Object]";
1886
1799
  const omitValue = (value, omittedKeys) => {
1887
1800
  if (Array.isArray(value)) return value.map((element) => omitValue(element, omittedKeys));
@@ -1891,8 +1804,7 @@ const omitValue = (value, omittedKeys) => {
1891
1804
  return omittedValue;
1892
1805
  };
1893
1806
  const omitDeep = (value, ...keys) => omitValue(value, new Set(keys));
1894
- //#endregion
1895
- //#region src/util/promise/createEvictingPromiseCache.ts
1807
+ // src/util/promise/createEvictingPromiseCache.ts
1896
1808
  const createEvictingPromiseCache = (getKey, load) => {
1897
1809
  const promiseMap = /* @__PURE__ */ new Map();
1898
1810
  return (...args) => {
@@ -1905,8 +1817,7 @@ const createEvictingPromiseCache = (getKey, load) => {
1905
1817
  });
1906
1818
  };
1907
1819
  };
1908
- //#endregion
1909
- //#region src/util/promise/settleAll.ts
1820
+ // src/util/promise/settleAll.ts
1910
1821
  const settleAll = async (tasks, concurrencyLimit = tasks.length) => {
1911
1822
  if (tasks.length === 0) return [];
1912
1823
  const values = [];
@@ -1920,11 +1831,9 @@ const settleAll = async (tasks, concurrencyLimit = tasks.length) => {
1920
1831
  }
1921
1832
  return values;
1922
1833
  };
1923
- //#endregion
1924
- //#region src/util/text/capitalize.ts
1834
+ // src/util/text/capitalize.ts
1925
1835
  const capitalize = (string) => `${string.charAt(0).toUpperCase()}${string.slice(1)}`;
1926
- //#endregion
1927
- //#region src/util/text/dedent.ts
1836
+ // src/util/text/dedent.ts
1928
1837
  const ESCAPE_CHARACTER = "\\";
1929
1838
  const LINE_FEED = "\n";
1930
1839
  const LINE_FEED_CHARACTER = {
@@ -2123,8 +2032,7 @@ const createDedent = (options) => {
2123
2032
  return dedent;
2124
2033
  };
2125
2034
  const dedent = createDedent({});
2126
- //#endregion
2127
- //#region src/util/text/encodeUrlSubDelimiters.ts
2035
+ // src/util/text/encodeUrlSubDelimiters.ts
2128
2036
  const EncodedSubDelimiterMap = {
2129
2037
  "!": "%21",
2130
2038
  "'": "%27",
@@ -2133,36 +2041,51 @@ const EncodedSubDelimiterMap = {
2133
2041
  "*": "%2A"
2134
2042
  };
2135
2043
  const encodeUrlSubDelimiters = (value) => Object.entries(EncodedSubDelimiterMap).reduce((encoded, [subDelimiter, encodedSubDelimiter]) => encoded.replaceAll(subDelimiter, encodedSubDelimiter), value);
2136
- //#endregion
2137
- //#region src/util/text/getDecodedUriComponent.ts
2044
+ // src/util/text/getDecodedUriComponent.ts
2138
2045
  const getDecodedUriComponent = (value, fallback) => getResult(() => decodeURIComponent(value)).unwrapOr(fallback);
2139
- //#endregion
2140
- //#region src/util/text/streamToText.ts
2046
+ // src/util/text/streamToText.ts
2141
2047
  const streamToText = async (readable) => {
2142
2048
  readable.setEncoding("utf8");
2143
2049
  let data = "";
2144
2050
  for await (const chunk of readable) data += chunk.toString();
2145
2051
  return data;
2146
2052
  };
2147
- //#endregion
2148
- //#region src/util/text/toKebabCase.ts
2053
+ // src/util/text/toKebabCase.ts
2149
2054
  const toKebabCase = (string) => string.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/gu)?.map((x) => x.toLowerCase()).join("-") ?? "";
2150
- //#endregion
2151
- //#region src/util/text/truncate.ts
2055
+ // src/util/text/truncate.ts
2152
2056
  const SUFFIX = "...";
2153
2057
  const truncate = (string, length) => {
2154
2058
  if (string.length <= length) return string;
2155
2059
  else if (length < 3) return string.slice(0, length);
2156
2060
  else return `${string.slice(0, length - 3)}${SUFFIX}`;
2157
2061
  };
2158
- //#endregion
2159
- //#region src/util/text/uncapitalize.ts
2062
+ // src/util/text/uncapitalize.ts
2160
2063
  const uncapitalize = (string) => `${string.charAt(0).toLowerCase()}${string.slice(1)}`;
2161
- //#endregion
2162
- //#region src/util/time/constants.ts
2064
+ // src/util/time/constants.ts
2163
2065
  const MILLISECONDS_PER_SECOND = 1e3;
2164
- //#endregion
2165
- //#region src/util/time/hrtime.ts
2066
+ // src/util/time/getExponentialBackoffDelayMs.ts
2067
+ const getExponentialBackoffDelayMs = (attempt, baseDelayMs, maxDelayMs) => Math.min(baseDelayMs * 2 ** attempt, maxDelayMs);
2068
+ // src/util/time/sleep.ts
2069
+ const sleep = (durationMs) => new Promise((resolve) => {
2070
+ setTimeout(() => {
2071
+ resolve();
2072
+ }, durationMs);
2073
+ });
2074
+ // src/util/time/createExponentialBackoff.ts
2075
+ const createExponentialBackoff = (baseDelayMs, maxDelayMs) => {
2076
+ let failureCount = 0;
2077
+ return async (operation) => {
2078
+ if (failureCount > 0) await sleep(getExponentialBackoffDelayMs(failureCount - 1, baseDelayMs, maxDelayMs));
2079
+ return getResultAsync(operation).match((value) => {
2080
+ failureCount = 0;
2081
+ return value;
2082
+ }, (error) => {
2083
+ failureCount += 1;
2084
+ throw error;
2085
+ });
2086
+ };
2087
+ };
2088
+ // src/util/time/hrtime.ts
2166
2089
  const hrtime = (previousHrTime) => {
2167
2090
  if (checkIsServer()) return process.hrtime(previousHrTime);
2168
2091
  const clocktime = performance.now() * .001;
@@ -2178,20 +2101,11 @@ const hrtime = (previousHrTime) => {
2178
2101
  }
2179
2102
  return [seconds, nanoseconds];
2180
2103
  };
2181
- //#endregion
2182
- //#region src/util/time/now.ts
2104
+ // src/util/time/now.ts
2183
2105
  const loadNanoseconds = hrtime();
2184
2106
  const loadMilliseconds = Date.now();
2185
2107
  const now = () => {
2186
2108
  const [seconds, nanoseconds] = hrtime(loadNanoseconds);
2187
2109
  return (BigInt(loadMilliseconds) * 10n ** 6n + (BigInt(seconds) * 10n ** 9n + BigInt(nanoseconds))).toString();
2188
2110
  };
2189
- //#endregion
2190
- //#region src/util/time/sleep.ts
2191
- const sleep = (durationMs) => new Promise((resolve) => {
2192
- setTimeout(() => {
2193
- resolve();
2194
- }, durationMs);
2195
- });
2196
- //#endregion
2197
- export { ALL_SPECIAL_VALUES, APPEND_SEGMENT, CHARSET_PARAMETER_REGEX, CUSTOM_EMOJI_ID_ATTRIBUTE, CUSTOM_EMOJI_NAME_ATTRIBUTE, DEFAULT_ALLOWED_ATTRIBUTES, DEFAULT_ALLOWED_SCHEMES, DEFAULT_ALLOWED_TAGS, DEFAULT_COMPRESSION_LEVEL, DEFAULT_FACET_SCORE, DEFAULT_LINK_ATTRIBUTES, DEFAULT_SOURCE_SCORE, DEFAULT_TEXT_CHARSET, DEFAULT_TYPE_SCORE, ESCAPED_ATTRIBUTE_CHARACTERS_REGEX, ESCAPED_TEXT_CHARACTERS_REGEX, FacetScoreMap, ForbiddenError, GIBIBYTE, HTML_NAMESPACE, ID_SEPARATOR, IMPORTANT_REGEX, InvalidOperationError, ItemMetadata, JSON_POINTER_REGEX, JsonPatchOperationType, KIBIBYTE, MAX_NESTING_DEPTH, MAX_READ_LIMIT, MAX_WINDOW_LOG, MEDIA_TYPE_REGEX, MENTION_EVERYONE_ID, MENTION_HERE_ID, MENTION_ID_ATTRIBUTE, MENTION_ITEM_TYPE_ATTRIBUTE, MENTION_LABEL_ATTRIBUTE, MENTION_SELECTOR, MENTION_TYPE, MENTION_TYPE_ATTRIBUTE, MILLISECONDS_PER_SECOND, MIN_WINDOW_LOG, MentionType, NON_TEXT_TAGS, NotFoundError, NotInitializedError, ObjectMethod, Operation, PATH_SEPARATOR_REGEX, RoutePath, SANITIZER_ADVISORY_WATCH_SINCE, SITE_NAME, SPOILER_ATTRIBUTE, SPOILER_SELECTOR, SRCSET_ATTRIBUTE, SRCSET_DESCRIPTOR_REGEX, Serializable, SourceScoreMap, TEXT_MEDIA_TYPE_REGEX, TypeScoreMap, TypedEventEmitter, URL_ATTRIBUTES, UUIDV4_REGEX, VOID_TAGS, WordFilteredError, addJsonValue, applyItemMetadataMixin, applyPatch, applyPatches, capitalize, charset, checkContainsProfanity, checkIsAllowedUrl, checkIsCustomMethod, checkIsDeepEqual, checkIsNestedControl, checkIsNestedInteraction, checkIsPlainObject, checkIsSameBytes, checkIsSameValueZero, checkIsServer, checkIsUnsafeUrlCharacter, checkIsWhitespaceCharacter, chunk, chunkBySerializedSize, clonePlainDeep, collectText, contentType, createEvictingPromiseCache, createHistory, createItemEntityTypeSchema, createNormalizedStringSchema, createUniqueArraySchema, css, dedent, downloadFile, downloadUrl, encodeUrlSubDelimiters, englishProfaneWords, escapeAttribute, escapeCharacters, escapeText, exhaustiveGuard, extension, filterAttributes, filterClasses, filterHtml, filterSrcset, filterStyle, getChildNodes, getDecodedUriComponent, getEndOfDay, getEnumerableKeys, getExtensionMimeTypeMap, getMediaType, getMentions, getMimeScore, getMimeTypeEntryMap, getOrCreate, getPropertyNames, getRawData, getRequestError, getResult, getResultAsync, getSynchronizedFunction, getTransactionDone, getTransactionObjectStore, getWindowLog, getZonedDateTime, hrtime, html, jsonDateParse, lookup, matchesClassPattern, mergeObjectsStrict, noop, normalizeString, now, omitDeep, openDatabase, parseArrayIndex, parseJsonPointer, pushHistory, readJsonValue, redoHistory, removeJsonValue, renderNode, reportFinalizerError, requestToPromise, sanitizeHtml, sanitizeTextHtml, settleAll, sleep, streamToText, takeOne, takeRandom, toAppError, toJsonPointer, toKebabCase, toRawDeep, truncate, uncapitalize, undoHistory, updateJsonValue, waitForSynchronizedFunctions, withFinalizer, withFinalizerAsync, wrapDatabase, wrapIndex, wrapObjectStore, wrapTransaction, wrapUpgradeDatabase, wrapUpgradeTransaction };
2111
+ export { ALL_SPECIAL_VALUES, APPEND_SEGMENT, CHARSET_PARAMETER_REGEX, CUSTOM_EMOJI_ID_ATTRIBUTE, CUSTOM_EMOJI_NAME_ATTRIBUTE, DEFAULT_ALLOWED_ATTRIBUTES, DEFAULT_ALLOWED_SCHEMES, DEFAULT_ALLOWED_TAGS, DEFAULT_COMPRESSION_LEVEL, DEFAULT_FACET_SCORE, DEFAULT_LINK_ATTRIBUTES, DEFAULT_SOURCE_SCORE, DEFAULT_TEXT_CHARSET, DEFAULT_TYPE_SCORE, ESCAPED_ATTRIBUTE_CHARACTERS_REGEX, ESCAPED_TEXT_CHARACTERS_REGEX, FacetScoreMap, ForbiddenError, GIBIBYTE, HTML_NAMESPACE, ID_SEPARATOR, IMPORTANT_REGEX, InvalidOperationError, ItemMetadata, ItemMetadataPropertyNames, JSON_POINTER_REGEX, JsonPatchOperationType, KIBIBYTE, MAX_NESTING_DEPTH, MAX_READ_LIMIT, MAX_WINDOW_LOG, MEDIA_TYPE_REGEX, MENTION_EVERYONE_ID, MENTION_HERE_ID, MENTION_ID_ATTRIBUTE, MENTION_ITEM_TYPE_ATTRIBUTE, MENTION_LABEL_ATTRIBUTE, MENTION_SELECTOR, MENTION_TYPE, MENTION_TYPE_ATTRIBUTE, MILLISECONDS_PER_SECOND, MIN_WINDOW_LOG, MentionType, NON_TEXT_TAGS, NotFoundError, NotInitializedError, ObjectMethod, Operation, PATH_SEPARATOR_REGEX, RoutePath, SANITIZER_ADVISORY_WATCH_SINCE, SITE_NAME, SPOILER_ATTRIBUTE, SPOILER_SELECTOR, SRCSET_ATTRIBUTE, SRCSET_DESCRIPTOR_REGEX, Serializable, SourceScoreMap, TEXT_MEDIA_TYPE_REGEX, TypeScoreMap, TypedEventEmitter, URL_ATTRIBUTES, UUIDV4_REGEX, VOID_TAGS, WordFilteredError, addJsonValue, applyItemMetadataMixin, applyPatch, applyPatches, capitalize, charset, checkContainsProfanity, checkIsAllowedUrl, checkIsCustomMethod, checkIsDeepEqual, checkIsNestedControl, checkIsNestedInteraction, checkIsOnlyReactor, checkIsPlainObject, checkIsSameBytes, checkIsSameValueZero, checkIsServer, checkIsSourceAllowed, checkIsUnsafeUrlCharacter, checkIsWhitespaceCharacter, chunk, chunkBySerializedSize, clonePlainDeep, collectText, contentType, createEvictingPromiseCache, createExponentialBackoff, createHistory, createItemEntityTypeSchema, createNormalizedStringSchema, createUniqueArraySchema, css, dedent, downloadFile, downloadUrl, encodeUrlSubDelimiters, englishProfaneWords, escapeAttribute, escapeCharacters, escapeText, exhaustiveGuard, extension, filterAttributes, filterClasses, filterHtml, filterSrcset, filterStyle, getChildNodes, getDecodedUriComponent, getEndOfDay, getEnumerableKeys, getExponentialBackoffDelayMs, getExtensionMimeTypeMap, getMediaType, getMentions, getMimeScore, getMimeTypeEntryMap, getOrCreate, getPropertyNames, getRawData, getRequestError, getResult, getResultAsync, getSynchronizedFunction, getTagPolicy, getTransactionDone, getTransactionObjectStore, getUpdatedUserIds, getWindowLog, getZonedDateTime, hrtime, html, jsonDateParse, lookup, matchesClassPattern, mergeObjectsStrict, noop, normalizeString, now, omitDeep, openDatabase, parseArrayIndex, parseJsonPointer, pushHistory, readJsonValue, redoHistory, removeJsonValue, renderNode, reportFinalizerError, requestToPromise, sanitizeHtml, sanitizeTextHtml, settleAll, sleep, streamToText, takeOne, takeRandom, toAppError, toJsonPointer, toKebabCase, toRawDeep, truncate, uncapitalize, undoHistory, updateJsonValue, waitForSynchronizedFunctions, withFinalizer, withFinalizerAsync, wrapDatabase, wrapIndex, wrapObjectStore, wrapTransaction, wrapUpgradeDatabase, wrapUpgradeTransaction };