@evolu/common 4.1.1 → 5.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/README.md +1 -1
  2. package/dist/src/Config.d.ts +27 -30
  3. package/dist/src/Config.d.ts.map +1 -1
  4. package/dist/src/Config.js +32 -5
  5. package/dist/src/Crdt.d.ts +5 -4
  6. package/dist/src/Crdt.d.ts.map +1 -1
  7. package/dist/src/Crdt.js +27 -24
  8. package/dist/src/Crypto.d.ts +16 -10
  9. package/dist/src/Crypto.d.ts.map +1 -1
  10. package/dist/src/Crypto.js +24 -11
  11. package/dist/src/Db.d.ts +58 -78
  12. package/dist/src/Db.d.ts.map +1 -1
  13. package/dist/src/Db.js +368 -170
  14. package/dist/src/Diff.d.ts +9 -3
  15. package/dist/src/Diff.d.ts.map +1 -1
  16. package/dist/src/Diff.js +12 -11
  17. package/dist/src/Error.d.ts +15 -0
  18. package/dist/src/Error.d.ts.map +1 -0
  19. package/dist/src/Error.js +14 -0
  20. package/dist/src/Evolu.d.ts +139 -91
  21. package/dist/src/Evolu.d.ts.map +1 -1
  22. package/dist/src/Evolu.js +267 -239
  23. package/dist/src/Model.d.ts +52 -0
  24. package/dist/src/Model.d.ts.map +1 -1
  25. package/dist/src/Model.js +47 -5
  26. package/dist/src/Owner.d.ts.map +1 -1
  27. package/dist/src/Owner.js +14 -8
  28. package/dist/src/Platform.d.ts +24 -34
  29. package/dist/src/Platform.d.ts.map +1 -1
  30. package/dist/src/Platform.js +9 -31
  31. package/dist/src/Public.d.ts +3 -5
  32. package/dist/src/Public.d.ts.map +1 -1
  33. package/dist/src/Public.js +2 -3
  34. package/dist/src/Sqlite.d.ts +25 -16
  35. package/dist/src/Sqlite.d.ts.map +1 -1
  36. package/dist/src/Sqlite.js +28 -20
  37. package/dist/src/Store.d.ts.map +1 -1
  38. package/dist/src/Sync.d.ts +70 -0
  39. package/dist/src/Sync.d.ts.map +1 -0
  40. package/dist/src/Sync.js +126 -0
  41. package/dist/src/index.d.ts +2 -5
  42. package/dist/src/index.d.ts.map +1 -1
  43. package/dist/src/index.js +2 -5
  44. package/package.json +12 -10
  45. package/src/Config.ts +77 -36
  46. package/src/Crdt.ts +61 -76
  47. package/src/Crypto.ts +83 -60
  48. package/src/Db.ts +782 -352
  49. package/src/Diff.ts +23 -21
  50. package/src/Error.ts +29 -0
  51. package/src/Evolu.ts +599 -499
  52. package/src/Model.ts +102 -6
  53. package/src/Owner.ts +24 -24
  54. package/src/Platform.ts +33 -81
  55. package/src/Public.ts +3 -5
  56. package/src/Sqlite.ts +81 -44
  57. package/src/Sync.ts +306 -0
  58. package/src/index.ts +2 -5
  59. package/dist/src/DbWorker.d.ts +0 -82
  60. package/dist/src/DbWorker.d.ts.map +0 -1
  61. package/dist/src/DbWorker.js +0 -335
  62. package/dist/src/ErrorStore.d.ts +0 -29
  63. package/dist/src/ErrorStore.d.ts.map +0 -1
  64. package/dist/src/ErrorStore.js +0 -13
  65. package/dist/src/OnCompletes.d.ts +0 -14
  66. package/dist/src/OnCompletes.d.ts.map +0 -1
  67. package/dist/src/OnCompletes.js +0 -25
  68. package/dist/src/SyncWorker.d.ts +0 -80
  69. package/dist/src/SyncWorker.d.ts.map +0 -1
  70. package/dist/src/SyncWorker.js +0 -150
  71. package/dist/src/Types.d.ts +0 -13
  72. package/dist/src/Types.d.ts.map +0 -1
  73. package/dist/src/Types.js +0 -1
  74. package/src/DbWorker.ts +0 -721
  75. package/src/ErrorStore.ts +0 -46
  76. package/src/OnCompletes.ts +0 -51
  77. package/src/SyncWorker.ts +0 -361
  78. package/src/Types.ts +0 -11
