@evolu/common 1.0.17 → 2.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 (75) hide show
  1. package/README.md +7 -7
  2. package/dist/src/Config.d.ts +4 -6
  3. package/dist/src/Config.d.ts.map +1 -1
  4. package/dist/src/Config.js +1 -1
  5. package/dist/src/Crdt.d.ts +15 -9
  6. package/dist/src/Crdt.d.ts.map +1 -1
  7. package/dist/src/Crdt.js +15 -14
  8. package/dist/src/Crypto.d.ts +7 -13
  9. package/dist/src/Crypto.d.ts.map +1 -1
  10. package/dist/src/Crypto.js +7 -9
  11. package/dist/src/Db.d.ts +36 -70
  12. package/dist/src/Db.d.ts.map +1 -1
  13. package/dist/src/Db.js +45 -51
  14. package/dist/src/DbWorker.d.ts +13 -14
  15. package/dist/src/DbWorker.d.ts.map +1 -1
  16. package/dist/src/DbWorker.js +56 -57
  17. package/dist/src/Diff.d.ts +3 -1
  18. package/dist/src/Diff.d.ts.map +1 -1
  19. package/dist/src/Diff.js +3 -7
  20. package/dist/src/{Errors.d.ts → ErrorStore.d.ts} +14 -7
  21. package/dist/src/ErrorStore.d.ts.map +1 -0
  22. package/dist/src/{Errors.js → ErrorStore.js} +2 -0
  23. package/dist/src/Evolu.d.ts +316 -58
  24. package/dist/src/Evolu.d.ts.map +1 -1
  25. package/dist/src/Evolu.js +199 -185
  26. package/dist/src/Model.d.ts +47 -57
  27. package/dist/src/Model.d.ts.map +1 -1
  28. package/dist/src/Model.js +30 -35
  29. package/dist/src/OnCompletes.d.ts +11 -0
  30. package/dist/src/OnCompletes.d.ts.map +1 -0
  31. package/dist/src/OnCompletes.js +21 -0
  32. package/dist/src/Owner.d.ts +31 -0
  33. package/dist/src/Owner.d.ts.map +1 -0
  34. package/dist/src/Owner.js +20 -0
  35. package/dist/src/Platform.d.ts +15 -8
  36. package/dist/src/Platform.d.ts.map +1 -1
  37. package/dist/src/Platform.js +5 -5
  38. package/dist/src/Protobuf.d.ts +25 -73
  39. package/dist/src/Protobuf.d.ts.map +1 -1
  40. package/dist/src/Protobuf.js +4 -12
  41. package/dist/src/Public.d.ts +5 -3
  42. package/dist/src/Public.d.ts.map +1 -1
  43. package/dist/src/Public.js +1 -0
  44. package/dist/src/Sqlite.d.ts +8 -11
  45. package/dist/src/Sqlite.d.ts.map +1 -1
  46. package/dist/src/Sqlite.js +7 -7
  47. package/dist/src/Store.d.ts +6 -5
  48. package/dist/src/Store.d.ts.map +1 -1
  49. package/dist/src/Store.js +21 -16
  50. package/dist/src/SyncWorker.d.ts +8 -2
  51. package/dist/src/SyncWorker.d.ts.map +1 -1
  52. package/dist/src/SyncWorker.js +12 -19
  53. package/dist/src/index.d.ts +6 -2
  54. package/dist/src/index.d.ts.map +1 -1
  55. package/dist/src/index.js +6 -2
  56. package/package.json +23 -13
  57. package/src/Config.ts +7 -7
  58. package/src/Crdt.ts +29 -26
  59. package/src/Crypto.ts +14 -19
  60. package/src/Db.ts +113 -166
  61. package/src/DbWorker.ts +110 -140
  62. package/src/Diff.ts +5 -7
  63. package/src/{Errors.ts → ErrorStore.ts} +17 -8
  64. package/src/Evolu.ts +682 -442
  65. package/src/Model.ts +60 -85
  66. package/src/OnCompletes.ts +46 -0
  67. package/src/Owner.ts +65 -0
  68. package/src/Platform.ts +24 -16
  69. package/src/Protobuf.ts +25 -73
  70. package/src/Public.ts +5 -3
  71. package/src/Sqlite.ts +13 -24
  72. package/src/Store.ts +36 -24
  73. package/src/SyncWorker.ts +30 -38
  74. package/src/index.ts +6 -2
  75. package/dist/src/Errors.d.ts.map +0 -1
