@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
package/src/Model.ts CHANGED
@@ -1,89 +1,70 @@
1
- import * as Schema from "@effect/schema/Schema";
1
+ import * as S from "@effect/schema/Schema";
2
2
  import { Brand } from "effect";
3
3
  import { maybeJson } from "./Sqlite.js";
4
4
 
5
5
  /**
6
- * Branded Id Schema for any table Id.
7
- * To create Id Schema for a specific table, use {@link id}.
6
+ * Branded Id Schema for any table Id. To create Id Schema for a specific table,
7
+ * use {@link id}.
8
8
  */
9
- export const Id = Schema.string.pipe(
10
- Schema.pattern(/^[\w-]{21}$/),
11
- Schema.brand("Id"),
12
- );
13
- export type Id = Schema.Schema.To<typeof Id>;
9
+ export const Id = S.string.pipe(S.pattern(/^[\w-]{21}$/), S.brand("Id"));
10
+ export type Id = S.Schema.To<typeof Id>;
14
11
 
15
12
  /**
16
13
  * A factory function to create {@link Id} Schema for a specific table.
17
14
  *
18
15
  * ### Example
19
16
  *
20
- * ```
21
- * import * as Schema from "@effect/schema/Schema";
17
+ * ```ts
18
+ * import * as S from "@effect/schema/Schema";
22
19
  * import * as Evolu from "@evolu/react";
23
20
  *
24
21
  * const TodoId = Evolu.id("Todo");
25
- * type TodoId = Schema.Schema.To<typeof TodoId>;
26
- *
27
- * if (!Schema.is(TodoId)(value)) return;
22
+ * type TodoId = S.Schema.To<typeof TodoId>;
28
23
  * ```
29
24
  */
30
25
  export const id = <T extends string>(
31
26
  table: T,
32
- ): Schema.BrandSchema<string, string & Brand.Brand<"Id"> & Brand.Brand<T>> =>
33
- Id.pipe(Schema.brand(table));
27
+ ): S.BrandSchema<string, string & Brand.Brand<"Id"> & Brand.Brand<T>> =>
28
+ Id.pipe(S.brand(table));
34
29
 
35
30
  /**
36
- * SQLite doesn't support the Date type, so Evolu uses SqliteDate instead.
37
- * Use the {@link cast} helper to cast SqliteDate from Date and back.
31
+ * SQLite doesn't support the Date type, so Evolu uses SqliteDate instead. Use
32
+ * the {@link cast} helper to cast SqliteDate from Date and back.
38
33
  * https://www.sqlite.org/quirks.html#no_separate_datetime_datatype
39
34
  */
