@evolu/common 8.5.0 → 8.6.1

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 (328) hide show
  1. package/dist/src/Array.d.ts +170 -97
  2. package/dist/src/Array.d.ts.map +1 -1
  3. package/dist/src/Array.js +67 -42
  4. package/dist/src/Assert.d.ts +233 -30
  5. package/dist/src/Assert.d.ts.map +1 -1
  6. package/dist/src/Assert.js +150 -30
  7. package/dist/src/BigInt.d.ts +3 -3
  8. package/dist/src/BigInt.js +3 -3
  9. package/dist/src/Brand.d.ts +7 -7
  10. package/dist/src/Buffer.d.ts +12 -4
  11. package/dist/src/Buffer.d.ts.map +1 -1
  12. package/dist/src/Cache.d.ts +8 -3
  13. package/dist/src/Cache.d.ts.map +1 -1
  14. package/dist/src/Cache.js +8 -3
  15. package/dist/src/Callbacks.d.ts +8 -4
  16. package/dist/src/Callbacks.d.ts.map +1 -1
  17. package/dist/src/Console.d.ts +45 -30
  18. package/dist/src/Console.d.ts.map +1 -1
  19. package/dist/src/Console.js +32 -21
  20. package/dist/src/Crypto.d.ts +13 -8
  21. package/dist/src/Crypto.d.ts.map +1 -1
  22. package/dist/src/Crypto.js +6 -3
  23. package/dist/src/Eq.d.ts +107 -58
  24. package/dist/src/Eq.d.ts.map +1 -1
  25. package/dist/src/Eq.js +308 -112
  26. package/dist/src/Function.d.ts +54 -24
  27. package/dist/src/Function.d.ts.map +1 -1
  28. package/dist/src/Function.js +34 -17
  29. package/dist/src/Http.d.ts +52 -19
  30. package/dist/src/Http.d.ts.map +1 -1
  31. package/dist/src/Identicon.d.ts +9 -4
  32. package/dist/src/Identicon.d.ts.map +1 -1
  33. package/dist/src/Identicon.js +9 -4
  34. package/dist/src/LockManager.d.ts +12 -10
  35. package/dist/src/LockManager.d.ts.map +1 -1
  36. package/dist/src/Lookup.d.ts +4 -2
  37. package/dist/src/Lookup.d.ts.map +1 -1
  38. package/dist/src/Lookup.js +4 -2
  39. package/dist/src/Number.d.ts +28 -24
  40. package/dist/src/Number.d.ts.map +1 -1
  41. package/dist/src/Number.js +16 -17
  42. package/dist/src/Object.d.ts +89 -47
  43. package/dist/src/Object.d.ts.map +1 -1
  44. package/dist/src/Object.js +88 -41
  45. package/dist/src/Option.d.ts +14 -5
  46. package/dist/src/Option.d.ts.map +1 -1
  47. package/dist/src/Option.js +14 -5
  48. package/dist/src/Order.d.ts +12 -12
  49. package/dist/src/Order.js +12 -12
  50. package/dist/src/Platform.d.ts +2 -2
  51. package/dist/src/Random.d.ts +7 -4
  52. package/dist/src/Random.d.ts.map +1 -1
  53. package/dist/src/Redacted.d.ts +13 -6
  54. package/dist/src/Redacted.d.ts.map +1 -1
  55. package/dist/src/Redacted.js +4 -2
  56. package/dist/src/Ref.d.ts +4 -4
  57. package/dist/src/Relation.d.ts +5 -7
  58. package/dist/src/Relation.d.ts.map +1 -1
  59. package/dist/src/Resource.d.ts +27 -12
  60. package/dist/src/Resource.d.ts.map +1 -1
  61. package/dist/src/Result.d.ts +258 -114
  62. package/dist/src/Result.d.ts.map +1 -1
  63. package/dist/src/Result.js +71 -34
  64. package/dist/src/Schedule.d.ts +233 -116
  65. package/dist/src/Schedule.d.ts.map +1 -1
  66. package/dist/src/Schedule.js +204 -110
  67. package/dist/src/Set.d.ts +43 -24
  68. package/dist/src/Set.d.ts.map +1 -1
  69. package/dist/src/Set.js +25 -13
  70. package/dist/src/Sqlite.d.ts +4 -4
  71. package/dist/src/Sqlite.d.ts.map +1 -1
  72. package/dist/src/Sqlite.js +9 -8
  73. package/dist/src/Task.d.ts +441 -212
  74. package/dist/src/Task.d.ts.map +1 -1
  75. package/dist/src/Task.js +238 -115
  76. package/dist/src/Test.d.ts +10 -4
  77. package/dist/src/Test.d.ts.map +1 -1
  78. package/dist/src/Test.js +10 -4
  79. package/dist/src/Time.d.ts +27 -17
  80. package/dist/src/Time.d.ts.map +1 -1
  81. package/dist/src/Time.js +16 -6
  82. package/dist/src/Type.d.ts +1096 -387
  83. package/dist/src/Type.d.ts.map +1 -1
  84. package/dist/src/Type.js +1046 -372
  85. package/dist/src/Types.d.ts +95 -40
  86. package/dist/src/Types.d.ts.map +1 -1
  87. package/dist/src/Types.js +13 -4
  88. package/dist/src/WebSocket.d.ts +14 -6
  89. package/dist/src/WebSocket.d.ts.map +1 -1
  90. package/dist/src/Worker.d.ts +10 -6
  91. package/dist/src/Worker.d.ts.map +1 -1
  92. package/dist/src/intl/_en.d.ts +3 -1
  93. package/dist/src/intl/_en.d.ts.map +1 -1
  94. package/dist/src/intl/_en.js +17 -3
  95. package/dist/src/intl/ar.d.ts +3 -1
  96. package/dist/src/intl/ar.d.ts.map +1 -1
  97. package/dist/src/intl/ar.js +15 -2
  98. package/dist/src/intl/bn.d.ts +3 -1
  99. package/dist/src/intl/bn.d.ts.map +1 -1
  100. package/dist/src/intl/bn.js +16 -3
  101. package/dist/src/intl/ca.d.ts +3 -1
  102. package/dist/src/intl/ca.d.ts.map +1 -1
  103. package/dist/src/intl/ca.js +16 -3
  104. package/dist/src/intl/cs.d.ts +3 -1
  105. package/dist/src/intl/cs.d.ts.map +1 -1
  106. package/dist/src/intl/cs.js +16 -3
  107. package/dist/src/intl/da.d.ts +3 -1
  108. package/dist/src/intl/da.d.ts.map +1 -1
  109. package/dist/src/intl/da.js +16 -3
  110. package/dist/src/intl/de.d.ts +3 -1
  111. package/dist/src/intl/de.d.ts.map +1 -1
  112. package/dist/src/intl/de.js +16 -3
  113. package/dist/src/intl/el.d.ts +3 -1
  114. package/dist/src/intl/el.d.ts.map +1 -1
  115. package/dist/src/intl/el.js +16 -3
  116. package/dist/src/intl/es.d.ts +3 -1
  117. package/dist/src/intl/es.d.ts.map +1 -1
  118. package/dist/src/intl/es.js +16 -3
  119. package/dist/src/intl/fa.d.ts +3 -1
  120. package/dist/src/intl/fa.d.ts.map +1 -1
  121. package/dist/src/intl/fa.js +16 -3
  122. package/dist/src/intl/fi.d.ts +3 -1
  123. package/dist/src/intl/fi.d.ts.map +1 -1
  124. package/dist/src/intl/fi.js +16 -3
  125. package/dist/src/intl/fil.d.ts +3 -1
  126. package/dist/src/intl/fil.d.ts.map +1 -1
  127. package/dist/src/intl/fil.js +16 -3
  128. package/dist/src/intl/fr.d.ts +3 -1
  129. package/dist/src/intl/fr.d.ts.map +1 -1
  130. package/dist/src/intl/fr.js +16 -3
  131. package/dist/src/intl/he.d.ts +3 -1
  132. package/dist/src/intl/he.d.ts.map +1 -1
  133. package/dist/src/intl/he.js +16 -3
  134. package/dist/src/intl/hi.d.ts +3 -1
  135. package/dist/src/intl/hi.d.ts.map +1 -1
  136. package/dist/src/intl/hi.js +16 -3
  137. package/dist/src/intl/hr.d.ts +3 -1
  138. package/dist/src/intl/hr.d.ts.map +1 -1
  139. package/dist/src/intl/hr.js +16 -3
  140. package/dist/src/intl/hu.d.ts +2 -1
  141. package/dist/src/intl/hu.d.ts.map +1 -1
  142. package/dist/src/intl/hu.js +15 -3
  143. package/dist/src/intl/id.d.ts +3 -1
  144. package/dist/src/intl/id.d.ts.map +1 -1
  145. package/dist/src/intl/id.js +16 -3
  146. package/dist/src/intl/it.d.ts +3 -1
  147. package/dist/src/intl/it.d.ts.map +1 -1
  148. package/dist/src/intl/it.js +16 -3
  149. package/dist/src/intl/ja.d.ts +3 -1
  150. package/dist/src/intl/ja.d.ts.map +1 -1
  151. package/dist/src/intl/ja.js +16 -3
  152. package/dist/src/intl/ko.d.ts +3 -1
  153. package/dist/src/intl/ko.d.ts.map +1 -1
  154. package/dist/src/intl/ko.js +16 -3
  155. package/dist/src/intl/ml.d.ts +3 -1
  156. package/dist/src/intl/ml.d.ts.map +1 -1
  157. package/dist/src/intl/ml.js +16 -3
  158. package/dist/src/intl/mr.d.ts +3 -1
  159. package/dist/src/intl/mr.d.ts.map +1 -1
  160. package/dist/src/intl/mr.js +16 -3
  161. package/dist/src/intl/ms.d.ts +3 -1
  162. package/dist/src/intl/ms.d.ts.map +1 -1
  163. package/dist/src/intl/ms.js +15 -2
  164. package/dist/src/intl/nb.d.ts +2 -1
  165. package/dist/src/intl/nb.d.ts.map +1 -1
  166. package/dist/src/intl/nb.js +14 -2
  167. package/dist/src/intl/nl.d.ts +3 -1
  168. package/dist/src/intl/nl.d.ts.map +1 -1
  169. package/dist/src/intl/nl.js +16 -3
  170. package/dist/src/intl/pa.d.ts +3 -1
  171. package/dist/src/intl/pa.d.ts.map +1 -1
  172. package/dist/src/intl/pa.js +16 -3
  173. package/dist/src/intl/pl.d.ts +2 -0
  174. package/dist/src/intl/pl.d.ts.map +1 -1
  175. package/dist/src/intl/pl.js +15 -2
  176. package/dist/src/intl/pt-BR.d.ts +3 -1
  177. package/dist/src/intl/pt-BR.d.ts.map +1 -1
  178. package/dist/src/intl/pt-BR.js +16 -3
  179. package/dist/src/intl/pt.d.ts +3 -1
  180. package/dist/src/intl/pt.d.ts.map +1 -1
  181. package/dist/src/intl/pt.js +15 -2
  182. package/dist/src/intl/ro.d.ts +3 -1
  183. package/dist/src/intl/ro.d.ts.map +1 -1
  184. package/dist/src/intl/ro.js +16 -3
  185. package/dist/src/intl/sk.d.ts +3 -1
  186. package/dist/src/intl/sk.d.ts.map +1 -1
  187. package/dist/src/intl/sk.js +15 -2
  188. package/dist/src/intl/sl.d.ts +3 -1
  189. package/dist/src/intl/sl.d.ts.map +1 -1
  190. package/dist/src/intl/sl.js +16 -3
  191. package/dist/src/intl/sv.d.ts +3 -1
  192. package/dist/src/intl/sv.d.ts.map +1 -1
  193. package/dist/src/intl/sv.js +16 -3
  194. package/dist/src/intl/sw.d.ts +1 -0
  195. package/dist/src/intl/sw.d.ts.map +1 -1
  196. package/dist/src/intl/sw.js +14 -2
  197. package/dist/src/intl/ta.d.ts +3 -1
  198. package/dist/src/intl/ta.d.ts.map +1 -1
  199. package/dist/src/intl/ta.js +16 -3
  200. package/dist/src/intl/te.d.ts +3 -1
  201. package/dist/src/intl/te.d.ts.map +1 -1
  202. package/dist/src/intl/te.js +16 -3
  203. package/dist/src/intl/th.d.ts +3 -1
  204. package/dist/src/intl/th.d.ts.map +1 -1
  205. package/dist/src/intl/th.js +16 -3
  206. package/dist/src/intl/tr.d.ts +3 -1
  207. package/dist/src/intl/tr.d.ts.map +1 -1
  208. package/dist/src/intl/tr.js +16 -3
  209. package/dist/src/intl/uk.d.ts +3 -1
  210. package/dist/src/intl/uk.d.ts.map +1 -1
  211. package/dist/src/intl/uk.js +16 -3
  212. package/dist/src/intl/ur.d.ts +3 -1
  213. package/dist/src/intl/ur.d.ts.map +1 -1
  214. package/dist/src/intl/ur.js +15 -2
  215. package/dist/src/intl/vi.d.ts +3 -1
  216. package/dist/src/intl/vi.d.ts.map +1 -1
  217. package/dist/src/intl/vi.js +16 -3
  218. package/dist/src/intl/zh-CN.d.ts +3 -1
  219. package/dist/src/intl/zh-CN.d.ts.map +1 -1
  220. package/dist/src/intl/zh-CN.js +16 -3
  221. package/dist/src/intl/zh-TW.d.ts +3 -1
  222. package/dist/src/intl/zh-TW.d.ts.map +1 -1
  223. package/dist/src/intl/zh-TW.js +16 -3
  224. package/dist/src/local-first/Evolu.d.ts +47 -24
  225. package/dist/src/local-first/Evolu.d.ts.map +1 -1
  226. package/dist/src/local-first/Owner.d.ts +10 -7
  227. package/dist/src/local-first/Owner.d.ts.map +1 -1
  228. package/dist/src/local-first/Owner.js +10 -7
  229. package/dist/src/local-first/Protocol.d.ts +5 -5
  230. package/dist/src/local-first/Protocol.js +7 -7
  231. package/dist/src/local-first/Query.d.ts +34 -21
  232. package/dist/src/local-first/Query.d.ts.map +1 -1
  233. package/dist/src/local-first/Query.js +25 -13
  234. package/dist/src/local-first/Relay.d.ts +12 -5
  235. package/dist/src/local-first/Relay.d.ts.map +1 -1
  236. package/dist/src/local-first/Schema.d.ts +19 -11
  237. package/dist/src/local-first/Schema.d.ts.map +1 -1
  238. package/dist/src/local-first/Schema.js +11 -6
  239. package/dist/src/local-first/Storage.d.ts +4 -2
  240. package/dist/src/local-first/Storage.d.ts.map +1 -1
  241. package/package.json +3 -4
  242. package/src/Array.ts +170 -97
  243. package/src/Assert.ts +336 -31
  244. package/src/BigInt.ts +3 -3
  245. package/src/Brand.ts +7 -7
  246. package/src/Buffer.ts +12 -4
  247. package/src/Cache.ts +8 -3
  248. package/src/Callbacks.ts +8 -4
  249. package/src/Console.ts +45 -30
  250. package/src/Crypto.ts +13 -8
  251. package/src/Eq.ts +450 -122
  252. package/src/Function.ts +54 -24
  253. package/src/Http.ts +52 -19
  254. package/src/Identicon.ts +9 -4
  255. package/src/LockManager.ts +12 -10
  256. package/src/Lookup.ts +4 -2
  257. package/src/Number.ts +28 -24
  258. package/src/Object.ts +115 -49
  259. package/src/Option.ts +14 -5
  260. package/src/Order.ts +12 -12
  261. package/src/Platform.ts +2 -2
  262. package/src/Random.ts +7 -4
  263. package/src/Redacted.ts +13 -6
  264. package/src/Ref.ts +4 -4
  265. package/src/Relation.ts +5 -7
  266. package/src/Resource.ts +27 -12
  267. package/src/Result.ts +258 -114
  268. package/src/Schedule.ts +233 -116
  269. package/src/Set.ts +43 -24
  270. package/src/Sqlite.ts +9 -8
  271. package/src/Task.ts +441 -212
  272. package/src/Test.ts +10 -4
  273. package/src/Time.ts +27 -17
  274. package/src/Type.ts +2077 -620
  275. package/src/Types.ts +108 -40
  276. package/src/WebSocket.ts +14 -6
  277. package/src/Worker.ts +10 -6
  278. package/src/intl/_en.ts +20 -4
  279. package/src/intl/ar.ts +17 -2
  280. package/src/intl/bn.ts +19 -4
  281. package/src/intl/ca.ts +19 -4
  282. package/src/intl/cs.ts +19 -4
  283. package/src/intl/da.ts +19 -4
  284. package/src/intl/de.ts +19 -4
  285. package/src/intl/el.ts +19 -4
  286. package/src/intl/es.ts +19 -4
  287. package/src/intl/fa.ts +19 -4
  288. package/src/intl/fi.ts +19 -4
  289. package/src/intl/fil.ts +19 -4
  290. package/src/intl/fr.ts +19 -4
  291. package/src/intl/he.ts +19 -4
  292. package/src/intl/hi.ts +19 -4
  293. package/src/intl/hr.ts +19 -4
  294. package/src/intl/hu.ts +18 -4
  295. package/src/intl/id.ts +19 -4
  296. package/src/intl/it.ts +19 -4
  297. package/src/intl/ja.ts +19 -4
  298. package/src/intl/ko.ts +19 -4
  299. package/src/intl/ml.ts +19 -4
  300. package/src/intl/mr.ts +19 -4
  301. package/src/intl/ms.ts +17 -2
  302. package/src/intl/nb.ts +16 -2
  303. package/src/intl/nl.ts +19 -4
  304. package/src/intl/pa.ts +19 -4
  305. package/src/intl/pl.ts +18 -2
  306. package/src/intl/pt-BR.ts +19 -4
  307. package/src/intl/pt.ts +17 -2
  308. package/src/intl/ro.ts +19 -4
  309. package/src/intl/sk.ts +17 -2
  310. package/src/intl/sl.ts +19 -4
  311. package/src/intl/sv.ts +19 -4
  312. package/src/intl/sw.ts +15 -2
  313. package/src/intl/ta.ts +19 -4
  314. package/src/intl/te.ts +19 -4
  315. package/src/intl/th.ts +19 -4
  316. package/src/intl/tr.ts +19 -4
  317. package/src/intl/uk.ts +19 -4
  318. package/src/intl/ur.ts +17 -2
  319. package/src/intl/vi.ts +19 -3
  320. package/src/intl/zh-CN.ts +19 -4
  321. package/src/intl/zh-TW.ts +19 -4
  322. package/src/local-first/Evolu.ts +47 -24
  323. package/src/local-first/Owner.ts +10 -7
  324. package/src/local-first/Protocol.ts +7 -7
  325. package/src/local-first/Query.ts +34 -21
  326. package/src/local-first/Relay.ts +12 -5
  327. package/src/local-first/Schema.ts +19 -11
  328. package/src/local-first/Storage.ts +4 -2
