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