@evolu/common 4.1.1 → 5.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 (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/dist/src/Model.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as S from "@effect/schema/Schema";
2
2
  import { maybeJson } from "./Sqlite.js";
3
3
  /** Branded Id Schema. To create Id Schema for a specific table, use {@link id}. */
4
- export const Id = S.string.pipe(S.pattern(/^[\w-]{21}$/), S.brand("Id"));
4
+ export const Id = S.String.pipe(S.pattern(/^[\w-]{21}$/), S.brand("Id"));
5
5
  /**
6
6
  * A factory function to create {@link Id} Schema for a specific table.
7
7
  *
@@ -18,13 +18,13 @@ export const id = (table) => Id.pipe(S.brand(table));
18
18
  * the {@link cast} helper to cast SqliteDate from Date and back.
19
19
  * https://www.sqlite.org/quirks.html#no_separate_datetime_datatype
20
20
  */
21
- export const SqliteDate = S.string.pipe(S.filter((s) => !isNaN(Date.parse(s))), S.brand("SqliteDate"));
21
+ export const SqliteDate = S.String.pipe(S.filter((s) => !isNaN(Date.parse(s))), S.brand("SqliteDate"));
22
22
  /**
23
23
  * SQLite doesn't support the boolean type, so Evolu uses SqliteBoolean instead.
24
24
  * Use the {@link cast} helper to cast SqliteBoolean from boolean and back.
25
25
  * https://www.sqlite.org/quirks.html#no_separate_boolean_datatype
26
26
  */
27
- export const SqliteBoolean = S.number.pipe(S.int(), S.filter((s) => s === 0 || s === 1), S.brand("SqliteBoolean"));
27
+ export const SqliteBoolean = S.Number.pipe(S.int(), S.filter((s) => s === 0 || s === 1), S.brand("SqliteBoolean"));
28
28
  export function cast(value) {
29
29
  if (typeof value === "boolean")
30
30
  return (value === true ? 1 : 0);
@@ -34,13 +34,55 @@ export function cast(value) {
34
34
  return value.toISOString();
35
35
  return new Date(value);
36
36
  }
37
+ /**
38
+ * Create table schema.
39
+ *
40
+ * Supported types are null, string, number, Uint8Array, JSON Object, and JSON
41
+ * Array. Use SqliteDate for dates and SqliteBoolean for booleans.
42
+ *
43
+ * Reserved columns are createdAt, updatedAt, isDeleted. Those columns are added
44
+ * by default.
45
+ *
46
+ * @example
47
+ * const TodoId = id("Todo");
48
+ * type TodoId = S.Schema.Type<typeof TodoId>;
49
+ *
50
+ * const TodoTable = table({
51
+ * id: TodoId,
52
+ * title: NonEmptyString1000,
53
+ * isCompleted: S.nullable(SqliteBoolean),
54
+ * });
55
+ * type TodoTable = S.Schema.Type<typeof TodoTable>;
56
+ */
57
+ export const table = (fields) => S.Struct(fields).pipe(S.extend(ReservedColumns));
58
+ const ReservedColumns = S.Struct({
59
+ createdAt: SqliteDate,
60
+ updatedAt: SqliteDate,
61
+ isDeleted: SqliteBoolean,
62
+ });
63
+ /**
64
+ * Create database schema.
65
+ *
66
+ * Tables with a name prefixed with _ are local-only, which means they are not
67
+ * synced. Local-only tables are useful for device-specific or temporal data.
68
+ *
69
+ * @example
70
+ * const Database = database({
71
+ * // A local-only table.
72
+ * _todo: TodoTable,
73
+ * todo: TodoTable,
74
+ * todoCategory: TodoCategoryTable,
75
+ * });
76
+ * type Database = S.Schema.Type<typeof Database>;
77
+ */
78
+ export const database = S.Struct;
37
79
  /**
38
80
  * String schema represents a string that is not stringified JSON. Using String
39
81
  * schema for strings stored in SQLite is crucial to ensure a stored string is
40
82
  * not automatically parsed to a JSON object or array when retrieved. Use String
41
83
  * schema for all string-based schemas.
42
84
  */
43
- export const String = S.string.pipe(S.filter((s) => {
85
+ export const String = S.String.pipe(S.filter((s) => {
44
86
  if (!maybeJson(s))
45
87
  return true;
46
88
  try {
@@ -80,4 +122,4 @@ export const NonEmptyString1000 = String.pipe(S.minLength(1), S.maxLength(1000),
80
122
  *
81
123
  * S.decode(PositiveInt)(value);
82
124
  */
83
- export const PositiveInt = S.number.pipe(S.int(), S.positive(), S.brand("PositiveInt"));
125
+ export const PositiveInt = S.Number.pipe(S.int(), S.positive(), S.brand("PositiveInt"));
@@ -1 +1 @@
1
- {"version":3,"file":"Owner.d.ts","sourceRoot":"","sources":["../../src/Owner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAgB,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,EAAE,EAAE,MAAM,YAAY,CAAC;AAEhC;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,KAAK;IACpB,0DAA0D;IAC1D,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAE5B,kEAAkE;IAClE,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IAErB,+DAA+D;IAC/D,QAAQ,CAAC,aAAa,EAAE,UAAU,CAAC;CACpC;AAED,eAAO,MAAM,KAAK,2BAA+C,CAAC;AAElE;;;GAGG;AACH,MAAM,MAAM,OAAO,GAAG,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AAEhD,eAAO,MAAM,SAAS,cACT,QAAQ,KAClB,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CA0BhC,CAAC"}
1
+ {"version":3,"file":"Owner.d.ts","sourceRoot":"","sources":["../../src/Owner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAgB,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,EAAE,EAAE,MAAM,YAAY,CAAC;AAEhC;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,KAAK;IACpB,0DAA0D;IAC1D,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAE5B,kEAAkE;IAClE,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IAErB,+DAA+D;IAC/D,QAAQ,CAAC,aAAa,EAAE,UAAU,CAAC;CACpC;AAED,eAAO,MAAM,KAAK,2BAAqC,CAAC;AAExD;;;GAGG;AACH,MAAM,MAAM,OAAO,GAAG,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AAEhD,eAAO,MAAM,SAAS,cACT,QAAQ,KAClB,OAAO,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAqBhC,CAAC"}
package/dist/src/Owner.js CHANGED
@@ -1,21 +1,27 @@
1
1
  import * as Context from "effect/Context";
2
2
  import * as Effect from "effect/Effect";
3
- import { urlAlphabet } from "nanoid";
4
3
  import { Bip39, slip21Derive } from "./Crypto.js";
5
- export const Owner = Context.GenericTag("@services/Owner");
4
+ export const Owner = Context.GenericTag("Owner");
6
5
  export const makeOwner = (mnemonic) => Effect.gen(function* (_) {
7
- const bip39 = yield* _(Bip39);
6
+ const bip39 = yield* Bip39;
8
7
  if (mnemonic == null)
9
- mnemonic = yield* _(bip39.make);
10
- const seed = yield* _(bip39.toSeed(mnemonic));
11
- const id = yield* _(slip21Derive(seed, ["Evolu", "Owner Id"]).pipe(Effect.map((key) => {
8
+ mnemonic = yield* bip39.make;
9
+ const seed = yield* bip39.toSeed(mnemonic);
10
+ const id = yield* Effect.map(slip21Derive(seed, ["Evolu", "Owner Id"]), (key) => {
12
11
  // convert key to nanoid
13
12
  let id = "";
14
13
  for (let i = 0; i < 21; i++) {
15
14
  id += urlAlphabet[key[i] & 63];
16
15
  }
17
16
  return id;
18
- })));
19
- const encryptionKey = yield* _(slip21Derive(seed, ["Evolu", "Encryption Key"]));
17
+ });
18
+ const encryptionKey = yield* slip21Derive(seed, [
19
+ "Evolu",
20
+ "Encryption Key",
21
+ ]);
20
22
  return { mnemonic, id, encryptionKey };
21
23
  });
24
+ // From https://github.com/ai/nanoid/blob/main/url-alphabet/index.js
25
+ // It's copy-pasted for now because NanoId import breaks Metro bundler.
26
+ // https://github.com/ai/nanoid/issues/468
27
+ const urlAlphabet = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";
@@ -1,47 +1,37 @@
1
1
  import * as Context from "effect/Context";
2
2
  import * as Effect from "effect/Effect";
3
- import * as Layer from "effect/Layer";
3
+ import * as Scope from "effect/Scope";
4
+ import { Config } from "./Config.js";
4
5
  /**
5
- * FlushSync lets you force React to flush any updates inside the provided
6
- * callback synchronously. This ensures that the DOM is updated immediately.
6
+ * FlushSync is a service for libraries like React to synchronously flush
7
+ * updates inside the provided callback to ensure the DOM is updated
8
+ * immediately.
7
9
  *
8
- * It's required only for React DOM. The other UI libraries probably don't need
9
- * that, so it should be a no-op.
10
+ * https://react.dev/reference/react-dom/flushSync
10
11
  */
11
12
  export type FlushSync = (callback: () => void) => void;
12
13
  export declare const FlushSync: Context.Tag<FlushSync, FlushSync>;
13
- export declare const FlushSyncDefaultLive: Layer.Layer<FlushSync, never, never>;
14
- export interface SyncLock {
15
- /**
16
- * Try to acquire a sync lock. The caller must not call sync if a sync lock
17
- * can't be acquired.
18
- */
19
- readonly acquire: Effect.Effect<boolean>;
20
- /** Release a sync lock. */
21
- readonly release: Effect.Effect<void>;
14
+ declare const AppState_base: Context.TagClass<AppState, "AppState", {
15
+ readonly init: (options: {
16
+ readonly reloadUrl: string;
17
+ readonly onRequestSync: () => void;
18
+ }) => Effect.Effect<AppStateReset>;
19
+ }>;
20
+ export declare class AppState extends AppState_base {
22
21
  }
23
- export declare const SyncLock: Context.Tag<SyncLock, SyncLock>;
24
- export type DbWorkerLock = (callback: () => Promise<void>) => void;
25
- export declare const DbWorkerLock: Context.Tag<DbWorkerLock, DbWorkerLock>;
26
- export type Fetch = (url: string, body: Uint8Array) => Effect.Effect<Response, FetchError>;
27
- export declare const Fetch: Context.Tag<Fetch, Fetch>;
28
- /**
29
- * This error occurs when there is a problem with the network connection, or the
30
- * server cannot be reached.
31
- */
32
- export interface FetchError {
33
- readonly _tag: "FetchError";
22
+ interface AppStateReset {
23
+ readonly reset: Effect.Effect<void>;
34
24
  }
35
- export declare const FetchLive: Layer.Layer<Fetch, never, never>;
36
- interface AppStateConfig {
37
- readonly onRequestSync: () => void;
25
+ declare const SyncLock_base: Context.TagClass<SyncLock, "SyncLock", {
26
+ readonly tryAcquire: Effect.Effect<SyncLockRelease, SyncLockAlreadySyncingError, Config | Scope.Scope>;
27
+ }>;
28
+ export declare class SyncLock extends SyncLock_base {
38
29
  }
39
- export interface AppState {
40
- readonly init: (config: AppStateConfig) => void;
41
- readonly reset: Effect.Effect<void>;
30
+ export interface SyncLockRelease {
31
+ readonly release: Effect.Effect<void>;
32
+ }
33
+ export declare class SyncLockAlreadySyncingError {
34
+ readonly _tag = "SyncLockAlreadySyncingError";
42
35
  }
43
- export declare const AppState: Context.Tag<AppState, AppState>;
44
- /** To detect whether DOM can be used. */
45
- export declare const canUseDom: boolean;
46
36
  export {};
47
37
  //# sourceMappingURL=Platform.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Platform.d.ts","sourceRoot":"","sources":["../../src/Platform.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAEtC;;;;;;GAMG;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;AAEvD,eAAO,MAAM,SAAS,mCAAuD,CAAC;AAE9E,eAAO,MAAM,oBAAoB,sCAEhC,CAAC;AAEF,MAAM,WAAW,QAAQ;IACvB;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAEzC,2BAA2B;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;CACvC;AAED,eAAO,MAAM,QAAQ,iCAAqD,CAAC;AAE3E,MAAM,MAAM,YAAY,GAAG,CAAC,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC;AACnE,eAAO,MAAM,YAAY,yCAExB,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG,CAClB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,UAAU,KACb,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;AAEzC,eAAO,MAAM,KAAK,2BAA+C,CAAC;AAElE;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;CAC7B;AAED,eAAO,MAAM,SAAS,kCAgBrB,CAAC;AAEF,UAAU,cAAc;IACtB,QAAQ,CAAC,aAAa,EAAE,MAAM,IAAI,CAAC;CACpC;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,CAAC;IAChD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;CACrC;AAED,eAAO,MAAM,QAAQ,iCAAqD,CAAC;AAE3E,yCAAyC;AACzC,eAAO,MAAM,SAAS,SAYlB,CAAC"}
1
+ {"version":3,"file":"Platform.d.ts","sourceRoot":"","sources":["../../src/Platform.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC;;;;;;GAMG;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;AACvD,eAAO,MAAM,SAAS,mCAA6C,CAAC;;mBAKjD,CAAC,OAAO,EAAE;QACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAC3B,QAAQ,CAAC,aAAa,EAAE,MAAM,IAAI,CAAC;KACpC,KAAK,OAAO,MAAM,CAAC,aAAa,CAAC;;AANtC,qBAAa,QAAS,SAAQ,aAQ3B;CAAG;AAEN,UAAU,aAAa;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;CACrC;;yBAKwB,OAAO,MAAM,CAChC,eAAe,EACf,2BAA2B,EAC3B,MAAM,GAAG,MAAM,KAAK,CACrB;;AAPL,qBAAa,QAAS,SAAQ,aAS3B;CAAG;AAEN,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;CACvC;AAED,qBAAa,2BAA2B;IACtC,QAAQ,CAAC,IAAI,iCAAiC;CAC/C"}
@@ -1,33 +1,11 @@
1
1
  import * as Context from "effect/Context";
2
- import * as Effect from "effect/Effect";
3
- import * as Layer from "effect/Layer";
4
- export const FlushSync = Context.GenericTag("@services/FlushSync");
5
- export const FlushSyncDefaultLive = Layer.succeed(FlushSync, (callback) => callback());
6
- export const SyncLock = Context.GenericTag("@services/SyncLock");
7
- export const DbWorkerLock = Context.GenericTag("@services/DbWorkerLock");
8
- export const Fetch = Context.GenericTag("@services/Fetch");
9
- export const FetchLive = Layer.succeed(Fetch, Fetch.of((url, body) => Effect.tryPromise({
10
- try: () => fetch(url, {
11
- method: "POST",
12
- body,
13
- headers: {
14
- "Content-Type": "application/x-protobuf",
15
- "Content-Length": body.length.toString(),
16
- },
17
- }),
18
- catch: () => ({ _tag: "FetchError" }),
19
- })));
20
- export const AppState = Context.GenericTag("@services/AppState");
21
- /** To detect whether DOM can be used. */
22
- export const canUseDom = (() => {
23
- // IDK why try-catch is necessary, but it is.
24
- // "ReferenceError: window is not defined" should not happen, but it does.
25
- try {
26
- return !!(typeof window !== "undefined" &&
27
- window.document &&
28
- window.document.createElement);
2
+ export const FlushSync = Context.GenericTag("FlushSync");
3
+ export class AppState extends Context.Tag("AppState")() {
4
+ }
5
+ export class SyncLock extends Context.Tag("SyncLock")() {
6
+ }
7
+ export class SyncLockAlreadySyncingError {
8
+ constructor() {
9
+ this._tag = "SyncLockAlreadySyncingError";
29
10
  }
30
- catch (e) {
31
- return false;
32
- }
33
- })();
11
+ }
@@ -3,12 +3,10 @@ export type { NotNull } from "kysely";
3
3
  export { jsonArrayFrom, jsonObjectFrom } from "kysely/helpers/sqlite";
4
4
  export type { Timestamp, TimestampError } from "./Crdt.js";
5
5
  export type { InvalidMnemonicError, Mnemonic } from "./Crypto.js";
6
- export { database, table } from "./Db.js";
7
6
  export type { ExtractRow, QueryResult } from "./Db.js";
8
- export type { EvoluError, UnexpectedError } from "./ErrorStore.js";
9
- export { createIndex } from "./Evolu.js";
7
+ export * from "./Error.js";
8
+ export { createIndexes } from "./Evolu.js";
10
9
  export * from "./Model.js";
11
10
  export type { Owner, OwnerId } from "./Owner.js";
12
- export { canUseDom } from "./Platform.js";
13
- export type { SyncState } from "./SyncWorker.js";
11
+ export type { SyncState } from "./Sync.js";
14
12
  //# sourceMappingURL=Public.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Public.d.ts","sourceRoot":"","sources":["../../src/Public.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAC7B,YAAY,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACtE,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3D,YAAY,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAC1C,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACvD,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,cAAc,YAAY,CAAC;AAC3B,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,YAAY,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"Public.d.ts","sourceRoot":"","sources":["../../src/Public.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAC7B,YAAY,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACtE,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3D,YAAY,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAClE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACvD,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,cAAc,YAAY,CAAC;AAC3B,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACjD,YAAY,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC"}
@@ -1,6 +1,5 @@
1
1
  export { sql } from "kysely";
2
2
  export { jsonArrayFrom, jsonObjectFrom } from "kysely/helpers/sqlite";
3
- export { database, table } from "./Db.js";
4
- export { createIndex } from "./Evolu.js";
3
+ export * from "./Error.js";
4
+ export { createIndexes } from "./Evolu.js";
5
5
  export * from "./Model.js";
6
- export { canUseDom } from "./Platform.js";
@@ -1,11 +1,33 @@
1
1
  import * as Context from "effect/Context";
2
2
  import * as Effect from "effect/Effect";
3
- import { Equivalence } from "effect/Equivalence";
3
+ import * as Layer from "effect/Layer";
4
4
  import * as Predicate from "effect/Predicate";
5
+ import { Config } from "./Config.js";
5
6
  export interface Sqlite {
6
7
  readonly exec: (query: SqliteQuery) => Effect.Effect<SqliteExecResult>;
8
+ readonly transaction: (
9
+ /**
10
+ * Use `exclusive` for mutations and `shared` for read-only queries. This
11
+ * shared/exclusive lock pattern allows multiple simultaneous readers but
12
+ * only one writer. In Evolu, this pattern also ensures that every write can
13
+ * be immediately read without waiting to complete. For example, we can add
14
+ * data on one page and then immediately redirect to another, and the data
15
+ * will be there.
16
+ *
17
+ * There is also a `last` mode that ensures no other transaction can run.
18
+ * It's for Db reset to ensure no data are accidentally saved after database
19
+ * wipe-out.
20
+ */
21
+ mode: SqliteTransactionMode) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Sqlite | R>;
7
22
  }
8
23
  export declare const Sqlite: Context.Tag<Sqlite, Sqlite>;
24
+ export type SqliteTransactionMode = "exclusive" | "shared" | "last";
25
+ declare const SqliteFactory_base: Context.TagClass<SqliteFactory, "SqliteFactory", {
26
+ readonly createSqlite: Effect.Effect<Sqlite, never, Config>;
27
+ }>;
28
+ export declare class SqliteFactory extends SqliteFactory_base {
29
+ static Common: Layer.Layer<SqliteFactory, never, SqliteFactory>;
30
+ }
9
31
  export interface SqliteQuery {
10
32
  readonly sql: string;
11
33
  readonly parameters?: Value[];
@@ -32,7 +54,8 @@ export interface SqliteExecResult {
32
54
  export type SqliteRow = Record<string, SqliteValue>;
33
55
  export declare const isJsonObjectOrArray: Predicate.Refinement<Value, JsonObjectOrArray>;
34
56
  export declare const valuesToSqliteValues: (values: ReadonlyArray<Value>) => SqliteValue[];
35
- export declare const maybeParseJson: (rows: SqliteRow[]) => SqliteRow[];
57
+ /** This function mutates for better performance. */
58
+ export declare const maybeParseJson: (rows: SqliteRow[]) => void;
36
59
  export declare const maybeJson: Predicate.Predicate<string>;
37
60
  export declare const isSqlMutation: (sql: string) => boolean;
38
61
  export declare const maybeLogSqliteQueryExecutionTime: (query: SqliteQuery) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
@@ -42,19 +65,5 @@ export type SqliteQueryPlanRow = {
42
65
  detail: string;
43
66
  };
44
67
  export declare const drawSqliteQueryPlan: (rows: SqliteQueryPlanRow[]) => string;
45
- export interface SqliteSchema {
46
- readonly tables: ReadonlyArray<Table>;
47
- readonly indexes: ReadonlyArray<Index>;
48
- }
49
- export interface Table {
50
- readonly name: string;
51
- readonly columns: ReadonlyArray<string>;
52
- }
53
- export interface Index {
54
- readonly name: string;
55
- readonly sql: string;
56
- }
57
- export declare const indexEquivalence: Equivalence<Index>;
58
- export declare const maybeLogSql: (query: SqliteQuery, logSql: boolean) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
59
68
  export {};
60
69
  //# sourceMappingURL=Sqlite.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Sqlite.d.ts","sourceRoot":"","sources":["../../src/Sqlite.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Sqlite.d.ts","sourceRoot":"","sources":["../../src/Sqlite.ts"],"names":[],"mappings":"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"}
@@ -1,10 +1,35 @@
1
+ import * as Console from "effect/Console";
1
2
  import * as Context from "effect/Context";
2
3
  import * as Effect from "effect/Effect";
4
+ import * as Exit from "effect/Exit";
5
+ import * as Layer from "effect/Layer";
3
6
  import * as Predicate from "effect/Predicate";
4
- export const Sqlite = Context.GenericTag("@services/Sqlite");
7
+ export const Sqlite = Context.GenericTag("Sqlite");
8
+ export class SqliteFactory extends Context.Tag("SqliteFactory")() {
9
+ }
10
+ SqliteFactory.Common = Layer.effect(SqliteFactory, Effect.map(SqliteFactory, (platformSqliteFactory) => ({
11
+ createSqlite: Effect.logTrace("SqliteFactory createSqlite").pipe(Effect.zipRight(platformSqliteFactory.createSqlite), Effect.map((platformSqlite) => ({
12
+ exec: (query) => platformSqlite.exec(query).pipe(Effect.tap((result) => {
13
+ maybeParseJson(result.rows);
14
+ }), Effect.tap((result) => ["begin", "rollback", "commit"].includes(query.sql)
15
+ ? Effect.logDebug(`SQLiteCommon ${query.sql} transaction`)
16
+ : Effect.logDebug(["SQLiteCommon exec", query, result]))),
17
+ transaction: (mode) => (effect) => {
18
+ // Shared is for readonly queries.
19
+ if (mode === "shared")
20
+ return platformSqlite.transaction(mode)(effect);
21
+ return Effect.flatMap(Sqlite, (sqlite) => Effect.acquireUseRelease(sqlite.exec({ sql: "begin" }), () => effect, (_, exit) => Exit.isFailure(exit)
22
+ ? sqlite.exec({ sql: "rollback" })
23
+ : sqlite.exec({ sql: "commit" }))).pipe(platformSqlite.transaction(mode));
24
+ },
25
+ }))),
26
+ })));
5
27
  export const isJsonObjectOrArray = (value) => value !== null && typeof value === "object" && !Predicate.isUint8Array(value);
6
28
  export const valuesToSqliteValues = (values) => values.map((value) => isJsonObjectOrArray(value) ? JSON.stringify(value) : value);
7
- export const maybeParseJson = (rows) => parseArray(rows);
29
+ /** This function mutates for better performance. */
30
+ export const maybeParseJson = (rows) => {
31
+ parseArray(rows);
32
+ };
8
33
  const parseArray = (a) => {
9
34
  for (let i = 0; i < a.length; ++i)
10
35
  a[i] = parse(a[i]);
@@ -50,10 +75,7 @@ export const isSqlMutation = (sql) => isSqlMutationRegEx.test(sql);
50
75
  export const maybeLogSqliteQueryExecutionTime = (query) => (effect) => {
51
76
  if (!query.options?.logQueryExecutionTime)
52
77
  return effect;
53
- return effect.pipe(Effect.tap(() => Effect.log("QueryExecutionTime")),
54
- // Not using Effect.log because of formating
55
- // eslint-disable-next-line no-console
56
- Effect.tap(() => console.log(query.sql)), Effect.withLogSpan("duration"));
78
+ return Effect.Do.pipe(Effect.let("start", () => performance.now()), Effect.bind("result", () => effect), Effect.let("elapsed", ({ start }) => performance.now() - start), Effect.tap(({ elapsed }) => Console.log(`QueryExecutionTime: ${elapsed}ms`, query)), Effect.map(({ result }) => result));
57
79
  };
58
80
  export const drawSqliteQueryPlan = (rows) => rows
59
81
  .map((row) => {
@@ -70,17 +92,3 @@ export const drawSqliteQueryPlan = (rows) => rows
70
92
  return `${" ".repeat(indent)}${row.detail}`;
71
93
  })
72
94
  .join("\n");
73
- export const indexEquivalence = (self, that) => self.name === that.name && self.sql === that.sql;
74
- export const maybeLogSql = (query, logSql) => (effect) => {
75
- if (!logSql)
76
- return effect;
77
- return effect.pipe(Effect.tap(() => Effect.log("SQL")),
78
- // Not using Effect.log because of formating
79
- Effect.tap(() => {
80
- // eslint-disable-next-line no-console
81
- console.log(query.sql);
82
- if (query.parameters && query.parameters.length > 0)
83
- // eslint-disable-next-line no-console
84
- console.log(query.parameters);
85
- }));
86
- };
@@ -1 +1 @@
1
- {"version":3,"file":"Store.d.ts","sourceRoot":"","sources":["../../src/Store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,MAAM,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC;AAElC,MAAM,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC;AAErC,MAAM,WAAW,KAAK,CAAC,CAAC;IAEtB,QAAQ,CAAC,SAAS,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,WAAW,CAAC;IACxD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAG3B,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;CACtD;AAED,eAAO,MAAM,SAAS,oBAAqB,CAAC,KAAG,aAAa,CAAC,MAAM,CAAC,CAAC,CA0BjE,CAAC"}
1
+ {"version":3,"file":"Store.d.ts","sourceRoot":"","sources":["../../src/Store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,MAAM,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC;AAElC,MAAM,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC;AAErC,MAAM,WAAW,KAAK,CAAC,CAAC;IAEtB,QAAQ,CAAC,SAAS,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,WAAW,CAAC;IACxD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAG3B,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;CACtD;AAED,eAAO,MAAM,SAAS,oBAAqB,CAAC,KAAG,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CA0BjE,CAAC"}
@@ -0,0 +1,70 @@
1
+ import * as Context from "effect/Context";
2
+ import * as Effect from "effect/Effect";
3
+ import { Config } from "./Config.js";
4
+ import { MerkleTree, Millis, Timestamp, TimestampString } from "./Crdt.js";
5
+ import { SecretBox } from "./Crypto.js";
6
+ import { Id } from "./Model.js";
7
+ import { Owner } from "./Owner.js";
8
+ import { Value } from "./Sqlite.js";
9
+ export interface Sync {
10
+ readonly init: (owner: Owner) => Effect.Effect<void>;
11
+ readonly sync: (syncData: SyncData) => Effect.Effect<SyncResult, SyncStateIsNotSynced, Config>;
12
+ }
13
+ export declare const Sync: Context.Tag<Sync, Sync>;
14
+ export interface SyncData {
15
+ merkleTree: MerkleTree;
16
+ timestamp: Timestamp;
17
+ messages?: ReadonlyArray<Message>;
18
+ }
19
+ export interface Message extends NewMessage {
20
+ readonly timestamp: TimestampString;
21
+ }
22
+ export interface NewMessage {
23
+ readonly table: string;
24
+ readonly row: Id;
25
+ readonly column: string;
26
+ readonly value: Value;
27
+ }
28
+ export interface SyncResult {
29
+ readonly messages: ReadonlyArray<Message>;
30
+ readonly merkleTree: MerkleTree;
31
+ }
32
+ /**
33
+ * The SyncState type represents the various states that a synchronization
34
+ * process can be in.
35
+ */
36
+ export type SyncState = SyncStateInitial | SyncStateIsSyncing | SyncStateIsSynced | SyncStateIsNotSynced;
37
+ /** On app start, we need to find out whether the state is synced. */
38
+ export interface SyncStateInitial {
39
+ readonly _tag: "SyncStateInitial";
40
+ }
41
+ export declare const initialSyncState: SyncStateInitial;
42
+ export interface SyncStateIsSyncing {
43
+ readonly _tag: "SyncStateIsSyncing";
44
+ }
45
+ export interface SyncStateIsSynced {
46
+ readonly _tag: "SyncStateIsSynced";
47
+ readonly time: Millis;
48
+ }
49
+ export interface SyncStateIsNotSynced {
50
+ readonly _tag: "SyncStateIsNotSynced";
51
+ readonly error: NetworkError | ServerError | PaymentRequiredError;
52
+ }
53
+ export interface NetworkError {
54
+ readonly _tag: "NetworkError";
55
+ }
56
+ export interface ServerError {
57
+ readonly _tag: "ServerError";
58
+ readonly status: number;
59
+ }
60
+ export interface PaymentRequiredError {
61
+ readonly _tag: "PaymentRequiredError";
62
+ }
63
+ declare const SyncFactory_base: Context.TagClass<SyncFactory, "SyncFactory", {
64
+ readonly createSync: Effect.Effect<Sync, never, never>;
65
+ }>;
66
+ export declare class SyncFactory extends SyncFactory_base {
67
+ }
68
+ export declare const createSync: Effect.Effect<Sync, never, SecretBox>;
69
+ export {};
70
+ //# sourceMappingURL=Sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Sync.d.ts","sourceRoot":"","sources":["../../src/Sync.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAE1C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAIxC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EACL,UAAU,EACV,MAAM,EACN,SAAS,EACT,eAAe,EAGhB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,EAAE,EAAE,MAAM,YAAY,CAAC;AAChC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAqB,KAAK,EAAE,MAAM,aAAa,CAAC;AAEvD,MAAM,WAAW,IAAI;IACnB,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACrD,QAAQ,CAAC,IAAI,EAAE,CACb,QAAQ,EAAE,QAAQ,KACf,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,oBAAoB,EAAE,MAAM,CAAC,CAAC;CAC9D;AAED,eAAO,MAAM,IAAI,yBAAmC,CAAC;AAErD,MAAM,WAAW,QAAQ;IACvB,UAAU,EAAE,UAAU,CAAC;IACvB,SAAS,EAAE,SAAS,CAAC;IACrB,QAAQ,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,OAAQ,SAAQ,UAAU;IACzC,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC;CACrC;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC;IACjB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IAC1C,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;CACjC;AAED;;;GAGG;AACH,MAAM,MAAM,SAAS,GACjB,gBAAgB,GAChB,kBAAkB,GAClB,iBAAiB,GACjB,oBAAoB,CAAC;AAEzB,qEAAqE;AACrE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;CACnC;AAGD,eAAO,MAAM,gBAAgB,EAAE,gBAA+C,CAAC;AAE/E,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;CACrC;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,sBAAsB,CAAC;IACtC,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,WAAW,GAAG,oBAAoB,CAAC;CACnE;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;CAC/B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,sBAAsB,CAAC;CACvC;;yBAKwB,OAAO,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC;;AAH1D,qBAAa,WAAY,SAAQ,gBAK9B;CAAG;AAEN,eAAO,MAAM,UAAU,uCAoHrB,CAAC"}