package/dist/src/Eq.js CHANGED
@@ -3,38 +3,48 @@
3
3
  *
4
4
  * @module
5
5
  */
6
+ import { getObjectKind } from "./Object.js";
6
7
  /**
7
- * Compares two values with strict equality (`===`).
8
+ * Compares two values using SameValue equality (`Object.is`).
8
9
  *
9
- * Strict equality considers `NaN` unequal to itself. Use {@link eqSameValueZero}
10
- * when values can contain `NaN` and equality must be reflexive.
10
+ * SameValue considers `NaN` equal to itself, distinguishes `0` from `-0`, and
11
+ * compares objects by reference identity.
12
+ *
13
+ * ### Example
14
+ *
15
+ * ```ts
16
+ * import { assertFalse, assertTrue, eqStrict } from "@evolu/common";
17
+ *
18
+ * assertTrue(eqStrict(NaN, NaN));
19
+ * assertFalse(eqStrict(0, -0));
20
+ * ```
11
21
  */
12
- export const eqStrict = (x, y) => x === y;
22
+ export const eqStrict = (x, y) => Object.is(x, y);
13
23
  /**
14
24
  * Compares two values using SameValueZero equality.
15
25
  *
16
26
  * SameValueZero is the standard equality algorithm used by `Map`, `Set`, and
17
- * `Array.prototype.includes`. It behaves like strict equality except that `NaN`
18
- * equals itself. Both algorithms consider `0` and `-0` equal.
27
+ * `Array.prototype.includes`. Like SameValue, it considers `NaN` equal to
28
+ * itself, but unlike SameValue, it considers `0` and `-0` equal.
19
29
  *
20
30
  * ### Example
21
31
  *
22
32
  * ```ts
23
- * import { eqSameValueZero } from "@evolu/common";
33
+ * import { assertFalse, assertTrue, eqSameValueZero } from "@evolu/common";
24
34
  *
25
- * expect(eqSameValueZero(NaN, NaN)).toBe(true);
26
- * expect(eqSameValueZero(0, -0)).toBe(true);
27
- * expect(eqSameValueZero({}, {})).toBe(false);
35
+ * assertTrue(eqSameValueZero(NaN, NaN));
36
+ * assertTrue(eqSameValueZero(0, -0));
37
+ * assertFalse(eqSameValueZero({}, {}));
28
38
  * ```
29
39
  */
