@evolu/common 8.0.0-next.4 → 8.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 (237) hide show
  1. package/dist/src/Array.d.ts +279 -173
  2. package/dist/src/Array.d.ts.map +1 -1
  3. package/dist/src/Array.js +105 -101
  4. package/dist/src/Assert.d.ts +44 -44
  5. package/dist/src/Assert.d.ts.map +1 -1
  6. package/dist/src/Assert.js +44 -32
  7. package/dist/src/BigInt.d.ts +6 -3
  8. package/dist/src/BigInt.d.ts.map +1 -1
  9. package/dist/src/BigInt.js +5 -2
  10. package/dist/src/Brand.d.ts +27 -40
  11. package/dist/src/Brand.d.ts.map +1 -1
  12. package/dist/src/Buffer.d.ts +27 -11
  13. package/dist/src/Buffer.d.ts.map +1 -1
  14. package/dist/src/Cache.d.ts +9 -4
  15. package/dist/src/Cache.d.ts.map +1 -1
  16. package/dist/src/Cache.js +8 -3
  17. package/dist/src/Callbacks.d.ts +30 -19
  18. package/dist/src/Callbacks.d.ts.map +1 -1
  19. package/dist/src/Console.d.ts +145 -66
  20. package/dist/src/Console.d.ts.map +1 -1
  21. package/dist/src/Console.js +91 -43
  22. package/dist/src/Crypto.d.ts +85 -42
  23. package/dist/src/Crypto.d.ts.map +1 -1
  24. package/dist/src/Crypto.js +44 -20
  25. package/dist/src/Eq.d.ts +87 -21
  26. package/dist/src/Eq.d.ts.map +1 -1
  27. package/dist/src/Eq.js +67 -19
  28. package/dist/src/Error.d.ts +5 -3
  29. package/dist/src/Error.d.ts.map +1 -1
  30. package/dist/src/Error.js +16 -0
  31. package/dist/src/Function.d.ts +119 -58
  32. package/dist/src/Function.d.ts.map +1 -1
  33. package/dist/src/Function.js +86 -43
  34. package/dist/src/Http.d.ts +394 -0
  35. package/dist/src/Http.d.ts.map +1 -0
  36. package/dist/src/Http.js +102 -0
  37. package/dist/src/Identicon.d.ts +16 -7
  38. package/dist/src/Identicon.d.ts.map +1 -1
  39. package/dist/src/Identicon.js +14 -5
  40. package/dist/src/LeakDetector.d.ts +88 -0
  41. package/dist/src/LeakDetector.d.ts.map +1 -0
  42. package/dist/src/LeakDetector.js +86 -0
  43. package/dist/src/LockManager.d.ts +18 -9
  44. package/dist/src/LockManager.d.ts.map +1 -1
  45. package/dist/src/LockManager.js +7 -8
  46. package/dist/src/Lookup.d.ts +43 -13
  47. package/dist/src/Lookup.d.ts.map +1 -1
  48. package/dist/src/Lookup.js +28 -8
  49. package/dist/src/Microtask.d.ts +1 -1
  50. package/dist/src/Microtask.d.ts.map +1 -1
  51. package/dist/src/Microtask.js +3 -7
  52. package/dist/src/Number.d.ts +49 -13
  53. package/dist/src/Number.d.ts.map +1 -1
  54. package/dist/src/Number.js +34 -5
  55. package/dist/src/Object.d.ts +160 -40
  56. package/dist/src/Object.d.ts.map +1 -1
  57. package/dist/src/Object.js +92 -46
  58. package/dist/src/Option.d.ts +10 -7
  59. package/dist/src/Option.d.ts.map +1 -1
  60. package/dist/src/Option.js +9 -6
  61. package/dist/src/Order.d.ts +21 -21
  62. package/dist/src/Order.d.ts.map +1 -1
  63. package/dist/src/Order.js +18 -21
  64. package/dist/src/Platform.d.ts +31 -0
  65. package/dist/src/Platform.d.ts.map +1 -1
  66. package/dist/src/Platform.js +98 -0
  67. package/dist/src/Random.d.ts +32 -17
  68. package/dist/src/Random.d.ts.map +1 -1
  69. package/dist/src/Random.js +12 -8
  70. package/dist/src/Redacted.d.ts +43 -29
  71. package/dist/src/Redacted.d.ts.map +1 -1
  72. package/dist/src/Redacted.js +14 -3
  73. package/dist/src/Ref.d.ts +11 -3
  74. package/dist/src/Ref.d.ts.map +1 -1
  75. package/dist/src/Ref.js +2 -2
  76. package/dist/src/RefCount.d.ts +2 -6
  77. package/dist/src/RefCount.d.ts.map +1 -1
  78. package/dist/src/RefCount.js +33 -90
  79. package/dist/src/Relation.d.ts +70 -5
  80. package/dist/src/Relation.d.ts.map +1 -1
  81. package/dist/src/Relation.js +77 -2
  82. package/dist/src/Resource.d.ts +590 -155
  83. package/dist/src/Resource.d.ts.map +1 -1
  84. package/dist/src/Resource.js +592 -343
  85. package/dist/src/Result.d.ts +838 -191
  86. package/dist/src/Result.d.ts.map +1 -1
  87. package/dist/src/Result.js +163 -102
  88. package/dist/src/Schedule.d.ts +684 -231
  89. package/dist/src/Schedule.d.ts.map +1 -1
  90. package/dist/src/Schedule.js +766 -295
  91. package/dist/src/Set.d.ts +89 -40
  92. package/dist/src/Set.d.ts.map +1 -1
  93. package/dist/src/Set.js +50 -29
  94. package/dist/src/Sqlite.d.ts +29 -72
  95. package/dist/src/Sqlite.d.ts.map +1 -1
  96. package/dist/src/Sqlite.js +41 -46
  97. package/dist/src/StackTrace.d.ts +40 -0
  98. package/dist/src/StackTrace.d.ts.map +1 -0
  99. package/dist/src/StackTrace.js +140 -0
  100. package/dist/src/Store.d.ts +5 -4
  101. package/dist/src/Store.d.ts.map +1 -1
  102. package/dist/src/Store.js +5 -4
  103. package/dist/src/String.d.ts +7 -1
  104. package/dist/src/String.d.ts.map +1 -1
  105. package/dist/src/String.js +20 -7
  106. package/dist/src/Task.d.ts +3572 -1770
  107. package/dist/src/Task.d.ts.map +1 -1
  108. package/dist/src/Task.js +1879 -1274
  109. package/dist/src/Test.d.ts +17 -125
  110. package/dist/src/Test.d.ts.map +1 -1
  111. package/dist/src/Test.js +17 -68
  112. package/dist/src/Time.d.ts +108 -49
  113. package/dist/src/Time.d.ts.map +1 -1
  114. package/dist/src/Time.js +172 -73
  115. package/dist/src/Type.d.ts +3542 -1926
  116. package/dist/src/Type.d.ts.map +1 -1
  117. package/dist/src/Type.js +3070 -1784
  118. package/dist/src/Types.d.ts +200 -108
  119. package/dist/src/Types.d.ts.map +1 -1
  120. package/dist/src/Types.js +39 -8
  121. package/dist/src/WebSocket.d.ts +48 -23
  122. package/dist/src/WebSocket.d.ts.map +1 -1
  123. package/dist/src/WebSocket.js +15 -6
  124. package/dist/src/Worker.d.ts +94 -36
  125. package/dist/src/Worker.d.ts.map +1 -1
  126. package/dist/src/Worker.js +58 -24
  127. package/dist/src/index.d.ts +55 -52
  128. package/dist/src/index.d.ts.map +1 -1
  129. package/dist/src/index.js +3 -1
  130. package/dist/src/intl/cs.d.ts +94 -0
  131. package/dist/src/intl/cs.d.ts.map +1 -0
  132. package/dist/src/intl/cs.js +220 -0
  133. package/dist/src/intl/index.d.ts +7 -0
  134. package/dist/src/intl/index.d.ts.map +1 -0
  135. package/dist/src/intl/index.js +6 -0
  136. package/dist/src/local-first/Db.d.ts +12 -8
  137. package/dist/src/local-first/Db.d.ts.map +1 -1
  138. package/dist/src/local-first/Db.js +109 -132
  139. package/dist/src/local-first/Error.d.ts +4 -4
  140. package/dist/src/local-first/Evolu.d.ts +338 -92
  141. package/dist/src/local-first/Evolu.d.ts.map +1 -1
  142. package/dist/src/local-first/Evolu.js +47 -55
  143. package/dist/src/local-first/LocalAuth.d.ts +4 -4
  144. package/dist/src/local-first/LocalAuth.d.ts.map +1 -1
  145. package/dist/src/local-first/Owner.d.ts +61 -24
  146. package/dist/src/local-first/Owner.d.ts.map +1 -1
  147. package/dist/src/local-first/Owner.js +45 -8
  148. package/dist/src/local-first/Protocol.d.ts +44 -31
  149. package/dist/src/local-first/Protocol.d.ts.map +1 -1
  150. package/dist/src/local-first/Protocol.js +36 -13
  151. package/dist/src/local-first/Query.d.ts +147 -62
  152. package/dist/src/local-first/Query.d.ts.map +1 -1
  153. package/dist/src/local-first/Query.js +112 -58
  154. package/dist/src/local-first/Relay.d.ts +44 -14
  155. package/dist/src/local-first/Relay.d.ts.map +1 -1
  156. package/dist/src/local-first/Schema.d.ts +92 -41
  157. package/dist/src/local-first/Schema.d.ts.map +1 -1
  158. package/dist/src/local-first/Schema.js +25 -8
  159. package/dist/src/local-first/Shared.d.ts +23 -21
  160. package/dist/src/local-first/Shared.d.ts.map +1 -1
  161. package/dist/src/local-first/Shared.js +100 -57
  162. package/dist/src/local-first/Storage.d.ts +53 -32
  163. package/dist/src/local-first/Storage.d.ts.map +1 -1
  164. package/dist/src/local-first/Storage.js +194 -234
  165. package/dist/src/local-first/Timestamp.d.ts +21 -21
  166. package/dist/src/local-first/Timestamp.d.ts.map +1 -1
  167. package/dist/src/local-first/Timestamp.js +2 -2
  168. package/dist/src/local-first/index.d.ts +11 -11
  169. package/package.json +14 -13
  170. package/src/Array.ts +306 -205
  171. package/src/Assert.ts +54 -69
  172. package/src/BigInt.ts +6 -3
  173. package/src/Brand.ts +27 -40
  174. package/src/Buffer.ts +28 -12
  175. package/src/Cache.ts +9 -4
  176. package/src/Callbacks.ts +30 -19
  177. package/src/Console.ts +156 -84
  178. package/src/Crypto.ts +83 -41
  179. package/src/Eq.ts +95 -22
  180. package/src/Error.ts +8 -4
  181. package/src/Function.ts +167 -59
  182. package/src/Http.ts +549 -0
  183. package/src/Identicon.ts +16 -7
  184. package/src/LeakDetector.ts +182 -0
  185. package/src/LockManager.ts +43 -39
  186. package/src/Lookup.ts +62 -28
  187. package/src/Microtask.ts +19 -23
  188. package/src/Number.ts +64 -12
  189. package/src/Object.ts +173 -49
  190. package/src/Option.ts +10 -7
  191. package/src/Order.ts +23 -21
  192. package/src/Platform.ts +136 -0
  193. package/src/Polyfills.ts +6 -12
  194. package/src/Random.ts +32 -19
  195. package/src/Redacted.ts +44 -30
  196. package/src/Ref.ts +14 -6
  197. package/src/RefCount.ts +38 -80
  198. package/src/Relation.ts +202 -10
  199. package/src/Resource.ts +1199 -591
  200. package/src/Result.ts +930 -271
  201. package/src/Schedule.ts +859 -343
  202. package/src/Set.ts +89 -40
  203. package/src/Sqlite.ts +144 -138
  204. package/src/StackTrace.ts +230 -0
  205. package/src/Store.ts +8 -7
  206. package/src/String.ts +22 -5
  207. package/src/Task.ts +5101 -2832
  208. package/src/Test.ts +20 -168
  209. package/src/Time.ts +293 -90
  210. package/src/Type.ts +10034 -4117
  211. package/src/Types.ts +227 -110
  212. package/src/WebSocket.ts +64 -36
  213. package/src/Worker.ts +180 -72
  214. package/src/index.ts +55 -52
  215. package/src/intl/cs.ts +388 -0
  216. package/src/intl/index.ts +7 -0
  217. package/src/local-first/Db.ts +152 -179
  218. package/src/local-first/Error.ts +4 -4
  219. package/src/local-first/Evolu.ts +495 -250
  220. package/src/local-first/LocalAuth.ts +6 -12
  221. package/src/local-first/Owner.ts +58 -21
  222. package/src/local-first/Protocol.ts +49 -31
  223. package/src/local-first/Query.ts +146 -61
  224. package/src/local-first/Relay.ts +51 -21
  225. package/src/local-first/Schema.ts +109 -51
  226. package/src/local-first/Shared.ts +266 -226
  227. package/src/local-first/Storage.ts +266 -264
  228. package/src/local-first/Timestamp.ts +25 -18
  229. package/src/local-first/index.ts +11 -11
  230. package/dist/src/Skiplist.d.ts +0 -28
  231. package/dist/src/Skiplist.d.ts.map +0 -1
  232. package/dist/src/Skiplist.js +0 -64
  233. package/dist/src/Tracer.d.ts +0 -48
  234. package/dist/src/Tracer.d.ts.map +0 -1
  235. package/dist/src/Tracer.js +0 -6
  236. package/src/Skiplist.ts +0 -108
  237. package/src/Tracer.ts +0 -54