package/src/Sync.ts ADDED
@@ -0,0 +1,306 @@
1
+ import * as Http from "@effect/platform/HttpClient";
2
+ import * as S from "@effect/schema/Schema";
3
+ import { concatBytes } from "@noble/ciphers/utils";
4
+ import { BinaryReader, BinaryWriter } from "@protobuf-ts/runtime";
5
+ import * as Arr from "effect/Array";
6
+ import * as Context from "effect/Context";
7
+ import * as Deferred from "effect/Deferred";
8
+ import * as Effect from "effect/Effect";
9
+ import { absurd } from "effect/Function";
10
+ import * as Option from "effect/Option";
11
+ import * as Predicate from "effect/Predicate";
12
+ import { Config } from "./Config.js";
13
+ import {
14
+ MerkleTree,
15
+ Millis,
16
+ Timestamp,
17
+ TimestampString,
18
+ merkleTreeToString,
19
+ unsafeMerkleTreeFromString,
20
+ } from "./Crdt.js";
21
+ import { SecretBox } from "./Crypto.js";
22
+ import { Id } from "./Model.js";
23
+ import { Owner } from "./Owner.js";
24
+ import * as Protobuf from "./Protobuf.js";
25
+ import { JsonObjectOrArray, Value } from "./Sqlite.js";
26
+
27
+ export interface Sync {
28
+ readonly init: (owner: Owner) => Effect.Effect<void>;
29
+ readonly sync: (
30
+ syncData: SyncData,
31
+ ) => Effect.Effect<SyncResult, SyncStateIsNotSynced, Config>;
32
+ }
33
+
34
+ export const Sync = Context.GenericTag<Sync>("Sync");
35
+
36
+ export interface SyncData {
37
+ merkleTree: MerkleTree;
38
+ timestamp: Timestamp;
39
+ messages?: ReadonlyArray<Message>;
40
+ }
41
+
42
+ export interface Message extends NewMessage {
43
+ readonly timestamp: TimestampString;
44
+ }
45
+
46
+ export interface NewMessage {
47
+ readonly table: string;
48
+ readonly row: Id;
49
+ readonly column: string;
50
+ readonly value: Value;
51
+ }
52
+
53
+ export interface SyncResult {
54
+ readonly messages: ReadonlyArray<Message>;
55
+ readonly merkleTree: MerkleTree;
56
+ }
57
+
58
+ /**
59
+ * The SyncState type represents the various states that a synchronization
60
+ * process can be in.
61
+ */
62
+ export type SyncState =
63
+ | SyncStateInitial
64
+ | SyncStateIsSyncing
65
+ | SyncStateIsSynced
66
+ | SyncStateIsNotSynced;
67
+
68
+ /** On app start, we need to find out whether the state is synced. */
69
+ export interface SyncStateInitial {
70
+ readonly _tag: "SyncStateInitial";
71
+ }
72
+
73
+ // To preserve identity.
74
+ export const initialSyncState: SyncStateInitial = { _tag: "SyncStateInitial" };
75
+
76
+ export interface SyncStateIsSyncing {
77
+ readonly _tag: "SyncStateIsSyncing";
78
+ }
79
+
80
+ export interface SyncStateIsSynced {
81
+ readonly _tag: "SyncStateIsSynced";
82
+ readonly time: Millis;
83
+ }
84
+
85
+ export interface SyncStateIsNotSynced {
86
+ readonly _tag: "SyncStateIsNotSynced";
87
+ readonly error: NetworkError | ServerError | PaymentRequiredError;
88
+ }
89
+
90
+ export interface NetworkError {
91
+ readonly _tag: "NetworkError";
92
+ }
93
+
94
+ export interface ServerError {
95
+ readonly _tag: "ServerError";
96
+ readonly status: number;
97
+ }
98
+
99
+ export interface PaymentRequiredError {
100
+ readonly _tag: "PaymentRequiredError";
101
+ }
102
+
103
+ export class SyncFactory extends Context.Tag("SyncFactory")<
104
+ SyncFactory,
105
+ {
106
+ readonly createSync: Effect.Effect<Sync, never, never>;
107
+ }
108
+ >() {}
109
+
110
+ export const createSync = Effect.gen(function* () {
111
+ const initContext = Context.empty().pipe(
112
+ Context.add(SecretBox, yield* SecretBox),
113
+ );
114
+
115
+ const afterInitContext =
116
+ yield* Deferred.make<Context.Context<SecretBox | Owner>>();
117
+
118
+ return Sync.of({
119
+ init: (owner) =>
120
+ Effect.logDebug(["Sync init", { owner }]).pipe(
121
+ Effect.tap(
122
+ Deferred.succeed(
123
+ afterInitContext,
124
+ initContext.pipe(Context.add(Owner, owner)),
125
+ ),
126
+ ),
127
+ ),
128
+ sync: ({ merkleTree, timestamp, messages }) =>
129
+ Effect.gen(function* () {
130
+ yield* Effect.logDebug([
131
+ "Sync request",
132
+ { merkleTree, timestamp, messages },
133
+ ]);
134
+ const secretBox = yield* SecretBox;
135
+ const owner = yield* Owner;
136
+ const config = yield* Config;
137
+
138
+ return yield* Effect.forEach(
139
+ messages || [],
140
+ ({ timestamp, ...newMessage }) =>
141
+ Effect.map(
142
+ secretBox.seal(
143
+ owner.encryptionKey,
144
+ newMessageToBinary(newMessage),
145
+ ),
146
+ (content): Protobuf.EncryptedMessage => ({ timestamp, content }),
147
+ ),
148
+ ).pipe(
149
+ Effect.map((encrypedMessages) =>
150
+ Protobuf.SyncRequest.toBinary(
151
+ {
152
+ messages: encrypedMessages,
153
+ userId: owner.id,
154
+ nodeId: timestamp.node,
155
+ merkleTree: merkleTreeToString(merkleTree),
156
+ },
157
+ binaryWriteOptions,
158
+ ),
159
+ ),
160
+ Effect.flatMap((body) =>
161
+ Http.request
162
+ .post(config.syncUrl)
163
+ .pipe(
164
+ Http.request.uint8ArrayBody(body, "application/x-protobuf"),
165
+ Http.client.fetchOk,
166
+ Http.response.arrayBuffer,
167
+ ),
168
+ ),
169
+ Effect.map((buffer) =>
170
+ Protobuf.SyncResponse.fromBinary(
171
+ new Uint8Array(buffer),
172
+ binaryReadOptions,
173
+ ),
174
+ ),
175
+ Effect.flatMap((syncResponse) =>
176
+ Effect.forEach(syncResponse.messages, (encrypedMessage) =>
177
+ Effect.map(
178
+ secretBox.open(owner.encryptionKey, encrypedMessage.content),
179
+ (binary) => [binary, encrypedMessage.timestamp] as const,
180
+ ),
181
+ ).pipe(
182
+ Effect.map(
183
+ Arr.filterMap(([binary, timestamp]) =>
184
+ Option.map(
185
+ newMessageFromBinary(binary),
186
+ (newMessage): Message => ({ ...newMessage, timestamp }),
187
+ ),
188
+ ),
189
+ ),
190
+ Effect.map((messages) => ({
191
+ messages,
192
+ merkleTree: unsafeMerkleTreeFromString(syncResponse.merkleTree),
193
+ })),
194
+ Effect.tap((response) =>
195
+ Effect.logDebug(["Sync response", response]),
196
+ ),
197
+ ),
198
+ ),
199
+ Effect.catchTag("RequestError", () =>
200
+ Effect.fail<SyncStateIsNotSynced>({
201
+ _tag: "SyncStateIsNotSynced",
202
+ error: { _tag: "NetworkError" },
203
+ }),
204
+ ),
205
+ Effect.catchTag("ResponseError", ({ response: { status } }) => {
206
+ switch (status) {
207
+ case 402:
208
+ return Effect.fail<SyncStateIsNotSynced>({
209
+ _tag: "SyncStateIsNotSynced",
210
+ error: { _tag: "PaymentRequiredError" },
211
+ });
212
+ default:
213
+ return Effect.fail<SyncStateIsNotSynced>({
214
+ _tag: "SyncStateIsNotSynced",
215
+ error: { _tag: "ServerError", status },
216
+ });
217
+ }
218
+ }),
219
+ );
220
+ }).pipe((effect) =>
221
+ Effect.flatMap(Deferred.await(afterInitContext), (context) =>
222
+ Effect.provide(effect, context),
223
+ ),
224
+ ),
225
+ });
226
+ });
227
+
228
+ const newMessageToBinary = ({ value, ...rest }: NewMessage): Uint8Array =>
229
+ concatBytes(
230
+ version1,
231
+ Protobuf.MessageContent.toBinary(
232
+ { value: valueToProtobuf(value), ...rest },
233
+ binaryWriteOptions,
234
+ ),
235
+ );
236
+
237
+ const version1 = new Uint8Array([0, 1]);
238
+
239
+ const valueToProtobuf = (value: Value): Protobuf.MessageContent["value"] => {
240
+ switch (typeof value) {
241
+ case "string":
242
+ return { oneofKind: "stringValue", stringValue: value };
243
+ case "number":
244
+ return {
245
+ oneofKind: "numberValue",
246
+ numberValue: S.encodeSync(S.NumberFromString)(value),
247
+ };
248
+ }
249
+ if (value == null) return { oneofKind: undefined };
250
+ if (Predicate.isUint8Array(value))
251
+ return { oneofKind: "bytesValue", bytesValue: value };
252
+ return { oneofKind: "jsonValue", jsonValue: JSON.stringify(value) };
253
+ };
254
+
255
+ // The 'protobuf-ts' uses TextEncoder, but polyfill fast-text-encoding
256
+ // doesn't support the fatal option.
257
+ // https://github.com/timostamm/protobuf-ts/issues/184#issuecomment-1658443836
258
+ const binaryWriteOptions = {
259
+ writerFactory: (): BinaryWriter =>
260
+ new BinaryWriter({
261
+ encode: (input: string): Uint8Array => new TextEncoder().encode(input),
262
+ }),
263
+ };
264
+
265
+ const binaryReadOptions = {
266
+ readerFactory: (bytes: Uint8Array): BinaryReader =>
267
+ new BinaryReader(bytes, {
268
+ decode: (input: Uint8Array): string => new TextDecoder().decode(input),
269
+ }),
270
+ };
271
+
272
+ const newMessageFromBinary = (
273
+ binary: Uint8Array,
274
+ ): Option.Option<NewMessage> => {
275
+ if (!startsWithArray(binary, version1)) return Option.none();
276
+ const { value, ...content } = Protobuf.MessageContent.fromBinary(
277
+ binary.slice(version1.length),
278
+ binaryReadOptions,
279
+ );
280
+ return Option.some({ value: valueFromProtobuf(value), ...content });
281
+ };
282
+
283
+ const startsWithArray = (array: Uint8Array, prefix: Uint8Array): boolean => {
284
+ if (prefix.length > array.length) return false;
285
+ for (let i = 0; i < prefix.length; i++) {
286
+ if (array[i] !== prefix[i]) return false;
287
+ }
288
+ return true;
289
+ };
290
+
291
+ const valueFromProtobuf = (value: Protobuf.MessageContent["value"]): Value => {
292
+ switch (value.oneofKind) {
293
+ case "numberValue":
294
+ return S.decodeSync(S.NumberFromString)(value.numberValue);
295
+ case "stringValue":
296
+ return value.stringValue;
297
+ case "bytesValue":
298
+ return value.bytesValue;
299
+ case "jsonValue":
300
+ return JSON.parse(value.jsonValue) as JsonObjectOrArray;
301
+ case undefined:
302
+ return null;
303
+ default:
304
+ return absurd(value);
305
+ }
306
+ };
package/src/index.ts CHANGED
@@ -2,17 +2,14 @@ export * from "./Config.js";
2
2
  export * from "./Crdt.js";
