@evolu/common 8.10.0 → 8.11.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 (144) hide show
  1. package/dist/src/Config.d.ts +22 -22
  2. package/dist/src/Config.d.ts.map +1 -1
  3. package/dist/src/Console.d.ts +62 -7
  4. package/dist/src/Console.d.ts.map +1 -1
  5. package/dist/src/Console.js +20 -4
  6. package/dist/src/Crypto.d.ts +76 -4
  7. package/dist/src/Crypto.d.ts.map +1 -1
  8. package/dist/src/Crypto.js +55 -4
  9. package/dist/src/Error.d.ts +45 -0
  10. package/dist/src/Error.d.ts.map +1 -1
  11. package/dist/src/Error.js +69 -0
  12. package/dist/src/Fs.d.ts +92 -18
  13. package/dist/src/Fs.d.ts.map +1 -1
  14. package/dist/src/Fs.js +2 -0
  15. package/dist/src/Identicon.d.ts +2 -2
  16. package/dist/src/Identicon.js +2 -2
  17. package/dist/src/LeakDetector.d.ts +22 -3
  18. package/dist/src/LeakDetector.d.ts.map +1 -1
  19. package/dist/src/LeakDetector.js +12 -2
  20. package/dist/src/LockManager.d.ts +8 -0
  21. package/dist/src/LockManager.d.ts.map +1 -1
  22. package/dist/src/LockManager.js +6 -0
  23. package/dist/src/Object.d.ts.map +1 -1
  24. package/dist/src/Object.js +5 -0
  25. package/dist/src/Platform.d.ts +47 -7
  26. package/dist/src/Platform.d.ts.map +1 -1
  27. package/dist/src/Platform.js +24 -5
  28. package/dist/src/Random.d.ts +25 -2
  29. package/dist/src/Random.d.ts.map +1 -1
  30. package/dist/src/Random.js +14 -2
  31. package/dist/src/Resource.d.ts +156 -1
  32. package/dist/src/Resource.d.ts.map +1 -1
  33. package/dist/src/Resource.js +201 -72
  34. package/dist/src/Schedule.d.ts +11 -10
  35. package/dist/src/Schedule.d.ts.map +1 -1
  36. package/dist/src/Schedule.js +1 -1
  37. package/dist/src/Sqlite.d.ts +132 -16
  38. package/dist/src/Sqlite.d.ts.map +1 -1
  39. package/dist/src/Sqlite.js +63 -9
  40. package/dist/src/Task.d.ts +15 -4
  41. package/dist/src/Task.d.ts.map +1 -1
  42. package/dist/src/Task.js +41 -15
  43. package/dist/src/Test.d.ts +9 -0
  44. package/dist/src/Test.d.ts.map +1 -1
  45. package/dist/src/Test.js +4 -0
  46. package/dist/src/Time.d.ts +106 -9
  47. package/dist/src/Time.d.ts.map +1 -1
  48. package/dist/src/Time.js +55 -4
  49. package/dist/src/Type.d.ts +1455 -1310
  50. package/dist/src/Type.d.ts.map +1 -1
  51. package/dist/src/Type.js +1274 -517
  52. package/dist/src/WebSocket.d.ts +164 -13
  53. package/dist/src/WebSocket.d.ts.map +1 -1
  54. package/dist/src/WebSocket.js +133 -24
  55. package/dist/src/Worker.d.ts +90 -8
  56. package/dist/src/Worker.d.ts.map +1 -1
  57. package/dist/src/Worker.js +28 -2
  58. package/dist/src/index.d.ts +6 -7
  59. package/dist/src/index.d.ts.map +1 -1
  60. package/dist/src/index.js +2 -3
  61. package/dist/src/local-first/Db.d.ts +52 -3
  62. package/dist/src/local-first/Db.d.ts.map +1 -1
  63. package/dist/src/local-first/Db.js +412 -137
  64. package/dist/src/local-first/Evolu.d.ts +336 -211
  65. package/dist/src/local-first/Evolu.d.ts.map +1 -1
  66. package/dist/src/local-first/Evolu.js +102 -15
  67. package/dist/src/local-first/Owner.d.ts +13 -30
  68. package/dist/src/local-first/Owner.d.ts.map +1 -1
  69. package/dist/src/local-first/Owner.js +13 -30
  70. package/dist/src/local-first/Protocol.d.ts +94 -16
  71. package/dist/src/local-first/Protocol.d.ts.map +1 -1
  72. package/dist/src/local-first/Protocol.js +118 -38
  73. package/dist/src/local-first/Query.d.ts +8 -15
  74. package/dist/src/local-first/Query.d.ts.map +1 -1
  75. package/dist/src/local-first/Schema.d.ts +335 -21
  76. package/dist/src/local-first/Schema.d.ts.map +1 -1
  77. package/dist/src/local-first/Schema.js +214 -17
  78. package/dist/src/local-first/Shared.d.ts +537 -22
  79. package/dist/src/local-first/Shared.d.ts.map +1 -1
  80. package/dist/src/local-first/Shared.js +1437 -234
  81. package/dist/src/local-first/Storage.d.ts +192 -14
  82. package/dist/src/local-first/Storage.d.ts.map +1 -1
  83. package/dist/src/local-first/Storage.js +81 -20
  84. package/dist/src/local-first/Timestamp.d.ts +392 -41
  85. package/dist/src/local-first/Timestamp.d.ts.map +1 -1
  86. package/dist/src/local-first/Timestamp.js +403 -81
  87. package/dist/src/local-first/index.d.ts +0 -1
  88. package/dist/src/local-first/index.d.ts.map +1 -1
  89. package/dist/src/local-first/index.js +0 -1
  90. package/package.json +1 -1
  91. package/src/Assert.test.ts +2 -5
  92. package/src/Config.test.ts +2 -6
  93. package/src/Config.ts +133 -133
  94. package/src/Console.ts +62 -7
  95. package/src/Crypto.ts +76 -4
  96. package/src/Eq.test.ts +2 -3
  97. package/src/Error.test.ts +76 -3
  98. package/src/Error.ts +71 -0
  99. package/src/Fs.ts +92 -18
  100. package/src/Identicon.ts +2 -2
  101. package/src/LeakDetector.ts +22 -3
  102. package/src/LockManager.ts +8 -0
  103. package/src/Object.test.ts +27 -12
  104. package/src/Object.ts +5 -0
  105. package/src/Platform.ts +50 -8
  106. package/src/Random.ts +25 -2
  107. package/src/Resource.test.ts +837 -0
  108. package/src/Resource.ts +235 -15
  109. package/src/Schedule.test.ts +50 -12
  110. package/src/Schedule.ts +24 -14
  111. package/src/Sqlite.ts +137 -17
  112. package/src/Task.test.ts +189 -8
  113. package/src/Task.ts +56 -17
  114. package/src/Test.ts +9 -0
  115. package/src/Time.ts +106 -9
  116. package/src/Type.test.ts +946 -1028
  117. package/src/Type.ts +4195 -3136
  118. package/src/Types.test.ts +4 -14
  119. package/src/WebSocket.ts +313 -40
  120. package/src/Worker.ts +90 -8
  121. package/src/index.ts +15 -6
  122. package/src/local-first/Db.ts +644 -339
  123. package/src/local-first/Evolu.test.ts +686 -21
  124. package/src/local-first/Evolu.ts +450 -228
  125. package/src/local-first/Owner.ts +13 -30
  126. package/src/local-first/Protocol.test.ts +617 -10
  127. package/src/local-first/Protocol.ts +196 -72
  128. package/src/local-first/Query.ts +8 -15
  129. package/src/local-first/Schema.test.ts +143 -0
  130. package/src/local-first/Schema.ts +363 -24
  131. package/src/local-first/Shared.test.ts +7731 -559
  132. package/src/local-first/Shared.ts +2036 -267
  133. package/src/local-first/Storage.ts +218 -32
  134. package/src/local-first/Timestamp.test.ts +344 -70
  135. package/src/local-first/Timestamp.ts +434 -118
  136. package/src/local-first/index.ts +0 -1
  137. package/dist/src/local-first/Error.d.ts +0 -12
  138. package/dist/src/local-first/Error.d.ts.map +0 -1
  139. package/dist/src/local-first/Error.js +0 -6
  140. package/dist/src/local-first/LocalAuth.d.ts +0 -150
  141. package/dist/src/local-first/LocalAuth.d.ts.map +0 -1
  142. package/dist/src/local-first/LocalAuth.js +0 -179
  143. package/src/local-first/Error.ts +0 -17
  144. package/src/local-first/LocalAuth.ts +0 -457
