@evolu/common 3.1.8 → 4.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 (47) hide show
  1. package/dist/src/Config.d.ts +6 -0
  2. package/dist/src/Config.d.ts.map +1 -1
  3. package/dist/src/Config.js +1 -0
  4. package/dist/src/Crdt.d.ts +2 -2
  5. package/dist/src/Crdt.d.ts.map +1 -1
  6. package/dist/src/Crdt.js +2 -2
  7. package/dist/src/Crypto.d.ts +5 -4
  8. package/dist/src/Crypto.d.ts.map +1 -1
  9. package/dist/src/Crypto.js +2 -2
  10. package/dist/src/Db.d.ts +2 -2
  11. package/dist/src/Db.d.ts.map +1 -1
  12. package/dist/src/Db.js +1 -3
  13. package/dist/src/DbWorker.d.ts +8 -8
  14. package/dist/src/DbWorker.d.ts.map +1 -1
  15. package/dist/src/DbWorker.js +44 -28
  16. package/dist/src/Evolu.d.ts +3 -4
  17. package/dist/src/Evolu.d.ts.map +1 -1
  18. package/dist/src/Evolu.js +4 -9
  19. package/dist/src/OnCompletes.d.ts +3 -3
  20. package/dist/src/OnCompletes.d.ts.map +1 -1
  21. package/dist/src/OnCompletes.js +3 -3
  22. package/dist/src/Platform.d.ts +3 -1
  23. package/dist/src/Platform.d.ts.map +1 -1
  24. package/dist/src/Platform.js +1 -0
  25. package/dist/src/Sql.d.ts.map +1 -1
  26. package/dist/src/Sql.js +4 -3
  27. package/dist/src/Sqlite.d.ts +2 -2
  28. package/dist/src/Sqlite.d.ts.map +1 -1
  29. package/dist/src/SyncWorker.d.ts +3 -4
  30. package/dist/src/SyncWorker.d.ts.map +1 -1
  31. package/dist/src/SyncWorker.js +1 -1
  32. package/dist/src/Types.d.ts +13 -0
  33. package/dist/src/Types.d.ts.map +1 -0
  34. package/dist/src/Types.js +1 -0
  35. package/package.json +5 -5
  36. package/src/Config.ts +8 -0
  37. package/src/Crdt.ts +2 -2
  38. package/src/Crypto.ts +11 -7
  39. package/src/Db.ts +3 -5
  40. package/src/DbWorker.ts +54 -44
  41. package/src/Evolu.ts +10 -12
  42. package/src/OnCompletes.ts +4 -4
  43. package/src/Platform.ts +6 -5
  44. package/src/Sql.ts +4 -3
  45. package/src/Sqlite.ts +2 -2
  46. package/src/SyncWorker.ts +4 -6
  47. package/src/Types.ts +11 -0
@@ -5,6 +5,7 @@ export const PlatformName = Context.GenericTag("@services/PlatformName");
5
5
  export const FlushSync = Context.GenericTag("@services/FlushSync");
6
6
  export const FlushSyncDefaultLive = Layer.succeed(FlushSync, (callback) => callback());
7
7
  export const SyncLock = Context.GenericTag("@services/SyncLock");
8
+ export const DbWorkerLock = Context.GenericTag("@services/DbWorkerLock");
8
9
  export const Fetch = Context.GenericTag("@services/Fetch");