40
- export const SqliteDate = Schema.string.pipe(
41
- Schema.filter((s) => !isNaN(Date.parse(s))),
42
- Schema.brand("SqliteDate"),
35
+ export const SqliteDate = S.string.pipe(
36
+ S.filter((s) => !isNaN(Date.parse(s))),
37
+ S.brand("SqliteDate"),
43
38
  );
44
- export type SqliteDate = Schema.Schema.To<typeof SqliteDate>;
39
+ export type SqliteDate = S.Schema.To<typeof SqliteDate>;
45
40
 
46
41
  /**
47
42
  * SQLite doesn't support the boolean type, so Evolu uses SqliteBoolean instead.
48
43
  * Use the {@link cast} helper to cast SqliteBoolean from boolean and back.
49
44
  * https://www.sqlite.org/quirks.html#no_separate_boolean_datatype
50
45
  */
51
- export const SqliteBoolean = Schema.number.pipe(
52
- Schema.int(),
53
- Schema.filter((s) => s === 0 || s === 1),
54
- Schema.brand("SqliteBoolean"),
46
+ export const SqliteBoolean = S.number.pipe(
47
+ S.int(),
48
+ S.filter((s) => s === 0 || s === 1),
49
+ S.brand("SqliteBoolean"),
55
50
  );
56
- export type SqliteBoolean = Schema.Schema.To<typeof SqliteBoolean>;
57
-
58
- /**
59
- * SQLite doesn't support Date nor Boolean types, so Evolu emulates them
60
- * with {@link SqliteBoolean} and {@link SqliteDate}.
61
- *
62
- * For {@link SqliteBoolean}, you can use JavaScript boolean.
63
- * For {@link SqliteDate}, you can use JavaScript Date.
64
- */
65
- export type CastableForMutate<T> = {
66
- readonly [K in keyof T]: T[K] extends SqliteBoolean
67
- ? boolean | SqliteBoolean
68
- : T[K] extends null | SqliteBoolean
69
- ? null | boolean | SqliteBoolean
70
- : T[K] extends SqliteDate
71
- ? Date | SqliteDate
72
- : T[K] extends null | SqliteDate
73
- ? null | Date | SqliteDate
74
- : T[K];
75
- };
51
+ export type SqliteBoolean = S.Schema.To<typeof SqliteBoolean>;
76
52
 
77
53
  /**
78
- * A helper for casting types not supported by SQLite.
79
- * SQLite doesn't support Date nor Boolean types, so Evolu emulates them
80
- * with {@link SqliteBoolean} and {@link SqliteDate}.
54
+ * A helper for casting types not supported by SQLite. SQLite doesn't support
55
+ * Date nor Boolean types, so Evolu emulates them with {@link SqliteBoolean} and
56
+ * {@link SqliteDate}.
81
57
  *
82
58
  * ### Example
83
59
  *
84
- * ```
85
- * // isDeleted is SqliteBoolean
86
- * .where("isDeleted", "is not", cast(true))
60
+ * ```ts
61
+ * const allTodosNotDeleted = evolu.createQuery((db) =>
62
+ * db
63
+ * .selectFrom("todo")
64
+ * .selectAll()
65
+ * // isDeleted is SqliteBoolean
66
+ * .where("isDeleted", "is not", Evolu.cast(true)),
67
+ * );
87
68
  * ```
88
69
  */
89
70
  export function cast(value: boolean): SqliteBoolean;
@@ -101,13 +82,13 @@ export function cast(
101
82
  }
102
83
 
103
84
  /**
104
- * String schema represents a string that is not stringified JSON. Using
105
- * String schema for strings stored in SQLite is crucial to ensure a stored
106
- * string is not automatically parsed to a JSON object or array when
107
- * retrieved. Use String schema for all string-based schemas.
85
+ * String schema represents a string that is not stringified JSON. Using String
86
+ * schema for strings stored in SQLite is crucial to ensure a stored string is
87
+ * not automatically parsed to a JSON object or array when retrieved. Use String
88
+ * schema for all string-based schemas.
108
89
  */
109
- export const String = Schema.string.pipe(
110
- Schema.filter(
90
+ export const String = S.string.pipe(
91
+ S.filter(
111
92
  (s) => {
112
93
  if (!maybeJson(s)) return true;
113
94
  try {
@@ -119,65 +100,59 @@ export const String = Schema.string.pipe(
119
100
  },
120
101
  { message: () => "a string that is not stringified JSON" },
121
102
  ),
122
- Schema.brand("String"),
103
+ S.brand("String"),
123
104
  );
124
- export type String = Schema.Schema.To<typeof String>;
105
+ export type String = S.Schema.To<typeof String>;
125
106
 
126
107
  /**
127
108
  * A string with a maximum length of 1000 characters.
128
109
  *
129
110
  * ### Example
130
111
  *
131
- * ```
132
- * import * as Schema from "@effect/schema/Schema";
112
+ * ```ts
113
+ * import * as S from "@effect/schema/Schema";
133
114
  * import * as Evolu from "@evolu/react";
134
115
  *
135
- * if (!Schema.is(Evolu.String1000)(value)) return;
136
- * function foo(value: Evolu.String1000) {}
116
+ * S.parse(Evolu.String1000)(value);
137
117
  * ```
138
118
  */
139
- export const String1000 = String.pipe(
140
- Schema.maxLength(1000),
141
- Schema.brand("String1000"),
142
- );
143
- export type String1000 = Schema.Schema.To<typeof String1000>;
119
+ export const String1000 = String.pipe(S.maxLength(1000), S.brand("String1000"));
120
+ export type String1000 = S.Schema.To<typeof String1000>;
144
121
 
145
122
  /**
146
123
  * A nonempty string with a maximum length of 1000 characters.
147
124
  *
148
125
  * ### Example
149
126
  *
150
- * ```
151
- * import * as Schema from "@effect/schema/Schema";
127
+ * ```ts
128
+ * import * as S from "@effect/schema/Schema";
152
129
  * import * as Evolu from "@evolu/react";
153
130
  *
154
- * if (!Schema.is(Evolu.NonEmptyString1000)(value)) return;
155
- * function foo(value: Evolu.NonEmptyString1000) {}
131
+ * S.parse(Evolu.NonEmptyString1000)(value);
156
132
  * ```
157
133
  */
158
134
  export const NonEmptyString1000 = String.pipe(
159
- Schema.minLength(1),
160
- Schema.maxLength(1000),
161
- Schema.brand("NonEmptyString1000"),
135
+ S.minLength(1),
136
+ S.maxLength(1000),
137
+ S.brand("NonEmptyString1000"),
162
138
  );
163
- export type NonEmptyString1000 = Schema.Schema.To<typeof NonEmptyString1000>;
139
+ export type NonEmptyString1000 = S.Schema.To<typeof NonEmptyString1000>;
164
140
 
165
141
  /**
166
142
  * A positive integer.
167
143
  *
168
144
  * ### Example
169
145
  *
170
- * ```
171
- * import * as Schema from "@effect/schema/Schema";
146
+ * ```ts
147
+ * import * as S from "@effect/schema/Schema";
172
148
  * import * as Evolu from "@evolu/react";
173
149
  *
174
- * if (!Schema.is(Evolu.PositiveInt)(value)) return;
175
- * function foo(value: Evolu.PositiveInt) {}
150
+ * S.parse(Evolu.PositiveInt)(value);
176
151
  * ```
177
152
  */
178
- export const PositiveInt = Schema.number.pipe(
179
- Schema.int(),
180
- Schema.positive(),
181
- Schema.brand("PositiveInt"),
153
+ export const PositiveInt = S.number.pipe(
154
+ S.int(),
155
+ S.positive(),
156
+ S.brand("PositiveInt"),
182
157
  );
183
- export type PositiveInt = Schema.Schema.To<typeof PositiveInt>;
158
+ export type PositiveInt = S.Schema.To<typeof PositiveInt>;
@@ -0,0 +1,46 @@
1
+ import { Brand, Context, Effect, Layer, Option, ReadonlyArray } from "effect";
2
+ import { NanoId } from "./Crypto.js";
3
+
4
+ export interface OnCompletes {
5
+ readonly add: (
6
+ onComplete: OnComplete,
7
+ ) => Effect.Effect<never, never, OnCompleteId>;
8
+
9
+ readonly complete: (
10
+ onCompleteIds: readonly OnCompleteId[],
11
+ ) => Effect.Effect<never, never, void>;
12
+ }
13
+
14
+ export type OnComplete = () => void;
15
+
16
+ export type OnCompleteId = string & Brand.Brand<"OnCompleteId">;
17
+
18
+ export const OnCompletes = Context.Tag<OnCompletes>();
19
+
20
+ export const OnCompletesLive = Layer.effect(
21
+ OnCompletes,
22
+ Effect.gen(function* (_) {
23
+ const nanoid = yield* _(NanoId);
24
+ const map = new Map<OnCompleteId, OnComplete>();
25
+
26
+ return OnCompletes.of({
27
+ add: (onComplete) =>
28
+ nanoid.nanoid.pipe(
29
+ Effect.map((nanoid) => {
30
+ const id = nanoid as OnCompleteId;
31
+ map.set(id, onComplete);
32
+ return id;
33
+ }),
34
+ ),
35
+
36
+ complete: (onCompleteIds) =>
37
+ Effect.sync(() => {
38
+ ReadonlyArray.filterMap(onCompleteIds, (id) => {
39
+ const onComplete = map.get(id);
40
+ map.delete(id);
41
+ return Option.fromNullable(onComplete);
42
+ }).forEach((onComplete) => onComplete());
43
+ }),
44
+ });
45
+ }),
46
+ );
package/src/Owner.ts ADDED
@@ -0,0 +1,65 @@
1
+ import { Brand, Context, Effect } from "effect";
2
+ import { urlAlphabet } from "nanoid";
3
+ import { Bip39, Mnemonic, slip21Derive } from "./Crypto.js";
4
+ import { Id } from "./Model.js";
5
+
6
+ /**
7
+ * The Owner represents the Evolu database owner, a user. Instead of traditional
8
+ * email with a password, the Owner uses a mnemonic, also known as a "seed
9
+ * phrase," which is a set of 12 words in a specific order chosen from a
10
+ * predefined list.
11
+ *
12
+ * The purpose of the BIP39 mnemonic is to provide a human-readable way of
13
+ * storing a private key.
14
+ *
15
+ * Mnemonic is generated safely in the user's device and must not be shared with
16
+ * anyone.
17
+ */
18
+ export interface Owner {
19
+ /** The {@link Mnemonic} associated with {@link Owner}. */
20
+ readonly mnemonic: Mnemonic;
21
+
22
+ /** The unique identifier safely derived from {@link Mnemonic}. */
23
+ readonly id: OwnerId;
24
+
25
+ /** The encryption key safely derived from {@link Mnemonic}. */
26
+ readonly encryptionKey: Uint8Array;
27
+ }
28
+
29
+ export const Owner = Context.Tag<Owner>();
30
+
31
+ /**
32
+ * The unique identifier of {@link Owner} safely derived from its
33
+ * {@link Mnemonic}.
34
+ */
35
+ export type OwnerId = Id & Brand.Brand<"Owner">;
36
+
37
+ export const makeOwner = (
38
+ mnemonic?: Mnemonic,
39
+ ): Effect.Effect<Bip39, never, Owner> =>
40
+ Effect.gen(function* (_) {
41
+ const bip39 = yield* _(Bip39);
42
+
43
+ if (mnemonic == null) mnemonic = yield* _(bip39.make);
44
+
45
+ const seed = yield* _(bip39.toSeed(mnemonic));
46
+
47
+ const id = yield* _(
48
+ slip21Derive(seed, ["Evolu", "Owner Id"]).pipe(
49
+ Effect.map((key) => {
50
+ // convert key to nanoid
51
+ let id = "";
52
+ for (let i = 0; i < 21; i++) {
53
+ id += urlAlphabet[key[i] & 63];
54
+ }
55
+ return id as OwnerId;
56
+ }),
57
+ ),
58
+ );
59
+
60
+ const encryptionKey = yield* _(
61
+ slip21Derive(seed, ["Evolu", "Encryption Key"]),
62
+ );
63
+
64
+ return { mnemonic, id, encryptionKey };
65
+ });
package/src/Platform.ts CHANGED
@@ -1,36 +1,40 @@
1
1
  import { Context, Effect, Layer } from "effect";
2
2
 
3
- export interface Platform {
4
- readonly name:
5
- | "server"
6
- | "web-with-opfs"
7
- | "web-without-opfs"
8
- | "react-native";
9
- }
3
+ export type PlatformName =
4
+ | "server"
5
+ | "web-with-opfs"
6
+ | "web-without-opfs"
7
+ | "react-native";
10
8
 
11
- export const Platform = Context.Tag<Platform>("evolu/Platform");
9
+ export const PlatformName = Context.Tag<PlatformName>();
12
10
 
13
11
  export type FlushSync = (callback: () => void) => void;
14
12
 
15
- export const FlushSync = Context.Tag<FlushSync>("evolu/FlushSync");
13
+ export const FlushSync = Context.Tag<FlushSync>();
16
14
 
17
15
  export interface SyncLock {
16
+ /**
17
+ * Try to acquire a sync lock. The caller must not call sync if a sync lock
18
+ * can't be acquired.
19
+ */
18
20
  readonly acquire: Effect.Effect<never, never, boolean>;
21
+
22
+ /** Release a sync lock. */
19
23
  readonly release: Effect.Effect<never, never, void>;
20
24
  }
21
25
 
22
- export const SyncLock = Context.Tag<SyncLock>("evolu/SyncLock");
26
+ export const SyncLock = Context.Tag<SyncLock>();
23
27
 
24
28
  export type Fetch = (
25
29
  url: string,
26
30
  body: Uint8Array,
27
31
  ) => Effect.Effect<never, FetchError, Response>;
28
32
 
29
- export const Fetch = Context.Tag<Fetch>("evolu/Fetch");
33
+ export const Fetch = Context.Tag<Fetch>();
30
34
 
31
35
  /**
32
- * This error occurs when there is a problem with the network connection,
33
- * or the server cannot be reached.
36
+ * This error occurs when there is a problem with the network connection, or the
37
+ * server cannot be reached.
34
38
  */
35
39
  export interface FetchError {
36
40
  readonly _tag: "FetchError";
@@ -54,13 +58,17 @@ export const FetchLive = Layer.succeed(
54
58
  ),
55
59
  );
56
60
 
61
+ interface AppStateConfig {
62
+ readonly onFocus: () => void;
63
+ readonly onReconnect: () => void;
64
+ }
65
+
57
66
  export interface AppState {
58
- readonly onFocus: (callback: () => void) => void;
59
- readonly onReconnect: (callback: () => void) => void;
67
+ readonly init: (config: AppStateConfig) => void;
60
68
  readonly reset: Effect.Effect<never, never, void>;
61
69
  }
62
70
 
63
- export const AppState = Context.Tag<AppState>("evolu/AppState");
71
+ export const AppState = Context.Tag<AppState>();
64
72
 
65
73
  /**
66
74
  * To detect whether DOM can be used.
package/src/Protobuf.ts CHANGED
@@ -5,101 +5,61 @@
5
5
  import { MessageType } from "@protobuf-ts/runtime";
6
6
  import { MerkleTreeString, TimestampString } from "./Crdt.js";
7
7
  import { NodeId } from "./Crypto.js";
8
- import { OwnerId } from "./Db.js";
8
+ import { OwnerId } from "./Owner.js";
9
9
  import { Id } from "./Model.js";
10
- /**
11
- * @generated from protobuf message SyncRequest
12
- */
10
+ /** @generated from protobuf message SyncRequest */
13
11
  export interface SyncRequest {
14
- /**
15
- * @generated from protobuf field: repeated EncryptedMessage messages = 1;
16
- */
12
+ /** @generated from protobuf field: repeated EncryptedMessage messages = 1; */
17
13
  messages: ReadonlyArray<EncryptedMessage>;
18
- /**
19
- * @generated from protobuf field: string userId = 2;
20
- */
14
+ /** @generated from protobuf field: string userId = 2; */
21
15
  userId: OwnerId;
22
- /**
23
- * @generated from protobuf field: string nodeId = 3;
24
- */
16
+ /** @generated from protobuf field: string nodeId = 3; */
25
17
  nodeId: NodeId;
26
- /**
27
- * @generated from protobuf field: string merkleTree = 4;
28
- */
18
+ /** @generated from protobuf field: string merkleTree = 4; */
29
19
  merkleTree: MerkleTreeString;
30
20
  }
31
- /**
32
- * @generated from protobuf message SyncResponse
33
- */
21
+ /** @generated from protobuf message SyncResponse */
34
22
  export interface SyncResponse {
35
- /**
36
- * @generated from protobuf field: repeated EncryptedMessage messages = 1;
37
- */
23
+ /** @generated from protobuf field: repeated EncryptedMessage messages = 1; */
38
24
  messages: ReadonlyArray<EncryptedMessage>;
39
- /**
40
- * @generated from protobuf field: string merkleTree = 2;
41
- */
25
+ /** @generated from protobuf field: string merkleTree = 2; */
42
26
  merkleTree: MerkleTreeString;
43
27
  }
44
- /**
45
- * @generated from protobuf message EncryptedMessage
46
- */
28
+ /** @generated from protobuf message EncryptedMessage */
47
29
  export interface EncryptedMessage {
48
- /**
49
- * @generated from protobuf field: string timestamp = 1;
50
- */
30
+ /** @generated from protobuf field: string timestamp = 1; */
51
31
  timestamp: TimestampString;
52
- /**
53
- * @generated from protobuf field: bytes content = 2;
54
- */
32
+ /** @generated from protobuf field: bytes content = 2; */
55
33
  content: Uint8Array;
56
34
  }
57
- /**
58
- * @generated from protobuf message MessageContent
59
- */
35
+ /** @generated from protobuf message MessageContent */
60
36
  export interface MessageContent {
61
- /**
62
- * @generated from protobuf field: string table = 1;
63
- */
37
+ /** @generated from protobuf field: string table = 1; */
64
38
  table: string;
65
- /**
66
- * @generated from protobuf field: string row = 2;
67
- */
39
+ /** @generated from protobuf field: string row = 2; */
68
40
  row: Id;
69
- /**
70
- * @generated from protobuf field: string column = 3;
71
- */
41
+ /** @generated from protobuf field: string column = 3; */
72
42
  column: string;
73
- /**
74
- * @generated from protobuf oneof: value
75
- */
43
+ /** @generated from protobuf oneof: value */
76
44
  value:
77
45
  | {
78
46
  oneofKind: "stringValue";
79
- /**
80
- * @generated from protobuf field: string stringValue = 4;
81
- */
47
+ /** @generated from protobuf field: string stringValue = 4; */
82
48
  stringValue: string;
83
49
  }
84
50
  | {
85
51
  oneofKind: "numberValue";
86
- /**
87
- * @generated from protobuf field: int32 numberValue = 5;
88
- */
52
+ /** @generated from protobuf field: int32 numberValue = 5; */
89
53
  numberValue: number;
90
54
  }
91
55
  | {
92
56
  oneofKind: "bytesValue";
93
- /**
94
- * @generated from protobuf field: bytes bytesValue = 6;
95
- */
57
+ /** @generated from protobuf field: bytes bytesValue = 6; */
96
58
  bytesValue: Uint8Array;
97
59
  }
98
60
  | {
99
61
  oneofKind: "jsonValue";
100
- /**
101
- * @generated from protobuf field: string jsonValue = 7;
102
- */
62
+ /** @generated from protobuf field: string jsonValue = 7; */
103
63
  jsonValue: string;
104
64
  }
105
65
  | {
@@ -123,9 +83,7 @@ class SyncRequest$Type extends MessageType<SyncRequest> {
123
83
  ]);
124
84
  }
125
85
  }
126
- /**
127
- * @generated MessageType for protobuf message SyncRequest
128
- */
86
+ /** @generated MessageType for protobuf message SyncRequest */
129
87
  export const SyncRequest = new SyncRequest$Type();
130
88
  // @generated message type with reflection information, may provide speed optimized methods
131
89
  class SyncResponse$Type extends MessageType<SyncResponse> {
@@ -142,9 +100,7 @@ class SyncResponse$Type extends MessageType<SyncResponse> {
142
100
  ]);
143
101
  }
144
102
  }
145
- /**
146
- * @generated MessageType for protobuf message SyncResponse
147
- */
103
+ /** @generated MessageType for protobuf message SyncResponse */
148
104
  export const SyncResponse = new SyncResponse$Type();
149
105
  // @generated message type with reflection information, may provide speed optimized methods
150
106
  class EncryptedMessage$Type extends MessageType<EncryptedMessage> {
@@ -155,9 +111,7 @@ class EncryptedMessage$Type extends MessageType<EncryptedMessage> {
155
111
  ]);
156
112
  }
157
113
  }
158
- /**
159
- * @generated MessageType for protobuf message EncryptedMessage
160
- */
114
+ /** @generated MessageType for protobuf message EncryptedMessage */
161
115
  export const EncryptedMessage = new EncryptedMessage$Type();
162
116
  // @generated message type with reflection information, may provide speed optimized methods
163
117
  class MessageContent$Type extends MessageType<MessageContent> {
@@ -197,7 +151,5 @@ class MessageContent$Type extends MessageType<MessageContent> {
197
151
  ]);
198
152
  }
199
153
  }