@@ -5,6 +5,7 @@
5
5
  */
6
6
  import type { NonEmptyReadonlyArray } from "../Array.ts";
7
7
  import type { Brand } from "../Brand.ts";
8
+ import type { DecryptWithXChaCha20Poly1305Error } from "../Crypto.ts";
8
9
  import type { RandomDep } from "../Random.ts";
9
10
  import type { SqliteDep } from "../Sqlite.ts";
10
11
  import type { Task } from "../Task.ts";
@@ -12,7 +13,13 @@ import { Boolean, Id, type InferType, NonNegativeInt, Null, type ObjectType, Pos
12
13
  import type { Awaitable } from "../Types.ts";
13
14
  import type { OwnerError, OwnerIdBytes } from "./Owner.ts";
14
15
  import { OwnerId, OwnerWriteKey } from "./Owner.ts";
16
+ import type { ProtocolInvalidDataError, ProtocolTimestampMismatchError } from "./Protocol.ts";
15
17
  import { Timestamp, TimestampBytes } from "./Timestamp.ts";
18
+ /**
19
+ * Configuration for {@link Storage}, such as quota checks.
20
+ *
21
+ * @group Core
22
+ */
16
23
  export interface StorageConfig {
17
24
  /**
18
25
  * Callback called before an attempt to write, to check if an {@link OwnerId}
@@ -67,12 +74,18 @@ export interface StorageConfig {
67
74
  readonly isOwnerWithinQuota: (ownerId: OwnerId, requiredBytes: PositiveInt) => Awaitable<boolean>;
68
75
  }
69
76
  /**
70
- * Evolu Storage.
77
+ * Replica storage used by Evolu's synchronization protocol.
78
+ *
79
+ * Protocol owns message framing, set reconciliation, and sync continuation.
80
+ * Storage owns batch acceptance, persistence, and the timestamp and fingerprint
81
+ * queries used by reconciliation. Protocol functions accept any implementation
82
+ * that satisfies this contract.
71
83
  *
72
- * Evolu Protocol is agnostic to storage implementation—any storage can be
73
- * plugged in, as long as it implements this interface. Implementations must
74
- * handle their own errors; return values only indicate overall success or
75
- * failure.
84
+ * {@link Storage.writeMessages} returns the {@link StorageWriteMessagesError}
85
+ * that made it store none of a batch. Implementations return expected write
86
+ * rejections without reporting them; the caller owns reporting. The client
87
+ * protocol forwards these errors unchanged, while the relay protocol maps them
88
+ * to wire error codes.
76
89
  *
77
90
  * The Storage API is synchronous because SQLite's synchronous API is the
78
91
  * fastest way to use SQLite. Synchronous bindings (like better-sqlite3) call
@@ -82,6 +95,8 @@ export interface StorageConfig {
82
95
  * The only exception is {@link Storage.writeMessages}, which is async to allow
83
96
  * for async validation logic before writing to storage. The write operation
84
97
  * itself remains synchronous.
98
+ *
99
+ * @group Core
85
100
  */
86
101
  export interface Storage {
87
102
  readonly getSize: (ownerId: OwnerIdBytes) => NonNegativeInt;
@@ -107,66 +122,157 @@ export interface Storage {
107
122
  /**
108
123
  * Write encrypted {@link CrdtMessage}s to storage.
109
124
  *
125
+ * Stores none of the messages and returns the cause when the batch cannot be
126
+ * accepted.
127
+ *
110
128
  * Must use a mutex per ownerId to ensure sequential processing and proper
111
129
  * protocol logic handling during sync operations.
112
130
  */
113
- readonly writeMessages: (ownerIdBytes: OwnerIdBytes, messages: NonEmptyReadonlyArray<EncryptedCrdtMessage>) => Task<void, StorageQuotaError>;
131
+ readonly writeMessages: (ownerIdBytes: OwnerIdBytes, messages: NonEmptyReadonlyArray<EncryptedCrdtMessage>) => Task<void, StorageWriteMessagesError>;
114
132
  /** Read encrypted {@link DbChange}s from storage. */
115
133
  readonly readDbChange: (ownerId: OwnerIdBytes, timestamp: TimestampBytes) => EncryptedDbChange;
116
134
  /** Delete all data for the given {@link Owner}. */
117
135
  readonly deleteOwner: (ownerId: OwnerIdBytes) => void;
118
136
  }
137
+ /**
138
+ * Dependency wrapper for {@link Storage}.
139
+ *
140
+ * @group Core
141
+ */
119
142
  export interface StorageDep {
120
143
  readonly storage: Storage;
121
144
  }
122
- /** Error when storage or billing quota is exceeded. */
145
+ /**
146
+ * Error when storage or billing quota is exceeded.
147
+ *
148
+ * @group Core
149
+ */
123
150
  export interface StorageQuotaError extends OwnerError, Typed<"StorageQuotaError"> {
124
151
  }
152
+ /**
153
+ * Expected reasons why {@link Storage.writeMessages} stored none of a batch.
154
+ *
155
+ * Each implementation returns the members that apply to it. The built-in relay
156
+ * storage currently stores opaque encrypted messages and rejects batches over
157
+ * quota. The built-in client storage decrypts and validates incoming messages
158
+ * before updating its clock and database tables. The contract permits quota
159
+ * checks on either side.
160
+ *
161
+ * @group Core
162
+ */
163
+ export type StorageWriteMessagesError = DecryptWithXChaCha20Poly1305Error | ProtocolInvalidDataError | ProtocolTimestampMismatchError | StorageQuotaError;
125
164
  /**
126
165
  * A cryptographic hash used for efficiently comparing collections of
127
166
  * {@link TimestampBytes}es.
128
167
  *
129
168
  * It consists of the first {@link fingerprintSize} bytes of the SHA-256 hash of
130
169
  * one or more timestamps.
170
+ *
171
+ * @group Ranges
131
172
  */
132
173
  export type Fingerprint = Uint8Array & Brand<"Fingerprint">;
174
+ /**
175
+ * Number of leading SHA-256 bytes that form a {@link Fingerprint}.
176
+ *
177
+ * @group Ranges
178
+ */
133
179
  export declare const fingerprintSize: number & Brand<"NonNaN"> & Brand<"Finite"> & Brand<"Int"> & Brand<"NonNegative">;
134
- /** A fingerprint of an empty range. */
180
+ /**
181
+ * A fingerprint of an empty range.
182
+ *
183
+ * @group Ranges
184
+ */
135
185
  export declare const zeroFingerprint: Fingerprint;
186
+ /**
187
+ * Common shape of every {@link Range}.
188
+ *
189
+ * @group Ranges
190
+ */
136
191
  export interface BaseRange {
137
192
  readonly upperBound: RangeUpperBound;
138
193
  }
139
194
  /**
140
195
  * Union type for Range's upperBound: either a {@link TimestampBytes} or
141
196
  * {@link InfiniteUpperBound}.
197
+ *
198
+ * @group Ranges
142
199
  */
143
200
  export type RangeUpperBound = TimestampBytes | InfiniteUpperBound;
201
+ /**
202
+ * Sentinel {@link RangeUpperBound} for a range without an upper limit.
203
+ *
204
+ * @group Ranges
205
+ */
144
206
  export declare const InfiniteUpperBound: unique symbol;
207
+ /**
208
+ * Type of the {@link InfiniteUpperBound} sentinel.
209
+ *
210
+ * @group Ranges
211
+ */
145
212
  export type InfiniteUpperBound = typeof InfiniteUpperBound;
213
+ /**
214
+ * Numeric tags discriminating {@link Range} variants.
215
+ *
216
+ * @group Ranges
217
+ */
146
218
  export declare const RangeType: {
147
219
  readonly Fingerprint: 1;
148
220
  readonly Skip: 0;
149
221
  readonly Timestamps: 2;
150
222
  };
223
+ /**
224
+ * Numeric tag of one {@link Range} variant.
225
+ *
226
+ * @group Ranges
227
+ */
151
228
  export type RangeType = (typeof RangeType)[keyof typeof RangeType];
229
+ /**
230
+ * Range with nothing to reconcile.
231
+ *
232
+ * @group Ranges
233
+ */
152
234
  export interface SkipRange extends BaseRange {
153
235
  readonly type: typeof RangeType.Skip;
154
236
  }
237
+ /**
238
+ * Range summarized by a {@link Fingerprint} for comparison.
239
+ *
240
+ * @group Ranges
241
+ */
155
242
  export interface FingerprintRange extends BaseRange {
156
243
  readonly type: typeof RangeType.Fingerprint;
157
244
  readonly fingerprint: Fingerprint;
158
245
  }
246
+ /**
247
+ * Range listing its {@link TimestampBytes} explicitly.
248
+ *
249
+ * @group Ranges
250
+ */
159
251
  export interface TimestampsRange extends BaseRange {
160
252
  readonly type: typeof RangeType.Timestamps;
161
253
  readonly timestamps: ReadonlyArray<TimestampBytes>;
162
254
  }
255
+ /**
256
+ * Range exchanged during sync: {@link SkipRange}, {@link FingerprintRange}, or
257
+ * {@link TimestampsRange}.
258
+ *
259
+ * @group Ranges
260
+ */
163
261
  export type Range = SkipRange | FingerprintRange | TimestampsRange;
164
- /** An encrypted {@link CrdtMessage}. */
262
+ /**
263
+ * An encrypted {@link CrdtMessage}.
264
+ *
265
+ * @group Messages
266
+ */
165
267
  export interface EncryptedCrdtMessage {
166
268
  readonly timestamp: Timestamp;
167
269
  readonly change: EncryptedDbChange;
168
270
  }
169
- /** Encrypted DbChange */
271
+ /**
272
+ * Encrypted DbChange
273
+ *
274
+ * @group Messages
275
+ */
170
276
  export type EncryptedDbChange = Uint8Array & Brand<"EncryptedDbChange">;
171
277
  /**
172
278
  * A CRDT message combining a unique {@link Timestamp} with a {@link DbChange}.
@@ -174,17 +280,38 @@ export type EncryptedDbChange = Uint8Array & Brand<"EncryptedDbChange">;
174
280
  * Used in Evolu's sync protocol to replicate data changes across devices. Evolu
175
281
  * operates as a durable queue, providing exactly-once delivery guarantees for
176
282
  * reliable synchronization across application restarts and network failures.
283
+ *
284
+ * @group Messages
177
285
  */
178
286
  export interface CrdtMessage {
179
287
  readonly timestamp: Timestamp;
180
288
  readonly change: DbChange;
181
289
  }
182
- /** Test helper for creating a simple {@link CrdtMessage}. */
290
+ /**
291
+ * Test helper for creating a simple {@link CrdtMessage}.
292
+ *
293
+ * @group Testing
294
+ */
183
295
  export declare const testCreateCrdtMessage: (id: Id, millis: number, name: string) => CrdtMessage;
296
+ /**
297
+ * Column values of a {@link DbChange}, keyed by column name.
298
+ *
299
+ * @group Messages
300
+ */
184
301
  export declare const DbChangeValues: import("../Type.ts").RecordType<import("../Type.ts").Type<"String", string, string, import("../Type.ts").TypeOfError<"String">, null, import("../Type.ts").TypeOfError<"String">, never, string, true>, UnionType<readonly [import("../Type.ts").BrandType<import("../Type.ts").BrandType<import("../Type.ts").Type<"Number", number, number, import("../Type.ts").TypeOfError<"Number">, null, import("../Type.ts").TypeOfError<"Number">, never, number, true>, "NonNaN", import("../Type.ts").NonNaNError>, "Finite", import("../Type.ts").FiniteError>, import("../Type.ts").LiteralType<null>, import("../Type.ts").Type<"String", string, string, import("../Type.ts").TypeOfError<"String">, null, import("../Type.ts").TypeOfError<"String">, never, string, true>, import("../Type.ts").Type<"Uint8Array", Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>, import("../Type.ts").ObjectTagError<"Uint8Array">, null, import("../Type.ts").ObjectTagError<"Uint8Array">, never, Uint8Array<ArrayBufferLike>, true>]>>;
185
302
  export type DbChangeValues = typeof DbChangeValues.Output;
303
+ /**
304
+ * Column values that contain no reserved system columns.
305
+ *
306
+ * @group Messages
307
+ */
186
308
  export declare const ValidDbChangeValues: import("../Type.ts").BrandType<import("../Type.ts").RecordType<import("../Type.ts").Type<"String", string, string, import("../Type.ts").TypeOfError<"String">, null, import("../Type.ts").TypeOfError<"String">, never, string, true>, UnionType<readonly [import("../Type.ts").BrandType<import("../Type.ts").BrandType<import("../Type.ts").Type<"Number", number, number, import("../Type.ts").TypeOfError<"Number">, null, import("../Type.ts").TypeOfError<"Number">, never, number, true>, "NonNaN", import("../Type.ts").NonNaNError>, "Finite", import("../Type.ts").FiniteError>, import("../Type.ts").LiteralType<null>, import("../Type.ts").Type<"String", string, string, import("../Type.ts").TypeOfError<"String">, null, import("../Type.ts").TypeOfError<"String">, never, string, true>, import("../Type.ts").Type<"Uint8Array", Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>, import("../Type.ts").ObjectTagError<"Uint8Array">, null, import("../Type.ts").ObjectTagError<"Uint8Array">, never, Uint8Array<ArrayBufferLike>, true>]>>, "ValidDbChangeValues", ValidDbChangeValuesError>;
187
309
  export type ValidDbChangeValues = typeof ValidDbChangeValues.Output;
310
+ /**
311
+ * Error produced when {@link DbChangeValues} contain reserved system columns.
312
+ *
313
+ * @group Messages
314
+ */
188
315
  export interface ValidDbChangeValuesError extends TypeError<"ValidDbChangeValues"> {
189
316
  readonly value: DbChangeValues;
190
317
  readonly invalidColumns: ReadonlyArray<string>;
@@ -192,6 +319,8 @@ export interface ValidDbChangeValuesError extends TypeError<"ValidDbChangeValues
192
319
  /**
193
320
  * A DbChange is a change to a table row. Together with a unique
194
321
  * {@link Timestamp}, it forms a {@link CrdtMessage}.
322
+ *
323
+ * @group Messages
195
324
  */
196
325
  export declare const DbChange: ObjectType<{
197
326
  readonly table: typeof String;
@@ -231,19 +360,36 @@ export interface DbChange extends InferType<typeof DbChange> {
231
360
  * each other, if necessary. One relay should handle hundreds of thousands of
232
361
  * users, and when it goes down, nothing happens, because it will be
233
362
  * synchronized later.
363
+ *
364
+ * @group SQLite
234
365
  */
235
366
  export interface BaseSqliteStorage extends Omit<Storage, "validateWriteKey" | "setWriteKey" | "writeMessages" | "readDbChange"> {
236
- /** Inserts a timestamp for an owner into the skiplist-based storage. */
237
- readonly insertTimestamp: (ownerId: OwnerIdBytes, timestamp: TimestampBytes, strategy: StorageInsertTimestampStrategy) => void;
367
+ /**
368
+ * Inserts a timestamp for an owner into the skiplist-based storage.
369
+ *
370
+ * Returns whether the timestamp was new. An existing timestamp is left
371
+ * unchanged.
372
+ */
373
+ readonly insertTimestamp: (ownerId: OwnerIdBytes, timestamp: TimestampBytes, strategy: StorageInsertTimestampStrategy) => boolean;
238
374
  /**
239
375
  * Efficiently checks which timestamps already exist in the database using a
240
376
  * single CTE query instead of N individual queries.
241
377
  */
242
378
  readonly getExistingTimestamps: (ownerIdBytes: OwnerIdBytes, timestampsBytes: NonEmptyReadonlyArray<TimestampBytes>) => ReadonlyArray<TimestampBytes>;
243
379
  }
380
+ /**
381
+ * Dependency wrapper for {@link BaseSqliteStorage}.
382
+ *
383
+ * @group SQLite
384
+ */
244
385
  export interface BaseSqliteStorageDep {
245
386
  readonly baseSqliteStorage: BaseSqliteStorage;
246
387
  }
388
+ /**
389
+ * Dependencies required by {@link createBaseSqliteStorage}.
390
+ *
391
+ * @group SQLite
392
+ */
247
393
  export type SqliteStorageDeps = RandomDep & SqliteDep;
248
394
  /**
249
395
  * Creates a {@link BaseSqliteStorage} implementation.
@@ -257,25 +403,55 @@ export type SqliteStorageDeps = RandomDep & SqliteDep;
257
403
  * Cloudflare Workers with Durable Objects, and other platforms where memory
258
404
  * doesn't persist between requests. While not extensively tested in all these
259
405
  * environments yet, the stateless design should work well across them.
406
+ *
407
+ * @group SQLite
260
408
  */
261
409
  export declare const createBaseSqliteStorage: (deps: SqliteStorageDeps) => BaseSqliteStorage;
410
+ /**
411
+ * Creates the SQLite tables used by {@link BaseSqliteStorage}.
412
+ *
413
+ * @group SQLite
414
+ */
262
415
  export declare const createBaseSqliteStorageTables: (deps: SqliteDep) => void;
416
+ /**
417
+ * Position at which a timestamp is inserted relative to existing timestamps.
418
+ *
419
+ * @group SQLite
420
+ */
263
421
  export type StorageInsertTimestampStrategy = "append" | "prepend" | "insert";
264
422
  /**
265
423
  * Determines the insertion strategy for a timestamp based on its position
266
424
  * relative to the current first and last timestamps.
267
425
  *
268
426
  * Returns a tuple with the strategy and updated timestamp bounds.
427
+ *
428
+ * @group SQLite
269
429
  */
270
430
  export declare const getTimestampInsertStrategy: (timestamp: TimestampBytes, firstTimestamp: TimestampBytes, lastTimestamp: TimestampBytes) => [strategy: StorageInsertTimestampStrategy, firstTimestamp: TimestampBytes, lastTimestamp: TimestampBytes];
431
+ /**
432
+ * Computes the {@link Fingerprint} of a single timestamp.
433
+ *
434
+ * @group Ranges
435
+ */
271
436
  export declare const timestampBytesToFingerprint: (timestamp: TimestampBytes) => Fingerprint;
272
437
  /**
273
438
  * Computes a brute-force {@link Fingerprint} from {@link TimestampBytes} values
274
439
  * for tests and benchmarks.
440
+ *
441
+ * @group Testing
275
442
  */
276
443
  export declare const testFingerprintTimestamps: (timestamps: ReadonlyArray<TimestampBytes>) => Fingerprint;
444
+ /**
445
+ * Reads the timestamp at a position within an owner's ordered timestamps.
446
+ *
447
+ * @group SQLite
448
+ */
277
449
  export declare const getTimestampByIndex: (deps: SqliteDep) => (ownerId: OwnerIdBytes, index: NonNegativeInt) => TimestampBytes;
278
- /** Reads owner usage from SQLite and returns default bounds when absent. */
450
+ /**
451
+ * Reads owner usage from SQLite and returns default bounds when absent.
452
+ *
453
+ * @group SQLite
454
+ */
279
455
  export declare const readOwnerUsageOrDefault: (deps: SqliteDep) => (ownerIdBytes: OwnerIdBytes, initialTimestamp: TimestampBytes) => {
280
456
  readonly storedBytes: NonNegativeInt | null;
281
457
  readonly firstTimestamp: TimestampBytes;
@@ -286,6 +462,8 @@ export declare const readOwnerUsageOrDefault: (deps: SqliteDep) => (ownerIdBytes
286
462
  *
287
463
  * Used by both relay and client to maintain firstTimestamp/lastTimestamp after
288
464
  * processing messages.
465
+ *
466
+ * @group SQLite
289
467
  */
290
468
  export declare const updateOwnerUsage: (deps: SqliteDep) => (ownerIdBytes: OwnerIdBytes, storedBytes: PositiveInt, firstTimestamp: TimestampBytes, lastTimestamp: TimestampBytes) => void;
291
469
  //# sourceMappingURL=Storage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Storage.d.ts","sourceRoot":"","sources":["../../../src/local-first/Storage.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Storage.d.ts","sourceRoot":"","sources":["../../../src/local-first/Storage.ts"],"names":[],"mappings":"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"}
@@ -15,16 +15,39 @@ import { Boolean, brand, Id, NonNegativeInt, Null, nullOr, object, PositiveInt,
15
15
  import { OwnerId, OwnerWriteKey } from "./Owner.js";
16
16
  import { systemColumnsWithId } from "./Schema.js";
17
17
  import { createTimestamp, orderTimestampBytes, Timestamp, TimestampBytes, } from "./Timestamp.js";
18
+ /**
19
+ * Number of leading SHA-256 bytes that form a {@link Fingerprint}.
20
+ *
21
+ * @group Ranges
22
+ */
18
23
  export const fingerprintSize = /*#__PURE__*/ NonNegativeInt.orThrow(12);
19
- /** A fingerprint of an empty range. */
24
+ /**
25
+ * A fingerprint of an empty range.
26
+ *
27
+ * @group Ranges
28
+ */
20
29
  export const zeroFingerprint = /*#__PURE__*/ new Uint8Array(fingerprintSize);
30
+ /**
31
+ * Sentinel {@link RangeUpperBound} for a range without an upper limit.
32
+ *
33
+ * @group Ranges
34
+ */
21
35
  export const InfiniteUpperBound = /*#__PURE__*/ Symbol("evolu.local-first.Storage.InfiniteUpperBound");
36
+ /**
37
+ * Numeric tags discriminating {@link Range} variants.
38
+ *
39
+ * @group Ranges
40
+ */
22
41
  export const RangeType = {
23
42
  Fingerprint: 1,
24
43
  Skip: 0,
25
44
  Timestamps: 2,
26
45
  };
27
- /** Test helper for creating a simple {@link CrdtMessage}. */
46
+ /**
47
+ * Test helper for creating a simple {@link CrdtMessage}.
48
+ *
49
+ * @group Testing
50
+ */
28
51
  export const testCreateCrdtMessage = (id, millis, name) => ({
29
52
  timestamp: createTimestamp({
30
53
  millis: Millis.orThrow(millis),
@@ -38,7 +61,17 @@ export const testCreateCrdtMessage = (id, millis, name) => ({
38
61
  isDelete: false,
39
62
  }),
40
63
  });
64
+ /**
65
+ * Column values of a {@link DbChange}, keyed by column name.
66
+ *
67
+ * @group Messages
68
+ */
41
69
  export const DbChangeValues = /*#__PURE__*/ record(String, SqliteValue);
70
+ /**
71
+ * Column values that contain no reserved system columns.
72
+ *
73
+ * @group Messages
74
+ */
42
75
  export const ValidDbChangeValues = /*#__PURE__*/ brand("ValidDbChangeValues", DbChangeValues, (value) => {
43
76
  const invalidColumns = systemColumnsWithId.filter((key) => key in value);
44
77
  if (invalidColumns.length > 0)
@@ -52,6 +85,8 @@ export const ValidDbChangeValues = /*#__PURE__*/ brand("ValidDbChangeValues", Db
52
85
  /**
53
86
  * A DbChange is a change to a table row. Together with a unique
54
87
  * {@link Timestamp}, it forms a {@link CrdtMessage}.
88
+ *
89
+ * @group Messages
55
90
  */
56
91
  export const DbChange = /*#__PURE__*/ object({
57
92
  table: String,
@@ -72,11 +107,13 @@ export const DbChange = /*#__PURE__*/ object({
72
107
  * Cloudflare Workers with Durable Objects, and other platforms where memory
73
108
  * doesn't persist between requests. While not extensively tested in all these
74
109
  * environments yet, the stateless design should work well across them.
110
+ *
111
+ * @group SQLite
75
112
  */
76
113
  export const createBaseSqliteStorage = (deps) => ({
77
114
  insertTimestamp: (ownerId, timestamp, strategy) => {
78
115
  const level = randomSkiplistLevel(deps);
79
- insertTimestamp(deps)(ownerId, timestamp, level, strategy);
116
+ return insertTimestamp(deps)(ownerId, timestamp, level, strategy);
80
117
  },
81
118
  getExistingTimestamps: (ownerIdBytes, timestampsBytes) => {
82
119
  const concatenatedTimestamps = concatBytes(...timestampsBytes);
@@ -150,6 +187,11 @@ export const createBaseSqliteStorage = (deps) => ({
150
187
  const assertBeginEnd = (begin, end) => {
151
188
  assert(begin <= end, "invalid begin or end");
152
189
  };
190
+ /**
191
+ * Creates the SQLite tables used by {@link BaseSqliteStorage}.
192
+ *
193
+ * @group SQLite
194
+ */
153
195
  export const createBaseSqliteStorageTables = (deps) => {
154
196
  for (const query of [
155
197
  /**
@@ -218,6 +260,8 @@ export const createBaseSqliteStorageTables = (deps) => {
218
260
  * relative to the current first and last timestamps.
219
261
  *
220
262
  * Returns a tuple with the strategy and updated timestamp bounds.
263
+ *
264
+ * @group SQLite
221
265
  */
222
266
  export const getTimestampInsertStrategy = (timestamp, firstTimestamp, lastTimestamp) => {
223
267
  if (orderTimestampBytes(timestamp, lastTimestamp) === 1) {
@@ -251,13 +295,13 @@ export const getTimestampInsertStrategy = (timestamp, firstTimestamp, lastTimest
251
295
  * key instead of repeating the same correlated range lookup for every column.
252
296
  *
253
297
  * Inserts are idempotent to support direct calls and message replay. `on
254
- * conflict do nothing` makes a duplicate insertion a no-op, and `changes() > 0`
255
- * ensures ancestor metadata is updated only when the preceding insertion added
256
- * a timestamp.
298
+ * conflict do nothing` makes a duplicate insertion a no-op that reports the
299
+ * timestamp as not new, so the follow-up statements update metadata only for a
300
+ * new timestamp.
257
301
  */
258
302
  const insertTimestamp = (deps) => (ownerId, timestamp, level, strategy) => {
259
303
  const [h1, h2] = fingerprintToSqliteFingerprint(timestampBytesToFingerprint(timestamp));
260
- let queries = [];
304
+ let queries;
261
305
  switch (strategy) {
262
306
  case "append":
263
307
  queries = [
@@ -431,10 +475,7 @@ const insertTimestamp = (deps) => (ownerId, timestamp, level, strategy) => {
431
475
  h2 = u.h2,
432
476
  c = c + 1
433
477
  from u
434
- where
435
- changes() > 0
436
- and ownerId = ${ownerId}
437
- and evolu_timestamp.t = u.t;
478
+ where ownerId = ${ownerId} and evolu_timestamp.t = u.t;
438
479
  `,
439
480
  ];
440
481
  break;
@@ -499,10 +540,7 @@ const insertTimestamp = (deps) => (ownerId, timestamp, level, strategy) => {
499
540
  h2 = u.h2,
500
541
  c = c + 1
501
542
  from u
502
- where
503
- changes() > 0
504
- and ownerId = ${ownerId}
505
- and evolu_timestamp.t = u.t;
543
+ where ownerId = ${ownerId} and evolu_timestamp.t = u.t;
506
544
  `,
507
545
  ]
508
546
  : [
@@ -684,15 +722,25 @@ const insertTimestamp = (deps) => (ownerId, timestamp, level, strategy) => {
684
722
  h2 = uh2,
685
723
  c = uc
686
724
  from u
687
- where changes() > 0 and ownerId = ${ownerId} and t = ut;
725
+ where ownerId = ${ownerId} and t = ut;
688
726
  `,
689
727
  ];
690
728
  break;
691
729
  }
692
- for (const query of queries) {
693
- deps.sqlite.exec(query);
694
- }
730
+ // The insert uses "on conflict do nothing". An existing timestamp changes
731
+ // nothing, and the metadata updates are skipped.
732
+ const [insert, ...updates] = queries;
733
+ if (deps.sqlite.exec(insert).changes === 0)
734
+ return false;
735
+ for (const update of updates)
736
+ deps.sqlite.exec(update);
737
+ return true;
695
738
  };
739
+ /**
740
+ * Computes the {@link Fingerprint} of a single timestamp.
741
+ *
742
+ * @group Ranges
743
+ */
696
744
  export const timestampBytesToFingerprint = (timestamp) => {
697
745
  const hash = sha256(timestamp).slice(0, fingerprintSize);
698
746
  return hash;
@@ -700,6 +748,8 @@ export const timestampBytesToFingerprint = (timestamp) => {
700
748
  /**
701
749
  * Computes a brute-force {@link Fingerprint} from {@link TimestampBytes} values
702
750
  * for tests and benchmarks.
751
+ *
752
+ * @group Testing
703
753
  */
704
754
  export const testFingerprintTimestamps = (timestamps) => timestamps
705
755
  .map(timestampBytesToFingerprint)
@@ -1013,6 +1063,11 @@ const fingerprintRanges = (deps) => (ownerId, buckets, upperBound = InfiniteUppe
1013
1063
  };
1014
1064
  // XOR in SQLite
1015
1065
  const x = (a, b) => sql.raw(`(${a} | ${b}) - (${a} & ${b})`);
1066
+ /**
1067
+ * Reads the timestamp at a position within an owner's ordered timestamps.
1068
+ *
1069
+ * @group SQLite
1070
+ */
1016
1071
  export const getTimestampByIndex = (deps) => (ownerId, index) => {
1017
1072
  const result = deps.sqlite.exec(sql.prepared `
1018
1073
  with
@@ -1087,7 +1142,11 @@ export const getTimestampByIndex = (deps) => (ownerId, index) => {
1087
1142
  `);
1088
1143
  return result.rows[0].pt;
1089
1144
  };
1090
- /** Reads owner usage from SQLite and returns default bounds when absent. */
1145
+ /**
1146
+ * Reads owner usage from SQLite and returns default bounds when absent.
1147
+ *
1148
+ * @group SQLite
1149
+ */
1091
1150
  export const readOwnerUsageOrDefault = (deps) => (ownerIdBytes, initialTimestamp) => {
1092
1151
  const result = deps.sqlite.exec(sql `
1093
1152
  select storedBytes, firstTimestamp, lastTimestamp
@@ -1115,6 +1174,8 @@ export const readOwnerUsageOrDefault = (deps) => (ownerIdBytes, initialTimestamp
1115
1174
  *
1116
1175
  * Used by both relay and client to maintain firstTimestamp/lastTimestamp after
1117
1176
  * processing messages.
1177
+ *
1178
+ * @group SQLite
1118
1179
  */
1119
1180
  export const updateOwnerUsage = (deps) => (ownerIdBytes, storedBytes, firstTimestamp, lastTimestamp) => {
1120
1181
  deps.sqlite.exec(sql `