30
40
  export const eqSameValueZero = (x, y) => x === y || Object.is(x, y);
31
- /** An {@link Eq} for strings using strict equality. */
41
+ /** An {@link Eq} for strings using {@link eqStrict}. */
32
42
  export const eqString = eqStrict;
33
43
  /** An {@link Eq} for numbers using {@link eqSameValueZero}. */
34
44
  export const eqNumber = eqSameValueZero;
35
- /** An {@link Eq} for bigints using strict equality. */
45
+ /** An {@link Eq} for bigints using {@link eqStrict}. */
36
46
  export const eqBigInt = eqStrict;
37
- /** An {@link Eq} for booleans using strict equality. */
47
+ /** An {@link Eq} for booleans using {@link eqStrict}. */
38
48
  export const eqBoolean = eqStrict;
39
49
  /** An {@link Eq} for `undefined`. */
40
50
  export const eqUndefined = eqStrict;
@@ -49,15 +59,20 @@ export const eqFromOrder = (order) => (x, y) => order(x, y) === 0;
49
59
  * ### Example
50
60
  *
51
61
  * ```ts
52
- * import { createEqArrayLike, eqNumber } from "@evolu/common";
62
+ * import {
63
+ * assertFalse,
64
+ * assertTrue,
65
+ * createEqArrayLike,
66
+ * eqNumber,
67
+ * } from "@evolu/common";
53
68
  *
54
69
  * const eqArrayNumber = createEqArrayLike(eqNumber);
55
70
  *
56
- * expect(eqArrayNumber([1, 2, 3], [1, 2, 3])).toBe(true);
57
- * expect(
71
+ * assertTrue(eqArrayNumber([1, 2, 3], [1, 2, 3]));
72
+ * assertTrue(
58
73
  * eqArrayNumber(new Uint8Array([1, 2, 3]), new Uint8Array([1, 2, 3])),
59
- * ).toBe(true);
60
- * expect(eqArrayNumber([1, 2, 3], [1, 2, 4])).toBe(false);
74
+ * );
75
+ * assertFalse(eqArrayNumber([1, 2, 3], [1, 2, 4]));
61
76
  * ```