200
- /**
201
- * @generated MessageType for protobuf message MessageContent
202
- */
154
+ /** @generated MessageType for protobuf message MessageContent */
203
155
  export const MessageContent = new MessageContent$Type();
package/src/Public.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  export { jsonArrayFrom, jsonObjectFrom } from "kysely/helpers/sqlite";
2
- export type { Mnemonic } from "./Crypto.js";
3
- export type { Owner, OwnerId } from "./Db.js";
4
- export type { EvoluError } from "./Errors.js";
2
+ export type { Timestamp, TimestampError } from "./Crdt.js";
3
+ export type { Mnemonic, InvalidMnemonicError } from "./Crypto.js";
4
+ export type { EvoluError, UnexpectedError } from "./ErrorStore.js";
5
5
  export * from "./Model.js";
6
+ export type { Owner, OwnerId } from "./Owner.js";
7
+ export { canUseDom } from "./Platform.js";
6
8
  export type { SyncState } from "./SyncWorker.js";
package/src/Sqlite.ts CHANGED
@@ -1,45 +1,37 @@
1
- import { Brand, Context, Effect, Predicate, ReadonlyRecord } from "effect";
1
+ import { Context, Effect, Predicate, ReadonlyRecord } from "effect";
2
2
 
3
3
  export interface Sqlite {
4
4
  readonly exec: (
5
- arg: string | QueryObject,
5
+ arg: string | SqliteQuery,
6
6
  ) => Effect.Effect<never, never, ExecResult>;
7
7
  }
