@evolu/common 6.0.1-preview.9 → 7.1.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.
Files changed (195) hide show
  1. package/README.md +27 -29
  2. package/dist/src/Array.d.ts +317 -12
  3. package/dist/src/Array.d.ts.map +1 -1
  4. package/dist/src/Array.js +219 -9
  5. package/dist/src/Assert.d.ts +0 -13
  6. package/dist/src/Assert.d.ts.map +1 -1
  7. package/dist/src/Assert.js +0 -15
  8. package/dist/src/Brand.d.ts +75 -0
  9. package/dist/src/Brand.d.ts.map +1 -0
  10. package/dist/src/Brand.js +1 -0
  11. package/dist/src/Buffer.d.ts +1 -1
  12. package/dist/src/Buffer.d.ts.map +1 -1
  13. package/dist/src/Buffer.js +8 -7
  14. package/dist/src/Cache.d.ts +39 -0
  15. package/dist/src/Cache.d.ts.map +1 -0
  16. package/dist/src/Cache.js +47 -0
  17. package/dist/src/Callbacks.d.ts +45 -12
  18. package/dist/src/Callbacks.d.ts.map +1 -1
  19. package/dist/src/Callbacks.js +14 -7
  20. package/dist/src/Console.d.ts +32 -7
  21. package/dist/src/Console.d.ts.map +1 -1
  22. package/dist/src/Console.js +73 -10
  23. package/dist/src/Crypto.d.ts +56 -42
  24. package/dist/src/Crypto.d.ts.map +1 -1
  25. package/dist/src/Crypto.js +45 -54
  26. package/dist/src/Evolu/Db.d.ts +162 -74
  27. package/dist/src/Evolu/Db.d.ts.map +1 -1
  28. package/dist/src/Evolu/Db.js +284 -702
  29. package/dist/src/Evolu/Diff.d.ts +3 -3
  30. package/dist/src/Evolu/Diff.d.ts.map +1 -1
  31. package/dist/src/Evolu/Diff.js +7 -5
  32. package/dist/src/Evolu/Evolu.d.ts +213 -133
  33. package/dist/src/Evolu/Evolu.d.ts.map +1 -1
  34. package/dist/src/Evolu/Evolu.js +189 -180
  35. package/dist/src/Evolu/Internal.d.ts +2 -4
  36. package/dist/src/Evolu/Internal.d.ts.map +1 -1
  37. package/dist/src/Evolu/Internal.js +2 -4
  38. package/dist/src/Evolu/LocalAuth.d.ts +150 -0
  39. package/dist/src/Evolu/LocalAuth.d.ts.map +1 -0
  40. package/dist/src/Evolu/LocalAuth.js +174 -0
  41. package/dist/src/Evolu/Owner.d.ts +273 -120
  42. package/dist/src/Evolu/Owner.d.ts.map +1 -1
  43. package/dist/src/Evolu/Owner.js +130 -104
  44. package/dist/src/Evolu/Platform.d.ts +9 -7
  45. package/dist/src/Evolu/Platform.d.ts.map +1 -1
  46. package/dist/src/Evolu/Protocol.d.ts +268 -240
  47. package/dist/src/Evolu/Protocol.d.ts.map +1 -1
  48. package/dist/src/Evolu/Protocol.js +595 -447
  49. package/dist/src/Evolu/Public.d.ts +7 -9
  50. package/dist/src/Evolu/Public.d.ts.map +1 -1
  51. package/dist/src/Evolu/Public.js +3 -4
  52. package/dist/src/Evolu/PublicKysely.d.ts.map +1 -1
  53. package/dist/src/Evolu/PublicKysely.js +3 -4
  54. package/dist/src/Evolu/Query.d.ts +2 -1
  55. package/dist/src/Evolu/Query.d.ts.map +1 -1
  56. package/dist/src/Evolu/Query.js +1 -1
  57. package/dist/src/Evolu/Relay.d.ts +91 -8
  58. package/dist/src/Evolu/Relay.d.ts.map +1 -1
  59. package/dist/src/Evolu/Relay.js +214 -88
  60. package/dist/src/Evolu/Schema.d.ts +125 -47
  61. package/dist/src/Evolu/Schema.d.ts.map +1 -1
  62. package/dist/src/Evolu/Schema.js +175 -31
  63. package/dist/src/Evolu/Storage.d.ts +249 -27
  64. package/dist/src/Evolu/Storage.d.ts.map +1 -1
  65. package/dist/src/Evolu/Storage.js +198 -92
  66. package/dist/src/Evolu/Sync.d.ts +68 -13
  67. package/dist/src/Evolu/Sync.d.ts.map +1 -1
  68. package/dist/src/Evolu/Sync.js +469 -20
  69. package/dist/src/Evolu/Timestamp.d.ts +83 -30
  70. package/dist/src/Evolu/Timestamp.d.ts.map +1 -1
  71. package/dist/src/Evolu/Timestamp.js +79 -34
  72. package/dist/src/Identicon.d.ts +35 -0
  73. package/dist/src/Identicon.d.ts.map +1 -0
  74. package/dist/src/Identicon.js +143 -0
  75. package/dist/src/Instances.d.ts +34 -0
  76. package/dist/src/Instances.d.ts.map +1 -0
  77. package/dist/src/Instances.js +44 -0
  78. package/dist/src/Number.d.ts +4 -3
  79. package/dist/src/Number.d.ts.map +1 -1
  80. package/dist/src/Number.js +5 -4
  81. package/dist/src/Object.d.ts +10 -4
  82. package/dist/src/Object.d.ts.map +1 -1
  83. package/dist/src/Object.js +9 -3
  84. package/dist/src/Order.d.ts +0 -5
  85. package/dist/src/Order.d.ts.map +1 -1
  86. package/dist/src/Order.js +0 -5
  87. package/dist/src/Platform.d.ts +15 -0
  88. package/dist/src/Platform.d.ts.map +1 -0
  89. package/dist/src/Platform.js +17 -0
  90. package/dist/src/Random.d.ts +3 -7
  91. package/dist/src/Random.d.ts.map +1 -1
  92. package/dist/src/Random.js +0 -5
  93. package/dist/src/Ref.d.ts.map +1 -1
  94. package/dist/src/Relation.d.ts +79 -0
  95. package/dist/src/Relation.d.ts.map +1 -0
  96. package/dist/src/Relation.js +127 -0
  97. package/dist/src/Resources.d.ts +118 -0
  98. package/dist/src/Resources.d.ts.map +1 -0
  99. package/dist/src/Resources.js +197 -0
  100. package/dist/src/Result.d.ts +189 -59
  101. package/dist/src/Result.d.ts.map +1 -1
  102. package/dist/src/Result.js +30 -241
  103. package/dist/src/Skiplist.js +2 -1
  104. package/dist/src/Sqlite.d.ts +89 -5
  105. package/dist/src/Sqlite.d.ts.map +1 -1
  106. package/dist/src/Sqlite.js +136 -9
  107. package/dist/src/Store.d.ts +0 -5
  108. package/dist/src/Store.d.ts.map +1 -1
  109. package/dist/src/Store.js +0 -5
  110. package/dist/src/Task.d.ts +580 -0
  111. package/dist/src/Task.d.ts.map +1 -0
  112. package/dist/src/Task.js +464 -0
  113. package/dist/src/Time.d.ts +66 -6
  114. package/dist/src/Time.d.ts.map +1 -1
  115. package/dist/src/Time.js +96 -7
  116. package/dist/src/Type.d.ts +677 -344
  117. package/dist/src/Type.d.ts.map +1 -1
  118. package/dist/src/Type.js +718 -467
  119. package/dist/src/Types.d.ts +38 -75
  120. package/dist/src/Types.d.ts.map +1 -1
  121. package/dist/src/WebSocket.d.ts +5 -7
  122. package/dist/src/WebSocket.d.ts.map +1 -1
  123. package/dist/src/WebSocket.js +12 -23
  124. package/dist/src/Worker.d.ts +39 -16
  125. package/dist/src/Worker.d.ts.map +1 -1
  126. package/dist/src/Worker.js +22 -9
  127. package/dist/src/index.d.ts +8 -3
  128. package/dist/src/index.d.ts.map +1 -1
  129. package/dist/src/index.js +8 -3
  130. package/package.json +14 -13
  131. package/src/Array.ts +396 -19
  132. package/src/Assert.ts +0 -35
  133. package/src/Brand.ts +75 -0
  134. package/src/Buffer.ts +7 -7
  135. package/src/Cache.ts +79 -0
  136. package/src/Callbacks.ts +62 -22
  137. package/src/Console.ts +92 -12
  138. package/src/Crypto.ts +99 -91
  139. package/src/Evolu/Db.ts +519 -1026
  140. package/src/Evolu/Diff.ts +7 -5
  141. package/src/Evolu/Evolu.ts +476 -360
  142. package/src/Evolu/Internal.ts +2 -4
  143. package/src/Evolu/LocalAuth.ts +463 -0
  144. package/src/Evolu/Owner.ts +355 -228
  145. package/src/Evolu/Platform.ts +9 -9
  146. package/src/Evolu/Protocol.ts +846 -742
  147. package/src/Evolu/Public.ts +8 -15
  148. package/src/Evolu/PublicKysely.ts +4 -5
  149. package/src/Evolu/Query.ts +3 -2
  150. package/src/Evolu/Relay.ts +406 -103
  151. package/src/Evolu/Schema.ts +323 -91
  152. package/src/Evolu/Storage.ts +559 -137
  153. package/src/Evolu/Sync.ts +819 -36
  154. package/src/Evolu/Timestamp.ts +90 -58
  155. package/src/Identicon.ts +197 -0
  156. package/src/Instances.ts +90 -0
  157. package/src/Number.ts +6 -10
  158. package/src/Object.ts +13 -5
  159. package/src/Order.ts +0 -6
  160. package/src/Platform.ts +20 -0
  161. package/src/Random.ts +3 -8
  162. package/src/Ref.ts +0 -5
  163. package/src/Relation.ts +234 -0
  164. package/src/Resources.ts +367 -0
  165. package/src/Result.ts +196 -61
  166. package/src/Skiplist.ts +1 -1
  167. package/src/Sqlite.ts +152 -17
  168. package/src/Store.ts +0 -5
  169. package/src/Task.ts +894 -0
  170. package/src/Time.ts +179 -10
  171. package/src/Type.ts +1136 -731
  172. package/src/Types.ts +43 -77
  173. package/src/WebSocket.ts +27 -31
  174. package/src/Worker.ts +72 -29
  175. package/src/index.ts +8 -3
  176. package/dist/src/Evolu/Config.d.ts +0 -69
  177. package/dist/src/Evolu/Config.d.ts.map +0 -1
  178. package/dist/src/Evolu/Config.js +0 -9
  179. package/dist/src/Evolu/Kysely.d.ts +0 -6
  180. package/dist/src/Evolu/Kysely.d.ts.map +0 -1
  181. package/dist/src/Evolu/Kysely.js +0 -21
  182. package/dist/src/ManyToManyMap.d.ts +0 -26
  183. package/dist/src/ManyToManyMap.d.ts.map +0 -1
  184. package/dist/src/ManyToManyMap.js +0 -92
  185. package/dist/src/NanoId.d.ts +0 -27
  186. package/dist/src/NanoId.d.ts.map +0 -1
  187. package/dist/src/NanoId.js +0 -6
  188. package/dist/src/Promise.d.ts +0 -180
  189. package/dist/src/Promise.d.ts.map +0 -1
  190. package/dist/src/Promise.js +0 -176
  191. package/src/Evolu/Config.ts +0 -83
  192. package/src/Evolu/Kysely.ts +0 -38
  193. package/src/ManyToManyMap.ts +0 -140
  194. package/src/NanoId.ts +0 -39
  195. package/src/Promise.ts +0 -295