62
77
  */
63
78
  export const createEqArrayLike = (item) => (x, y) => {
@@ -72,19 +87,20 @@ export const createEqArrayLike = (item) => (x, y) => {
72
87
  return true;
73
88
  };
74
89
  /**
75
- * Compares two array-like structures by strict reference equality (`===`).
90
+ * Compares two array-like structures element by element using {@link eqStrict}.
76
91
  *
77
- * Useful for structural sharing checks where elements are compared by identity.
92
+ * Useful for structural sharing checks where objects are compared by reference
93
+ * identity. `NaN` elements are equal, while `0` and `-0` elements differ.
78
94
  *
79
95
  * ### Example
80
96
  *
81
97
  * ```ts
82
- * import { eqArrayStrict } from "@evolu/common";
98
+ * import { assertFalse, assertTrue, eqArrayStrict } from "@evolu/common";
83
99
  *
84
100
  * const a = { x: 1 };
85
101
  * const b = { x: 1 };
86
- * expect(eqArrayStrict([a, a], [a, a])).toBe(true);
87
- * expect(eqArrayStrict([a], [b])).toBe(false);
102
+ * assertTrue(eqArrayStrict([a, a], [a, a]));
103
+ * assertFalse(eqArrayStrict([a], [b]));
88
104
  * ```
89
105
  */
90
106
  export const eqArrayStrict = /*#__PURE__*/ createEqArrayLike(eqStrict);
@@ -94,12 +110,27 @@ export const eqArrayStrict = /*#__PURE__*/ createEqArrayLike(eqStrict);
94
110
  * ### Example
95
111
  *
96
112
  * ```ts
97
- * import { eqArrayNumber } from "@evolu/common";
113
+ * import { assertTrue, eqArrayNumber } from "@evolu/common";
98
114
  *
99
- * expect(eqArrayNumber([1, NaN], [1, NaN])).toBe(true);
115
+ * assertTrue(eqArrayNumber([1, NaN], [1, NaN]));
100
116
  * ```
101
117
  */
102
118
  export const eqArrayNumber = /*#__PURE__*/ createEqArrayLike(eqNumber);
119
+ /**
120
+ * Compares two Uint8Arrays by byte value.
121
+ *
122
+ * ### Example
123
+ *
124
+ * ```ts
125
+ * import { assertFalse, assertTrue, eqUint8Array } from "@evolu/common";
126
+ *
127
+ * assertTrue(eqUint8Array(new Uint8Array([1, 2]), new Uint8Array([1, 2])));
128
+ * assertFalse(
129
+ * eqUint8Array(new Uint8Array([1, 2]), new Uint8Array([1, 3])),
130
+ * );
131
+ * ```
132
+ */
133
+ export const eqUint8Array = eqArrayNumber;
103
134
  /**
104
135
  * Creates an equivalence function for objects based on an equivalence for their
105
136
  * fields.
@@ -107,12 +138,17 @@ export const eqArrayNumber = /*#__PURE__*/ createEqArrayLike(eqNumber);
107
138
  * ### Example
108
139
  *
109
140
  * ```ts
110
- * import { createEqObject, eqNumber } from "@evolu/common";
141
+ * import {
142
+ * assertFalse,
143
+ * assertTrue,
144
+ * createEqObject,
145
+ * eqNumber,
146
+ * } from "@evolu/common";
111
147
  *
112
148
  * const eqObjectNumber = createEqObject({ a: eqNumber });
113
149
  *
114
- * expect(eqObjectNumber({ a: 1 }, { a: 1 })).toBe(true);
115
- * expect(eqObjectNumber({ a: 1 }, { a: 2 })).toBe(false);
150
+ * assertTrue(eqObjectNumber({ a: 1 }, { a: 1 }));
151
+ * assertFalse(eqObjectNumber({ a: 1 }, { a: 2 }));
116
152
  * ```
117
153
  */
118
154
  export const createEqObject = (eqs) => (x, y) => {
@@ -125,111 +161,271 @@ export const createEqObject = (eqs) => (x, y) => {
125
161
  }
126
162
  return true;
127
163
  };
164
+ export function eqData(actual, expected) {
165
+ return eqDataInternal(actual, expected, {
166
+ pairs: [],
167
+ rightsByLeft: new Map(),
168
+ });
169
+ }
128
170
  /**
129
- * Deeply compares two {@link JsonValue} values for equality.
130
- *
131
- * - Uses an iterative approach with a stack to handle large or deeply nested
132
- * objects without risking stack overflow.
133
- * - Defensively handles circular references in runtime values without looping,
134
- * although cyclic values are not valid JSON.
135
- * - Unlike JSON.stringify, this function directly compares values, avoiding
136
- * serialization overhead and leveraging short-circuit evaluation for faster
137
- * failure on mismatched structures.
171
+ * Compares two {@link JsonValue} values using {@link eqData}.
138
172
  *
139
173
  * ### Example
140
174
  *
141
175
  * ```ts
142
- * import { eqJsonValue, type JsonValue } from "@evolu/common";
176
+ * import { assertTrue, eqJsonValue, type JsonValue } from "@evolu/common";
143
177
  *
144
178
  * const first: JsonValue = { profile: { name: "Ada" } };
145
179
  * const second: JsonValue = { profile: { name: "Ada" } };
146
180
  *
147
- * expect(eqJsonValue(first, second)).toBe(true);
181
+ * assertTrue(eqJsonValue(first, second));
148
182
  * ```
149
183
  */
150
- export const eqJsonValue = (a, b) => {
151
- const stack = [[a, b]];
152
- const seen = new WeakMap();
153
- while (stack.length > 0) {
154
- const [x, y] = stack.pop();
155
- if (x === y)
156
- continue;
157
- const typeX = typeof x;
158
- const typeY = typeof y;
159
- if (typeX !== typeY || x === null || y === null)
184
+ export const eqJsonValue = eqData;
185
+ /** Compares two {@link JsonValueInput} values using {@link eqData}. */
186
+ export const eqJsonValueInput = eqData;
187
+ const eqDataInternal = (actual, expected, context) => {
188
+ const frames = [{ kind: "Compare", actual, expected }];
189
+ const attempts = [];
190
+ const retryFailedCandidate = (_frame) => {
191
+ const attempt = attempts.pop();
192
+ if (attempt === undefined)
160
193
  return false;
161
- if (typeX === "number" && isNaN(x) && isNaN(y)) {
162
- continue;
163
- }
164
- if (typeX === "object") {
165
- const isArrayX = Array.isArray(x);
166
- const isArrayY = Array.isArray(y);
167
- if (isArrayX !== isArrayY)
168
- return false;
169
- const xObj = x;
170
- const yObj = y;
171
- if (seen.has(xObj)) {
172
- const ySet = seen.get(xObj);
173
- if (ySet.has(yObj)) {
174
- continue;
175
- }
176
- ySet.add(yObj);
194
+ rollbackEqDataContext(context, attempt.contextCheckpoint);
195
+ frames.length = attempt.frameCheckpoint;
196
+ frames.push(attempt.retry);
197
+ return true;
198
+ };
199
+ while (frames.length > 0) {
200
+ const frame = frames.pop();
201
+ if (frame.kind === "Compare") {
202
+ const x = frame.actual;
203
+ const y = frame.expected;
204
+ if (eqSameValueZero(x, y))
205
+ continue;
206
+ if (typeof x !== typeof y) {
207
+ frames.push({ kind: "Fail" });
208
+ continue;
209
+ }
210
+ if (typeof x !== "object" ||
211
+ x === null ||
212
+ typeof y !== "object" ||
213
+ y === null) {
214
+ frames.push({ kind: "Fail" });
215
+ continue;
216
+ }
217
+ const rights = context.rightsByLeft.get(x);
218
+ if (rights?.has(y))
219
+ continue;
220
+ if (rights === undefined) {
221
+ context.rightsByLeft.set(x, new Set([y]));
177
222
  }
178
223
  else {
179
- const ySet = new WeakSet();
180
- ySet.add(yObj);
181
- seen.set(xObj, ySet);
224
+ rights.add(y);
225
+ }
226
+ context.pairs.push([x, y]);
227
+ const xKind = getObjectKind(x);
228
+ const yKind = getObjectKind(y);
229
+ if (xKind !== yKind) {
230
+ frames.push({ kind: "Fail" });
231
+ continue;
182
232
  }
183
- if (isArrayX && isArrayY) {
184
- const xArr = x;
185
- const yArr = y;
186
- if (xArr.length !== yArr.length)
187
- return false;
188
- for (let i = 0; i < xArr.length; i++) {
189
- stack.push([xArr[i], yArr[i]]);
233
+ if (xKind === "Array") {
234
+ const xArray = x;
235
+ const yArray = y;
236
+ if (xArray.length !== yArray.length ||
237
+ Reflect.ownKeys(xArray).length !== xArray.length + 1 ||
238
+ Reflect.ownKeys(yArray).length !== yArray.length + 1) {
239
+ frames.push({ kind: "Fail" });
240
+ continue;
241
+ }
242
+ let valid = true;
243
+ for (let index = 0; index < xArray.length; index++) {
244
+ const xDescriptor = Object.getOwnPropertyDescriptor(xArray, index);
245
+ const yDescriptor = Object.getOwnPropertyDescriptor(yArray, index);
246
+ if (xDescriptor === undefined ||
247
+ yDescriptor === undefined ||
248
+ !("value" in xDescriptor) ||
249
+ !("value" in yDescriptor)) {
250
+ valid = false;
251
+ break;
252
+ }
253
+ frames.push({
254
+ kind: "Compare",
255
+ actual: xDescriptor.value,
256
+ expected: yDescriptor.value,
257
+ });
190
258
  }
259
+ if (!valid)
260
+ frames.push({ kind: "Fail" });
261
+ continue;
191
262
  }
192
- else {
193
- const xObjTyped = x;
194
- const yObjTyped = y;
195
- const xKeys = Object.keys(xObjTyped);
196
- const yKeys = Object.keys(yObjTyped);
197
- if (xKeys.length !== yKeys.length)
198
- return false;
199
- const yKeySet = new Set(yKeys);
200
- for (const key of xKeys) {
201
- if (!yKeySet.has(key))
202
- return false;
203
- stack.push([xObjTyped[key], yObjTyped[key]]);
263
+ switch (xKind) {
264
+ case "Date":
265
+ if (!Object.is(Date.prototype.getTime.call(x), Date.prototype.getTime.call(y))) {
266
+ frames.push({ kind: "Fail" });
267
+ }
268
+ continue;
269
+ case "Uint8Array":
270
+ if (!eqUint8Array(x, y)) {
271
+ frames.push({ kind: "Fail" });
272
+ }
273
+ continue;
274
+ case "Set": {
275
+ const xSet = x;
276
+ const ySet = y;
277
+ if (Reflect.ownKeys(x).length !== 0 ||
278
+ Reflect.ownKeys(y).length !== 0 ||
279
+ xSet.size !== ySet.size) {
280
+ frames.push({ kind: "Fail" });
281
+ continue;
282
+ }
283
+ frames.push({
284
+ kind: "Set",
285
+ actual: Array.from(xSet),
286
+ actualIndex: 0,
287
+ unmatched: Array.from(ySet),
288
+ candidateIndex: 0,
289
+ });
290
+ continue;
291
+ }
292
+ case "Map": {
293
+ const xMap = x;
294
+ const yMap = y;
295
+ if (Reflect.ownKeys(x).length !== 0 ||
296
+ Reflect.ownKeys(y).length !== 0 ||
297
+ xMap.size !== yMap.size) {
298
+ frames.push({ kind: "Fail" });
299
+ continue;
300
+ }
301
+ frames.push({
302
+ kind: "Map",
303
+ actual: Array.from(xMap),
304
+ actualIndex: 0,
305
+ unmatched: Array.from(yMap),
306
+ candidateIndex: 0,
307
+ });
308
+ continue;
309
+ }
310
+ case "Object": {
311
+ const xKeys = Reflect.ownKeys(x);
312
+ const yKeys = Reflect.ownKeys(y);
313
+ if (xKeys.length !== yKeys.length) {
314
+ frames.push({ kind: "Fail" });
315
+ continue;
316
+ }
317
+ let valid = true;
318
+ for (const key of xKeys) {
319
+ if (typeof key !== "string") {
320
+ valid = false;
321
+ break;
322
+ }
323
+ const xDescriptor = Object.getOwnPropertyDescriptor(x, key);
324
+ const yDescriptor = Object.getOwnPropertyDescriptor(y, key);
325
+ if (xDescriptor === undefined ||
326
+ yDescriptor === undefined ||
327
+ !("value" in xDescriptor) ||
328
+ !("value" in yDescriptor) ||
329
+ !xDescriptor.enumerable ||
330
+ !yDescriptor.enumerable) {
331
+ valid = false;
332
+ break;
333
+ }
334
+ frames.push({
335
+ kind: "Compare",
336
+ actual: xDescriptor.value,
337
+ expected: yDescriptor.value,
338
+ });
339
+ }
340
+ if (!valid)
341
+ frames.push({ kind: "Fail" });
342
+ continue;
204
343
  }
344
+ case "Unsupported":
345
+ frames.push({ kind: "Fail" });
346
+ continue;
205
347
  }
206
348
  }
207
- else {
208
- return false;
349
+ if (frame.kind === "Set") {
350
+ if (frame.actualIndex === frame.actual.length)
351
+ continue;
352
+ if (frame.candidateIndex === frame.unmatched.length) {
353
+ frames.push({ kind: "Fail" });
354
+ continue;
355
+ }
356
+ const attempt = {
357
+ contextCheckpoint: context.pairs.length,
358
+ frameCheckpoint: frames.length,
359
+ retry: { ...frame, candidateIndex: frame.candidateIndex + 1 },
360
+ };
361
+ attempts.push(attempt);
362
+ frames.push({ kind: "CommitSet", match: frame });
363
+ frames.push({
364
+ kind: "Compare",
365
+ actual: frame.actual[frame.actualIndex],
366
+ expected: frame.unmatched[frame.candidateIndex],
367
+ });
368
+ continue;
369
+ }
370
+ if (frame.kind === "Map") {
371
+ if (frame.actualIndex === frame.actual.length)
372
+ continue;
373
+ if (frame.candidateIndex === frame.unmatched.length) {
374
+ frames.push({ kind: "Fail" });
375
+ continue;
376
+ }
377
+ const [actualKey, actualValue] = frame.actual[frame.actualIndex];
378
+ const [expectedKey, expectedValue] = frame.unmatched[frame.candidateIndex];
379
+ const attempt = {
380
+ contextCheckpoint: context.pairs.length,
381
+ frameCheckpoint: frames.length,
382
+ retry: { ...frame, candidateIndex: frame.candidateIndex + 1 },
383
+ };
384
+ attempts.push(attempt);
385
+ frames.push({ kind: "CommitMap", match: frame });
386
+ frames.push({
387
+ kind: "Compare",
388
+ actual: actualValue,
389
+ expected: expectedValue,
390
+ });
391
+ frames.push({
392
+ kind: "Compare",
393
+ actual: actualKey,
394
+ expected: expectedKey,
395
+ });
396
+ continue;
209
397
  }
398
+ if (frame.kind === "CommitSet") {
399
+ attempts.pop();
400
+ frame.match.unmatched.splice(frame.match.candidateIndex, 1);
401
+ frames.push({
402
+ ...frame.match,
403
+ actualIndex: frame.match.actualIndex + 1,
404
+ candidateIndex: 0,
405
+ });
406
+ continue;
407
+ }
408
+ if (frame.kind === "CommitMap") {
409
+ attempts.pop();
410
+ frame.match.unmatched.splice(frame.match.candidateIndex, 1);
411
+ frames.push({
412
+ ...frame.match,
413
+ actualIndex: frame.match.actualIndex + 1,
414
+ candidateIndex: 0,
415
+ });
416
+ continue;
417
+ }
418
+ if (!retryFailedCandidate(frame))
419
+ return false;
210
420
  }
211
421
  return true;
212
422
  };
213
- /**
214
- * Deeply compares two {@link JsonValueInput} values for equality.
215
- *
216
- * - Uses an iterative approach with a stack to handle large or deeply nested
217
- * objects without risking stack overflow.
218
- * - Defensively handles circular references in runtime values without looping,
219
- * although cyclic values are not valid JSON.
220
- * - Unlike JSON.stringify, this function directly compares values, avoiding
221
- * serialization overhead and leveraging short-circuit evaluation for faster
222
- * failure on mismatched structures.
223
- *
224
- * ### Example
225
- *
226
- * ```ts
227
- * import { eqJsonValueInput, type JsonValueInput } from "@evolu/common";
228
- *
229
- * const first: JsonValueInput = { profile: { name: "Ada" } };
230
- * const second: JsonValueInput = { profile: { name: "Ada" } };
231
- *
232
- * expect(eqJsonValueInput(first, second)).toBe(true);
233
- * ```
234
- */
235
- export const eqJsonValueInput = (a, b) => eqJsonValue(a, b);
423
+ const rollbackEqDataContext = (context, checkpoint) => {
424
+ while (context.pairs.length > checkpoint) {
425
+ const [left, right] = context.pairs.pop();
426
+ const rights = context.rightsByLeft.get(left);
427
+ rights.delete(right);
428
+ if (rights.size === 0)
429
+ context.rightsByLeft.delete(left);
430
+ }
431
+ };