@@ -1,11 +1,13 @@
1
- import { Brand, Context, Effect, Layer, ReadonlyArray, ReadonlyRecord } from "effect";
1
+ import { Context, Effect, Layer, ReadonlyArray, ReadonlyRecord } from "effect";
2
2
  import { Config } from "./Config.js";
3
3
  import { Bip39, Mnemonic, NanoId } from "./Crypto.js";
4
- import { Owner, Tables } from "./Db.js";
4
+ import { Queries, Query, Tables } from "./Db.js";
5
5
  import { QueryPatches } from "./Diff.js";
6
- import { EvoluError } from "./Errors.js";
6
+ import { EvoluError } from "./ErrorStore.js";
7
7
  import { Id, SqliteDate } from "./Model.js";
8
- import { Query, Row, Sqlite, Value } from "./Sqlite.js";
8
+ import { OnCompleteId } from "./OnCompletes.js";
9
+ import { Owner } from "./Owner.js";
10
+ import { Sqlite, Value } from "./Sqlite.js";
9
11
  import { NewMessage, SyncState, SyncWorker, SyncWorkerOutputSyncResponse } from "./SyncWorker.js";
10
12
  export interface DbWorker {
11
13
  readonly postMessage: (input: DbWorkerInput) => void;
@@ -16,7 +18,6 @@ export type DbWorkerInput = DbWorkerInputInit | DbWorkerInputQuery | DbWorkerInp
16
18
  interface DbWorkerInputInit {
17
19
  readonly _tag: "init";
18
20
  readonly config: Config;
19
- readonly tables: Tables;
20
21
  }
21
22
  interface DbWorkerInputQuery {
22
23
  readonly _tag: "query";
@@ -24,12 +25,12 @@ interface DbWorkerInputQuery {
24
25
  }
25
26
  interface DbWorkerInputMutate {
26
27
  readonly _tag: "mutate";
27
- readonly items: ReadonlyArray.NonEmptyReadonlyArray<MutateItem>;
28
- readonly queries: ReadonlyArray<Query>;
28
+ readonly mutations: ReadonlyArray.NonEmptyReadonlyArray<Mutation>;
29
+ readonly queries: Queries;
29
30
  }
30
31
  interface DbWorkerInputSync {
31
32
  readonly _tag: "sync";
32
- readonly queries: ReadonlyArray<Query>;
33
+ readonly queries: Queries;
33
34
  }
34
35
  interface DbWorkerInputReset {
35
36
  readonly _tag: "reset";
@@ -40,11 +41,11 @@ interface DbWorkerInputEnsureSchema {
40
41
  readonly tables: Tables;
41
42
  }
42
43
  export type DbWorkerOutput = DbWorkerOutputOnError | DbWorkerOutputOnOwner | DbWorkerOutputOnQuery | DbWorkerOutputOnReceive | DbWorkerOutputOnResetOrRestore | DbWorkerOutputOnSyncState;
43
- interface DbWorkerOutputOnError {
44
+ export interface DbWorkerOutputOnError {
44
45
  readonly _tag: "onError";
45
46
  readonly error: EvoluError;
46
47
  }
47
- interface DbWorkerOutputOnOwner {
48
+ export interface DbWorkerOutputOnOwner {
48
49
  readonly _tag: "onOwner";
49
50
  readonly owner: Owner;
50
51
  }
@@ -53,7 +54,6 @@ export interface DbWorkerOutputOnQuery {
53
54
  readonly queriesPatches: ReadonlyArray<QueryPatches>;
54
55
  readonly onCompleteIds: ReadonlyArray<OnCompleteId>;
55
56
  }
56
- export type OnCompleteId = string & Brand.Brand<"Id"> & Brand.Brand<"OnComplete">;
57
57
  interface DbWorkerOutputOnReceive {
58
58
  readonly _tag: "onReceive";
59
59
  }
@@ -64,7 +64,7 @@ interface DbWorkerOutputOnSyncState {
64
64
  readonly _tag: "onSyncState";
65
65
  readonly state: SyncState;
66
66
  }
67
- export interface MutateItem {
67
+ export interface Mutation {
68
68
  readonly table: string;
69
69
  readonly id: Id;
70
70
  readonly values: ReadonlyRecord.ReadonlyRecord<Value | Date | boolean | undefined>;
@@ -72,8 +72,7 @@ export interface MutateItem {
72
72
  readonly now: SqliteDate;
73
73
  readonly onCompleteId: OnCompleteId | null;
74
74
  }
75
- export type RowsCacheMap = ReadonlyMap<Query, ReadonlyArray<Row>>;
76
- export declare const mutateItemsToNewMessages: (items: ReadonlyArray<MutateItem>) => ReadonlyArray<NewMessage>;
75
+ export declare const mutationsToNewMessages: (mutations: ReadonlyArray<Mutation>) => ReadonlyArray<NewMessage>;
77
76
  export declare const upsertValueIntoTableRowColumn: (message: NewMessage, messages: ReadonlyArray<NewMessage>) => Effect.Effect<Sqlite, never, void>;
78
77
  export declare const DbWorkerLive: Layer.Layer<Bip39 | NanoId | Sqlite | SyncWorker, never, DbWorker>;
79
78
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"DbWorker.d.ts","sourceRoot":"","sources":["../../src/DbWorker.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"DbWorker.d.ts","sourceRoot":"","sources":["../../src/DbWorker.ts"],"names":[],"mappings":"AACA,OAAO,EACL,OAAO,EACP,MAAM,EAEN,KAAK,EAGL,aAAa,EACb,cAAc,EAEf,MAAM,QAAQ,CAAC;AAChB,OAAO,EAAE,MAAM,EAAc,MAAM,aAAa,CAAC;AAoBjD,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EACL,OAAO,EACP,KAAK,EAIL,MAAM,EAMP,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,YAAY,EAAe,MAAM,WAAW,CAAC;AACtD,OAAO,EAAE,UAAU,EAAuB,MAAM,iBAAiB,CAAC;AAClE,OAAO,EAAE,EAAE,EAAE,UAAU,EAAQ,MAAM,YAAY,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,KAAK,EAAW,MAAM,YAAY,CAAC;AAE5C,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAEL,UAAU,EAEV,SAAS,EACT,UAAU,EACV,4BAA4B,EAE7B,MAAM,iBAAiB,CAAC;AAEzB,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IACrD,SAAS,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,CAAC;CAC7C;AAED,eAAO,MAAM,QAAQ,iCAA0B,CAAC;AAEhD,MAAM,MAAM,aAAa,GACrB,iBAAiB,GACjB,kBAAkB,GAClB,mBAAmB,GACnB,iBAAiB,GACjB,kBAAkB,GAClB,yBAAyB,GACzB,4BAA4B,CAAC;AAEjC,UAAU,iBAAiB;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,UAAU,kBAAkB;IAC1B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;CAC9D;AAED,UAAU,mBAAmB;IAC3B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IAClE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED,UAAU,iBAAiB;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED,UAAU,kBAAkB;IAC1B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC;CAC9B;AAED,UAAU,yBAAyB;IACjC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAMD,MAAM,MAAM,cAAc,GACtB,qBAAqB,GACrB,qBAAqB,GACrB,qBAAqB,GACrB,uBAAuB,GACvB,8BAA8B,GAC9B,yBAAyB,CAAC;AAE9B,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;CAC5B;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;CACvB;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,cAAc,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACrD,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;CACrD;AAED,UAAU,uBAAuB;IAC/B,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;CAC5B;AAED,UAAU,8BAA8B;IACtC,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;CACnC;AAED,UAAU,yBAAyB;IACjC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;CAC3B;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC;IAChB,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC,cAAc,CAC5C,KAAK,GAAG,IAAI,GAAG,OAAO,GAAG,SAAS,CACnC,CAAC;IACF,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC;IACzB,QAAQ,CAAC,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;CAC5C;AAwED,eAAO,MAAM,sBAAsB,cACtB,cAAc,QAAQ,CAAC,KACjC,cAAc,UAAU,CAqCxB,CAAC;AAyBJ,eAAO,MAAM,6BAA6B,YAC/B,UAAU,YACT,cAAc,UAAU,CAAC,KAClC,aAAa,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,CAiBhC,CAAC;AAyQL,eAAO,MAAM,YAAY,oEAkHxB,CAAC"}
@@ -1,36 +1,36 @@
1
1
  import { hexToBytes } from "@noble/ciphers/utils";
2
- import { Context, Effect, Function, Layer, Option, ReadonlyArray, Ref, pipe, } from "effect";
2
+ import { Context, Effect, Function, Layer, Match, Option, ReadonlyArray, pipe, } from "effect";
3
3
  import { Config, ConfigLive } from "./Config.js";
4
4
  import { Time, TimeLive, diffMerkleTrees, insertIntoMerkleTree, makeSyncTimestamp, merkleTreeToString, receiveTimestamp, sendTimestamp, timestampToString, unsafeTimestampFromString, } from "./Crdt.js";
5
5
  import { Bip39, NanoId } from "./Crypto.js";
6
- import { Owner, ensureSchema, lazyInit, someDefectToNoSuchTableOrColumnError, transaction, } from "./Db.js";
6
+ import { RowsStore, RowsStoreLive, deserializeQuery, ensureSchema, lazyInit, someDefectToNoSuchTableOrColumnError, transaction, } from "./Db.js";
7
7
  import { makePatches } from "./Diff.js";
8
- import { makeUnexpectedError } from "./Errors.js";
8
+ import { makeUnexpectedError } from "./ErrorStore.js";
9
9
  import { cast } from "./Model.js";
10
+ import { Owner } from "./Owner.js";
10
11
  import * as Sql from "./Sql.js";
11
- import { Sqlite, queryObjectFromQuery } from "./Sqlite.js";
12
+ import { Sqlite } from "./Sqlite.js";
12
13
  import { NewMessageEquivalence, SyncWorker, SyncWorkerPostMessage, } from "./SyncWorker.js";
13
- export const DbWorker = Context.Tag("evolu/DbWorker");
14
- const DbWorkerOnMessage = Context.Tag("evolu/DbWorkerOnMessage");
15
- const init = (input) => Effect.gen(function* (_) {
14
+ export const DbWorker = Context.Tag();
15
+ const DbWorkerOnMessage = Context.Tag();
16
+ const init = Effect.gen(function* (_) {
16
17
  const sqlite = yield* _(Sqlite);
17
18
  return yield* _(sqlite.exec(Sql.selectOwner), Effect.map(({ rows: [row] }) => ({
18
19
  id: row.id,
19
20
  mnemonic: row.mnemonic,
20
21
  // expo-sqlite 11.3.2 doesn't support Uint8Array
21
22
  encryptionKey: hexToBytes(row.encryptionKey),
22
- })), someDefectToNoSuchTableOrColumnError, Effect.catchTag("NoSuchTableOrColumnError", () => lazyInit()), Effect.tap(() => ensureSchema(input.tables)));
23
+ })), someDefectToNoSuchTableOrColumnError, Effect.catchTag("NoSuchTableOrColumnError", () => lazyInit()));
23
24
  });
24
- const RowsCacheRef = Context.Tag("evolu/RowsCacheRef");
25
25
  const query = ({ queries, onCompleteIds = [], }) => Effect.gen(function* (_) {
26
26
  const sqlite = yield* _(Sqlite);
27
- const rowsCache = yield* _(RowsCacheRef);
27
+ const rowsStore = yield* _(RowsStore);
28
28
  const dbWorkerOnMessage = yield* _(DbWorkerOnMessage);
29
- const queriesRows = yield* _(Effect.forEach(queries, (query) => sqlite
30
- .exec(queryObjectFromQuery(query))
29
+ const queriesRows = yield* _(ReadonlyArray.dedupe(queries), Effect.forEach((query) => sqlite
30
+ .exec(deserializeQuery(query))
31
31
  .pipe(Effect.map((result) => [query, result.rows]))));
32
- const previous = yield* _(Ref.get(rowsCache));
33
- yield* _(Ref.set(rowsCache, new Map([...previous, ...queriesRows])));
32
+ const previous = rowsStore.getState();
33
+ yield* _(rowsStore.setState(new Map([...previous, ...queriesRows])));
34
34
  const queriesPatches = queriesRows.map(([query, rows]) => ({
35
35
  query,
36
36
  patches: makePatches(previous.get(query), rows),
@@ -41,7 +41,7 @@ const readTimestampAndMerkleTree = Sqlite.pipe(Effect.flatMap((sqlite) => sqlite
41
41
  timestamp: unsafeTimestampFromString(timestamp),
42
42
  merkleTree: merkleTree,
43
43
  })));
44
- export const mutateItemsToNewMessages = (items) => pipe(items, ReadonlyArray.map(({ id, isInsert, now, table, values }) => pipe(Object.entries(values), ReadonlyArray.filterMap(([key, value]) =>
44
+ export const mutationsToNewMessages = (mutations) => pipe(mutations, ReadonlyArray.map(({ id, isInsert, now, table, values }) => pipe(Object.entries(values), ReadonlyArray.filterMap(([key, value]) =>
45
45
  // The value can be undefined if exactOptionalPropertyTypes isn't true.
46
46
  // Don't insert nulls because null is the default value.
47
47
  value === undefined || (isInsert && value == null)
@@ -125,15 +125,15 @@ const writeTimestampAndMerkleTree = ({ timestamp, merkleTree, }) => Effect.flatM
125
125
  merkleTreeToString(merkleTree),
126
126
  ],
127
127
  }));
128
- const mutate = ({ items, queries, }) => Effect.gen(function* (_) {
129
- const [toSync, localOnlyItems] = ReadonlyArray.partition(items, (item) => item.table.startsWith("_"));
130
- const [toUpsert, toDelete] = ReadonlyArray.partition(localOnlyItems, (item) => mutateItemsToNewMessages([item]).some((message) => message.column === "isDeleted" && message.value === 1)).map(mutateItemsToNewMessages);
128
+ const mutate = ({ mutations, queries, }) => Effect.gen(function* (_) {
129
+ const [toSync, localOnly] = ReadonlyArray.partition(mutations, (item) => item.table.startsWith("_"));
130
+ const [toUpsert, toDelete] = ReadonlyArray.partition(localOnly, (item) => mutationsToNewMessages([item]).some((message) => message.column === "isDeleted" && message.value === 1)).map(mutationsToNewMessages);
131
131
  yield* _(Effect.forEach(toUpsert, (message) => upsertValueIntoTableRowColumn(message, toUpsert)));
132
132
  const { exec } = yield* _(Sqlite);
133
133
  yield* _(Effect.forEach(toDelete, ({ table, row }) => exec({ sql: Sql.deleteTableRow(table), parameters: [row] })));
134
134
  if (toSync.length > 0) {
135
135
  let { timestamp, merkleTree } = yield* _(readTimestampAndMerkleTree);
136
- const messages = yield* _(mutateItemsToNewMessages(toSync), Effect.forEach((message) => Effect.map(sendTimestamp(timestamp), (nextTimestamp) => {
136
+ const messages = yield* _(mutationsToNewMessages(toSync), Effect.forEach((message) => Effect.map(sendTimestamp(timestamp), (nextTimestamp) => {
137
137
  timestamp = nextTimestamp;
138
138
  return { ...message, timestamp: timestampToString(timestamp) };
139
139
  })));
@@ -149,20 +149,20 @@ const mutate = ({ items, queries, }) => Effect.gen(function* (_) {
149
149
  syncLoopCount: 0,
150
150
  });
151
151
  }
152
- const onCompleteIds = ReadonlyArray.filterMap(items, (item) => Option.fromNullable(item.onCompleteId));
152
+ const onCompleteIds = ReadonlyArray.filterMap(mutations, (item) => Option.fromNullable(item.onCompleteId));
153
153
  if (queries.length > 0 || onCompleteIds.length > 0)
154
154
  yield* _(query({ queries, onCompleteIds }));
155
155
  });
156
156
  const handleSyncResponse = ({ messages, ...response }) => Effect.gen(function* (_) {
157
157
  let { timestamp, merkleTree } = yield* _(readTimestampAndMerkleTree);
158
+ const dbWorkerOnMessage = yield* _(DbWorkerOnMessage);
158
159
  if (messages.length > 0) {
159
160
  for (const message of messages)
160
161
  timestamp = yield* _(unsafeTimestampFromString(message.timestamp), (remote) => receiveTimestamp({ local: timestamp, remote }));
161
162
  merkleTree = yield* _(applyMessages({ merkleTree, messages }));
162
163
  yield* _(writeTimestampAndMerkleTree({ timestamp, merkleTree }));
164
+ dbWorkerOnMessage({ _tag: "onReceive" });
163
165
  }
164
- const dbWorkerOnMessage = yield* _(DbWorkerOnMessage);
165
- dbWorkerOnMessage({ _tag: "onReceive" });
166
166
  const diff = diffMerkleTrees(response.merkleTree, merkleTree);
167
167
  const syncWorkerPostMessage = yield* _(SyncWorkerPostMessage);
168
168
  if (Option.isNone(diff)) {
@@ -176,11 +176,19 @@ const handleSyncResponse = ({ messages, ...response }) => Effect.gen(function* (
176
176
  });
177
177
  return;
178
178
  }
179
- const [sqlite, config, owner] = yield* _(Effect.all([Sqlite, Config, Owner]));
179
+ const sqlite = yield* _(Sqlite);
180
+ const config = yield* _(Config);
181
+ const owner = yield* _(Owner);
180
182
  const messagesToSync = yield* _(sqlite.exec({
181
183
  sql: Sql.selectMessagesToSync,
182
184
  parameters: [timestampToString(makeSyncTimestamp(diff.value))],
183
185
  }), Effect.map(({ rows }) => rows));
186
+ if (response.syncLoopCount > 100) {
187
+ // TODO: dbWorkerOnMessage({ _tag: "onError" });
188
+ // eslint-disable-next-line no-console
189
+ console.error("Evolu: syncLoopCount > 100");
190
+ return;
191
+ }
184
192
  syncWorkerPostMessage({
185
193
  _tag: "sync",
186
194
  syncUrl: config.syncUrl,
@@ -194,12 +202,10 @@ const handleSyncResponse = ({ messages, ...response }) => Effect.gen(function* (
194
202
  const sync = ({ queries, }) => Effect.gen(function* (_) {
195
203
  if (queries.length > 0)
196
204
  yield* _(query({ queries }));
197
- const [syncWorkerPostMessage, config, owner, timestampAndMerkleTree] = yield* _(Effect.all([
198
- SyncWorkerPostMessage,
199
- Config,
200
- Owner,
201
- readTimestampAndMerkleTree,
202
- ]));
205
+ const syncWorkerPostMessage = yield* _(SyncWorkerPostMessage);
206
+ const config = yield* _(Config);
207
+ const owner = yield* _(Owner);
208
+ const timestampAndMerkleTree = yield* _(readTimestampAndMerkleTree);
203
209
  syncWorkerPostMessage({
204
210
  ...timestampAndMerkleTree,
205
211
  _tag: "sync",
@@ -224,7 +230,6 @@ const reset = (input) => Effect.gen(function* (_) {
224
230
  });
225
231
  export const DbWorkerLive = Layer.effect(DbWorker, Effect.gen(function* (_) {
226
232
  const syncWorker = yield* _(SyncWorker);
227
- const rowsCacheRef = yield* _(Ref.make(new Map()));
228
233
  const onError = (error) => Effect.sync(() => {
229
234
  dbWorker.onMessage({ _tag: "onError", error });
230
235
  });
@@ -240,49 +245,43 @@ export const DbWorkerLive = Layer.effect(DbWorker, Effect.gen(function* (_) {
240
245
  dbWorker.onMessage({ _tag: "onSyncState", state: output });
241
246
  }
242
247
  };
243
- const context = Context.empty().pipe(Context.add(Sqlite, yield* _(Sqlite)), Context.add(Bip39, yield* _(Bip39)), Context.add(NanoId, yield* _(NanoId)));
244
- const run = (effect) => effect.pipe(Effect.catchAllDefect(makeUnexpectedError), transaction, Effect.catchAll(onError), Effect.provide(context), Effect.runPromise);
248
+ const runContext = Context.empty().pipe(Context.add(Sqlite, yield* _(Sqlite)), Context.add(Bip39, yield* _(Bip39)), Context.add(NanoId, yield* _(NanoId)), Context.add(DbWorkerOnMessage, (output) => {
249
+ dbWorker.onMessage(output);
250
+ }));
251
+ const run = (effect) => effect.pipe(Effect.catchAllDefect(makeUnexpectedError), transaction, Effect.catchAll(onError), Effect.provide(runContext), Effect.runPromise);
245
252
  // Write for reset only in case init fails.
246
253
  const writeForInitFail = (input) => {
247
254
  if (input._tag !== "reset")
248
255
  return Promise.resolve(undefined);
249
- return reset(input).pipe(Effect.provideService(DbWorkerOnMessage, dbWorker.onMessage), Effect.provide(context), run);
256
+ return reset(input).pipe(run);
250
257
  };
251
- const makeWriteForInitSuccess = (owner, config) => {
258
+ const makeWriteForInitSuccess = (config, owner) => {
252
259
  let skipAllBecauseOfReset = false;
253
- const layer = Layer.mergeAll(ConfigLive(config), Layer.succeed(DbWorkerOnMessage, dbWorker.onMessage), Layer.succeed(Owner, owner), Layer.succeed(SyncWorkerPostMessage, syncWorker.postMessage), Layer.succeed(RowsCacheRef, rowsCacheRef), TimeLive);
254
- const mapInputToEffect = (input) => {
255
- switch (input._tag) {
256
- case "init":
257
- return makeUnexpectedError(new Error("init must be called once"));
258
- case "query":
259
- return query(input);
260
- case "mutate":
261
- return mutate(input);
262
- case "sync":
263
- return sync(input);
264
- case "reset":
265
- skipAllBecauseOfReset = true;
266
- return reset(input);
267
- case "ensureSchema":
268
- return ensureSchema(input.tables);
269
- case "SyncWorkerOutputSyncResponse":
270
- return handleSyncResponse(input);
271
- }
272
- };
260
+ const layer = Layer.mergeAll(ConfigLive(config), Layer.succeed(Owner, owner), Layer.succeed(SyncWorkerPostMessage, syncWorker.postMessage), RowsStoreLive, TimeLive);
273
261
  return (input) => {
274
262
  if (skipAllBecauseOfReset)
275
263
  return Promise.resolve(undefined);
276
- return mapInputToEffect(input).pipe(Effect.provide(layer), run);
264
+ return Match.value(input).pipe(Match.tagsExhaustive({
265
+ init: () => makeUnexpectedError(new Error("init must be called once")),
266
+ query,
267
+ mutate,
268
+ sync,
269
+ reset: (input) => {
270
+ skipAllBecauseOfReset = true;
271
+ return reset(input);
272
+ },
273
+ ensureSchema: ({ tables }) => ensureSchema(tables),
274
+ SyncWorkerOutputSyncResponse: handleSyncResponse,
275
+ }), Effect.provide(layer), run);
277
276
  };
278
277
  };
279
278
  let write = (input) => {
280
279
  if (input._tag !== "init")
281
280
  return run(makeUnexpectedError(new Error("init must be called first")));
282
281
  write = writeForInitFail;
283
- return init(input).pipe(Effect.map((owner) => {
282
+ return init.pipe(Effect.map((owner) => {
284
283
  dbWorker.onMessage({ _tag: "onOwner", owner });
285
- write = makeWriteForInitSuccess(owner, input.config);
284
+ write = makeWriteForInitSuccess(input.config, owner);
286
285
  }), run);
287
286
  };
288
287
  let messageQueue = Promise.resolve(undefined);
@@ -1,4 +1,6 @@
1
- import { Query, Row, Value } from "./Sqlite.js";
1
+ import { ReadonlyArray } from "effect";
2
+ import { Query, Row } from "./Db.js";
3
+ import { Value } from "./Sqlite.js";
2
4
  export interface QueryPatches {
3
5
  readonly query: Query;
4
6
  readonly patches: ReadonlyArray<Patch>;
@@ -1 +1 @@
1
- {"version":3,"file":"Diff.d.ts","sourceRoot":"","sources":["../../src/Diff.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC;CACxC;AAED,MAAM,MAAM,KAAK,GAAG,eAAe,GAAG,cAAc,CAAC;AAErD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,EAAE,YAAY,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,EAAE,WAAW,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC;CACrB;AAED,eAAO,MAAM,YAAY,YACb,cAAc,KAAK,CAAC,eACpB,cAAc,GAAG,CAAC,KAAG,cAAc,GAAG,CAYnC,CAAC;AAQhB,eAAO,MAAM,WAAW,iBACR,cAAc,GAAG,CAAC,GAAG,SAAS,YAClC,cAAc,GAAG,CAAC,KAC3B,SAAS,KAAK,EA2BhB,CAAC;AAEF,eAAO,MAAM,QAAQ,MAChB,KAAK,GAAG,GAAG,GAAG,cAAc,GAAG,CAAC,KAChC,KAAK,GAAG,GAAG,GAAG,cAAc,GAAG,CAAC,KAClC,OAkCF,CAAC"}
1
+ {"version":3,"file":"Diff.d.ts","sourceRoot":"","sources":["../../src/Diff.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,aAAa,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEpC,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC;CACxC;AAED,MAAM,MAAM,KAAK,GAAG,eAAe,GAAG,cAAc,CAAC;AAErD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,EAAE,YAAY,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,EAAE,WAAW,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC;CACrB;AAED,eAAO,MAAM,YAAY,YACb,cAAc,KAAK,CAAC,eACpB,cAAc,GAAG,CAAC,KAAG,cAAc,GAAG,CASnC,CAAC;AAQhB,eAAO,MAAM,WAAW,iBACR,cAAc,GAAG,CAAC,GAAG,SAAS,YAClC,cAAc,GAAG,CAAC,KAC3B,SAAS,KAAK,EA2BhB,CAAC;AAEF,eAAO,MAAM,QAAQ,MAChB,KAAK,GAAG,GAAG,GAAG,cAAc,GAAG,CAAC,KAChC,KAAK,GAAG,GAAG,GAAG,cAAc,GAAG,CAAC,KAClC,OAkCF,CAAC"}
package/dist/src/Diff.js CHANGED
@@ -1,14 +1,10 @@
1
- import { Predicate } from "effect";
2
- export const applyPatches = (patches) => (current) => patches.reduce((a, patch) => {
1
+ import { Predicate, ReadonlyArray } from "effect";
2
+ export const applyPatches = (patches) => (current) => patches.reduce((next, patch) => {
3
3
  switch (patch.op) {
4
4
  case "replaceAll":
5
5
  return patch.value;
6
6
  case "replaceAt": {
7
- if (a === undefined)
8
- return a;
9
- const next = [...a];
10
- next[patch.index] = patch.value;
11
- return next;
7
+ return ReadonlyArray.replace(next, patch.index, patch.value);
12
8
  }
13
9
  }
14
10
  }, current);
@@ -1,19 +1,26 @@
1
1
  import { Effect } from "effect";
2
2
  import { TimestampError } from "./Crdt.js";
3
+ export declare const makeErrorStore: Effect.Effect<never, never, import("./Store.js").Store<EvoluError | null>>;
4
+ /** The EvoluError type is used to represent errors that can occur in Evolu. */
3
5
  export type EvoluError = UnexpectedError | TimestampError;
6
+ /**
7
+ * The UnexpectedError interface is designed to represent errors that can occur
8
+ * unexpectedly anywhere, even in third-party libraries, because Evolu uses
9
+ * Effect to track all errors.
10
+ */
11
+ export interface UnexpectedError {
12
+ readonly _tag: "UnexpectedError";
13
+ readonly error: TransferableError;
14
+ }
15
+ export declare const makeUnexpectedError: (error: unknown) => Effect.Effect<never, UnexpectedError, never>;
4
16
  /**
5
17
  * We can't use the whole error because of WebWorker postMessage DataCloneError
6
- * in Safari and Firefox.
18
+ * in Safari and Firefox. TODO:
7
19
  * https://discord.com/channels/795981131316985866/795983589644304396/1096736473396564079
8
20
  */
9
21
  interface TransferableError {
10
22
  readonly message: string;
11
23
  readonly stack: string | undefined;
12
24
  }
13
- export interface UnexpectedError {
14
- readonly _tag: "UnexpectedError";
15
- readonly error: TransferableError;
16
- }
17
- export declare const makeUnexpectedError: (error: unknown) => Effect.Effect<never, UnexpectedError, never>;
18
25
  export {};
19
- //# sourceMappingURL=Errors.d.ts.map
26
+ //# sourceMappingURL=ErrorStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ErrorStore.d.ts","sourceRoot":"","sources":["../../src/ErrorStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAG3C,eAAO,MAAM,cAAc,4EAAqC,CAAC;AAEjE,+EAA+E;AAC/E,MAAM,MAAM,UAAU,GAAG,eAAe,GAAG,cAAc,CAAC;AAE1D;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE,iBAAiB,CAAC;CACnC;AAED,eAAO,MAAM,mBAAmB,UACvB,OAAO,KACb,aAAa,CAAC,KAAK,EAAE,eAAe,EAAE,KAAK,CAU7C,CAAC;AAEF;;;;GAIG;AACH,UAAU,iBAAiB;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;CACpC"}
@@ -1,4 +1,6 @@
1
1
  import { Effect } from "effect";
2
+ import { makeStore } from "./Store.js";
3
+ export const makeErrorStore = makeStore(null);
2
4
  export const makeUnexpectedError = (error) => {
3
5
  const isError = error instanceof Error;
4
6
  return Effect.fail({