@@ -9,25 +9,29 @@ import {
9
9
  firstInArray,
10
10
  type NonEmptyArray,
11
11
  type NonEmptyReadonlyArray,
12
- } from "../Array.js";
13
- import { assert, assertNonEmptyReadonlyArray, assertType } from "../Assert.js";
14
- import type { ConsoleLevel } from "../Console.js";
12
+ } from "../Array.ts";
13
+ import {
14
+ assert,
15
+ assertNonEmptyReadonlyArray,
16
+ assertNonNullable,
17
+ } from "../Assert.ts";
18
+ import type { ConsoleLevel } from "../Console.ts";
15
19
  import {
16
20
  EncryptionKey,
17
21
  type DecryptWithXChaCha20Poly1305Error,
18
22
  type RandomBytesDep,
19
- } from "../Crypto.js";
20
- import { exhaustiveCheck, lazyFalse, lazyVoid } from "../Function.js";
21
- import type { LockManagerDep } from "../LockManager.js";
22
- import { acquireLeaderLock } from "../LockManager.js";
23
- import { createRecord, getProperty, objectToEntries } from "../Object.js";
24
- import { ok, type Result } from "../Result.js";
23
+ } from "../Crypto.ts";
24
+ import { constFalse, constVoid } from "../Function.ts";
25
+ import type { LockManagerDep } from "../LockManager.ts";
26
+ import { acquireLeaderLock } from "../LockManager.ts";
27
+ import { createMutableRecord, getOwnProp, objectToEntries } from "../Object.ts";
28
+ import { ok, type Result } from "../Result.ts";
25
29
  import type {
26
30
  CreateSqliteDriverDep,
27
31
  SqliteDep,
28
32
  SqliteRow,
29
33
  SqliteSchema,
30
- } from "../Sqlite.js";
34
+ } from "../Sqlite.ts";
31
35
  import {
32
36
  booleanToSqliteBoolean,
33
37
  createSqlite,
@@ -36,27 +40,28 @@ import {
36
40
  sqliteBooleanToBoolean,
37
41
  sqliteQueryStringToSqliteQuery,
38
42
  SqliteValue,
39
- } from "../Sqlite.js";
40
- import { callback, type Task } from "../Task.js";
41
- import { Millis, millisToDateIso, type TimeDep } from "../Time.js";
42
- import type { Name } from "../Type.js";
43
+ } from "../Sqlite.ts";
44
+ import { callback, type Run, type Task } from "../Task.ts";
45
+ import { Millis, millisToDateIso, type TimeDep } from "../Time.ts";
43
46
  import {
47
+ assertType,
48
+ type ExtractTyped,
44
49
  Id,
45
50
  IdBytes,
46
51
  idBytesToId,
47
52
  idToIdBytes,
53
+ type Name,
48
54
  onePositiveInt,
49
- } from "../Type.js";
50
- import type { ExtractType } from "../Types.js";
55
+ } from "../Type.ts";
51
56
  import type {
52
57
  CreateBroadcastChannelDep,
53
58
  NativeMessagePort,
54
59
  Worker,
55
60
  WorkerDeps,
56
61
  WorkerSelf,
57
- } from "../Worker.js";
58
- import type { OwnerId, OwnerIdBytes } from "./Owner.js";
59
- import { ownerIdBytesToOwnerId, ownerIdToOwnerIdBytes } from "./Owner.js";
62
+ } from "../Worker.ts";
63
+ import type { OwnerId, OwnerIdBytes } from "./Owner.ts";
64
+ import { ownerIdBytesToOwnerId, ownerIdToOwnerIdBytes } from "./Owner.ts";
60
65
  import {
61
66
  applyProtocolMessageAsClient,
62
67
  createProtocolMessageForSync,
@@ -67,22 +72,22 @@ import {
67
72
  type ProtocolInvalidDataError,
68
73
  type ProtocolMessage,
69
74
  type ProtocolTimestampMismatchError,
70
- } from "./Protocol.js";
71
- import type { Query, RowsByQueryMap } from "./Query.js";
72
- import type { MutationChange, SqliteSchemaDep } from "./Schema.js";
75
+ } from "./Protocol.ts";
76
+ import type { Query, RowsByQueryMap } from "./Query.ts";
77
+ import type { MutationChange, SqliteSchemaDep } from "./Schema.ts";
73
78
  import {
74
79
  ensureSqliteSchema,
75
80
  getEvoluSqliteSchema,
76
81
  systemColumns,
77
- } from "./Schema.js";
82
+ } from "./Schema.ts";
78
83
  import type {
79
84
  ConsoleEntryOrError,
80
85
  DbWorkerInput,
81
86
  DbWorkerOutput,
82
87
  DbWorkerQueuedResponse,
83
88
  DbWorkerRequest,
84
- } from "./Shared.js";
85
- import { consoleEntryOrErrorBroadcastChannelName } from "./Shared.js";
89
+ } from "./Shared.ts";
90
+ import { consoleEntryOrErrorBroadcastChannelName } from "./Shared.ts";
86
91
  import {
87
92
  createBaseSqliteStorage,
88
93
  createBaseSqliteStorageTables,
@@ -94,13 +99,13 @@ import {
94
99
  type BaseSqliteStorageDep,
95
100
  type CrdtMessage,
96
101
  type Storage,
97
- } from "./Storage.js";
102
+ } from "./Storage.ts";
98
103
  import type {
99
104
  Timestamp,
100
105
  TimestampCounterOverflowError,
101
106
  TimestampDriftError,
102
107
  TimestampTimeOutOfRangeError,
103
- } from "./Timestamp.js";
108
+ } from "./Timestamp.ts";
104
109
  import {
105
110
  createInitialTimestamp,
106
111
  defaultTimestampMaxDrift,
@@ -110,7 +115,7 @@ import {
110
115
  timestampBytesToTimestamp,
111
116
  timestampToTimestampBytes,
112
117
  type TimestampConfigDep,
113
- } from "./Timestamp.js";
118
+ } from "./Timestamp.ts";
114
119
 
