@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
package/src/Time.ts CHANGED
@@ -1,22 +1,37 @@
1
- /**
2
- *
3
- *
4
- * @module
5
- */
1
+ import { assert } from "./Assert.js";
2
+ import { DateIso, NonNegativeInt } from "./Type.js";
6
3
 
7
4
  /** Retrieves the current time in milliseconds, similar to `Date.now()`. */
8
5
  export interface Time {
9
6
  readonly now: () => number;
7
+ readonly nowIso: () => DateIso;
10
8
  }
11
9
 
12
10
  export interface TimeDep {
13
11
  readonly time: Time;
14
12
  }
15
13
 
16
- /** Creates a {@link Time} using Date.now(). */
17
- export const createTime = (): Time => ({
18
- now: () => Date.now(),
19
- });
14
+ /**
15
+ * Creates a {@link Time} using Date.now().
16
+ *
17
+ * If the system clock is misconfigured (out of allowed range), the application
18
+ * will fail with an assertion error. This is intentional - there's no
19
+ * reasonable fallback when the system clock is fundamentally wrong.
20
+ */
21
+ export const createTime = (): Time => {
22
+ const time: Time = {
23
+ now: () => {
24
+ const iso = time.nowIso();
25
+ return new globalThis.Date(iso).getTime();
26
+ },
27
+ nowIso: () => {
28
+ const iso = new globalThis.Date().toISOString();
29
+ assert(DateIso.is(iso), "System clock returned invalid ISO date");
30
+ return iso;
31
+ },
32
+ };
33
+ return time;
34
+ };
20
35
 
21
36
  /**
22
37
  * Creates a {@link Time} that returns a monotonically increasing number based on
@@ -24,7 +39,7 @@ export const createTime = (): Time => ({
24
39
  */