9
10
  export const FetchLive = Layer.succeed(Fetch, Fetch.of((url, body) => Effect.tryPromise({
10
11
  try: () => fetch(url, {
@@ -1 +1 @@
1
- {"version":3,"file":"Sql.d.ts","sourceRoot":"","sources":["../../src/Sql.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,WAAW,yFAOvB,CAAC;AAEF,eAAO,MAAM,kBAAkB,yKAS9B,CAAC;AAEF,eAAO,MAAM,uBAAuB,yHAInC,CAAC;AAEF,eAAO,MAAM,gBAAgB,yKAS5B,CAAC;AAEF,eAAO,MAAM,WAAW,0KAWvB,CAAC;AAEF,eAAO,MAAM,iCAAiC,4EAM7C,CAAC;AAEF,eAAO,MAAM,oCAAoC,wKAahD,CAAC;AAEF,eAAO,MAAM,6BAA6B,UACjC,MAAM,UACL,MAAM,KACb,MAOF,CAAC;AAEF,eAAO,MAAM,cAAc,UAAW,MAAM,KAAG,MAI9C,CAAC;AAEF,eAAO,MAAM,uBAAuB,uJAMnC,CAAC;AAEF,eAAO,MAAM,iCAAiC,gFAK7C,CAAC;AAEF,eAAO,MAAM,oBAAoB,uGAShC,CAAC"}
1
+ {"version":3,"file":"Sql.d.ts","sourceRoot":"","sources":["../../src/Sql.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,WAAW,yFAOvB,CAAC;AAEF,eAAO,MAAM,kBAAkB,yKAS9B,CAAC;AAEF,eAAO,MAAM,uBAAuB,yHAInC,CAAC;AAEF,eAAO,MAAM,gBAAgB,yKAS5B,CAAC;AAEF,eAAO,MAAM,WAAW,0KAWvB,CAAC;AAEF,eAAO,MAAM,iCAAiC,4EAM7C,CAAC;AAEF,eAAO,MAAM,oCAAoC,wKAahD,CAAC;AAEF,eAAO,MAAM,6BAA6B,UACjC,MAAM,UACL,MAAM,KACb,MAQF,CAAC;AAEF,eAAO,MAAM,cAAc,UAAW,MAAM,KAAG,MAI9C,CAAC;AAEF,eAAO,MAAM,uBAAuB,uJAMnC,CAAC;AAEF,eAAO,MAAM,iCAAiC,gFAK7C,CAAC;AAEF,eAAO,MAAM,oBAAoB,uGAShC,CAAC"}
package/dist/src/Sql.js CHANGED
@@ -69,11 +69,12 @@ LIMIT
69
69
  `;
70
70
  export const upsertValueIntoTableRowColumn = (table, column) => `
71
71
  INSERT INTO
72
- "${table}" ("id", "${column}")
72
+ "${table}" ("id", "${column}", "createdAt", "updatedAt")
73
73
  VALUES
74
- (?, ?)
74
+ (?, ?, ?, ?)
75
75
  ON CONFLICT DO UPDATE SET
76
- "${column}" = ?
76
+ "${column}" = ?,
77
+ "updatedAt" = ?
77
78
  `;
78
79
  export const deleteTableRow = (table) => `
79
80
  DELETE FROM "${table}"
@@ -2,7 +2,7 @@ import * as Context from "effect/Context";
2
2
  import * as Effect from "effect/Effect";
3
3
  import * as Predicate from "effect/Predicate";
4
4
  export interface Sqlite {
5
- readonly exec: (arg: string | SqliteQuery) => Effect.Effect<ExecResult>;
5
+ readonly exec: (arg: string | SqliteQuery) => Effect.Effect<SqliteExecResult>;
6
6
  }
7
7
  export declare const Sqlite: Context.Tag<Sqlite, Sqlite>;
8
8
  export interface SqliteQuery {
@@ -18,7 +18,7 @@ type JsonObject = {
18
18
  type JsonArray = ReadonlyArray<Json>;
19
19
  type JsonPrimitive = string | number | boolean | null;
20
20
  type Json = JsonPrimitive | JsonObject | JsonArray;
21
- interface ExecResult {
21
+ export interface SqliteExecResult {
22
22
  readonly rows: SqliteRow[];
23
23
  readonly changes: number;
24
24
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Sqlite.d.ts","sourceRoot":"","sources":["../../src/Sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,SAAS,MAAM,kBAAkB,CAAC;AAE9C,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,KAAK,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;CACzE;AAED,eAAO,MAAM,MAAM,6BAAiD,CAAC;AAErE,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,UAAU,EAAE,KAAK,EAAE,CAAC;CAC9B;AAED,MAAM,MAAM,KAAK,GAAG,WAAW,GAAG,iBAAiB,CAAC;AACpD,MAAM,MAAM,WAAW,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC;AAC9D,MAAM,MAAM,iBAAiB,GAAG,UAAU,GAAG,SAAS,CAAC;AACvD,KAAK,UAAU,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAC1C,KAAK,SAAS,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;AACrC,KAAK,aAAa,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;AACtD,KAAK,IAAI,GAAG,aAAa,GAAG,UAAU,GAAG,SAAS,CAAC;AAEnD,UAAU,UAAU;IAClB,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAEpD,eAAO,MAAM,mBAAmB,EAAE,SAAS,CAAC,UAAU,CACpD,KAAK,EACL,iBAAiB,CAE4D,CAAC;AAEhF,eAAO,MAAM,oBAAoB,WACvB,cAAc,KAAK,CAAC,KAC3B,WAAW,EAGX,CAAC;AAEJ,eAAO,MAAM,iBAAiB,QAAS,MAAM,GAAG,WAAW,KAAG,WAG7D,CAAC;AAEF,eAAO,MAAM,cAAc,SAAU,SAAS,EAAE,KAAG,SAAS,EAC1C,CAAC;AA0BnB,eAAO,MAAM,SAAS,EAAE,SAAS,CAAC,SAAS,CAAC,MAAM,CACpB,CAAC"}
1
+ {"version":3,"file":"Sqlite.d.ts","sourceRoot":"","sources":["../../src/Sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,SAAS,MAAM,kBAAkB,CAAC;AAE9C,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,KAAK,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;CAC/E;AAED,eAAO,MAAM,MAAM,6BAAiD,CAAC;AAErE,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,UAAU,EAAE,KAAK,EAAE,CAAC;CAC9B;AAED,MAAM,MAAM,KAAK,GAAG,WAAW,GAAG,iBAAiB,CAAC;AACpD,MAAM,MAAM,WAAW,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC;AAC9D,MAAM,MAAM,iBAAiB,GAAG,UAAU,GAAG,SAAS,CAAC;AACvD,KAAK,UAAU,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAC1C,KAAK,SAAS,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;AACrC,KAAK,aAAa,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;AACtD,KAAK,IAAI,GAAG,aAAa,GAAG,UAAU,GAAG,SAAS,CAAC;AAEnD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAEpD,eAAO,MAAM,mBAAmB,EAAE,SAAS,CAAC,UAAU,CACpD,KAAK,EACL,iBAAiB,CAE4D,CAAC;AAEhF,eAAO,MAAM,oBAAoB,WACvB,cAAc,KAAK,CAAC,KAC3B,WAAW,EAGX,CAAC;AAEJ,eAAO,MAAM,iBAAiB,QAAS,MAAM,GAAG,WAAW,KAAG,WAG7D,CAAC;AAEF,eAAO,MAAM,cAAc,SAAU,SAAS,EAAE,KAAG,SAAS,EAC1C,CAAC;AA0BnB,eAAO,MAAM,SAAS,EAAE,SAAS,CAAC,SAAS,CAAC,MAAM,CACpB,CAAC"}
@@ -8,9 +8,8 @@ import { Id } from "./Model.js";
8
8
  import { Owner } from "./Owner.js";
9
9
  import { Fetch, SyncLock } from "./Platform.js";
10
10
  import { Value } from "./Sqlite.js";
11
- export interface SyncWorker {
12
- readonly postMessage: (input: SyncWorkerInput) => void;
13
- onMessage: (output: SyncWorkerOutput) => void;
11
+ import { Messaging } from "./Types.js";
12
+ export interface SyncWorker extends Messaging<SyncWorkerInput, SyncWorkerOutput> {
14
13
  }
15
14
  export declare const SyncWorker: Context.Tag<SyncWorker, SyncWorker>;
16
15
  export type SyncWorkerPostMessage = SyncWorker["postMessage"];
@@ -76,6 +75,6 @@ export interface SyncStateServerError {
76
75
  export interface SyncStatePaymentRequiredError {
77
76
  readonly _tag: "PaymentRequiredError";
78
77
  }
79
- export declare const SyncWorkerLive: Layer.Layer<SyncWorker, never, SecretBox | SyncLock | Fetch>;
78
+ export declare const SyncWorkerCommonLive: Layer.Layer<SyncWorker, never, SecretBox | SyncLock | Fetch>;
80
79
  export {};
81
80
  //# sourceMappingURL=SyncWorker.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SyncWorker.d.ts","sourceRoot":"","sources":["../../src/SyncWorker.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SyncWorker.d.ts","sourceRoot":"","sources":["../../src/SyncWorker.ts"],"names":[],"mappings":"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"}
@@ -131,7 +131,7 @@ const sync = (input) => Effect.gen(function* (_) {
131
131
  syncLoopCount: input.syncLoopCount,
132
132
  })))), Effect.tapError(() => syncLock.release), Effect.merge, Effect.map(syncWorkerOnMessage));
133
133
  });
134
- export const SyncWorkerLive = Layer.effect(SyncWorker, Effect.gen(function* (_) {
134
+ export const SyncWorkerCommonLive = Layer.effect(SyncWorker, Effect.gen(function* (_) {
135
135
  const syncLock = yield* _(SyncLock);
136
136
  const onError = (error) => Effect.sync(() => {
137
137
  syncWorker.onMessage(error);
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Add types for WebWorker and BroadcastChannel. Messages must have a `_tag`
3
+ * property.
4
+ */
5
+ export interface Messaging<Input extends {
6
+ _tag: string;
7
+ }, Output extends {
8
+ _tag: string;
9
+ }> {
10
+ readonly postMessage: (input: Input) => void;
11
+ onMessage: (output: Output) => void;
12
+ }
13
+ //# sourceMappingURL=Types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Types.d.ts","sourceRoot":"","sources":["../../src/Types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,SAAS,CACxB,KAAK,SAAS;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,EAC9B,MAAM,SAAS;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE;IAE/B,QAAQ,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAC7C,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC"}
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evolu/common",
3
- "version": "3.1.8",
3
+ "version": "4.0.0",
4
4
  "description": "Local-first platform designed for privacy, ease of use, and no vendor lock-in to sync and backup people's lifetime data",
5
5
  "keywords": [
6
6
  "evolu",
@@ -52,11 +52,11 @@
52
52
  "nanoid": "^5.0.6"
53
53
  },
54
54
  "devDependencies": {
55
- "@effect/schema": "^0.63.0",
55
+ "@effect/schema": "^0.63.2",
56
56
  "@protobuf-ts/plugin": "^2.9.3",
57
57
  "@protobuf-ts/protoc": "^2.9.3",
58
58
  "array-shuffle": "^3.0.0",
59
- "effect": "2.4.0",
59
+ "effect": "2.4.1",
60
60
  "eslint": "^8.57.0",
61
61
  "typescript": "^5.3.3",
62
62
  "vitest": "^1.3.1",
@@ -64,8 +64,8 @@
64
64
  "eslint-config-evolu": "1.0.0"
65
65
  },
66
66
  "peerDependencies": {
67
- "@effect/schema": "^0.63.0",
68
- "effect": "2.4.0"
67
+ "@effect/schema": "^0.63.2",
68
+ "effect": "2.4.1"
69
69
  },
70
70
  "publishConfig": {
71
71
  "access": "public"
package/src/Config.ts CHANGED
@@ -16,6 +16,13 @@ export interface Config {
16
16
  * 1000 (5 minutes).
17
17
  */
18
18
  readonly maxDrift: number;
19
+
20
+ /**
21
+ * Evolu application name. For now, this is only useful for localhost
22
+ * development, where we want each application to have its own database. The
23
+ * default value is: "Evolu".
24
+ */
25
+ readonly name: string;
19
26
  }
20
27
 
21
28
  export const Config = Context.GenericTag<Config>("@services/Config");
@@ -27,6 +34,7 @@ export const ConfigLive = (config?: Partial<Config>): Layer.Layer<Config> =>
27
34
  syncUrl: "https://evolu.world",
28
35
  maxDrift: 5 * 60 * 1000,
29
36
  reloadUrl: "/",
37
+ name: "Evolu",
30
38
  ...config,
31
39
  }),
32
40
  );
package/src/Crdt.ts CHANGED
@@ -10,7 +10,7 @@ import * as Option from "effect/Option";
10
10
  import * as ReadonlyArray from "effect/ReadonlyArray";
11
11
  import * as String from "effect/String";
12
12
  import { Config } from "./Config.js";
13
- import { NanoId, NodeId } from "./Crypto.js";
13
+ import { NanoIdGenerator, NodeId } from "./Crypto.js";
14
14
  import { murmurhash } from "./Murmurhash.js";
15
15
 
16
16
  // https://muratbuffalo.blogspot.com/2014/07/hybrid-logical-clocks.html
@@ -86,7 +86,7 @@ export const makeSyncTimestamp = (
86
86
  node: syncNodeId,
87
87
  });
88
88
 
89
- export const makeInitialTimestamp = NanoId.pipe(
89
+ export const makeInitialTimestamp = NanoIdGenerator.pipe(
90
90
  Effect.flatMap(({ nanoidAsNodeId }) => nanoidAsNodeId),
91
91
  Effect.map(
92
92
  (node): Timestamp => ({
package/src/Crypto.ts CHANGED
@@ -36,12 +36,16 @@ export interface InvalidMnemonicError {
36
36
  */
37
37
  export type Mnemonic = string & Brand.Brand<"Mnemonic">;
38
38
 
39
- export interface NanoId {
40
- readonly nanoid: Effect.Effect<string>;
39
+ export interface NanoIdGenerator {
40
+ readonly nanoid: Effect.Effect<NanoId>;
41
41
  readonly nanoidAsNodeId: Effect.Effect<NodeId>;
42
42
  }
43
43
 
44
- export const NanoId = Context.GenericTag<NanoId>("@services/NanoId");
44
+ export const NanoIdGenerator = Context.GenericTag<NanoIdGenerator>(
45
+ "@services/NanoIdGenerator",
46
+ );
47
+
48
+ export type NanoId = string & Brand.Brand<"NanoId">;
45
49
 
46
50
  export const NodeId = S.string.pipe(
47
51
  S.pattern(/^[\w-]{16}$/),
@@ -51,10 +55,10 @@ export type NodeId = S.Schema.To<typeof NodeId>;
51
55
 
52
56
  const nanoidForNodeId = customAlphabet("0123456789abcdef", 16);
53
57
 
54
- export const NanoIdLive = Layer.succeed(
55
- NanoId,
56
- NanoId.of({
57
- nanoid: Effect.sync(() => nanoid()),
58
+ export const NanoIdGeneratorLive = Layer.succeed(
59
+ NanoIdGenerator,
60
+ NanoIdGenerator.of({
61
+ nanoid: Effect.sync(() => nanoid() as NanoId),
58
62
  nanoidAsNodeId: Effect.sync(() => nanoidForNodeId() as NodeId),
59
63
  }),
60
64
  );
package/src/Db.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import * as AST from "@effect/schema/AST";
2
2
  import * as S from "@effect/schema/Schema";
3
3
  import { make } from "@effect/schema/Schema";
4
- import { bytesToHex } from "@noble/ciphers/utils";
5
4
  import * as Brand from "effect/Brand";
6
5
  import * as Context from "effect/Context";
7
6
  import * as Effect from "effect/Effect";
@@ -21,7 +20,7 @@ import {
21
20
  merkleTreeToString,
22
21
  timestampToString,
23
22
  } from "./Crdt.js";
24
- import { Bip39, Mnemonic, NanoId } from "./Crypto.js";
23
+ import { Bip39, Mnemonic, NanoIdGenerator } from "./Crypto.js";
25
24
  import { EvoluTypeError } from "./ErrorStore.js";
26
25
  import { Id, SqliteBoolean, SqliteDate } from "./Model.js";
27
26
  import { Owner, makeOwner } from "./Owner.js";
@@ -323,7 +322,7 @@ export const someDefectToNoSuchTableOrColumnError = Effect.catchSomeDefect(
323
322
 
324
323
  export const lazyInit = (
325
324
  mnemonic?: Mnemonic,
326
- ): Effect.Effect<Owner, never, Sqlite | Bip39 | NanoId> =>
325
+ ): Effect.Effect<Owner, never, Sqlite | Bip39 | NanoIdGenerator> =>
327
326
  Effect.gen(function* (_) {
328
327
  const [owner, sqlite, initialTimestampString] = yield* _(
329
328
  Effect.all([makeOwner(mnemonic), Sqlite, makeInitialTimestamp], {
@@ -341,8 +340,7 @@ export const lazyInit = (
341
340
  parameters: [
342
341
  owner.id,
343
342
  owner.mnemonic,
344
- // expo-sqlite 11.3.2 doesn't support Uint8Array
345
- bytesToHex(owner.encryptionKey),
343
+ owner.encryptionKey,
346
344
  timestampToString(initialTimestampString),
347
345
  merkleTreeToString(initialMerkleTree),
348
346
  ],
package/src/DbWorker.ts CHANGED
@@ -1,4 +1,3 @@
1
- import { hexToBytes } from "@noble/ciphers/utils";
2
1
  import * as Context from "effect/Context";
3
2
  import * as Effect from "effect/Effect";
4
3
  import * as Function from "effect/Function";
@@ -11,6 +10,7 @@ import * as ReadonlyRecord from "effect/ReadonlyRecord";
11
10
  import { Config, ConfigLive } from "./Config.js";
12
11
  import {
13
12
  MerkleTree,
13
+ Millis,
14
14
  Time,
15
15
  TimeLive,
16
16
  Timestamp,
@@ -28,7 +28,7 @@ import {
28
28
  timestampToString,
29
29
  unsafeTimestampFromString,
30
30
  } from "./Crdt.js";
31
- import { Bip39, Mnemonic, NanoId } from "./Crypto.js";
31
+ import { Bip39, Mnemonic, NanoIdGenerator } from "./Crypto.js";
32
32
  import {
33
33
  Queries,
34
34
  Query,
@@ -44,9 +44,10 @@ import {
44
44
  } from "./Db.js";
45
45
  import { QueryPatches, makePatches } from "./Diff.js";
46
46
  import { EvoluError, makeUnexpectedError } from "./ErrorStore.js";
47
- import { Id, SqliteDate, cast } from "./Model.js";
47
+ import { Id, cast } from "./Model.js";
48
48
  import { OnCompleteId } from "./OnCompletes.js";
49
49
  import { Owner, OwnerId } from "./Owner.js";
50
+ import { DbWorkerLock } from "./Platform.js";
50
51
  import * as Sql from "./Sql.js";
51
52
  import { Sqlite, Value } from "./Sqlite.js";
52
53
  import {
@@ -58,12 +59,9 @@ import {
58
59
  SyncWorkerOutputSyncResponse,
59
60
  SyncWorkerPostMessage,
60
61
  } from "./SyncWorker.js";
62
+ import { Messaging } from "./Types.js";
61
63
 
62
- export interface DbWorker {
63
- readonly postMessage: (input: DbWorkerInput) => void;
64
- onMessage: (output: DbWorkerOutput) => void;
65
- }
66
-
64
+ export interface DbWorker extends Messaging<DbWorkerInput, DbWorkerOutput> {}
67
65
  export const DbWorker = Context.GenericTag<DbWorker>("@services/DbWorker");
68
66
 
69
67
  export type DbWorkerInput =
@@ -157,7 +155,6 @@ export interface Mutation {
157
155
  Value | Date | boolean | undefined
158
156
  >;
159
157
  readonly isInsert: boolean;
160
- readonly now: SqliteDate;
161
158
  readonly onCompleteId: OnCompleteId | null;
162
159
  }
163
160
 
@@ -170,8 +167,7 @@ const init = Effect.gen(function* (_) {
170
167
  ({ rows: [row] }): Owner => ({
171
168
  id: row.id as OwnerId,
172
169
  mnemonic: row.mnemonic as Mnemonic,
173
- // expo-sqlite 11.3.2 doesn't support Uint8Array
174
- encryptionKey: hexToBytes(row.encryptionKey as string),
170
+ encryptionKey: row.encryptionKey as Uint8Array,
175
171
  }),
176
172
  ),
177
173
  someDefectToNoSuchTableOrColumnError,
@@ -222,9 +218,8 @@ const readTimestampAndMerkleTree = Sqlite.pipe(
222
218
  Effect.flatMap((sqlite) =>
223
219
  sqlite.exec(Sql.selectOwnerTimestampAndMerkleTree),
224
220
  ),
225
- Effect.map((result) => result.rows),
226
221
  Effect.map(
227
- ([{ timestamp, merkleTree }]): TimestampAndMerkleTree => ({
222
+ ({ rows: [{ timestamp, merkleTree }] }): TimestampAndMerkleTree => ({
228
223
  timestamp: unsafeTimestampFromString(timestamp as TimestampString),
229
224
  merkleTree: merkleTree as MerkleTree,
230
225
  }),
@@ -236,9 +231,10 @@ export const mutationsToNewMessages = (
236
231
  ): ReadonlyArray<NewMessage> =>
237
232
  pipe(
238
233
  mutations,
239
- ReadonlyArray.map(({ id, isInsert, now, table, values }) =>
234
+ ReadonlyArray.map(({ id, isInsert, table, values }) =>
240
235
  pipe(
241
236
  Object.entries(values),
237
+ // Filter values.
242
238
  ReadonlyArray.filterMap(([key, value]) =>
243
239
  // The value can be undefined if exactOptionalPropertyTypes isn't true.
244
240
  // Don't insert nulls because null is the default value.
@@ -246,6 +242,7 @@ export const mutationsToNewMessages = (
246
242
  ? Option.none()
247
243
  : Option.some([key, value] as const),
248
244
  ),
245
+ // Cast values.
249
246
  ReadonlyArray.map(
250
247
  ([key, value]) =>
251
248
  [
@@ -257,7 +254,6 @@ export const mutationsToNewMessages = (
257
254
  : value,
258
255
  ] as const,
259
256
  ),
260
- ReadonlyArray.append([isInsert ? "createdAt" : "updatedAt", now]),
261
257
  ReadonlyArray.map(
262
258
  ([key, value]): NewMessage => ({
263
259
  table,
@@ -282,7 +278,7 @@ const ensureSchemaByNewMessages = (
282
278
  if (table == null) {
283
279
  tablesMap.set(message.table, {
284
280
  name: message.table,
285
- columns: [message.column],
281
+ columns: [message.column, "createdAt", "updatedAt"],
286
282
  });
287
283
  return;
288
284
  }
@@ -298,13 +294,21 @@ const ensureSchemaByNewMessages = (
298
294
  export const upsertValueIntoTableRowColumn = (
299
295
  message: NewMessage,
300
296
  messages: ReadonlyArray<NewMessage>,
297
+ millis: Millis,
301
298
  ): Effect.Effect<void, never, Sqlite> =>
302
299
  Effect.gen(function* (_) {
303
300
  const sqlite = yield* _(Sqlite);
304
-
301
+ const createdAtOrUpdatedAt = cast(new Date(millis));
305
302
  const insert = sqlite.exec({
306
303
  sql: Sql.upsertValueIntoTableRowColumn(message.table, message.column),
307
- parameters: [message.row, message.value, message.value],
304
+ parameters: [
305
+ message.row,
306
+ message.value,
307
+ createdAtOrUpdatedAt,
308
+ createdAtOrUpdatedAt,
309
+ message.value,
310
+ createdAtOrUpdatedAt,
311
+ ],
308
312
  });
309
313
 
310
314
  yield* _(
@@ -340,7 +344,8 @@ const applyMessages = ({
340
344
  );
341
345
 
342
346
  if (timestamp == null || timestamp < message.timestamp) {
343
- yield* _(upsertValueIntoTableRowColumn(message, messages));
347
+ const { millis } = unsafeTimestampFromString(message.timestamp);
348
+ yield* _(upsertValueIntoTableRowColumn(message, messages, millis));
344
349
  }
345
350
 
346
351
  if (timestamp == null || timestamp !== message.timestamp) {
@@ -406,11 +411,11 @@ const mutate = ({
406
411
  ),
407
412
  ).map(mutationsToNewMessages);
408
413
 
409
- yield* _(
410
- Effect.forEach(toUpsert, (message) =>
411
- upsertValueIntoTableRowColumn(message, toUpsert),
412
- ),
413
- );
414
+ const time = yield* _(Time);
415
+ for (const messageToUpsert of toUpsert) {
416
+ const now = yield* _(time.now);
417
+ yield* _(upsertValueIntoTableRowColumn(messageToUpsert, toUpsert, now));
418
+ }
414
419
 
415
420
  const { exec } = yield* _(Sqlite);
416
421
  yield* _(
@@ -537,8 +542,8 @@ const sync = ({
537
542
  > =>
538
543
  Effect.gen(function* (_) {
539
544
  if (queries.length > 0) yield* _(query({ queries }));
540
-
541
- (yield* _(SyncWorkerPostMessage))({
545
+ const syncWorkerPostMessage = yield* _(SyncWorkerPostMessage);
546
+ syncWorkerPostMessage({
542
547
  _tag: "sync",
543
548
  ...(yield* _(readTimestampAndMerkleTree)),
544
549
  syncUrl: (yield* _(Config)).syncUrl,
@@ -550,7 +555,11 @@ const sync = ({
550
555
 
551
556
  const reset = (
552
557
  input: DbWorkerInputReset,
553
- ): Effect.Effect<void, never, Sqlite | Bip39 | NanoId | DbWorkerOnMessage> =>
558
+ ): Effect.Effect<
559
+ void,
560
+ never,
561
+ Sqlite | Bip39 | NanoIdGenerator | DbWorkerOnMessage
562
+ > =>
554
563
  Effect.gen(function* (_) {
555
564
  const sqlite = yield* _(Sqlite);
556
565
 
@@ -575,7 +584,7 @@ const reset = (
575
584
  onMessage({ _tag: "onResetOrRestore" });
576
585
  });
577
586
 
578
- export const DbWorkerLive = Layer.effect(
587
+ export const DbWorkerCommonLive = Layer.effect(
579
588
  DbWorker,
580
589
  Effect.gen(function* (_) {
581
590
  const syncWorker = yield* _(SyncWorker);
@@ -591,7 +600,7 @@ export const DbWorkerLive = Layer.effect(
591
600
  onError(output).pipe(Effect.runSync);
592
601
  break;
593
602
  case "SyncWorkerOutputSyncResponse":
594
- postMessage(output);
603
+ dbWorker.postMessage(output);
595
604
  break;
596
605
  default:
597
606
  dbWorker.onMessage({ _tag: "onSyncState", state: output });
@@ -601,7 +610,7 @@ export const DbWorkerLive = Layer.effect(
601
610
  const runContext = Context.empty().pipe(
602
611
  Context.add(Sqlite, yield* _(Sqlite)),
603
612
  Context.add(Bip39, yield* _(Bip39)),
604
- Context.add(NanoId, yield* _(NanoId)),
613
+ Context.add(NanoIdGenerator, yield* _(NanoIdGenerator)),
605
614
  Context.add(DbWorkerOnMessage, (output) => {
606
615
  dbWorker.onMessage(output);
607
616
  }),
@@ -611,7 +620,7 @@ export const DbWorkerLive = Layer.effect(
611
620
  effect: Effect.Effect<
612
621
  void,
613
622
  EvoluError,
614
- Sqlite | Bip39 | NanoId | DbWorkerOnMessage
623
+ Sqlite | Bip39 | NanoIdGenerator | DbWorkerOnMessage
615
624
  >,
616
625
  ): Promise<void> =>
617
626
  effect.pipe(
@@ -622,15 +631,18 @@ export const DbWorkerLive = Layer.effect(
622
631
  Effect.runPromise,
623
632
  );
624
633
 
625
- type Write = (input: DbWorkerInput) => Promise<void>;
634
+ type HandleInput = (input: DbWorkerInput) => Promise<void>;
626
635
 
627
- // Write for reset only in case init fails.
628
- const writeForInitFail: Write = (input): Promise<void> => {
636
+ /** If init fails, we have to allow reset at least. */
637
+ const handleInputForInitFail: HandleInput = (input): Promise<void> => {
629
638
  if (input._tag !== "reset") return Promise.resolve(undefined);
630
639
  return reset(input).pipe(run);
631
640
  };
632
641
 
633
- const makeWriteForInitSuccess = (config: Config, owner: Owner): Write => {
642
+ const makeHandleInputForInitSuccess = (
643
+ config: Config,
644
+ owner: Owner,
645
+ ): HandleInput => {
634
646
  let skipAllBecauseOfReset = false;
635
647
 
636
648
  const layer = Layer.mergeAll(
@@ -663,27 +675,25 @@ export const DbWorkerLive = Layer.effect(
663
675
  };
664
676
  };
665
677
 
666
- let write: Write = (input) => {
678
+ let handleInput: HandleInput = (input) => {
667
679
  if (input._tag !== "init")
668
680
  return run(makeUnexpectedError(new Error("init must be called first")));
669
- write = writeForInitFail;
681
+ handleInput = handleInputForInitFail;
670
682
  return init.pipe(
671
683
  Effect.map((owner) => {
672
684
  dbWorker.onMessage({ _tag: "onOwner", owner });
673
- write = makeWriteForInitSuccess(input.config, owner);
685
+ handleInput = makeHandleInputForInitSuccess(input.config, owner);
674
686
  }),
675
687
  run,
676
688
  );
677
689
  };
678
690
 
679
- let messageQueue: Promise<void> = Promise.resolve(undefined);
680
-
681
- const postMessage: DbWorker["postMessage"] = (input) => {
682
- messageQueue = messageQueue.then(() => write(input));
683
- };
691
+ const dbWorkerLock = yield* _(DbWorkerLock);
684
692
 
685
693
  const dbWorker: DbWorker = {
686
- postMessage,
694
+ postMessage: (input) => {
695
+ dbWorkerLock(() => handleInput(input));
696
+ },
687
697
  onMessage: Function.constVoid,
688
698
  };
689
699
 
package/src/Evolu.ts CHANGED
@@ -10,8 +10,7 @@ import * as Number from "effect/Number";
10
10
  import * as ReadonlyArray from "effect/ReadonlyArray";
11
11
  import * as Kysely from "kysely";
12
12
  import { Config, ConfigLive } from "./Config.js";
13
- import { Time, TimeLive } from "./Crdt.js";
14
- import { Mnemonic, NanoId, NanoIdLive } from "./Crypto.js";
13
+ import { Mnemonic, NanoIdGenerator, NanoIdGeneratorLive } from "./Crypto.js";
15
14
  import {
16
15
  DatabaseSchema,
17
16
  Queries,
@@ -29,7 +28,7 @@ import {
29
28
  import { DbWorker, DbWorkerOutputOnQuery, Mutation } from "./DbWorker.js";
30
29
  import { applyPatches } from "./Diff.js";
31
30
  import { EvoluError, makeErrorStore } from "./ErrorStore.js";
32
- import { SqliteBoolean, SqliteDate, cast } from "./Model.js";
31
+ import { SqliteBoolean, SqliteDate } from "./Model.js";
33
32
  import { OnCompletes, OnCompletesLive } from "./OnCompletes.js";
34
33
  import { Owner } from "./Owner.js";
35
34
  import { AppState, FlushSync, PlatformName } from "./Platform.js";
@@ -323,13 +322,15 @@ type QueryCallback<S extends DatabaseSchema, R extends Row> = (
323
322
  ) => Kysely.SelectQueryBuilder<any, any, R>;
324
323
 
325
324
  type QuerySchema<S extends DatabaseSchema> = {
326
- readonly [Table in keyof S]: NullableExceptId<{
325
+ readonly [Table in keyof S]: NullableExceptForIdAndAutomaticColumns<{
327
326
  readonly [Column in keyof S[Table]]: S[Table][Column];
328
327
  }>;
329
328
  };
330
329
 
331
- type NullableExceptId<T> = {
332
- readonly [K in keyof T]: K extends "id" ? T[K] : T[K] | null;
330
+ type NullableExceptForIdAndAutomaticColumns<T> = {
331
+ readonly [K in keyof T]: K extends "id" | "createdAt" | "updatedAt"
332
+ ? T[K]
333
+ : T[K] | null;
333
334
  };
334
335
 
335
336
  const kysely = new Kysely.Kysely<QuerySchema<DatabaseSchema>>({
@@ -643,9 +644,8 @@ type Castable<T> = {
643
644
  const MutateLive = Layer.effect(
644
645
  Mutate,
645
646
  Effect.gen(function* (_) {
646
- const nanoid = yield* _(NanoId);
647
+ const { nanoid } = yield* _(NanoIdGenerator);
647
648
  const onCompletes = yield* _(OnCompletes);
648
- const time = yield* _(Time);
649
649
  const subscribedQueries = yield* _(SubscribedQueries);
650
650
  const loadingPromises = yield* _(LoadingPromises);
651
651
  const dbWorker = yield* _(DbWorker);
@@ -653,7 +653,7 @@ const MutateLive = Layer.effect(
653
653
 
654
654
  return Mutate.of((table, { id, ...values }, onComplete) => {
655
655
  const isInsert = id == null;
656
- if (isInsert) id = Effect.runSync(nanoid.nanoid) as never;
656
+ if (isInsert) id = Effect.runSync(nanoid) as never;
657
657
 
658
658
  const onCompleteId = onComplete
659
659
  ? onCompletes.add(onComplete).pipe(Effect.runSync)
@@ -666,7 +666,6 @@ const MutateLive = Layer.effect(
666
666
  id,
667
667
  values,
668
668
  isInsert,
669
- now: cast(new Date(Effect.runSync(time.now))),
670
669
  onCompleteId,
671
670
  },
672
671
  ];
@@ -785,9 +784,8 @@ const EvoluCommon = Layer.effect(
785
784
  Layer.provide(Layer.merge(RowsStoreLive, OnCompletesLive)),
786
785
  );
787
786
 
788
- /** EvoluCommonLive has only platform independent side-effects. */
789
787
  export const EvoluCommonLive = EvoluCommon.pipe(
790
- Layer.provide(Layer.merge(TimeLive, NanoIdLive)),
788
+ Layer.provide(NanoIdGeneratorLive),
791
789
  );
792
790
 
793
791
  /**
@@ -4,7 +4,7 @@ import * as Effect from "effect/Effect";
4
4
  import * as Layer from "effect/Layer";
5
5
  import * as Option from "effect/Option";
6
6
  import * as ReadonlyArray from "effect/ReadonlyArray";
7
- import { NanoId } from "./Crypto.js";
7
+ import { NanoId, NanoIdGenerator } from "./Crypto.js";
8
8
 
9
9
  export interface OnCompletes {
10
10
  readonly add: (onComplete: OnComplete) => Effect.Effect<OnCompleteId>;
@@ -16,7 +16,7 @@ export interface OnCompletes {
16
16
 
17
17
  export type OnComplete = () => void;
18
18
 
19
- export type OnCompleteId = string & Brand.Brand<"OnCompleteId">;
19
+ export type OnCompleteId = NanoId & Brand.Brand<"OnCompleteId">;
20
20
 
21
21
  export const OnCompletes = Context.GenericTag<OnCompletes>(
22
22
  "@services/OnCompletes",
@@ -25,12 +25,12 @@ export const OnCompletes = Context.GenericTag<OnCompletes>(
25
25
  export const OnCompletesLive = Layer.effect(
26
26
  OnCompletes,
27
27
  Effect.gen(function* (_) {
28
- const nanoid = yield* _(NanoId);
28
+ const { nanoid } = yield* _(NanoIdGenerator);
29
29
  const map = new Map<OnCompleteId, OnComplete>();
30
30
 
31
31
  return OnCompletes.of({
32
32
  add: (onComplete) =>
33
- nanoid.nanoid.pipe(
33
+ nanoid.pipe(
34
34
  Effect.map((nanoid) => {
35
35
  const id = nanoid as OnCompleteId;
36
36
  map.set(id, onComplete);