@evolu/common 5.4.7 → 6.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 (242) hide show
  1. package/README.md +30 -34
  2. package/dist/src/Array.d.ts +17 -0
  3. package/dist/src/Array.d.ts.map +1 -0
  4. package/dist/src/Array.js +12 -0
  5. package/dist/src/Assert.d.ts +68 -0
  6. package/dist/src/Assert.d.ts.map +1 -0
  7. package/dist/src/Assert.js +77 -0
  8. package/dist/src/BigInt.d.ts +20 -0
  9. package/dist/src/BigInt.d.ts.map +1 -0
  10. package/dist/src/BigInt.js +18 -0
  11. package/dist/src/Buffer.d.ts +92 -0
  12. package/dist/src/Buffer.d.ts.map +1 -0
  13. package/dist/src/Buffer.js +62 -0
  14. package/dist/src/Callbacks.d.ts +20 -0
  15. package/dist/src/Callbacks.d.ts.map +1 -0
  16. package/dist/src/Callbacks.js +18 -0
  17. package/dist/src/Console.d.ts +78 -0
  18. package/dist/src/Console.d.ts.map +1 -0
  19. package/dist/src/Console.js +103 -0
  20. package/dist/src/Crypto.d.ts +72 -39
  21. package/dist/src/Crypto.d.ts.map +1 -1
  22. package/dist/src/Crypto.js +89 -54
  23. package/dist/src/Eq.d.ts +97 -0
  24. package/dist/src/Eq.d.ts.map +1 -0
  25. package/dist/src/Eq.js +167 -0
  26. package/dist/src/Error.d.ts +14 -10
  27. package/dist/src/Error.d.ts.map +1 -1
  28. package/dist/src/Error.js +43 -11
  29. package/dist/src/Evolu/Config.d.ts +69 -0
  30. package/dist/src/Evolu/Config.d.ts.map +1 -0
  31. package/dist/src/Evolu/Config.js +9 -0
  32. package/dist/src/Evolu/Db.d.ts +126 -0
  33. package/dist/src/Evolu/Db.d.ts.map +1 -0
  34. package/dist/src/Evolu/Db.js +774 -0
  35. package/dist/src/Evolu/Diff.d.ts +43 -0
  36. package/dist/src/Evolu/Diff.d.ts.map +1 -0
  37. package/dist/src/Evolu/Diff.js +95 -0
  38. package/dist/src/Evolu/Evolu.d.ts +334 -0
  39. package/dist/src/Evolu/Evolu.d.ts.map +1 -0
  40. package/dist/src/Evolu/Evolu.js +434 -0
  41. package/dist/src/Evolu/Internal.d.ts +26 -0
  42. package/dist/src/Evolu/Internal.d.ts.map +1 -0
  43. package/dist/src/Evolu/Internal.js +25 -0
  44. package/dist/src/Evolu/Kysely.d.ts +6 -0
  45. package/dist/src/Evolu/Kysely.d.ts.map +1 -0
  46. package/dist/src/Evolu/Kysely.js +21 -0
  47. package/dist/src/Evolu/Owner.d.ts +155 -0
  48. package/dist/src/Evolu/Owner.d.ts.map +1 -0
  49. package/dist/src/Evolu/Owner.js +126 -0
  50. package/dist/src/Evolu/Platform.d.ts +23 -0
  51. package/dist/src/Evolu/Platform.d.ts.map +1 -0
  52. package/dist/src/Evolu/Platform.js +1 -0
  53. package/dist/src/Evolu/Protocol.d.ts +401 -0
  54. package/dist/src/Evolu/Protocol.d.ts.map +1 -0
  55. package/dist/src/Evolu/Protocol.js +1151 -0
  56. package/dist/src/Evolu/Public.d.ts +18 -0
  57. package/dist/src/Evolu/Public.d.ts.map +1 -0
  58. package/dist/src/Evolu/Public.js +11 -0
  59. package/dist/src/Evolu/PublicKysely.d.ts +148 -0
  60. package/dist/src/Evolu/PublicKysely.d.ts.map +1 -0
  61. package/dist/src/Evolu/PublicKysely.js +185 -0
  62. package/dist/src/Evolu/Query.d.ts +63 -0
  63. package/dist/src/Evolu/Query.d.ts.map +1 -0
  64. package/dist/src/Evolu/Query.js +61 -0
  65. package/dist/src/Evolu/Relay.d.ts +13 -0
  66. package/dist/src/Evolu/Relay.d.ts.map +1 -0
  67. package/dist/src/Evolu/Relay.js +109 -0
  68. package/dist/src/Evolu/Schema.d.ts +201 -0
  69. package/dist/src/Evolu/Schema.d.ts.map +1 -0
  70. package/dist/src/Evolu/Schema.js +150 -0
  71. package/dist/src/Evolu/Storage.d.ts +49 -0
  72. package/dist/src/Evolu/Storage.d.ts.map +1 -0
  73. package/dist/src/Evolu/Storage.js +1111 -0
  74. package/dist/src/Evolu/Sync.d.ts +59 -0
  75. package/dist/src/Evolu/Sync.d.ts.map +1 -0
  76. package/dist/src/Evolu/Sync.js +29 -0
  77. package/dist/src/Evolu/Timestamp.d.ts +106 -0
  78. package/dist/src/Evolu/Timestamp.d.ts.map +1 -0
  79. package/dist/src/Evolu/Timestamp.js +179 -0
  80. package/dist/src/Function.d.ts +54 -0
  81. package/dist/src/Function.d.ts.map +1 -0
  82. package/dist/src/Function.js +38 -0
  83. package/dist/src/ManyToManyMap.d.ts +26 -0
  84. package/dist/src/ManyToManyMap.d.ts.map +1 -0
  85. package/dist/src/ManyToManyMap.js +92 -0
  86. package/dist/src/NanoId.d.ts +27 -0
  87. package/dist/src/NanoId.d.ts.map +1 -0
  88. package/dist/src/NanoId.js +6 -0
  89. package/dist/src/Number.d.ts +42 -0
  90. package/dist/src/Number.d.ts.map +1 -0
  91. package/dist/src/Number.js +55 -0
  92. package/dist/src/Object.d.ts +35 -0
  93. package/dist/src/Object.d.ts.map +1 -0
  94. package/dist/src/Object.js +36 -0
  95. package/dist/src/Order.d.ts +90 -0
  96. package/dist/src/Order.d.ts.map +1 -0
  97. package/dist/src/Order.js +85 -0
  98. package/dist/src/Promise.d.ts +180 -0
  99. package/dist/src/Promise.d.ts.map +1 -0
  100. package/dist/src/Promise.js +176 -0
  101. package/dist/src/Random.d.ts +52 -0
  102. package/dist/src/Random.d.ts.map +1 -0
  103. package/dist/src/Random.js +29 -0
  104. package/dist/src/Ref.d.ts +40 -0
  105. package/dist/src/Ref.d.ts.map +1 -0
  106. package/dist/src/Ref.js +13 -0
  107. package/dist/src/Result.d.ts +421 -0
  108. package/dist/src/Result.d.ts.map +1 -0
  109. package/dist/src/Result.js +357 -0
  110. package/dist/src/Skiplist.d.ts +23 -0
  111. package/dist/src/Skiplist.d.ts.map +1 -0
  112. package/dist/src/Skiplist.js +58 -0
  113. package/dist/src/Sqlite.d.ts +116 -52
  114. package/dist/src/Sqlite.d.ts.map +1 -1
  115. package/dist/src/Sqlite.js +183 -67
  116. package/dist/src/Store.d.ts +45 -8
  117. package/dist/src/Store.d.ts.map +1 -1
  118. package/dist/src/Store.js +33 -17
  119. package/dist/src/String.d.ts +2 -0
  120. package/dist/src/String.d.ts.map +1 -0
  121. package/dist/src/String.js +14 -0
  122. package/dist/src/Time.d.ts +20 -0
  123. package/dist/src/Time.d.ts.map +1 -0
  124. package/dist/src/Time.js +25 -0
  125. package/dist/src/Type.d.ts +1937 -0
  126. package/dist/src/Type.d.ts.map +1 -0
  127. package/dist/src/Type.js +2002 -0
  128. package/dist/src/Types.d.ts +188 -0
  129. package/dist/src/Types.d.ts.map +1 -0
  130. package/dist/src/Types.js +6 -0
  131. package/dist/src/WebSocket.d.ts +112 -0
  132. package/dist/src/WebSocket.d.ts.map +1 -0
  133. package/dist/src/WebSocket.js +139 -0
  134. package/dist/src/Worker.d.ts +44 -0
  135. package/dist/src/Worker.d.ts.map +1 -0
  136. package/dist/src/Worker.js +66 -0
  137. package/dist/src/index.d.ts +24 -11
  138. package/dist/src/index.d.ts.map +1 -1
  139. package/dist/src/index.js +24 -11
  140. package/package.json +29 -38
  141. package/src/Array.ts +39 -0
  142. package/src/Assert.ts +116 -0
  143. package/src/BigInt.ts +29 -0
  144. package/src/Buffer.ts +175 -0
  145. package/src/Callbacks.ts +43 -0
  146. package/src/Console.ts +159 -0
  147. package/src/Crypto.ts +169 -115
  148. package/src/Eq.ts +204 -0
  149. package/src/Error.ts +57 -20
  150. package/src/Evolu/Config.ts +83 -0
  151. package/src/Evolu/Db.ts +1275 -0
  152. package/src/Evolu/Diff.ts +142 -0
  153. package/src/Evolu/Evolu.ts +947 -0
  154. package/src/Evolu/Internal.ts +26 -0
  155. package/src/Evolu/Kysely.ts +38 -0
  156. package/src/Evolu/Owner.ts +296 -0
  157. package/src/Evolu/Platform.ts +27 -0
  158. package/src/Evolu/Protocol.ts +1857 -0
  159. package/src/Evolu/Public.ts +43 -0
  160. package/src/Evolu/PublicKysely.ts +240 -0
  161. package/src/Evolu/Query.ts +167 -0
  162. package/src/Evolu/Relay.ts +142 -0
  163. package/src/Evolu/Schema.ts +417 -0
  164. package/src/Evolu/Storage.ts +1281 -0
  165. package/src/Evolu/Sync.ts +105 -0
  166. package/src/Evolu/Timestamp.ts +311 -0
  167. package/src/Function.ts +58 -0
  168. package/src/ManyToManyMap.ts +140 -0
  169. package/src/NanoId.ts +39 -0
  170. package/src/Number.ts +90 -0
  171. package/src/Object.ts +64 -0
  172. package/src/Order.ts +113 -0
  173. package/src/Promise.ts +295 -0
  174. package/src/Random.ts +68 -0
  175. package/src/Ref.ts +63 -0
  176. package/src/Result.ts +453 -0
  177. package/src/Skiplist.ts +102 -0
  178. package/src/Sqlite.ts +366 -153
  179. package/src/Store.ts +79 -36
  180. package/src/String.ts +10 -0
  181. package/src/Time.ts +36 -0
  182. package/src/Type.ts +3978 -0
  183. package/src/Types.ts +209 -0
  184. package/src/WebSocket.ts +273 -0
  185. package/src/Worker.ts +129 -0
  186. package/src/index.ts +24 -11
  187. package/dist/src/Config.d.ts +0 -56
  188. package/dist/src/Config.d.ts.map +0 -1
  189. package/dist/src/Config.js +0 -39
  190. package/dist/src/Crdt.d.ts +0 -89
  191. package/dist/src/Crdt.d.ts.map +0 -1
  192. package/dist/src/Crdt.js +0 -181
  193. package/dist/src/Db.d.ts +0 -107
  194. package/dist/src/Db.d.ts.map +0 -1
  195. package/dist/src/Db.js +0 -443
  196. package/dist/src/Diff.d.ts +0 -27
  197. package/dist/src/Diff.d.ts.map +0 -1
  198. package/dist/src/Diff.js +0 -84
  199. package/dist/src/Evolu.d.ts +0 -426
  200. package/dist/src/Evolu.d.ts.map +0 -1
  201. package/dist/src/Evolu.js +0 -333
  202. package/dist/src/Model.d.ts +0 -141
  203. package/dist/src/Model.d.ts.map +0 -1
  204. package/dist/src/Model.js +0 -125
  205. package/dist/src/Murmurhash.d.ts +0 -2
  206. package/dist/src/Murmurhash.d.ts.map +0 -1
  207. package/dist/src/Murmurhash.js +0 -60
  208. package/dist/src/Owner.d.ts +0 -33
  209. package/dist/src/Owner.d.ts.map +0 -1
  210. package/dist/src/Owner.js +0 -26
  211. package/dist/src/Platform.d.ts +0 -37
  212. package/dist/src/Platform.d.ts.map +0 -1
  213. package/dist/src/Platform.js +0 -11
  214. package/dist/src/Protobuf.d.ts +0 -81
  215. package/dist/src/Protobuf.d.ts.map +0 -1
  216. package/dist/src/Protobuf.js +0 -92
  217. package/dist/src/Public.d.ts +0 -13
  218. package/dist/src/Public.d.ts.map +0 -1
  219. package/dist/src/Public.js +0 -6
  220. package/dist/src/Socket.d.ts +0 -8
  221. package/dist/src/Socket.d.ts.map +0 -1
  222. package/dist/src/Socket.js +0 -51
  223. package/dist/src/Sql.d.ts +0 -12
  224. package/dist/src/Sql.d.ts.map +0 -1
  225. package/dist/src/Sql.js +0 -30
  226. package/dist/src/Sync.d.ts +0 -70
  227. package/dist/src/Sync.d.ts.map +0 -1
  228. package/dist/src/Sync.js +0 -127
  229. package/src/Config.ts +0 -119
  230. package/src/Crdt.ts +0 -361
  231. package/src/Db.ts +0 -955
  232. package/src/Diff.ts +0 -114
  233. package/src/Evolu.ts +0 -1016
  234. package/src/Model.ts +0 -233
  235. package/src/Murmurhash.ts +0 -70
  236. package/src/Owner.ts +0 -69
  237. package/src/Platform.ts +0 -47
  238. package/src/Protobuf.ts +0 -155
  239. package/src/Public.ts +0 -12
  240. package/src/Socket.ts +0 -83
  241. package/src/Sql.ts +0 -41
  242. package/src/Sync.ts +0 -315