115
120
  export type DbWorker = Worker<DbWorkerInit>;
116
121
 
@@ -135,29 +140,23 @@ export type DbWorkerDeps = WorkerDeps &
135
140
  LockManagerDep &
136
141
  CreateSqliteDriverDep;
137
142
 
143
+ /**
144
+ * Starts the platform-agnostic Evolu DbWorker and owns its resources until the
145
+ * worker receives a dispose message or its {@link Run} is aborted.
146
+ */
138
147
  export const startDbWorker =
139
148
  (self: WorkerSelf<DbWorkerInit>): Task<void, never, DbWorkerDeps> =>
140
149
  async (run) => {
141
150
  await using disposer = new AsyncDisposableStack();
142
151
  disposer.use(self);
143
- const dbWorkerRun = disposer.use(run.create());
144
- const { deps } = dbWorkerRun;
145
-
146
- let initialized = false;
152
+ const { deps } = run;
147
153
 
148
- const initMessage = await dbWorkerRun.orThrow(
149
- callback<DbWorkerInit>(({ ok }) => {
150
- self.onMessage = (message) => {
151
- assert(!initialized, "DbWorker must be initialized only once");
152
- initialized = true;
153
- ok(message);
154
- };
154
+ const initMessage = await run.ok(
155
+ callback<DbWorkerInit>(({ resolve }) => {
156
+ self.onMessage = (message) => resolve(ok(message));
155
157
  }),
156
158
  );
157
159
 
158
- const console = deps.console.child(initMessage.name).child("DbWorker");
159
- console.setLevel(initMessage.consoleLevel);
160
-
161
160
  const port = disposer.use(
162
161
  deps.createMessagePort<DbWorkerOutput, DbWorkerInput>(initMessage.port),
163
162
  );
@@ -177,16 +176,11 @@ export const startDbWorker =
177
176
  });
178
177
  }),