25
40
  export const createTestTime = (): Time => {
26
41
  let now = 0;
27
- return {
42
+ const time: Time = {
28
43
  now: () => {
29
44
  const current = now;
30
45
  queueMicrotask(() => {
@@ -32,5 +47,159 @@ export const createTestTime = (): Time => {
32
47
  });
33
48
  return current;
34
49
  },
50
+ nowIso: () =>
51
+ DateIso.orThrow(new globalThis.Date(time.now()).toISOString()),
35
52
  };
53
+ return time;
54
+ };
55
+
56
+ /** Single digit 0-9. Used internally for {@link DurationString} validation. */
57
+ export type D = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9";
58
+
59
+ /**
60
+ * Minutes and seconds 1-59. Used internally for {@link DurationString}
61
+ * validation. Uses single digits for 1-9, full numbers for 10-59.
62
+ */
63
+ export type MmSs =
64
+ | Exclude<D, "0"> // 1..9 (single digit)
65
+ | `1${D}` // 10..19
66
+ | `2${D}` // 20..29
67
+ | `3${D}` // 30..39
68
+ | `4${D}` // 40..49
69
+ | `5${D}`; // 50..59
70
+
71
+ /** Hours 1-23. Used internally for {@link DurationString} validation. */
72
+ export type Hours =
73
+ | Exclude<D, "0"> // 1-9
74
+ | `1${D}` // 10-19
75
+ | `2${"0" | "1" | "2" | "3"}`; // 20-23
76
+
77
+ /** Days 1-99. Used internally for {@link DurationString} validation. */
78
+ export type Days = Exclude<D, "0"> | `${Exclude<D, "0">}${D}`;
79
+
80
+ /**
81
+ * Template literal type for compile-time validated duration strings.
82
+ *
83
+ * Allowed patterns: basic units (ms, s, m, h, d) and logical combinations
84
+ * (s+ms, m+s, h+m, d+h).
85
+ *
86
+ * Supported formats:
87
+ *
88
+ * - Milliseconds: `0ms`, `1ms`, `500ms`, `999ms`
89
+ * - Seconds: `5s`, `30s` (1-59, single digit for 1-9)
90
+ * - Minutes: `5m`, `30m` (1-59, single digit for 1-9)
91
+ * - Hours: `1h`, `12h`, `23h` (1-23)
92
+ * - Days: `1d`, `30d`, `99d` (1-99)
93
+ * - Combinations: `1s 250ms`, `30m 15s`, `2h 45m`, `7d 12h`
94
+ *
95
+ * Note: Duration strings are for developer experience only - they provide
96
+ * readable, compile-time validated expressions but should never be persisted or
97
+ * parsed from users as they are not localized. Always convert to NonNegativeInt
98
+ * (milliseconds) for storage and APIs.
99
+ */
100
+ export type DurationString =
101
+ | `${D}ms`
102
+ | `${D}${D}ms`
103
+ | `${D}${D}${D}ms`
104
+ | `${MmSs}s`
105
+ | `${MmSs}m`
106
+ | `${Hours}h`
107
+ | `${Days}d`
108
+ | `${MmSs}s ${D}ms`
109
+ | `${MmSs}s ${D}${D}ms`
110
+ | `${MmSs}s ${D}${D}${D}ms`
111
+ | `${MmSs}m ${MmSs}s`
112
+ | `${Hours}h ${MmSs}m`
113
+ | `${Days}d ${Hours}h`;
114
+
115
+ /**
116
+ * Duration can be either a {@link DurationString} or milliseconds as
117
+ * {@link NonNegativeInt}.
118
+ */
119
+ export type Duration = DurationString | NonNegativeInt;
120
+
121
+ /**
122
+ * Converts a duration to milliseconds.
123
+ *
124
+ * Accepts either a {@link DurationString} (e.g., "5m", "1h 30m") or milliseconds
125
+ * as {@link NonNegativeInt}.
126
+ *
127
+ * ### Example
128
+ *
129
+ * ```ts
130
+ * durationToNonNegativeInt("0ms"); // 0 ✅
131
+ * durationToNonNegativeInt("500ms"); // 500 ✅
132
+ * durationToNonNegativeInt("30s"); // 30000 ✅
133
+ * durationToNonNegativeInt("5m"); // 300000 ✅
134
+ * durationToNonNegativeInt("12h"); // 43200000 ✅
135
+ * durationToNonNegativeInt("7d"); // 604800000 ✅
136
+ * durationToNonNegativeInt("2h 45m"); // 9900000 ✅
137
+ * durationToNonNegativeInt(5000); // 5000 ✅ (already milliseconds)
138
+ * ```
139
+ */
140
+ export const durationToNonNegativeInt = (
141
+ duration: Duration,
142
+ ): NonNegativeInt => {
143
+ // If it's already a NonNegativeInt (milliseconds), return as-is
144
+ if (typeof duration === "number") {
145
+ return duration;
146
+ }
147
+
148
+ // Parse duration string without regex to avoid ReDoS vulnerabilities
149
+ const units = {
150
+ ms: 1,
151
+ s: 1000,
152
+ m: 60000,
153
+ h: 3600000,
154
+ d: 86400000, // 24 * 60 * 60 * 1000
155
+ } as const;
156
+
157
+ let total = 0;
158
+ let i = 0;
159
+
160
+ while (i < duration.length) {
161
+ // Skip whitespace
162
+ while (i < duration.length && duration[i] === " ") {
163
+ i++;
164
+ }
165
+
166
+ if (i >= duration.length) break;
167
+
168
+ // Parse number
169
+ let numStr = "";
170
+ while (i < duration.length && duration[i] >= "0" && duration[i] <= "9") {
171
+ numStr += duration[i];
172
+ i++;
173
+ }
174
+
175
+ if (numStr === "") break;
176
+
177
+ // Parse unit (ms or single char s/m/h/d)
178
+ let unit = "";
179
+ if (i < duration.length) {
180
+ if (
181
+ duration[i] === "m" &&
182
+ i + 1 < duration.length &&
183
+ duration[i + 1] === "s"
184
+ ) {
185
+ unit = "ms";
186
+ i += 2;
187
+ } else if (
188
+ duration[i] === "s" ||
189
+ duration[i] === "m" ||
190
+ duration[i] === "h" ||
191
+ duration[i] === "d"
192
+ ) {
193
+ unit = duration[i];
194
+ i++;
195
+ }
196
+ }
197
+
198
+ if (unit === "") break;
199
+
200
+ const value = parseInt(numStr, 10);
201
+ total += value * units[unit as keyof typeof units];
202
+ }
203
+
204
+ return NonNegativeInt.orThrow(total);
36
205
  };