@@ -0,0 +1,18 @@
1
+ /**
2
+ * 💾
3
+ *
4
+ * @module
5
+ */
6
+ export { createEvolu } from "./Evolu.js";
7
+ export type { Evolu, EvoluConfigWithInitialData, EvoluDeps, EvoluError, } from "./Evolu.js";
8
+ export * from "./Owner.js";
9
+ export { binaryIdToId, idToBinaryId } from "./Protocol.js";
10
+ export type { BinaryId } from "./Protocol.js";
11
+ export * as kysely from "./PublicKysely.js";
12
+ export type { InferRow, Query, QueryRows, Row } from "./Query.js";
13
+ export { formatValidMutationSizeError } from "./Schema.js";
14
+ export type { EvoluSchema, ValidMutationSizeError } from "./Schema.js";
15
+ export type { NetworkError, PaymentRequiredError, ServerError, SyncState, SyncStateInitial, SyncStateIsNotSynced, SyncStateIsSynced, SyncStateIsSyncing, } from "./Sync.js";
16
+ export { binaryTimestampToTimestamp, Timestamp, timestampToBinaryTimestamp, } from "./Timestamp.js";
17
+ export type { BinaryTimestamp, TimestampCounterOverflowError, TimestampDriftError, TimestampDuplicateNodeError, TimestampError, TimestampTimeOutOfRangeError, } from "./Timestamp.js";
18
+ //# sourceMappingURL=Public.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Public.d.ts","sourceRoot":"","sources":["../../../src/Evolu/Public.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,YAAY,EACV,KAAK,EACL,0BAA0B,EAC1B,SAAS,EACT,UAAU,GACX,MAAM,YAAY,CAAC;AACpB,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC3D,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,MAAM,MAAM,mBAAmB,CAAC;AAC5C,YAAY,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,EAAE,4BAA4B,EAAE,MAAM,aAAa,CAAC;AAC3D,YAAY,EAAE,WAAW,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACvE,YAAY,EACV,YAAY,EACZ,oBAAoB,EACpB,WAAW,EACX,SAAS,EACT,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,0BAA0B,EAC1B,SAAS,EACT,0BAA0B,GAC3B,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,eAAe,EACf,6BAA6B,EAC7B,mBAAmB,EACnB,2BAA2B,EAC3B,cAAc,EACd,4BAA4B,GAC7B,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * 💾
3
+ *
4
+ * @module
5
+ */
6
+ export { createEvolu } from "./Evolu.js";
7
+ export * from "./Owner.js";
8
+ export { binaryIdToId, idToBinaryId } from "./Protocol.js";
9
+ export * as kysely from "./PublicKysely.js";
10
+ export { formatValidMutationSizeError } from "./Schema.js";
11
+ export { binaryTimestampToTimestamp, Timestamp, timestampToBinaryTimestamp, } from "./Timestamp.js";
@@ -0,0 +1,148 @@
1
+ import { AliasableExpression, Expression, RawBuilder, SelectQueryNode, Simplify } from "kysely";
2
+ export { sql } from "kysely";
3
+ export type { NotNull } from "kysely";
4
+ /**
5
+ * A SQLite helper for aggregating a subquery into a JSON array.
6
+ *
7
+ * ### Examples
8
+ *
9
+ * ```ts
10
+ * import { kysely } from "@evolu/common";
11
+ *
12
+ * // TODO: Update for Evolu
13
+ * const result = await db
14
+ * .selectFrom("person")
15
+ * .select((eb) => [
16
+ * "id",
17
+ * kysely
18
+ * .jsonArrayFrom(
19
+ * eb
20
+ * .selectFrom("pet")
21
+ * .select(["pet.id as pet_id", "pet.name"])
22
+ * .whereRef("pet.owner_id", "=", "person.id")
23
+ * .orderBy("pet.name"),
24
+ * )
25
+ * .as("pets"),
26
+ * ])
27
+ * .execute();
28
+ *
29
+ * result[0]?.id;
30
+ * result[0]?.pets[0].pet_id;
31
+ * result[0]?.pets[0].name;
32
+ * ```
33
+ *
34
+ * The generated SQL (SQLite):
35
+ *
36
+ * ```sql
37
+ * select "id", (
38
+ * select coalesce(json_group_array(json_object(
39
+ * 'pet_id', "agg"."pet_id",
40
+ * 'name', "agg"."name"
41
+ * )), '[]') from (
42
+ * select "pet"."id" as "pet_id", "pet"."name"
43
+ * from "pet"
44
+ * where "pet"."owner_id" = "person"."id"
45
+ * order by "pet"."name"
46
+ * ) as "agg"
47
+ * ) as "pets"
48
+ * from "person"
49
+ * ```
50
+ */
51
+ export declare function jsonArrayFrom<O>(expr: SelectQueryBuilderExpression<O>): RawBuilder<Array<Simplify<O>>>;
52
+ /**
53
+ * A SQLite helper for turning a subquery into a JSON object.
54
+ *
55
+ * The subquery must only return one row.
56
+ *
57
+ * ### Examples
58
+ *
59
+ * ```ts
60
+ * import { kysely } from "@evolu/common";
61
+ *
62
+ * // TODO: Update for Evolu
63
+ * const result = await db
64
+ * .selectFrom("person")
65
+ * .select((eb) => [
66
+ * "id",
67
+ * jsonObjectFrom(
68
+ * eb
69
+ * .selectFrom("pet")
70
+ * .select(["pet.id as pet_id", "pet.name"])
71
+ * .whereRef("pet.owner_id", "=", "person.id")
72
+ * .where("pet.is_favorite", "=", true),
73
+ * ).as("favorite_pet"),
74
+ * ])
75
+ * .execute();
76
+ *
77
+ * result[0]?.id;
78
+ * result[0]?.favorite_pet?.pet_id;
79
+ * result[0]?.favorite_pet?.name;
80
+ * ```
81
+ *
82
+ * The generated SQL (SQLite):
83
+ *
84
+ * ```sql
85
+ * select "id", (
86
+ * select json_object(
87
+ * 'pet_id', "obj"."pet_id",
88
+ * 'name', "obj"."name"
89
+ * ) from (
90
+ * select "pet"."id" as "pet_id", "pet"."name"
91
+ * from "pet"
92
+ * where "pet"."owner_id" = "person"."id"
93
+ * and "pet"."is_favorite" = ?
94
+ * ) as obj
95
+ * ) as "favorite_pet"
96
+ * from "person";
97
+ * ```
98
+ */
99
+ export declare function jsonObjectFrom<O>(expr: SelectQueryBuilderExpression<O>): RawBuilder<Simplify<O> | null>;
100
+ /**
101
+ * The SQLite `json_object` function.
102
+ *
103
+ * ### Examples
104
+ *
105
+ * ```ts
106
+ * import { kysely } from "@evolu/common";
107
+ *
108
+ * // TODO: Update for Evolu
109
+ * const result = await db
110
+ * .selectFrom("person")
111
+ * .select((eb) => [
112
+ * "id",
113
+ * kysely
114
+ * .jsonBuildObject({
115
+ * first: eb.ref("first_name"),
116
+ * last: eb.ref("last_name"),
117
+ * full: kysely.sql<string>`first_name || ' ' || last_name`,
118
+ * })
119
+ * .as("name"),
120
+ * ])
121
+ * .execute();
122
+ *
123
+ * result[0]?.id;
124
+ * result[0]?.name.first;
125
+ * result[0]?.name.last;
126
+ * result[0]?.name.full;
127
+ * ```
128
+ *
129
+ * The generated SQL (SQLite):
130
+ *
131
+ * ```sql
132
+ * select "id", json_object(
133
+ * 'first', first_name,
134
+ * 'last', last_name,
135
+ * 'full', "first_name" || ' ' || "last_name"
136
+ * ) as "name"
137
+ * from "person"
138
+ * ```
139
+ */
140
+ export declare function jsonBuildObject<O extends Record<string, Expression<unknown>>>(obj: O): RawBuilder<Simplify<{
141
+ [K in keyof O]: O[K] extends Expression<infer V> ? V : never;
142
+ }>>;
143
+ interface SelectQueryBuilderExpression<O> extends AliasableExpression<O> {
144
+ get isSelectQueryBuilder(): true;
145
+ toOperationNode(): SelectQueryNode;
146
+ }
147
+ export declare function getJsonObjectArgs(node: SelectQueryNode, table: string): Array<Expression<unknown> | string>;
148
+ //# sourceMappingURL=PublicKysely.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PublicKysely.d.ts","sourceRoot":"","sources":["../../../src/Evolu/PublicKysely.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EAGnB,UAAU,EAGV,UAAU,EAEV,eAAe,EACf,QAAQ,EAIT,MAAM,QAAQ,CAAC;AAGhB,OAAO,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAC7B,YAAY,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAGH,wBAAgB,aAAa,CAAC,CAAC,EAC3B,IAAI,EAAE,4BAA4B,CAAC,CAAC,CAAC,GACpC,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAIhC;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAGH,wBAAgB,cAAc,CAAC,CAAC,EAC5B,IAAI,EAAE,4BAA4B,CAAC,CAAC,CAAC,GACpC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAIhC;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAGH,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,EACzE,GAAG,EAAE,CAAC,GACL,UAAU,CACX,QAAQ,CAAC;KACN,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK;CAC7D,CAAC,CACH,CAIA;AAEH,UAAU,4BAA4B,CAAC,CAAC,CAAE,SAAQ,mBAAmB,CAAC,CAAC,CAAC;IACtE,IAAI,oBAAoB,IAAI,IAAI,CAAC;IACjC,eAAe,IAAI,eAAe,CAAC;CACpC;AAeD,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,eAAe,EACrB,KAAK,EAAE,MAAM,GACZ,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,MAAM,CAAC,CAoBrC"}
@@ -0,0 +1,185 @@
1
+ import { AliasNode, ColumnNode, ExpressionWrapper, IdentifierNode, ReferenceNode, sql, TableNode, ValueNode, } from "kysely";
2
+ import { kyselyJsonIdentifier } from "./Diff.js";
3
+ export { sql } from "kysely";
4
+ /**
5
+ * A SQLite helper for aggregating a subquery into a JSON array.
6
+ *
7
+ * ### Examples
8
+ *
9
+ * ```ts
10
+ * import { kysely } from "@evolu/common";
11
+ *
12
+ * // TODO: Update for Evolu
13
+ * const result = await db
14
+ * .selectFrom("person")
15
+ * .select((eb) => [
16
+ * "id",
17
+ * kysely
18
+ * .jsonArrayFrom(
19
+ * eb
20
+ * .selectFrom("pet")
21
+ * .select(["pet.id as pet_id", "pet.name"])
22
+ * .whereRef("pet.owner_id", "=", "person.id")
23
+ * .orderBy("pet.name"),
24
+ * )
25
+ * .as("pets"),
26
+ * ])
27
+ * .execute();
28
+ *
29
+ * result[0]?.id;
30
+ * result[0]?.pets[0].pet_id;
31
+ * result[0]?.pets[0].name;
32
+ * ```
33
+ *
34
+ * The generated SQL (SQLite):
35
+ *
36
+ * ```sql
37
+ * select "id", (
38
+ * select coalesce(json_group_array(json_object(
39
+ * 'pet_id', "agg"."pet_id",
40
+ * 'name', "agg"."name"
41
+ * )), '[]') from (
42
+ * select "pet"."id" as "pet_id", "pet"."name"
43
+ * from "pet"
44
+ * where "pet"."owner_id" = "person"."id"
45
+ * order by "pet"."name"
46
+ * ) as "agg"
47
+ * ) as "pets"
48
+ * from "person"
49
+ * ```
50
+ */
51
+ // SQL formatting breaks generated SQL for some reason.
52
+ // prettier-ignore
53
+ export function jsonArrayFrom(expr) {
54
+ return sql `(select ${sql.lit(kyselyJsonIdentifier)} || coalesce(json_group_array(json_object(${sql.join(getSqliteJsonObjectArgs(expr.toOperationNode(), 'agg'))})), '[]') from ${expr} as agg)`;
55
+ }
56
+ /**
57
+ * A SQLite helper for turning a subquery into a JSON object.
58
+ *
59
+ * The subquery must only return one row.
60
+ *
61
+ * ### Examples
62
+ *
63
+ * ```ts
64
+ * import { kysely } from "@evolu/common";
65
+ *
66
+ * // TODO: Update for Evolu
67
+ * const result = await db
68
+ * .selectFrom("person")
69
+ * .select((eb) => [
70
+ * "id",
71
+ * jsonObjectFrom(
72
+ * eb
73
+ * .selectFrom("pet")
74
+ * .select(["pet.id as pet_id", "pet.name"])
75
+ * .whereRef("pet.owner_id", "=", "person.id")
76
+ * .where("pet.is_favorite", "=", true),
77
+ * ).as("favorite_pet"),
78
+ * ])
79
+ * .execute();
80
+ *
81
+ * result[0]?.id;
82
+ * result[0]?.favorite_pet?.pet_id;
83
+ * result[0]?.favorite_pet?.name;
84
+ * ```
85
+ *
86
+ * The generated SQL (SQLite):
87
+ *
88
+ * ```sql
89
+ * select "id", (
90
+ * select json_object(
91
+ * 'pet_id', "obj"."pet_id",
92
+ * 'name', "obj"."name"
93
+ * ) from (
94
+ * select "pet"."id" as "pet_id", "pet"."name"
95
+ * from "pet"
96
+ * where "pet"."owner_id" = "person"."id"
97
+ * and "pet"."is_favorite" = ?
98
+ * ) as obj
99
+ * ) as "favorite_pet"
100
+ * from "person";
101
+ * ```
102
+ */
103
+ // SQL formatting breaks generated SQL for some reason.
104
+ // prettier-ignore
105
+ export function jsonObjectFrom(expr) {
106
+ return sql `(select ${sql.lit(kyselyJsonIdentifier)} || json_object(${sql.join(getSqliteJsonObjectArgs(expr.toOperationNode(), 'obj'))}) from ${expr} as obj)`;
107
+ }
108
+ /**
109
+ * The SQLite `json_object` function.
110
+ *
111
+ * ### Examples
112
+ *
113
+ * ```ts
114
+ * import { kysely } from "@evolu/common";
115
+ *
116
+ * // TODO: Update for Evolu
117
+ * const result = await db
118
+ * .selectFrom("person")
119
+ * .select((eb) => [
120
+ * "id",
121
+ * kysely
122
+ * .jsonBuildObject({
123
+ * first: eb.ref("first_name"),
124
+ * last: eb.ref("last_name"),
125
+ * full: kysely.sql<string>`first_name || ' ' || last_name`,
126
+ * })
127
+ * .as("name"),
128
+ * ])
129
+ * .execute();
130
+ *
131
+ * result[0]?.id;
132
+ * result[0]?.name.first;
133
+ * result[0]?.name.last;
134
+ * result[0]?.name.full;
135
+ * ```
136
+ *
137
+ * The generated SQL (SQLite):
138
+ *
139
+ * ```sql
140
+ * select "id", json_object(
141
+ * 'first', first_name,
142
+ * 'last', last_name,
143
+ * 'full', "first_name" || ' ' || "last_name"
144
+ * ) as "name"
145
+ * from "person"
146
+ * ```
147
+ */
148
+ // SQL formatting breaks generated SQL for some reason.
149
+ // prettier-ignore
150
+ export function jsonBuildObject(obj) {
151
+ return sql `${sql.lit(kyselyJsonIdentifier)} || json_object(${sql.join(Object.keys(obj).flatMap((k) => [sql.lit(k), obj[k]]))})`;
152
+ }
153
+ function getSqliteJsonObjectArgs(node, table) {
154
+ try {
155
+ return getJsonObjectArgs(node, table);
156
+ }
157
+ catch {
158
+ throw new Error("SQLite jsonArrayFrom and jsonObjectFrom functions can only handle explicit selections due to limitations of the json_object function. selectAll() is not allowed in the subquery.");
159
+ }
160
+ }
161
+ export function getJsonObjectArgs(node, table) {
162
+ const args = [];
163
+ args.push(kyselyJsonIdentifier, kyselyJsonIdentifier);
164
+ for (const { selection: s } of node.selections ?? []) {
165
+ if (ReferenceNode.is(s) && ColumnNode.is(s.column)) {
166
+ args.push(colName(s.column.column.name), colRef(table, s.column.column.name));
167
+ }
168
+ else if (ColumnNode.is(s)) {
169
+ args.push(colName(s.column.name), colRef(table, s.column.name));
170
+ }
171
+ else if (AliasNode.is(s) && IdentifierNode.is(s.alias)) {
172
+ args.push(colName(s.alias.name), colRef(table, s.alias.name));
173
+ }
174
+ else {
175
+ throw new Error(`can't extract column names from the select query node`);
176
+ }
177
+ }
178
+ return args;
179
+ }
180
+ function colName(col) {
181
+ return new ExpressionWrapper(ValueNode.createImmediate(col));
182
+ }
183
+ function colRef(table, col) {
184
+ return new ExpressionWrapper(ReferenceNode.create(ColumnNode.create(col), TableNode.create(table)));
185
+ }
@@ -0,0 +1,63 @@
1
+ import { SqliteQuery, SqliteRow, SqliteValue } from "../Sqlite.js";
2
+ import { Store, StoreSubscribe } from "../Store.js";
3
+ import { Brand, Simplify } from "../Types.js";
4
+ /**
5
+ * A type-safe SQL query.
6
+ *
7
+ * ### Example
8
+ *
9
+ * ```ts
10
+ * const allTodos = evolu.createQuery((db) =>
11
+ * db.selectFrom("todo").selectAll(),
12
+ * );
13
+ * type AllTodosRow = typeof allTodos.Row;
14
+ * ```
15
+ */
16
+ export type Query<R extends Row = Row> = string & Brand<"Query"> & {
17
+ /**
18
+ * A shorthand for {@link InferRow}.
19
+ *
20
+ * ### Example
21
+ *
22
+ * ```ts
23
+ * const allTodos = evolu.createQuery((db) =>
24
+ * db.selectFrom("todo").selectAll(),
25
+ * );
26
+ * type AllTodosRow = typeof allTodos.Row;
27
+ * ```
28
+ */
29
+ Row: R;
30
+ };
31
+ /**
32
+ * Evolu serializes {@link SqliteQuery} into a string to be easily used as a key
33
+ * and for comparison.
34
+ */
35
+ export declare const serializeQuery: <R extends Row>(query: SqliteQuery) => Query<R>;
36
+ export declare const deserializeQuery: <R extends Row>(query: Query<R>) => SqliteQuery;
37
+ export type InferRow<T extends Query> = T extends Query<infer R> ? R : never;
38
+ export interface Row {
39
+ readonly [key: string]: SqliteValue | Row | ReadonlyArray<Row>;
40
+ }
41
+ export declare const emptyRows: ReadonlyArray<Row>;
42
+ /** Rows returned by a query. */
43
+ export type QueryRows<R extends Row = Row> = ReadonlyArray<Readonly<Simplify<R>>>;
44
+ export type Queries<R extends Row = Row> = ReadonlyArray<Query<R>>;
45
+ export type QueriesToQueryRows<Q extends Queries> = {
46
+ [P in keyof Q]: Q[P] extends Query<infer R> ? QueryRows<R> : never;
47
+ };
48
+ export type QueriesToQueryRowsPromises<Q extends Queries> = {
49
+ [P in keyof Q]: Q[P] extends Query<infer R> ? Promise<QueryRows<R>> : never;
50
+ };
51
+ export type QueryRowsMap = ReadonlyMap<Query, ReadonlyArray<Row>>;
52
+ export interface QueryRowsCache {
53
+ readonly set: (queriesRows: ReadonlyArray<readonly [Query, ReadonlyArray<SqliteRow>]>) => void;
54
+ readonly get: () => QueryRowsMap;
55
+ }
56
+ export declare const createQueryRowsCache: () => QueryRowsCache;
57
+ export interface SubscribedQueries {
58
+ subscribe: (query: Query) => StoreSubscribe;
59
+ has: (query: Query) => boolean;
60
+ get: () => ReadonlyArray<Query>;
61
+ }
62
+ export declare const createSubscribedQueries: (rowsStore: Store<QueryRowsMap>) => SubscribedQueries;
63
+ //# sourceMappingURL=Query.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Query.d.ts","sourceRoot":"","sources":["../../../src/Evolu/Query.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,WAAW,EAEX,SAAS,EACT,WAAW,EACZ,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE9C;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,KAAK,CAAC,CAAC,SAAS,GAAG,GAAG,GAAG,IAAI,MAAM,GAC7C,KAAK,CAAC,OAAO,CAAC,GAAG;IACf;;;;;;;;;;;OAWG;IACH,GAAG,EAAE,CAAC,CAAC;CACR,CAAC;AAEJ;;;GAGG;AACH,eAAO,MAAM,cAAc,GAAI,CAAC,SAAS,GAAG,EAAE,OAAO,WAAW,KAAG,KAAK,CAAC,CAAC,CAYzE,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,CAAC,SAAS,GAAG,EAC5C,OAAO,KAAK,CAAC,CAAC,CAAC,KACd,WAoBF,CAAC;AAEF,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS,KAAK,IAAI,CAAC,SAAS,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAE7E,MAAM,WAAW,GAAG;IAClB,QAAQ,EAAE,GAAG,EAAE,MAAM,GACjB,WAAW,GACX,GAAG,GACH,aAAa,CAAC,GAAG,CAAC,CAAC;CACxB;AAGD,eAAO,MAAM,SAAS,EAAE,aAAa,CAAC,GAAG,CAAM,CAAC;AAEhD,gCAAgC;AAChC,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,GAAG,GAAG,GAAG,IAAI,aAAa,CACxD,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CACtB,CAAC;AAEF,MAAM,MAAM,OAAO,CAAC,CAAC,SAAS,GAAG,GAAG,GAAG,IAAI,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAEnE,MAAM,MAAM,kBAAkB,CAAC,CAAC,SAAS,OAAO,IAAI;KACjD,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,KAAK;CACnE,CAAC;AAEF,MAAM,MAAM,0BAA0B,CAAC,CAAC,SAAS,OAAO,IAAI;KACzD,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK;CAC5E,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,WAAW,CAAC,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC;AAElE,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,GAAG,EAAE,CACZ,WAAW,EAAE,aAAa,CAAC,SAAS,CAAC,KAAK,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,KACnE,IAAI,CAAC;IACV,QAAQ,CAAC,GAAG,EAAE,MAAM,YAAY,CAAC;CAClC;AAED,eAAO,MAAM,oBAAoB,QAAO,cAWvC,CAAC;AAEF,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,cAAc,CAAC;IAE5C,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC;IAE/B,GAAG,EAAE,MAAM,aAAa,CAAC,KAAK,CAAC,CAAC;CACjC;AAED,eAAO,MAAM,uBAAuB,GAClC,WAAW,KAAK,CAAC,YAAY,CAAC,KAC7B,iBAwBF,CAAC"}
@@ -0,0 +1,61 @@
1
+ import { bytesToHex, hexToBytes } from "../Buffer.js";
2
+ import { objectToEntries } from "../Object.js";
3
+ /**
4
+ * Evolu serializes {@link SqliteQuery} into a string to be easily used as a key
5
+ * and for comparison.
6
+ */
7
+ export const serializeQuery = (query) => {
8
+ const params = query.parameters.map((v) => v instanceof Uint8Array
9
+ ? ["b", bytesToHex(v)]
10
+ : ["j", v]);
11
+ const options = query.options
12
+ ? objectToEntries(query.options).sort(([a], [b]) => a.localeCompare(b))
13
+ : [];
14
+ return JSON.stringify([query.sql, params, options]);
15
+ };
16
+ export const deserializeQuery = (query) => {
17
+ const [sql, paramsArr, optionsArr] = JSON.parse(query);
18
+ const parameters = paramsArr.map(([type, value]) => type === "b" ? hexToBytes(value) : value);
19
+ const options = optionsArr.length
20
+ ? Object.fromEntries(optionsArr)
21
+ : undefined;
22
+ return {
23
+ sql,
24
+ parameters,
25
+ ...(options !== undefined && { options }),
26
+ };
27
+ };
28
+ // To preserve identity.
29
+ export const emptyRows = [];
30
+ export const createQueryRowsCache = () => {
31
+ let queryRowsCache = new Map();
32
+ const cache = {
33
+ set: (queriesRows) => {
34
+ queryRowsCache = new Map([...queryRowsCache, ...queriesRows]);
35
+ },
36
+ get: () => queryRowsCache,
37
+ };
38
+ return cache;
39
+ };
40
+ export const createSubscribedQueries = (rowsStore) => {
41
+ const subscribedQueryMap = new Map();
42
+ const subscribedQueries = {
43
+ subscribe: (query) => (listener) => {
44
+ subscribedQueryMap.set(query, (subscribedQueryMap.get(query) ?? 0) + 1);
45
+ const unsubscribe = rowsStore.subscribe(listener);
46
+ return () => {
47
+ const count = subscribedQueryMap.get(query);
48
+ if (count != null && count > 1) {
49
+ subscribedQueryMap.set(query, count - 1);
50
+ }
51
+ else {
52
+ subscribedQueryMap.delete(query);
53
+ }
54
+ unsubscribe();
55
+ };
56
+ },
57
+ get: () => [...subscribedQueryMap.keys()],
58
+ has: (query) => subscribedQueryMap.has(query),
59
+ };
60
+ return subscribedQueries;
61
+ };
@@ -0,0 +1,13 @@
1
+ import { ConsoleConfig } from "../Console.js";
2
+ import { Result } from "../Result.js";
3
+ import { SqliteError } from "../Sqlite.js";
4
+ import { SimpleName } from "../Type.js";
5
+ import { Storage } from "./Protocol.js";
6
+ import { CreateSqliteStorageBaseOptions, SqliteStorageDeps } from "./Storage.js";
7
+ export interface Relay extends Disposable {
8
+ }
9
+ export interface RelayConfig extends ConsoleConfig {
10
+ readonly name?: SimpleName;
11
+ }
12
+ export declare const createRelayStorage: (deps: SqliteStorageDeps) => (options: CreateSqliteStorageBaseOptions) => Result<Storage, SqliteError>;
13
+ //# sourceMappingURL=Relay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Relay.d.ts","sourceRoot":"","sources":["../../../src/Evolu/Relay.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,OAAO,EAAM,MAAM,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAO,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,OAAO,EAAqB,OAAO,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EAEL,8BAA8B,EAC9B,iBAAiB,EAClB,MAAM,cAAc,CAAC;AAGtB,MAAM,WAAW,KAAM,SAAQ,UAAU;CAAG;AAE5C,MAAM,WAAW,WAAY,SAAQ,aAAa;IAChD,QAAQ,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC;CAC5B;AAED,eAAO,MAAM,kBAAkB,GAC5B,MAAM,iBAAiB,MACvB,SAAS,8BAA8B,KAAG,MAAM,CAAC,OAAO,EAAE,WAAW,CAsHrE,CAAC"}
@@ -0,0 +1,109 @@
1
+ import { isNonEmptyReadonlyArray } from "../Array.js";
2
+ import { eqArrayNumber } from "../Eq.js";
3
+ import { ok } from "../Result.js";
4
+ import { sql } from "../Sqlite.js";
5
+ import { createSqliteStorageBase, } from "./Storage.js";
6
+ import { timestampToBinaryTimestamp } from "./Timestamp.js";
7
+ export const createRelayStorage = (deps) => (options) => {
8
+ const sqliteStorageBase = createSqliteStorageBase(deps)(options);
9
+ if (!sqliteStorageBase.ok)
10
+ return sqliteStorageBase;
11
+ for (const query of [
12
+ sql `
13
+ create table if not exists evolu_writeKey (
14
+ "ownerId" blob not null,
15
+ "writeKey" blob not null,
16
+ primary key ("ownerId")
17
+ )
18
+ strict;
19
+ `,
20
+ sql `
21
+ create table if not exists evolu_message (
22
+ "ownerId" blob not null,
23
+ "timestamp" blob not null,
24
+ "change" blob not null,
25
+ primary key ("ownerId", "timestamp")
26
+ )
27
+ strict;
28
+ `,
29
+ ]) {
30
+ const result = deps.sqlite.exec(query);
31
+ if (!result.ok)
32
+ return result;
33
+ }
34
+ return ok({
35
+ ...sqliteStorageBase.value,
36
+ /**
37
+ * Lazily authorizes the initiator's {@link WriteKey} for the given
38
+ * {@link OwnerId}.
39
+ *
40
+ * - If the {@link OwnerId} does not exist, it is created and associated with
41
+ * the provided write key.
42
+ * - If the {@link OwnerId} exists, the provided write key is compared to the
43
+ * stored key.
44
+ */
45
+ validateWriteKey: (ownerId, writeKey) => {
46
+ const selectWriteKey = deps.sqlite.exec(sql `
47
+ select writeKey
48
+ from evolu_writeKey
49
+ where ownerId = ${ownerId};
50
+ `);
51
+ if (!selectWriteKey.ok) {
52
+ options.onStorageError(selectWriteKey.error);
53
+ return false;
54
+ }
55
+ const { rows } = selectWriteKey.value;
56
+ if (!isNonEmptyReadonlyArray(rows)) {
57
+ const insertWriteKey = deps.sqlite.exec(sql `
58
+ insert into evolu_writeKey (ownerId, writeKey)
59
+ values (${ownerId}, ${writeKey});
60
+ `);
61
+ if (!insertWriteKey.ok) {
62
+ options.onStorageError(insertWriteKey.error);
63
+ return false;
64
+ }
65
+ return true;
66
+ }
67
+ return eqArrayNumber(rows[0].writeKey, writeKey);
68
+ },
69
+ writeMessages: (ownerId, messages) => {
70
+ const result = deps.sqlite.transaction(() => {
71
+ for (const message of messages) {
72
+ const insertTimestampResult = sqliteStorageBase.value.insertTimestamp(ownerId, timestampToBinaryTimestamp(message.timestamp));
73
+ if (!insertTimestampResult.ok)
74
+ return insertTimestampResult;
75
+ const insertMessage = deps.sqlite.exec(sql `
76
+ insert into evolu_message ("ownerId", "timestamp", "change")
77
+ values
78
+ (
79
+ ${ownerId},
80
+ ${timestampToBinaryTimestamp(message.timestamp)},
81
+ ${message.change}
82
+ )
83
+ on conflict do nothing;
84
+ `);
85
+ if (!insertMessage.ok)
86
+ return insertMessage;
87
+ }
88
+ return ok();
89
+ });
90
+ if (!result.ok) {
91
+ options.onStorageError(result.error);
92
+ return false;
93
+ }
94
+ return true;
95
+ },
96
+ readDbChange: (ownerId, timestamp) => {
97
+ const result = deps.sqlite.exec(sql `
98
+ select "change"
99
+ from evolu_message
100
+ where "ownerId" = ${ownerId} and "timestamp" = ${timestamp};
101
+ `);
102
+ if (!result.ok) {
103
+ options.onStorageError(result.error);
104
+ return null;
105
+ }
106
+ return result.value.rows[0]?.change;
107
+ },
108
+ });
109
+ };