8
8
 
9
- export const Sqlite = Context.Tag<Sqlite>("evolu/Sqlite");
9
+ export const Sqlite = Context.Tag<Sqlite>();
10
10
 
11
- export interface QueryObject {
11
+ export interface SqliteQuery {
12
12
  readonly sql: string;
13
- readonly parameters: ReadonlyArray<Value>;
13
+ readonly parameters: Value[];
14
14
  }
15
15
 
16
16
  export type Value = SqliteValue | JsonObjectOrArray;
17
-
18
17
  export type SqliteValue = null | string | number | Uint8Array;
19
- export type SqliteRow = Record<string, SqliteValue>;
20
-
21
18
  export type JsonObjectOrArray = JsonObject | JsonArray;
22
-
23
19
  type JsonObject = ReadonlyRecord.ReadonlyRecord<Json>;
24
20
  type JsonArray = ReadonlyArray<Json>;
25
21
  type Json = string | number | boolean | null | JsonObject | JsonArray;
26
22
 
27
23
  interface ExecResult {
28
- readonly rows: ReadonlyArray<Row>;
24
+ readonly rows: SqliteRow[];
29
25
  readonly changes: number;
30
26
  }
31
27
 
32
- export type Row = ReadonlyRecord.ReadonlyRecord<
33
- Value | Row | ReadonlyArray<Row>
34
- >;
35
-
36
- export type Query = string & Brand.Brand<"Query">;
28
+ export type SqliteRow = Record<string, SqliteValue>;
37
29
 
38
30
  export const isJsonObjectOrArray: Predicate.Refinement<
39
31
  Value,
40
32
  JsonObjectOrArray
41
33
  > = (value): value is JsonObjectOrArray =>
42
- value !== null && typeof value === "object" && !(value instanceof Uint8Array);
34
+ value !== null && typeof value === "object" && !Predicate.isUint8Array(value);
43
35
 
44
36
  export const valuesToSqliteValues = (
45
37
  values: ReadonlyArray<Value>,
@@ -48,15 +40,13 @@ export const valuesToSqliteValues = (
48
40
  isJsonObjectOrArray(value) ? JSON.stringify(value) : value,
49
41
  );
50
42
 
51
- export const queryObjectToQuery = ({ sql, parameters }: QueryObject): Query =>
52
- JSON.stringify({ sql, parameters }) as Query;
53
-
54
- export const queryObjectFromQuery = (s: Query): QueryObject =>
55
- JSON.parse(s) as QueryObject;
43
+ export const ensureSqliteQuery = (arg: string | SqliteQuery): SqliteQuery => {
44
+ if (typeof arg !== "string") return arg;
45
+ return { sql: arg, parameters: [] };
46
+ };
56
47
 
57
- export const parseJsonResults = (rows: SqliteRow[]): void => {
48
+ export const maybeParseJson = (rows: SqliteRow[]): SqliteRow[] =>
58
49
  parseArray(rows);
59
- };
60
50
 
61
51
  const parseArray = <T>(a: T[]): T[] => {
62
52
  for (let i = 0; i < a.length; ++i) a[i] = parse(a[i]) as T;
@@ -67,7 +57,6 @@ const parse = (o: unknown): unknown => {
67
57
  if (Predicate.isString(o)) return parseString(o);
68
58
  // eslint-disable-next-line @typescript-eslint/no-unsafe-return
69
59
  if (Array.isArray(o)) return parseArray(o);
70
- // Predicate.isReadonlyRecord
71
60
  if (typeof o === "object" && o !== null && !Predicate.isUint8Array(o))
72
61
  return parseObject(o as Record<string, unknown>);
73
62
  return o;