3
3
  export * from "./Crypto.js";
4
4
  export * from "./Db.js";
5
- export * from "./DbWorker.js";
6
5
  export * from "./Diff.js";
7
- export * from "./ErrorStore.js";
6
+ export * from "./Error.js";
8
7
  export * from "./Evolu.js";
9
8
  export * from "./Model.js";
10
9
  export * from "./Murmurhash.js";
11
- export * from "./OnCompletes.js";
12
10
  export * from "./Owner.js";
13
11
  export * from "./Platform.js";
14
12
  export * from "./Protobuf.js";
15
- export * from "./Public.js";
16
13
  export * from "./Sqlite.js";
17
14
  export * from "./Store.js";
18
- export * from "./SyncWorker.js";
15
+ export * from "./Sync.js";
@@ -1,82 +0,0 @@
1
- import * as Context from "effect/Context";
2
- import * as Effect from "effect/Effect";
3
- import * as Layer from "effect/Layer";
4
- import * as ReadonlyArray from "effect/ReadonlyArray";
5
- import * as ReadonlyRecord from "effect/ReadonlyRecord";
6
- import { Config } from "./Config.js";
7
- import { Millis } from "./Crdt.js";
8
- import { Bip39, Mnemonic, NanoIdGenerator } from "./Crypto.js";
9
- import { Queries, Query } from "./Db.js";
10
- import { QueryPatches } from "./Diff.js";
11
- import { EvoluError } from "./ErrorStore.js";
12
- import { Id } from "./Model.js";
13
- import { OnCompleteId } from "./OnCompletes.js";
14
- import { Owner } from "./Owner.js";
15
- import { DbWorkerLock } from "./Platform.js";
16
- import { Sqlite, SqliteSchema, Value } from "./Sqlite.js";
17
- import { NewMessage, SyncState, SyncWorker, SyncWorkerOutputSyncResponse } from "./SyncWorker.js";
18
- import { Messaging } from "./Types.js";
19
- export interface DbWorker extends Messaging<DbWorkerInput, DbWorkerOutput> {
20
- }
21
- export declare const DbWorker: Context.Tag<DbWorker, DbWorker>;
22
- export type DbWorkerInput = DbWorkerInputInit | DbWorkerInputQuery | DbWorkerInputMutate | DbWorkerInputSync | DbWorkerInputReset | DbWorkerInputEnsureSchema | SyncWorkerOutputSyncResponse;
23
- interface DbWorkerInputInit {
24
- readonly _tag: "init";
25
- readonly config: Config;
26
- }
27
- interface DbWorkerInputQuery {
28
- readonly _tag: "query";
29
- readonly queries: ReadonlyArray.NonEmptyReadonlyArray<Query>;
30
- }
31
- interface DbWorkerInputMutate {
32
- readonly _tag: "mutate";
33
- readonly mutations: ReadonlyArray.NonEmptyReadonlyArray<Mutation>;
34
- readonly queries: Queries;
35
- }
36
- interface DbWorkerInputSync {
37
- readonly _tag: "sync";
38
- readonly queries: Queries;
39
- }
40
- interface DbWorkerInputReset {
41
- readonly _tag: "reset";
42
- readonly mnemonic?: Mnemonic;
43
- }
44
- interface DbWorkerInputEnsureSchema extends SqliteSchema {
45
- readonly _tag: "ensureSchema";
46
- }
47
- export type DbWorkerOutput = DbWorkerOutputOnError | DbWorkerOutputOnOwner | DbWorkerOutputOnQuery | DbWorkerOutputOnReceive | DbWorkerOutputOnResetOrRestore | DbWorkerOutputOnSyncState;
48
- export interface DbWorkerOutputOnError {
49
- readonly _tag: "onError";
50
- readonly error: EvoluError;
51
- }
52
- export interface DbWorkerOutputOnOwner {
53
- readonly _tag: "onOwner";
54
- readonly owner: Owner;
55
- }
56
- export interface DbWorkerOutputOnQuery {
57
- readonly _tag: "onQuery";
58
- readonly queriesPatches: ReadonlyArray<QueryPatches>;
59
- readonly onCompleteIds: ReadonlyArray<OnCompleteId>;
60
- }
61
- interface DbWorkerOutputOnReceive {
62
- readonly _tag: "onReceive";
63
- }
64
- interface DbWorkerOutputOnResetOrRestore {
65
- readonly _tag: "onResetOrRestore";
66
- }
67
- interface DbWorkerOutputOnSyncState {
68
- readonly _tag: "onSyncState";
69
- readonly state: SyncState;
70
- }
71
- export interface Mutation {
72
- readonly table: string;
73
- readonly id: Id;
74
- readonly values: ReadonlyRecord.ReadonlyRecord<string, Value | Date | boolean | undefined>;
75
- readonly isInsert: boolean;
76
- readonly onCompleteId: OnCompleteId | null;
77
- }
78
- export declare const mutationsToNewMessages: (mutations: ReadonlyArray<Mutation>) => ReadonlyArray<NewMessage>;
79
- export declare const upsertValueIntoTableRowColumn: (message: NewMessage, messages: ReadonlyArray<NewMessage>, millis: Millis) => Effect.Effect<void, never, Sqlite>;
80
- export declare const DbWorkerCommonLive: Layer.Layer<DbWorker, never, Bip39 | NanoIdGenerator | Sqlite | DbWorkerLock | SyncWorker>;
81
- export {};
82
- //# sourceMappingURL=DbWorker.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DbWorker.d.ts","sourceRoot":"","sources":["../../src/DbWorker.ts"],"names":[],"mappings":"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"}