179
178
  );
180
- console.debug("createDbWorker");
181
-
182
- disposer.use(
183
- await dbWorkerRun.orThrow(acquireLeaderLock(initMessage.name)),
184
- );
185
179
 
186
- port.postMessage({ type: "LeaderAcquired", name: initMessage.name });
180
+ disposer.use(await run.ok(acquireLeaderLock(initMessage.name)));
187
181
 
188
182
  const sqlite = disposer.use(
189
- await dbWorkerRun.orThrow(
183
+ await run.ok(
190
184
  createSqlite(
191
185
  initMessage.name,
192
186
  initMessage.memoryOnly
@@ -195,21 +189,15 @@ export const startDbWorker =
195
189
  ),
196
190
  ),
197
191
  );
198
- console.debug("SQLite created");
199
-
200
- const baseSqliteStorage = createBaseSqliteStorage({
201
- sqlite,
202
- ...dbWorkerRun.deps,
203
- });
204
192
 
193
+ const baseSqliteStorage = createBaseSqliteStorage({ sqlite, ...deps });
205
194
  const dbDeps = {
206
- ...dbWorkerRun.deps,
195
+ ...deps,
207
196
  sqlite,
208
197
  sqliteSchema: initMessage.sqliteSchema,
209
198
  baseSqliteStorage,
210
199
  timestampConfig: { maxDrift: defaultTimestampMaxDrift },
211
200
  };
212
-
213
201
  const currentSchema = getEvoluSqliteSchema(dbDeps)();
214
202
  const dbIsInitialized = "evolu_version" in currentSchema.tables;
215
203
  const clock = createClock(dbDeps)(dbIsInitialized);
@@ -228,152 +216,135 @@ export const startDbWorker =
228
216
  });