@@ -63,18 +63,3 @@ export const assertNonEmptyArray = (arr, message = "Expected a non-empty array."
63
63
  export const assertNonEmptyReadonlyArray = (arr, message = "Expected a non-empty readonly array.") => {
64
64
  assert(arr.length > 0, message);
65
65
  };
66
- /**
67
- * Asserts no error reaches a `.catch` block, throwing a developer error if it
68
- * does. Used in Promise chains where errors indicate bugs to be fixed.
69
- *
70
- * ### Example
71
- *
72
- * ```ts
73
- * Promise.reject("test").catch((e) =>
74
- * assertNoErrorInCatch("WebSocket retry", e),
75
- * );
76
- * ```
77
- */
78
- export function assertNoErrorInCatch(context, error) {
79
- throw Object.assign(new Error(`Error in ${context}: an unexpected error reached a catch block and requires a fix`), { cause: error });
80
- }
@@ -0,0 +1,75 @@
1
+ /**
2
+ * A utility interface for creating branded types.
3
+ *
4
+ * Branded types enhance type safety by differentiating otherwise identical base
5
+ * types, such as `number` or `string`, to enforce stricter type checks.
6
+ *
7
+ * Supports multiple brands, allowing types to act like flags.
8
+ *
9
+ * ### Example 1: Single Brand
10
+ *
11
+ * ```ts
12
+ * // A branded type definition
13
+ * type UserId = number & Brand<"UserId">;
14
+ *
15
+ * // A function that creates `UserId` values.
16
+ * // Casting with `as UserId` is unsafe, so `createUserId` must be unit-tested.
17
+ * const createUserId = (): UserId => {
18
+ * return 123 as UserId; // Unsafe casting
19
+ * };
20
+ *
21
+ * const userId = createUserId();
22
+ *
23
+ * // A function that accepts only `UserId`.
24
+ * const getUser = (id: UserId) => {
25
+ * // Implementation
26
+ * };
27
+ *
28
+ * getUser(userId); // ✅ Valid
29
+ * getUser(123); // ❌ TypeScript error
30
+ * getUser("123"); // ❌ TypeScript error
31
+ * ```
32
+ *
33
+ * ### Example 2: Multiple Brands
34
+ *
35
+ * ```ts
36
+ * // Define branded types
37
+ * type Min1 = string & Brand<"Min1">;
38
+ * type Max100 = string & Brand<"Max100">;
39
+ * type Min1Max100 = string & Brand<"Min1" | "Max100">;
40
+ *
41
+ * // Functions requiring specific brands
42
+ * const requiresMin1 = (value: Min1): void => {};
43
+ * const requiresMax100 = (value: Max100): void => {};
44
+ *
45
+ * // Values with single brands
46
+ * const min1Value: Min1 = "hello" as Min1;
47
+ * const max100Value: Max100 = "world" as Max100;
48
+ *
49
+ * // Value with multiple brands
50
+ * const min1Max100Value: Min1Max100 = "typescript" as Min1Max100;
51
+ *
52
+ * // Valid cases
53
+ * requiresMin1(min1Value); // ✅ Valid
54
+ * requiresMax100(max100Value); // ✅ Valid
55
+ * requiresMin1(min1Max100Value); // ✅ Valid: Min1Max100 satisfies Min1
56
+ * requiresMax100(min1Max100Value); // ✅ Valid: Min1Max100 satisfies Max100
57
+ * ```
58
+ */
59
+ export interface Brand<B extends string> {
60
+ readonly [__brand]: Readonly<Record<B, true>>;
61
+ }
62
+ declare const __brand: unique symbol;
63
+ /**
64
+ * Determines whether a type `T` is a branded type.
65
+ *
66
+ * Works with any base type intersected with a `Brand`.
67
+ *
68
+ * ### Example
69
+ *
70
+ * - `IsBranded<string>` -> false
71
+ * - `IsBranded<string & Brand<"X">>` -> true
72
+ */
73
+ export type IsBranded<T> = T extends Brand<string> ? true : false;
74
+ export {};
75
+ //# sourceMappingURL=Brand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Brand.d.ts","sourceRoot":"","sources":["../../src/Brand.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AACH,MAAM,WAAW,KAAK,CAAC,CAAC,SAAS,MAAM;IACrC,QAAQ,CAAC,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;CAC/C;AAED,OAAO,CAAC,MAAM,OAAO,EAAE,OAAO,MAAM,CAAC;AAErC;;;;;;;;;GASG;AACH,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,KAAK,CAAC,MAAM,CAAC,GAAG,IAAI,GAAG,KAAK,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -1,5 +1,5 @@
1
1
  import { NonNegativeInt } from "./Type.js";
2
- export { bytesToHex, bytesToUtf8, concatBytes, hexToBytes, utf8ToBytes, } from "@noble/ciphers/utils";
2
+ export { bytesToHex, bytesToUtf8, concatBytes, hexToBytes, utf8ToBytes, } from "@noble/ciphers/utils.js";
3
3
  /**
4
4
  * Custom error for {@link Buffer}-related failures like premature end of data.
5
5
  * Provides better stack traces for debugging binary protocol issues.
@@ -1 +1 @@
1
- {"version":3,"file":"Buffer.d.ts","sourceRoot":"","sources":["../../src/Buffer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EACL,UAAU,EACV,WAAW,EACX,WAAW,EACX,UAAU,EACV,WAAW,GACZ,MAAM,sBAAsB,CAAC;AAE9B;;;GAGG;AACH,qBAAa,WAAY,SAAQ,KAAK;gBACxB,OAAO,EAAE,MAAM;CAM5B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,MAAM,WAAW,MAAM;IACrB,sDAAsD;IACtD,WAAW,EAAE,MAAM,cAAc,CAAC;IAElC,gEAAgE;IAChE,SAAS,EAAE,MAAM,cAAc,CAAC;IAEhC;;;OAGG;IACH,MAAM,EAAE,CAAC,GAAG,EAAE,UAAU,GAAG,SAAS,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;IAEtD;;;OAGG;IACH,KAAK,EAAE,MAAM,cAAc,CAAC;IAE5B;;;OAGG;IACH,MAAM,EAAE,CAAC,CAAC,EAAE,cAAc,KAAK,UAAU,CAAC;IAE1C;;;OAGG;IACH,QAAQ,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,CAAC;IAE3C;;;;;;OAMG;IACH,KAAK,EAAE,MAAM,IAAI,CAAC;IAElB;;;;OAIG;IACH,MAAM,EAAE,MAAM,UAAU,CAAC;CAC1B;AAED,eAAO,MAAM,YAAY,GACvB,YAAY,UAAU,GAAG,SAAS,CAAC,MAAM,CAAC,KACzC,MA4DF,CAAC"}
1
+ {"version":3,"file":"Buffer.d.ts","sourceRoot":"","sources":["../../src/Buffer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EACL,UAAU,EACV,WAAW,EACX,WAAW,EACX,UAAU,EACV,WAAW,GACZ,MAAM,yBAAyB,CAAC;AAEjC;;;GAGG;AACH,qBAAa,WAAY,SAAQ,KAAK;gBACxB,OAAO,EAAE,MAAM;CAM5B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,MAAM,WAAW,MAAM;IACrB,sDAAsD;IACtD,WAAW,EAAE,MAAM,cAAc,CAAC;IAElC,gEAAgE;IAChE,SAAS,EAAE,MAAM,cAAc,CAAC;IAEhC;;;OAGG;IACH,MAAM,EAAE,CAAC,GAAG,EAAE,UAAU,GAAG,SAAS,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;IAEtD;;;OAGG;IACH,KAAK,EAAE,MAAM,cAAc,CAAC;IAE5B;;;OAGG;IACH,MAAM,EAAE,CAAC,CAAC,EAAE,cAAc,KAAK,UAAU,CAAC;IAE1C;;;OAGG;IACH,QAAQ,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,CAAC;IAE3C;;;;;;OAMG;IACH,KAAK,EAAE,MAAM,IAAI,CAAC;IAElB;;;;OAIG;IACH,MAAM,EAAE,MAAM,UAAU,CAAC;CAC1B;AAED,eAAO,MAAM,YAAY,GACvB,YAAY,UAAU,GAAG,SAAS,CAAC,MAAM,CAAC,KACzC,MA4DF,CAAC"}
@@ -1,4 +1,5 @@
1
- export { bytesToHex, bytesToUtf8, concatBytes, hexToBytes, utf8ToBytes, } from "@noble/ciphers/utils";
1
+ import { NonNegativeInt } from "./Type.js";
2
+ export { bytesToHex, bytesToUtf8, concatBytes, hexToBytes, utf8ToBytes, } from "@noble/ciphers/utils.js";
2
3
  /**
3
4
  * Custom error for {@link Buffer}-related failures like premature end of data.
4
5
  * Provides better stack traces for debugging binary protocol issues.
@@ -14,9 +15,9 @@ export const createBuffer = (arrayLike) => {
14
15
  let value = arrayLike
15
16
  ? new globalThis.Uint8Array(arrayLike)
16
17
  : new globalThis.Uint8Array(512);
17
- let length = (arrayLike ? arrayLike.length : 0);
18
+ let length = NonNegativeInt.orThrow(arrayLike ? arrayLike.length : 0);
18
19
  const buffer = {
19
- getCapacity: () => value.length,
20
+ getCapacity: () => NonNegativeInt.orThrow(value.length),
20
21
  getLength: () => length,
21
22
  extend: (arg) => {
22
23
  const targetSize = length + arg.length;
@@ -27,7 +28,7 @@ export const createBuffer = (arrayLike) => {
27
28
  value.set(oldValue);
28
29
  }
29
30
  value.set(arg, length);
30
- length = (length + arg.length);
31
+ length = NonNegativeInt.orThrow(length + arg.length);
31
32
  },
32
33
  shift: () => {
33
34
  if (length === 0) {
@@ -36,7 +37,7 @@ export const createBuffer = (arrayLike) => {
36
37
  const first = value[0];
37
38
  value = value.subarray(1);
38
39
  length--;
39
- return first;
40
+ return NonNegativeInt.orThrow(first);
40
41
  },
41
42
  shiftN: (n) => {
42
43
  if (length < n) {
@@ -44,7 +45,7 @@ export const createBuffer = (arrayLike) => {
44
45
  }
45
46
  const subarray = value.subarray(0, n);
46
47
  value = value.subarray(n);
47
- length = (length - n);
48
+ length = NonNegativeInt.orThrow(length - n);
48
49
  return subarray;
49
50
  },
50
51
  truncate: (newLength) => {
@@ -54,7 +55,7 @@ export const createBuffer = (arrayLike) => {
54
55
  length = newLength;
55
56
  },
56
57
  reset: () => {
57
- length = 0;
58
+ length = NonNegativeInt.orThrow(0);
58
59
  },
59
60
  unwrap: () => value.subarray(0, length),
60
61
  };
@@ -0,0 +1,39 @@
1
+ import { PositiveInt } from "./Type.js";
2
+ /**
3
+ * Generic cache interface providing basic key-value storage operations.
4
+ *
5
+ * Keys are compared by reference (standard Map semantics).
6
+ *
7
+ * Note: Cache does not extend Map because eviction policies (like in LRU)
8
+ * violate the Liskov Substitution Principle.
9
+ */
10
+ export interface Cache<K, V> {
11
+ /** Checks if a key exists in the cache. */
12
+ has: (key: K) => boolean;
13
+ /** Retrieves the value for a key, or undefined if not present. */
14
+ get: (key: K) => V | undefined;
15
+ /** Stores a key-value pair in the cache. */
16
+ set: (key: K, val: V) => void;
17
+ /** Removes a key from the cache. */
18
+ delete: (key: K) => void;
19
+ /** Returns a readonly view of the internal Map. */
20
+ readonly map: ReadonlyMap<K, V>;
21
+ }
22
+ /**
23
+ * Creates an LRU (least recently used) cache with a maximum capacity.
24
+ *
25
+ * When the cache reaches capacity, the least recently used entry is evicted.
26
+ * Both `get` and `set` operations update the access order.
27
+ *
28
+ * ### Example
29
+ *
30
+ * ```ts
31
+ * const cache = createLruCache<string, number>(2);
32
+ * cache.set("a", 1);
33
+ * cache.set("b", 2);
34
+ * cache.set("c", 3); // Evicts "a"
35
+ * cache.has("a"); // false
36
+ * ```
37
+ */
38
+ export declare const createLruCache: <K, V>(capacity: PositiveInt) => Cache<K, V>;
39
+ //# sourceMappingURL=Cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Cache.d.ts","sourceRoot":"","sources":["../../src/Cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC;;;;;;;GAOG;AACH,MAAM,WAAW,KAAK,CAAC,CAAC,EAAE,CAAC;IACzB,2CAA2C;IAC3C,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,OAAO,CAAC;IAEzB,kEAAkE;IAClE,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,SAAS,CAAC;IAE/B,4CAA4C;IAC5C,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC;IAE9B,oCAAoC;IACpC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC;IAEzB,mDAAmD;IACnD,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;CACjC;AAED;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,cAAc,GAAI,CAAC,EAAE,CAAC,EAAE,UAAU,WAAW,KAAG,KAAK,CAAC,CAAC,EAAE,CAAC,CAmCtE,CAAC"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Creates an LRU (least recently used) cache with a maximum capacity.
3
+ *
4
+ * When the cache reaches capacity, the least recently used entry is evicted.
5
+ * Both `get` and `set` operations update the access order.
6
+ *
7
+ * ### Example
8
+ *
9
+ * ```ts
10
+ * const cache = createLruCache<string, number>(2);
11
+ * cache.set("a", 1);
12
+ * cache.set("b", 2);
13
+ * cache.set("c", 3); // Evicts "a"
14
+ * cache.has("a"); // false
15
+ * ```
16
+ */
17
+ export const createLruCache = (capacity) => {
18
+ const internalMap = new Map();
19
+ return {
20
+ has: (key) => internalMap.has(key),
21
+ get: (key) => {
22
+ const value = internalMap.get(key);
23
+ if (value === undefined)
24
+ return undefined;
25
+ // Move to end (most recently used)
26
+ internalMap.delete(key);
27
+ internalMap.set(key, value);
28
+ return value;
29
+ },
30
+ set: (key, val) => {
31
+ // If key exists, delete it first to update order
32
+ if (internalMap.has(key)) {
33
+ internalMap.delete(key);
34
+ }
35
+ else if (internalMap.size === capacity) {
36
+ // Evict least recently used (first entry)
37
+ const firstKey = internalMap.keys().next().value;
38
+ internalMap.delete(firstKey);
39
+ }
40
+ internalMap.set(key, val);
41
+ },
42
+ delete: (key) => {
43
+ internalMap.delete(key);
44
+ },
45
+ map: internalMap,
46
+ };
47
+ };
@@ -1,20 +1,53 @@
1
- import { NanoIdLibDep } from "./NanoId.js";
2
- import { Brand } from "./Types.js";
1
+ import { Brand } from "./Brand.js";
2
+ import { RandomBytesDep } from "./Crypto.js";
3
+ import { Id } from "./Type.js";
3
4
  /**
4
- * Manages one-time callback functions.
5
+ * Request-response correlation for callbacks across boundaries.
5
6
  *
6
- * Allows registering callbacks with a unique ID and executing them once with an
7
- * optional argument. Executed callbacks are automatically removed.
7
+ * Stores callbacks with unique IDs and executes them once with an optional
8
+ * argument. Executed callbacks are automatically removed.
8
9
  *
9
- * This is useful for managing event-driven or asynchronous workflows where
10
- * callbacks need to be invoked only once.
10
+ * This is useful for correlating asynchronous request-response operations
11
+ * across boundaries where callback functions cannot be passed directly (e.g.,
12
+ * web workers, message queues).
13
+ *
14
+ * The `execute` method intentionally does not use try-catch or {@link Result}
15
+ * because it's the callback's responsibility to handle its own errors.
16
+ *
17
+ * ### Example
18
+ *
19
+ * ```ts
20
+ * // No-argument callbacks
21
+ * const callbacks = createCallbacks(deps);
22
+ * const id = callbacks.register(() => console.log("called"));
23
+ * callbacks.execute(id);
24
+ *
25
+ * // With argument callbacks
26
+ * const stringCallbacks = createCallbacks<string>(deps);
27
+ * const id = stringCallbacks.register((value) => {
28
+ * console.log(value);
29
+ * });
30
+ * stringCallbacks.execute(id, "hello");
31
+ *
32
+ * // Promise.withResolvers pattern
33
+ * const promiseCallbacks = createCallbacks<string>(deps);
34
+ * const { promise, resolve } = Promise.withResolvers<string>();
35
+ * const id = promiseCallbacks.register(resolve);
36
+ * promiseCallbacks.execute(id, "resolved value");
37
+ * await promise; // "resolved value"
38
+ * ```
39
+ *
40
+ * @template T - The type of argument passed to callbacks (defaults to undefined
41
+ * for no-argument callbacks)
11
42
  */
12
- export interface Callbacks {
43
+ export interface Callbacks<T = undefined> {
13
44
  /** Registers a callback function and returns a unique ID. */
14
- readonly register: (callback: (arg?: unknown) => void) => CallbackId;
45
+ readonly register: (callback: (arg: T) => void) => CallbackId;
15
46
  /** Executes and removes a callback associated with the given ID. */
16
- readonly execute: (id: CallbackId, arg?: unknown) => void;
47
+ readonly execute: T extends undefined ? (id: CallbackId) => undefined : (id: CallbackId, arg: T) => undefined;
17
48
  }
18
- export type CallbackId = string & Brand<"CallbackId">;
19
- export declare const createCallbacks: (deps: NanoIdLibDep) => Callbacks;
49
+ /** Unique identifier for a callback in {@link Callbacks}. */
50
+ export type CallbackId = Id & Brand<"Callback">;
51
+ /** Creates a new {@link Callbacks}. */
52
+ export declare const createCallbacks: <T = undefined>(deps: RandomBytesDep) => Callbacks<T>;
20
53
  //# sourceMappingURL=Callbacks.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Callbacks.d.ts","sourceRoot":"","sources":["../../src/Callbacks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC;;;;;;;;GAQG;AACH,MAAM,WAAW,SAAS;IACxB,6DAA6D;IAC7D,QAAQ,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,EAAE,OAAO,KAAK,IAAI,KAAK,UAAU,CAAC;IAErE,oEAAoE;IACpE,QAAQ,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,UAAU,EAAE,GAAG,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;CAC3D;AAED,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,KAAK,CAAC,YAAY,CAAC,CAAC;AAEtD,eAAO,MAAM,eAAe,GAAI,MAAM,YAAY,KAAG,SAoBpD,CAAC"}
1
+ {"version":3,"file":"Callbacks.d.ts","sourceRoot":"","sources":["../../src/Callbacks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,OAAO,EAAY,EAAE,EAAE,MAAM,WAAW,CAAC;AAEzC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,MAAM,WAAW,SAAS,CAAC,CAAC,GAAG,SAAS;IACtC,6DAA6D;IAC7D,QAAQ,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,KAAK,UAAU,CAAC;IAE9D,oEAAoE;IACpE,QAAQ,CAAC,OAAO,EAAE,CAAC,SAAS,SAAS,GACjC,CAAC,EAAE,EAAE,UAAU,KAAK,SAAS,GAC7B,CAAC,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,KAAK,SAAS,CAAC;CAC3C;AAED,6DAA6D;AAC7D,MAAM,MAAM,UAAU,GAAG,EAAE,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC;AAEhD,uCAAuC;AACvC,eAAO,MAAM,eAAe,GAAI,CAAC,GAAG,SAAS,EAC3C,MAAM,cAAc,KACnB,SAAS,CAAC,CAAC,CAsBb,CAAC"}
@@ -1,18 +1,25 @@
1
+ import { createId } from "./Type.js";
2
+ /** Creates a new {@link Callbacks}. */
1
3
  export const createCallbacks = (deps) => {
2
4
  const callbackMap = new Map();
3
- const callbacks = {
5
+ return {
4
6
  register: (callback) => {
5
- const id = deps.nanoIdLib.nanoid();
7
+ const id = createId(deps);
6
8
  callbackMap.set(id, callback);
7
9
  return id;
8
10
  },
9
- execute: (id, arg) => {
11
+ execute: (id, ...args) => {
10
12
  const callback = callbackMap.get(id);
11
- if (callback) {
12
- callbackMap.delete(id);
13
- callback(arg);
13
+ if (!callback)
14
+ return;
15
+ callbackMap.delete(id);
16
+ if (args.length === 0) {
17
+ // Called without argument (undefined case)
18
+ callback();
19
+ }
20
+ else {
21
+ callback(args[0]);
14
22
  }
15
23
  },
16
24
  };
17
- return callbacks;
18
25
  };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * 📝 Cross-platform console
2
+ * Cross-platform console
3
3
  *
4
4
  * Console abstraction for Chrome 123+, Firefox 125+, Safari 18.1+, Node.js
5
5
  * 22.x+, and React Native 0.75+. Includes methods guaranteed to be available in
@@ -13,14 +13,28 @@
13
13
  * ### Example
14
14
  *
15
15
  * ```ts
16
- * deps.console.log("[db]", "send data message", protocolMessage);
16
+ * deps.console.log("[evolu]", "createEvoluInstance", { name });
17
17
  * ```
18
18
  *
19
19
  * **Tip**: In browser dev tools, you can filter logs by tag (e.g., `[db]`) to
20
- * quickly find relevant messages.
20
+ * quickly find relevant messages. In Node.js, use `grep` to filter output:
21
21
  *
22
- * **Warning**: If you encounter platform-specific issues or missing methods,
23
- * please contribute a PR with details about the environment and behavior.
22
+ * ```bash
23
+ * node app.js | grep "\[relay\]" # Show only relay logs
24
+ * node app.js | grep -E "\[db\]|\[sql\]" # Show db and sql logs
25
+ * node app.js | grep -v "\[debug\]" # Hide debug logs
26
+ * ```
27
+ *
28
+ * Or add to package.json scripts:
29
+ *
30
+ * ```json
31
+ * {
32
+ * "scripts": {
33
+ * "dev:relay": "node app.js | grep \"\\[relay\\]\"",
34
+ * "dev:db": "node app.js | grep -E \"\\[db\\]|\\[sql\\]\""
35
+ * }
36
+ * }
37
+ * ```
24
38
  *
25
39
  * @module
26
40
  */
@@ -43,6 +57,8 @@ export interface Console {
43
57
  debug: (...args: Array<any>) => void;
44
58
  /** Starts a timer with an optional label */
45
59
  time: (label?: string) => void;
60
+ /** Logs the elapsed time for a timer without ending it */
61
+ timeLog: (label?: string, ...data: Array<any>) => void;
46
62
  /** Ends a timer and logs the elapsed time */
47
63
  timeEnd: (label?: string) => void;
48
64
  /** Displays an object's properties in a detailed format */
@@ -55,8 +71,6 @@ export interface Console {
55
71
  countReset: (label?: string) => void;
56
72
  /** Writes a message if the value is falsy, otherwise does nothing */
57
73
  assert: (value: any, message?: string, ...optionalParams: Array<any>) => void;
58
- /** Logs the elapsed time for a timer without ending it */
59
- timeLog: (label?: string, ...data: Array<any>) => void;
60
74
  /** Prints a stack trace with an optional message */
61
75
  trace: (message?: any, ...optionalParams: Array<any>) => void;
62
76
  }
@@ -75,4 +89,15 @@ export interface ConsoleConfig {
75
89
  }
76
90
  /** Creates a console instance using the global console. */
77
91
  export declare const createConsole: (config?: ConsoleConfig) => Console;
92
+ export interface ConsoleWithTimeConfig extends ConsoleConfig {
93
+ /**
94
+ * Type of timestamp to prepend to log messages.
95
+ *
96
+ * - 'absolute': Shows actual time (e.g., "14:32:15.234")
97
+ * - 'relative': Shows time since console creation (e.g., "+1.234s")
98
+ */
99
+ readonly timestampType: "absolute" | "relative";
100
+ }
101
+ /** Creates a console instance with timestamp prefixes. */
102
+ export declare const createConsoleWithTime: (config?: ConsoleWithTimeConfig) => Console;
78
103
  //# sourceMappingURL=Console.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Console.d.ts","sourceRoot":"","sources":["../../src/Console.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH;;;GAGG;AACH,MAAM,WAAW,OAAO;IACtB,sEAAsE;IACtE,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,uCAAuC;IACvC,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;IAEnC,2DAA2D;IAC3D,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;IAEpC,gCAAgC;IAChC,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;IAEpC,+BAA+B;IAC/B,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;IAErC,8BAA8B;IAC9B,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;IAErC,4CAA4C;IAC5C,IAAI,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAE/B,6CAA6C;IAC7C,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAElC,2DAA2D;IAC3D,GAAG,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;IAE1C,uCAAuC;IACvC,KAAK,EAAE,CAAC,WAAW,EAAE,GAAG,EAAE,UAAU,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;IAE9D,yEAAyE;IACzE,KAAK,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAEhC,6CAA6C;IAC7C,UAAU,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAErC,qEAAqE;IACrE,MAAM,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,cAAc,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;IAE9E,0DAA0D;IAC1D,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;IAEvD,oDAAoD;IACpD,KAAK,EAAE,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,GAAG,cAAc,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;CAC/D;AAED,6DAA6D;AAC7D,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,aAAa;IAC5B;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,2DAA2D;AAC3D,eAAO,MAAM,aAAa,GAAI,SAAQ,aAAkB,KAAG,OAgE1D,CAAC"}
1
+ {"version":3,"file":"Console.d.ts","sourceRoot":"","sources":["../../src/Console.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH;;;GAGG;AACH,MAAM,WAAW,OAAO;IACtB,sEAAsE;IACtE,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,uCAAuC;IACvC,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;IAEnC,2DAA2D;IAC3D,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;IAEpC,gCAAgC;IAChC,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;IAEpC,+BAA+B;IAC/B,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;IAErC,8BAA8B;IAC9B,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;IAErC,4CAA4C;IAC5C,IAAI,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAE/B,0DAA0D;IAC1D,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;IAEvD,6CAA6C;IAC7C,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAElC,2DAA2D;IAC3D,GAAG,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;IAE1C,uCAAuC;IACvC,KAAK,EAAE,CAAC,WAAW,EAAE,GAAG,EAAE,UAAU,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;IAE9D,yEAAyE;IACzE,KAAK,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAEhC,6CAA6C;IAC7C,UAAU,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAErC,qEAAqE;IACrE,MAAM,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,cAAc,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;IAE9E,oDAAoD;IACpD,KAAK,EAAE,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,GAAG,cAAc,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;CAC/D;AAED,6DAA6D;AAC7D,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,aAAa;IAC5B;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,2DAA2D;AAC3D,eAAO,MAAM,aAAa,GAAI,SAAQ,aAAkB,KAAG,OAgE1D,CAAC;AAEF,MAAM,WAAW,qBAAsB,SAAQ,aAAa;IAC1D;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,EAAE,UAAU,GAAG,UAAU,CAAC;CACjD;AAED,0DAA0D;AAC1D,eAAO,MAAM,qBAAqB,GAChC,SAAQ,qBAAqD,KAC5D,OAmDF,CAAC"}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * 📝 Cross-platform console
2
+ * Cross-platform console
3
3
  *
4
4
  * Console abstraction for Chrome 123+, Firefox 125+, Safari 18.1+, Node.js
5
5
  * 22.x+, and React Native 0.75+. Includes methods guaranteed to be available in
@@ -13,14 +13,28 @@
13
13
  * ### Example
14
14
  *
15
15
  * ```ts
16
- * deps.console.log("[db]", "send data message", protocolMessage);
16
+ * deps.console.log("[evolu]", "createEvoluInstance", { name });
17
17
  * ```
18
18
  *
19
19
  * **Tip**: In browser dev tools, you can filter logs by tag (e.g., `[db]`) to
20
- * quickly find relevant messages.
20
+ * quickly find relevant messages. In Node.js, use `grep` to filter output:
21
21
  *
22
- * **Warning**: If you encounter platform-specific issues or missing methods,
23
- * please contribute a PR with details about the environment and behavior.
22
+ * ```bash
23
+ * node app.js | grep "\[relay\]" # Show only relay logs
24
+ * node app.js | grep -E "\[db\]|\[sql\]" # Show db and sql logs
25
+ * node app.js | grep -v "\[debug\]" # Hide debug logs
26
+ * ```
27
+ *
28
+ * Or add to package.json scripts:
29
+ *
30
+ * ```json
31
+ * {
32
+ * "scripts": {
33
+ * "dev:relay": "node app.js | grep \"\\[relay\\]\"",
34
+ * "dev:db": "node app.js | grep -E \"\\[db\\]|\\[sql\\]\""
35
+ * }
36
+ * }
37
+ * ```
24
38
  *
25
39
  * @module
26
40
  */
@@ -58,6 +72,11 @@ export const createConsole = (config = {}) => {
58
72
  if (instance.enabled)
59
73
  console.time(label);
60
74
  },
75
+ timeLog: (label, ...data) => {
76
+ // eslint-disable-next-line no-console, @typescript-eslint/no-unsafe-argument
77
+ if (instance.enabled)
78
+ console.timeLog(label, ...data);
79
+ },
61
80
  timeEnd: (label) => {
62
81
  // eslint-disable-next-line no-console
63
82
  if (instance.enabled)
@@ -88,11 +107,6 @@ export const createConsole = (config = {}) => {
88
107
  if (instance.enabled)
89
108
  console.assert(value, message, ...optionalParams);
90
109
  },
91
- timeLog: (label, ...data) => {
92
- // eslint-disable-next-line no-console, @typescript-eslint/no-unsafe-argument
93
- if (instance.enabled)
94
- console.timeLog(label, ...data);
95
- },
96
110
  trace: (message, ...optionalParams) => {
97
111
  // eslint-disable-next-line no-console, @typescript-eslint/no-unsafe-argument
98
112
  if (instance.enabled)
@@ -101,3 +115,52 @@ export const createConsole = (config = {}) => {
101
115
  };
102
116
  return instance;
103
117
  };
118
+ /** Creates a console instance with timestamp prefixes. */
119
+ export const createConsoleWithTime = (config = { timestampType: "relative" }) => {
120
+ const console = createConsole(config);
121
+ const startTime = performance.now();
122
+ const getTimestamp = () => {
123
+ if (config.timestampType === "relative") {
124
+ const elapsed = (performance.now() - startTime) / 1000;
125
+ // Format for better readability at different time scales
126
+ if (elapsed < 60) {
127
+ // Under 1 minute: show seconds with millisecond precision
128
+ return `+${elapsed.toFixed(3)}s`;
129
+ }
130
+ else if (elapsed < 3600) {
131
+ // 1 minute to 1 hour: show minutes and seconds with millisecond precision
132
+ const minutes = Math.floor(elapsed / 60);
133
+ const seconds = (elapsed % 60).toFixed(3);
134
+ return `+${minutes}m${seconds}s`;
135
+ }
136
+ else {
137
+ // Over 1 hour: show hours, minutes, and seconds with millisecond precision
138
+ const hours = Math.floor(elapsed / 3600);
139
+ const minutes = Math.floor((elapsed % 3600) / 60);
140
+ const seconds = ((elapsed % 3600) % 60).toFixed(3);
141
+ return `+${hours}h${minutes}m${seconds}s`;
142
+ }
143
+ }
144
+ else {
145
+ // Absolute time - format as HH:MM:SS.mmm
146
+ const now = new Date();
147
+ const hours = now.getHours().toString().padStart(2, "0");
148
+ const minutes = now.getMinutes().toString().padStart(2, "0");
149
+ const seconds = now.getSeconds().toString().padStart(2, "0");
150
+ const milliseconds = now.getMilliseconds().toString().padStart(3, "0");
151
+ return `${hours}:${minutes}:${seconds}.${milliseconds}`;
152
+ }
153
+ };
154
+ const withTimestamp = (fn) => (...args) => {
155
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
156
+ fn(`[${getTimestamp()}]`, ...args);
157
+ };
158
+ // Override methods that should have timestamps
159
+ console.log = withTimestamp(console.log);
160
+ console.info = withTimestamp(console.info);
161
+ console.warn = withTimestamp(console.warn);
162
+ console.error = withTimestamp(console.error);
163
+ console.debug = withTimestamp(console.debug);
164
+ console.trace = withTimestamp(console.trace);
165
+ return console;
166
+ };