229
217
  },
230
218
  });
219
+ const dbWorkerRun = disposer.use(run.create({ storage }));
231
220
 
232
- const disposables = disposer.move();
233
- const dbWorkerRunWithStorage = dbWorkerRun.addDeps({ storage });
234
-
235
- port.onMessage = (input) => {
236
- if (input.type === "Dispose") {
237
- if (!disposables.disposed) console.debug("disposeDbWorker");
238
- void disposables.disposeAsync();
239
- return;
240
- }
241
-
242
- const { callbackId, request } = input;
243
-
244
- const postQueuedResponse = (response: DbWorkerQueuedResponse): void => {
245
- port.postMessage(
246
- { type: "OnQueuedResponse", callbackId, response },
247
- response.type === "ForEvolu" && response.message.type === "Export"
248
- ? [response.message.file.buffer]
249
- : undefined,
250
- );
251
- };
252
-
253
- switch (request.type) {
254
- case "ForEvolu": {
255
- switch (request.message.type) {
256
- case "Mutate": {
257
- const result = handleMutation({ ...dbDeps, clock })(
258
- request.message,
259
- );
260
- if (!result.ok) {
261
- consoleEntryOrErrorBroadcastChannel.postMessage({
262
- type: "Error",
263
- error: result.error,
264
- });
265
- } else {
266
- postQueuedResponse({
267
- type: "ForEvolu",
268
- id: request.id,
269
- message: result.value,
270
- });
271
- }
272
- break;
273
- }
274
-
275
- case "Query":
276
- postQueuedResponse({
277
- type: "ForEvolu",
278
- id: request.id,
279
- message: {
280
- type: "Query",
281
- rowsByQuery: loadQueries(dbDeps)(request.message.queries),
282
- },
283
- });
284
- break;
285
-
286
- case "Export":
287
- postQueuedResponse({
288
- type: "ForEvolu",
289
- id: request.id,
290
- message: {
291
- type: "Export",
292
- file: dbDeps.sqlite.export(),
293
- },
294
- });
295
- break;
221
+ port.postMessage({ type: "LeaderAcquired", name: initMessage.name });
296
222
 
297
- default:
298
- exhaustiveCheck(request.message);
223
+ await run.ok(
224
+ callback<void>(({ resolve }) => {
225
+ port.onMessage = (input) => {
226
+ if (input.type === "Dispose") {
227
+ resolve(ok());
228
+ return;
299
229
  }
300
- break;
301
- }
302
-
303
- case "ForSharedWorker": {
304
- switch (request.message.type) {
305
- case "CreateSyncMessages": {
306
- const protocolMessagesByOwnerId = new Map<
307
- OwnerId,
308
- ProtocolMessage
309
- >();
310
-
311
- for (const owner of request.message.owners) {
312
- storage.setRequestContext(owner.encryptionKey);
313
- const protocolMessage = createProtocolMessageForSync({
314
- storage,
315
- console,
316
- })(owner.id, SubscriptionFlags.Subscribe);
317
- protocolMessagesByOwnerId.set(owner.id, protocolMessage);
318
- }
319
-
320
- postQueuedResponse({
321
- type: "ForSharedWorker",
322
- message: {
323
- type: "CreateSyncMessages",
324
- protocolMessagesByOwnerId,
325
- },
326
- });
327
- break;
328
- }
329
230
 
330
- case "ApplySyncMessage": {
231
+ const { callbackId, request } = input;
232
+ const postQueuedResponse = (
233
+ response: DbWorkerQueuedResponse,
234
+ ): void => {
235
+ port.postMessage(
236
+ {
237
+ type: "OnQueuedResponse",
238
+ callbackId,
239
+ response,
240
+ },
241
+ response.type === "ForEvolu" && response.message.type === "Export"
242
+ ? [response.message.file.buffer]
243
+ : undefined,
244
+ );
245
+ };
246
+
247
+ if (request.type === "ForSharedWorker") {
248
+ if (request.message.type === "ApplySyncMessage") {
331
249
  const { owner, inputMessage } = request.message;
332
250
 
333
- dbWorkerRunWithStorage<void, never>(async (run) => {
251
+ void dbWorkerRun(async (run) => {
334
252
  storage.setRequestContext(owner.encryptionKey);
335
253
 
336
- const result = await run(
254
+ const result = await run.abortable(
337
255
  applyProtocolMessageAsClient(inputMessage, {
338
256
  writeKey: owner.writeKey,
339
257
  }),
340
258
  );
341
259
 
342
- const didWriteMessages = storage.didWriteMessages();
343
-
344
260
  postQueuedResponse({
345
261
  type: "ForSharedWorker",
346
262
  message: {
347
263
  type: "ApplySyncMessage",
348
264
  ownerId: owner.id,
349
- didWriteMessages,
265
+ didWriteMessages: storage.didWriteMessages(),
350
266
  result,
351
267
  },
352
268
  });
353
269
 
354
270
  return ok();
355
271
  });
356
- break;
272
+ return;
357
273
  }
358
274
 
359
- default:
360
- exhaustiveCheck(request.message);
275
+ const protocolMessagesByOwnerId = new Map<
276
+ OwnerId,
277
+ ProtocolMessage
278
+ >();
279
+
280
+ for (const owner of request.message.owners) {
281
+ storage.setRequestContext(owner.encryptionKey);
282
+ protocolMessagesByOwnerId.set(
283
+ owner.id,
284
+ createProtocolMessageForSync({
285
+ storage,
286
+ console: deps.console,
287
+ })(owner.id, SubscriptionFlags.Subscribe),
288
+ );
289
+ }
290
+
291
+ postQueuedResponse({
292
+ type: "ForSharedWorker",
293
+ message: {
294
+ type: "CreateSyncMessages",
295
+ protocolMessagesByOwnerId,
296
+ },
297
+ });
298
+ return;
361
299
  }
362
- break;
363
- }
364
300
 
365
- default:
366
- exhaustiveCheck(request);
367
- }
368
- };
301
+ if (request.message.type === "Query") {
302
+ postQueuedResponse({
303
+ type: "ForEvolu",
304
+ id: request.id,
305
+ message: {
306
+ type: "Query",
307
+ rowsByQuery: loadQueries(dbDeps)(request.message.queries),
308
+ },
309
+ });
310
+ return;
311
+ }
369
312
 
370
- return ok();
313
+ if (request.message.type === "Export") {
314
+ postQueuedResponse({
315
+ type: "ForEvolu",
316
+ id: request.id,
317
+ message: {
318
+ type: "Export",
319
+ file: sqlite.export(),
320
+ },
321
+ });
322
+ return;
323
+ }
324
+
325
+ const result = handleMutation({ ...dbDeps, clock })(request.message);
326
+ if (!result.ok) {
327
+ consoleEntryOrErrorBroadcastChannel.postMessage({
328
+ type: "Error",
329
+ error: result.error,
330
+ });
331
+ return;
332
+ }
371
333
 
372
- // TODO: Add parallel stale-leader detection.
373
- // Heartbeat is emitted by the active DB worker and sent to
374
- // SharedWorker. SharedWorker tracks last-seen heartbeat per Evolu
375
- // name and if silent for 10 seconds, it waits for another DB worker
376
- // to announce itself alive and then routes requests to that worker.
334
+ postQueuedResponse({
335
+ type: "ForEvolu",
336
+ id: request.id,
337
+ message: result.value,
338
+ });
339
+ };
340
+
341
+ return () => {
342
+ port.onMessage = null;
343
+ };
344
+ }),
345
+ );
346
+
347
+ return ok();
377
348
  };
378
349
 
379
350
  /**
@@ -565,7 +536,7 @@ const tryApplyQuarantinedMessages = (
565
536
  const validateColumnValue =
566
537
  (deps: SqliteSchemaDep) =>
567
538
  (table: string, column: string, _value: SqliteValue): boolean => {
568
- const schemaColumns = getProperty(deps.sqliteSchema.tables, table);
539
+ const schemaColumns = getOwnProp(deps.sqliteSchema.tables, table);
569
540
  return (
570
541
  schemaColumns != null &&
571
542
  (systemColumnsWithoutOwnerId.has(column) || schemaColumns.has(column))
@@ -682,8 +653,8 @@ const createClientStorage =
682
653
  didWriteMessages: () => didWriteMessages,
683
654
 
684
655
  // Not implemented yet.
685
- validateWriteKey: lazyFalse,
686
- setWriteKey: lazyVoid,
656
+ validateWriteKey: constFalse,
657
+ setWriteKey: constVoid,
687
658
 
688
659
  writeMessages: (ownerIdBytes, encryptedMessages) => () => {
689
660
  // TODO: Add quota checking for collaborative scenarios.
@@ -751,7 +722,7 @@ const createClientStorage =
751
722
  assertNonEmptyReadonlyArray(rows, "Every timestamp must have rows");
752
723
  const firstRow = firstInArray(rows);
753
724
 
754
- const values = createRecord<string, SqliteValue>();
725
+ const values = createMutableRecord<string, SqliteValue>();
755
726
  let isInsert: DbChange["isInsert"] = false;
756
727
  let isDelete: DbChange["isDelete"] = null;
757
728
 
@@ -799,8 +770,8 @@ const handleMutation =
799
770
  TimestampConfigDep,
800
771
  ) =>
801
772
  (
802
- message: ExtractType<
803
- ExtractType<DbWorkerRequest, "ForEvolu">["message"],
773
+ message: ExtractTyped<
774
+ ExtractTyped<DbWorkerRequest, "ForEvolu">["message"],
804
775
  "Mutate"
805
776
  >,
806
777
  ): Result<
@@ -870,6 +841,7 @@ const applyLocalOnlyChange =
870
841
  const columns = dbChangeToColumns(change, deps.time.now());
871
842
 
872
843
  for (const [column, value] of columns) {
844
+ assertNonNullable(value);
873
845
  deps.sqlite.exec(sql.prepared`
874
846
  insert into ${sql.identifier(change.table)}
875
847
  ("ownerId", "id", ${sql.identifier(column)})
@@ -899,6 +871,7 @@ const applyMessages =
899
871
  const timestampBytes = timestampToTimestampBytes(timestamp);
900
872
 
901
873
  for (const [column, value] of columns) {
874
+ assertNonNullable(value);
902
875
  if (validateColumnValue(deps)(change.table, column, value)) {
903
876
  applyColumnChange(deps)(
904
877
  ownerIdBytes,
@@ -4,10 +4,10 @@
4
4
  * @module
5
5
  */
6
6
 
7
- import type { DecryptWithXChaCha20Poly1305Error } from "../Crypto.js";
8
- import type { UnknownError } from "../Error.js";
9
- import type { ProtocolError } from "./Protocol.js";
10
- import type { TimestampError } from "./Timestamp.js";
7
+ import type { DecryptWithXChaCha20Poly1305Error } from "../Crypto.ts";
8
+ import type { UnknownError } from "../Error.ts";
9
+ import type { ProtocolError } from "./Protocol.ts";
10
+ import type { TimestampError } from "./Timestamp.ts";
11
11
 
12
12
  /** Represents errors that can occur in Evolu. */
13
13
  export type EvoluError =