@evolu/common 7.4.0 → 8.0.0-next.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 (251) hide show
  1. package/README.md +4 -61
  2. package/dist/src/Array.d.ts +343 -102
  3. package/dist/src/Array.d.ts.map +1 -1
  4. package/dist/src/Array.js +181 -85
  5. package/dist/src/Assert.d.ts +57 -11
  6. package/dist/src/Assert.d.ts.map +1 -1
  7. package/dist/src/Assert.js +47 -11
  8. package/dist/src/BigInt.d.ts +6 -1
  9. package/dist/src/BigInt.d.ts.map +1 -1
  10. package/dist/src/BigInt.js +5 -0
  11. package/dist/src/Brand.d.ts +40 -12
  12. package/dist/src/Brand.d.ts.map +1 -1
  13. package/dist/src/Brand.js +5 -0
  14. package/dist/src/Buffer.d.ts +6 -1
  15. package/dist/src/Buffer.d.ts.map +1 -1
  16. package/dist/src/Buffer.js +7 -2
  17. package/dist/src/Cache.d.ts +10 -2
  18. package/dist/src/Cache.d.ts.map +1 -1
  19. package/dist/src/Cache.js +6 -0
  20. package/dist/src/Callbacks.d.ts +10 -7
  21. package/dist/src/Callbacks.d.ts.map +1 -1
  22. package/dist/src/Callbacks.js +23 -13
  23. package/dist/src/Console.d.ts +361 -69
  24. package/dist/src/Console.d.ts.map +1 -1
  25. package/dist/src/Console.js +217 -117
  26. package/dist/src/Crypto.d.ts +70 -21
  27. package/dist/src/Crypto.d.ts.map +1 -1
  28. package/dist/src/Crypto.js +72 -27
  29. package/dist/src/Eq.d.ts +22 -2
  30. package/dist/src/Eq.d.ts.map +1 -1
  31. package/dist/src/Eq.js +21 -1
  32. package/dist/src/Error.d.ts +23 -12
  33. package/dist/src/Error.d.ts.map +1 -1
  34. package/dist/src/Error.js +27 -11
  35. package/dist/src/Function.d.ts +128 -56
  36. package/dist/src/Function.d.ts.map +1 -1
  37. package/dist/src/Function.js +118 -14
  38. package/dist/src/Identicon.d.ts +5 -0
  39. package/dist/src/Identicon.d.ts.map +1 -1
  40. package/dist/src/Identicon.js +6 -1
  41. package/dist/src/Lookup.d.ts +160 -0
  42. package/dist/src/Lookup.d.ts.map +1 -0
  43. package/dist/src/Lookup.js +192 -0
  44. package/dist/src/Microtask.d.ts +21 -0
  45. package/dist/src/Microtask.d.ts.map +1 -0
  46. package/dist/src/Microtask.js +37 -0
  47. package/dist/src/Number.d.ts +18 -4
  48. package/dist/src/Number.d.ts.map +1 -1
  49. package/dist/src/Number.js +23 -1
  50. package/dist/src/Object.d.ts +110 -5
  51. package/dist/src/Object.d.ts.map +1 -1
  52. package/dist/src/Object.js +108 -5
  53. package/dist/src/Option.d.ts +58 -0
  54. package/dist/src/Option.d.ts.map +1 -0
  55. package/dist/src/Option.js +43 -0
  56. package/dist/src/Order.d.ts +5 -0
  57. package/dist/src/Order.d.ts.map +1 -1
  58. package/dist/src/Order.js +8 -3
  59. package/dist/src/Platform.d.ts +36 -2
  60. package/dist/src/Platform.d.ts.map +1 -1
  61. package/dist/src/Platform.js +10 -6
  62. package/dist/src/Polyfills.d.ts +27 -0
  63. package/dist/src/Polyfills.d.ts.map +1 -0
  64. package/dist/src/Polyfills.js +299 -0
  65. package/dist/src/Random.d.ts +18 -7
  66. package/dist/src/Random.d.ts.map +1 -1
  67. package/dist/src/Random.js +9 -7
  68. package/dist/src/Redacted.d.ts +7 -4
  69. package/dist/src/Redacted.d.ts.map +1 -1
  70. package/dist/src/Redacted.js +5 -0
  71. package/dist/src/Ref.d.ts +31 -16
  72. package/dist/src/Ref.d.ts.map +1 -1
  73. package/dist/src/Ref.js +35 -7
  74. package/dist/src/RefCount.d.ts +62 -0
  75. package/dist/src/RefCount.d.ts.map +1 -0
  76. package/dist/src/RefCount.js +83 -0
  77. package/dist/src/Relation.d.ts +84 -29
  78. package/dist/src/Relation.d.ts.map +1 -1
  79. package/dist/src/Relation.js +83 -105
  80. package/dist/src/Resource.d.ts +263 -0
  81. package/dist/src/Resource.d.ts.map +1 -0
  82. package/dist/src/Resource.js +389 -0
  83. package/dist/src/Result.d.ts +390 -374
  84. package/dist/src/Result.d.ts.map +1 -1
  85. package/dist/src/Result.js +142 -70
  86. package/dist/src/Schedule.d.ts +953 -0
  87. package/dist/src/Schedule.d.ts.map +1 -0
  88. package/dist/src/Schedule.js +1199 -0
  89. package/dist/src/Set.d.ts +181 -0
  90. package/dist/src/Set.d.ts.map +1 -0
  91. package/dist/src/Set.js +137 -0
  92. package/dist/src/Skiplist.d.ts +6 -1
  93. package/dist/src/Skiplist.d.ts.map +1 -1
  94. package/dist/src/Skiplist.js +5 -0
  95. package/dist/src/Sqlite.d.ts +160 -60
  96. package/dist/src/Sqlite.d.ts.map +1 -1
  97. package/dist/src/Sqlite.js +290 -190
  98. package/dist/src/Store.d.ts +36 -28
  99. package/dist/src/Store.d.ts.map +1 -1
  100. package/dist/src/Store.js +55 -15
  101. package/dist/src/String.d.ts +5 -0
  102. package/dist/src/String.d.ts.map +1 -1
  103. package/dist/src/String.js +5 -0
  104. package/dist/src/Task.d.ts +2263 -423
  105. package/dist/src/Task.d.ts.map +1 -1
  106. package/dist/src/Task.js +1488 -348
  107. package/dist/src/Test.d.ts +122 -0
  108. package/dist/src/Test.d.ts.map +1 -0
  109. package/dist/src/Test.js +66 -0
  110. package/dist/src/Time.d.ts +201 -48
  111. package/dist/src/Time.d.ts.map +1 -1
  112. package/dist/src/Time.js +190 -86
  113. package/dist/src/Tracer.d.ts +48 -0
  114. package/dist/src/Tracer.d.ts.map +1 -0
  115. package/dist/src/Tracer.js +6 -0
  116. package/dist/src/Type.d.ts +582 -209
  117. package/dist/src/Type.d.ts.map +1 -1
  118. package/dist/src/Type.js +362 -240
  119. package/dist/src/Types.d.ts +160 -6
  120. package/dist/src/Types.d.ts.map +1 -1
  121. package/dist/src/Types.js +22 -2
  122. package/dist/src/WebSocket.d.ts +113 -58
  123. package/dist/src/WebSocket.d.ts.map +1 -1
  124. package/dist/src/WebSocket.js +210 -118
  125. package/dist/src/Worker.d.ts +245 -60
  126. package/dist/src/Worker.d.ts.map +1 -1
  127. package/dist/src/Worker.js +220 -64
  128. package/dist/src/index.d.ts +25 -3
  129. package/dist/src/index.d.ts.map +1 -1
  130. package/dist/src/index.js +19 -3
  131. package/dist/src/local-first/Db.d.ts +24 -213
  132. package/dist/src/local-first/Db.d.ts.map +1 -1
  133. package/dist/src/local-first/Db.js +622 -293
  134. package/dist/src/local-first/Error.d.ts +12 -0
  135. package/dist/src/local-first/Error.d.ts.map +1 -0
  136. package/dist/src/local-first/Error.js +6 -0
  137. package/dist/src/local-first/Evolu.d.ts +330 -285
  138. package/dist/src/local-first/Evolu.d.ts.map +1 -1
  139. package/dist/src/local-first/Evolu.js +472 -402
  140. package/dist/src/local-first/LocalAuth.d.ts +10 -10
  141. package/dist/src/local-first/LocalAuth.d.ts.map +1 -1
  142. package/dist/src/local-first/LocalAuth.js +6 -1
  143. package/dist/src/local-first/Owner.d.ts +70 -27
  144. package/dist/src/local-first/Owner.d.ts.map +1 -1
  145. package/dist/src/local-first/Owner.js +27 -14
  146. package/dist/src/local-first/Protocol.d.ts +58 -50
  147. package/dist/src/local-first/Protocol.d.ts.map +1 -1
  148. package/dist/src/local-first/Protocol.js +253 -155
  149. package/dist/src/local-first/Query.d.ts +133 -43
  150. package/dist/src/local-first/Query.d.ts.map +1 -1
  151. package/dist/src/local-first/Query.js +139 -90
  152. package/dist/src/local-first/Relay.d.ts +18 -38
  153. package/dist/src/local-first/Relay.d.ts.map +1 -1
  154. package/dist/src/local-first/Relay.js +59 -171
  155. package/dist/src/local-first/Schema.d.ts +139 -144
  156. package/dist/src/local-first/Schema.d.ts.map +1 -1
  157. package/dist/src/local-first/Schema.js +78 -163
  158. package/dist/src/local-first/Shared.d.ts +125 -0
  159. package/dist/src/local-first/Shared.d.ts.map +1 -0
  160. package/dist/src/local-first/Shared.js +569 -0
  161. package/dist/src/local-first/Storage.d.ts +50 -53
  162. package/dist/src/local-first/Storage.d.ts.map +1 -1
  163. package/dist/src/local-first/Storage.js +121 -173
  164. package/dist/src/local-first/Timestamp.d.ts +28 -35
  165. package/dist/src/local-first/Timestamp.d.ts.map +1 -1
  166. package/dist/src/local-first/Timestamp.js +24 -25
  167. package/dist/src/local-first/index.d.ts +2 -15
  168. package/dist/src/local-first/index.d.ts.map +1 -1
  169. package/dist/src/local-first/index.js +2 -15
  170. package/package.json +36 -26
  171. package/src/Array.ts +467 -106
  172. package/src/Assert.ts +87 -12
  173. package/src/BigInt.ts +7 -1
  174. package/src/Brand.ts +41 -12
  175. package/src/Buffer.ts +10 -4
  176. package/src/Cache.ts +11 -2
  177. package/src/Callbacks.ts +33 -23
  178. package/src/Console.ts +567 -178
  179. package/src/Crypto.ts +111 -62
  180. package/src/Eq.ts +30 -3
  181. package/src/Error.ts +50 -34
  182. package/src/Function.ts +140 -68
  183. package/src/Identicon.ts +7 -1
  184. package/src/Lookup.ts +415 -0
  185. package/src/Microtask.ts +58 -0
  186. package/src/Number.ts +40 -7
  187. package/src/Object.ts +155 -16
  188. package/src/Option.ts +74 -0
  189. package/src/Order.ts +11 -3
  190. package/src/Platform.ts +43 -7
  191. package/src/Polyfills.ts +465 -0
  192. package/src/Random.ts +25 -11
  193. package/src/Redacted.ts +8 -4
  194. package/src/Ref.ts +72 -21
  195. package/src/RefCount.ts +170 -0
  196. package/src/Relation.ts +188 -136
  197. package/src/Resource.ts +864 -0
  198. package/src/Result.ts +548 -381
  199. package/src/Schedule.ts +1471 -0
  200. package/src/Set.ts +247 -0
  201. package/src/Skiplist.ts +7 -1
  202. package/src/Sqlite.ts +409 -304
  203. package/src/Store.ts +94 -48
  204. package/src/String.ts +6 -0
  205. package/src/Task.ts +3685 -740
  206. package/src/Test.ts +162 -0
  207. package/src/Time.ts +348 -145
  208. package/src/Tracer.ts +54 -0
  209. package/src/Type.ts +1064 -630
  210. package/src/Types.ts +202 -7
  211. package/src/WebSocket.ts +311 -178
  212. package/src/Worker.ts +527 -147
  213. package/src/index.ts +74 -3
  214. package/src/local-first/Db.ts +871 -597
  215. package/src/local-first/Error.ts +17 -0
  216. package/src/local-first/Evolu.ts +884 -823
  217. package/src/local-first/LocalAuth.ts +10 -10
  218. package/src/local-first/Owner.ts +94 -42
  219. package/src/local-first/Protocol.ts +440 -303
  220. package/src/local-first/Query.ts +243 -194
  221. package/src/local-first/Relay.ts +91 -252
  222. package/src/local-first/Schema.ts +284 -394
  223. package/src/local-first/Shared.ts +932 -0
  224. package/src/local-first/Storage.ts +209 -282
  225. package/src/local-first/Timestamp.ts +38 -45
  226. package/src/local-first/index.ts +2 -16
  227. package/LICENSE +0 -21
  228. package/dist/src/Instances.d.ts +0 -34
  229. package/dist/src/Instances.d.ts.map +0 -1
  230. package/dist/src/Instances.js +0 -44
  231. package/dist/src/Resources.d.ts +0 -118
  232. package/dist/src/Resources.d.ts.map +0 -1
  233. package/dist/src/Resources.js +0 -197
  234. package/dist/src/local-first/Platform.d.ts +0 -25
  235. package/dist/src/local-first/Platform.d.ts.map +0 -1
  236. package/dist/src/local-first/Platform.js +0 -1
  237. package/dist/src/local-first/Public.d.ts +0 -22
  238. package/dist/src/local-first/Public.d.ts.map +0 -1
  239. package/dist/src/local-first/Public.js +0 -15
  240. package/dist/src/local-first/PublicKysely.d.ts +0 -148
  241. package/dist/src/local-first/PublicKysely.d.ts.map +0 -1
  242. package/dist/src/local-first/PublicKysely.js +0 -184
  243. package/dist/src/local-first/Sync.d.ts +0 -112
  244. package/dist/src/local-first/Sync.d.ts.map +0 -1
  245. package/dist/src/local-first/Sync.js +0 -529
  246. package/src/Instances.ts +0 -90
  247. package/src/Resources.ts +0 -367
  248. package/src/local-first/Platform.ts +0 -27
  249. package/src/local-first/Public.ts +0 -42
  250. package/src/local-first/PublicKysely.ts +0 -239
  251. package/src/local-first/Sync.ts +0 -960
@@ -1,170 +1,90 @@
1
+ /**
2
+ * Database schema definition and validation.
3
+ *
4
+ * @module
5
+ */
1
6
  import * as Kysely from "kysely";
2
- import { createRecord, getProperty, mapObject, } from "../Object.js";
3
- import { ok } from "../Result.js";
4
- import { sql, SqliteBoolean, } from "../Sqlite.js";
5
- import { array, DateIso, nullableToOptional, nullOr, object, omit, optional, record, set, String, validMutationSize, } from "../Type.js";
7
+ import { getProperty, mapObject } from "../Object.js";
8
+ import { eqSqliteIndex, getSqliteSchema, sql, sqliteQueryToSqliteQueryString, SqliteBoolean, SqliteValue, } from "../Sqlite.js";
9
+ import { DateIso, IdBytes, nullOr, object, } from "../Type.js";
6
10
  import { OwnerId } from "./Owner.js";
7
- import { readonly } from "../Function.js";
8
- export const evoluSchemaToDbSchema = (schema, indexesConfig) => {
9
- const tables = mapObject(schema, (table) => new Set(Object.keys(table).filter((k) => k !== "id")));
10
- const indexes = indexesConfig
11
- ? indexesConfig(createIndex).map((index) => ({
12
- name: index.toOperationNode().name.name,
13
- sql: index.compile().sql,
14
- }))
15
- : [];
16
- return { tables, indexes };
17
- };
11
+ import { TimestampBytes } from "./Timestamp.js";
18
12
  /**
19
13
  * System columns that are implicitly defined by Evolu.
20
14
  *
21
- * - `createdAt`: Set by Evolu on row creation, derived from {@link Timestamp}.
22
- * - `updatedAt`: Set by Evolu on every row change, derived from {@link Timestamp}.
15
+ * - `createdAt`: Set by Evolu on row creation, derived from Timestamp.
16
+ * - `updatedAt`: Set by Evolu on every row change, derived from Timestamp.
23
17
  * - `isDeleted`: Soft delete flag created by Evolu and used by the developer to
24
18
  * mark rows as deleted.
25
19
  * - `ownerId`: Represents ownership and logically partitions the database.
26
20
  */
27
- export const SystemColumns = object({
21
+ export const SystemColumns = /*#__PURE__*/ object({
28
22
  createdAt: DateIso,
29
23
  updatedAt: DateIso,
30
- isDeleted: nullOr(SqliteBoolean),
24
+ isDeleted: /*#__PURE__*/ nullOr(SqliteBoolean),
31
25
  ownerId: OwnerId,
32
26
  });
33
- export const systemColumns = readonly(new Set(Object.keys(SystemColumns.props)));
34
- export const systemColumnsWithId = readonly([...systemColumns, "id"]);
35
- /**
36
- * Type Factory to create insertable {@link Type}. It makes nullable Types
37
- * optional (so they are not required), omits Id, and ensures the
38
- * {@link maxMutationSize}.
39
- *
40
- * ### Example
41
- *
42
- * ```ts
43
- * const InsertableTodo = insertable(Schema.todo);
44
- * type InsertableTodo = typeof InsertableTodo.Type;
45
- * const todo = InsertableTodo.from({ title });
46
- * if (!todo.ok) return; // handle errors
47
- * ```
48
- */
49
- export const insertable = (props) => {
50
- const optionalNullable = nullableToOptional(props);
51
- const withoutId = omit(optionalNullable, "id");
52
- return validMutationSize(withoutId);
27
+ export const systemColumns = /*#__PURE__*/ new Set(
28
+ /*#__PURE__*/ Object.keys(SystemColumns.props));
29
+ export const systemColumnsWithId = [
30
+ ...systemColumns,
31
+ "id",
32
+ ];
33
+ export const evoluSchemaToSqliteSchema = (schema, indexesConfig) => {
34
+ const validSchema = schema;
35
+ const tables = mapObject(validSchema, (table) => new Set(Object.keys(table).filter((k) => k !== "id")));
36
+ const indexes = indexesConfig
37
+ ? indexesConfig(createIndex).map((index) => ({
38
+ name: index.toOperationNode().name.name,
39
+ sql: index.compile().sql,
40
+ }))
41
+ : [];
42
+ return { tables, indexes };
53
43
  };
54
44
  /**
55
- * Type Factory to create updateable {@link Type}. It makes everything except for
56
- * the `id` column optional (so they are not required) and ensures the
57
- * {@link maxMutationSize}.
45
+ * Creates a query builder from a {@link EvoluSchema}.
46
+ *
47
+ * Supports Kysely relation-style query composition (nested objects/arrays via
48
+ * JSON subqueries), such as {@link evoluJsonObjectFrom} and
49
+ * {@link evoluJsonArrayFrom}. These helpers are Evolu's safer SQLite variants of
50
+ * the
51
+ * {@link https://kysely.dev/docs/recipes/relations | Kysely relations recipe}.
58
52
  *
59
53
  * ### Example
60
54
  *
61
55
  * ```ts
62
- * const UpdateableTodo = updateable(Schema.todo);
63
- * type UpdateableTodo = typeof UpdateableTodo.Type;
64
- *
65
- * // `id` is required; all other fields are optional.
66
- * const todoResult = UpdateableTodo.from({
67
- * id: "123",
68
- * title: "New Title",
69
- * });
70
- * if (!todo.ok) return; // handle errors
71
- * ```
72
- */
73
- export const updateable = (props) => {
74
- const propsWithIsDeleted = { ...props, isDeleted: SqliteBoolean };
75
- const updateableProps = mapObject(propsWithIsDeleted, (value, key) => key === "id" ? value : optional(value));
76
- return validMutationSize(object(updateableProps));
77
- };
78
- /**
79
- * Type Factory to create an upsertable Type. It makes nullable Types optional
80
- * (so they are not required) and ensures the {@link maxMutationSize}.
81
- *
82
- * Upsert is like insert, except it requires an ID. It's useful for inserting
83
- * rows with external ID via {@link createIdFromString}.
56
+ * const Schema = {
57
+ * todo: {
58
+ * id: id("Todo"),
59
+ * title: NonEmptyString100,
60
+ * isCompleted: nullOr(SqliteBoolean),
61
+ * },
62
+ * };
84
63
  *
85
- * Note that it's not possible to upsert a row with `createdAt` nor `updatedAt`,
86
- * because they are derived from {@link CrdtMessage} timestamp. For external
87
- * createdAt, use a different column.
64
+ * // Create a typed query builder (once per schema)
65
+ * const createQuery = createQueryBuilder(Schema);
88
66
  *
89
- * ### Example
90
- *
91
- * ```ts
92
- * const UpsertableTodo = upsertable(Schema.todo);
93
- * type UpsertableTodo = typeof UpsertableTodo.Type;
94
- * const todo = UpsertableTodo.from({
95
- * id,
96
- * title,
97
- * });
98
- * if (!todo.ok) return; // handle errors
67
+ * // Use it for all queries
68
+ * const todosQuery = createQuery((db) =>
69
+ * db.selectFrom("todo").select(["id", "title", "isCompleted"]),
70
+ * );
99
71
  * ```
100
72
  */
101
- export const upsertable = (props) => {
102
- const propsWithDefaults = {
103
- ...props,
104
- isDeleted: optional(SqliteBoolean),
73
+ export const createQueryBuilder = (_schema) => {
74
+ const createQuery = (queryCallback, options) => {
75
+ const compiledQuery = queryCallback(kysely).compile();
76
+ const sqliteQuery = {
77
+ sql: compiledQuery.sql,
78
+ parameters: compiledQuery.parameters,
79
+ ...(options && { options }),
80
+ };
81
+ return sqliteQueryToSqliteQueryString(sqliteQuery);
105
82
  };
106
- return validMutationSize(nullableToOptional(propsWithDefaults));
83
+ return createQuery;
107
84
  };
108
- export const DbIndex = object({ name: String, sql: String });
109
- export const DbSchema = object({
110
- tables: record(String, set(String)),
111
- indexes: array(DbIndex),
112
- });
113
- /** Get the current database schema by reading SQLite metadata. */
114
- export const getDbSchema = (deps) => ({ allIndexes = false } = {}) => {
115
- const tables = createRecord();
116
- const tableAndColumnInfoRows = deps.sqlite.exec(sql `
117
- select
118
- sqlite_master.name as tableName,
119
- table_info.name as columnName
120
- from
121
- sqlite_master
122
- join pragma_table_info(sqlite_master.name) as table_info;
123
- `);
124
- if (!tableAndColumnInfoRows.ok)
125
- return tableAndColumnInfoRows;
126
- tableAndColumnInfoRows.value.rows.forEach((row) => {
127
- const { tableName, columnName } = row;
128
- (tables[tableName] ??= new Set()).add(columnName);
129
- });
130
- const indexesRows = deps.sqlite.exec(allIndexes
131
- ? sql `
132
- select name, sql
133
- from sqlite_master
134
- where type = 'index' and name not like 'sqlite_%';
135
- `
136
- : sql `
137
- select name, sql
138
- from sqlite_master
139
- where
140
- type = 'index'
141
- and name not like 'sqlite_%'
142
- and name not like 'evolu_%';
143
- `);
144
- if (!indexesRows.ok)
145
- return indexesRows;
146
- const indexes = indexesRows.value.rows.map((row) => ({
147
- name: row.name,
148
- /**
149
- * SQLite returns "CREATE INDEX" for "create index" for some reason.
150
- * Other keywords remain unchanged. We have to normalize the casing for
151
- * {@link indexesAreEqual} manually.
152
- */
153
- sql: row.sql
154
- .replace("CREATE INDEX", "create index")
155
- .replace("CREATE UNIQUE INDEX", "create unique index"),
156
- }));
157
- return ok({ tables, indexes });
158
- };
159
- const indexesAreEqual = (self, that) => self.name === that.name && self.sql === that.sql;
160
- export const ensureDbSchema = (deps) => (newSchema, currentSchema) => {
85
+ export const ensureSqliteSchema = (deps) => (newSchema, currentSchema) => {
161
86
  const queries = [];
162
- if (!currentSchema) {
163
- const dbSchema = getDbSchema(deps)();
164
- if (!dbSchema.ok)
165
- return dbSchema;
166
- currentSchema = dbSchema.value;
167
- }
87
+ currentSchema ??= getEvoluSqliteSchema(deps)();
168
88
  for (const [tableName, newColumns] of Object.entries(newSchema.tables)) {
169
89
  const currentColumns = getProperty(currentSchema.tables, tableName);
170
90
  if (!currentColumns) {
@@ -181,40 +101,23 @@ export const ensureDbSchema = (deps) => (newSchema, currentSchema) => {
181
101
  }
182
102
  // Remove current indexes that are not in the newSchema.
183
103
  currentSchema.indexes
184
- .filter((currentIndex) => !newSchema.indexes.some((newIndex) => indexesAreEqual(newIndex, currentIndex)))
104
+ .filter((currentIndex) => !newSchema.indexes.some((newIndex) => eqSqliteIndex(newIndex, currentIndex)))
185
105
  .forEach((index) => {
186
106
  queries.push(sql `drop index ${sql.identifier(index.name)};`);
187
107
  });
188
108
  // Add new indexes that are not in the currentSchema.
189
109
  newSchema.indexes
190
- .filter((newIndex) => !currentSchema.indexes.some((currentIndex) => indexesAreEqual(newIndex, currentIndex)))
110
+ .filter((newIndex) => !currentSchema.indexes.some((currentIndex) => eqSqliteIndex(newIndex, currentIndex)))
191
111
  .forEach((newIndex) => {
192
112
  queries.push({ sql: `${newIndex.sql};`, parameters: [] });
193
113
  });
194
114
  for (const query of queries) {
195
- const result = deps.sqlite.exec(query);
196
- if (!result.ok)
197
- return result;
115
+ deps.sqlite.exec(query);
198
116
  }
199
- return ok();
200
117
  };
201
- const createAppTable = (tableName, columns) => sql `
202
- create table ${sql.identifier(tableName)} (
203
- "id" text,
204
- ${sql.raw(`${[...systemColumns, ...columns]
205
- // With strict tables and any type, data is preserved exactly as received
206
- // without any type affinity coercion. This allows storing any data type
207
- // while maintaining strict null enforcement for primary key columns.
208
- // TODO: Use proper SQLite types for system columns (text for createdAt,
209
- // updatedAt, ownerId, integer for isDeleted) instead of "any".
210
- .map((name) => `${sql.identifier(name).sql} any`)
211
- .join(", ")}, `)}
212
- primary key ("ownerId", "id")
213
- )
214
- without rowid, strict;
215
- `;
118
+ export const getEvoluSqliteSchema = (deps) => () => getSqliteSchema(deps)({ excludeIndexNamePrefix: "evolu_" });
216
119
  // https://kysely.dev/docs/recipes/splitting-query-building-and-execution
217
- export const kysely = new Kysely.Kysely({
120
+ export const kysely = /*#__PURE__*/ new Kysely.Kysely({
218
121
  dialect: {
219
122
  createAdapter: () => new Kysely.SqliteAdapter(),
220
123
  createDriver: () => new Kysely.DummyDriver(),
@@ -225,3 +128,15 @@ export const kysely = new Kysely.Kysely({
225
128
  },
226
129
  });
227
130
  const createIndex = kysely.schema.createIndex.bind(kysely.schema);
131
+ const createAppTable = (tableName, columns) => sql `
132
+ create table ${sql.identifier(tableName)} (
133
+ "id" text,
134
+ ${sql.raw([...systemColumns, ...columns]
135
+ // In STRICT tables, ANY columns accept any SQLite storage class without
136
+ // affinity coercion, while the primary key still enforces non-nullness.
137
+ .map((name) => `${sql.identifier(name).sql} any`)
138
+ .join(", "))},
139
+ primary key ("ownerId", "id")
140
+ )
141
+ without rowid, strict;
142
+ `;
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Platform-agnostic Evolu SharedWorker.
3
+ *
4
+ * @module
5
+ */
6
+ import { type NonEmptyReadonlyArray } from "../Array.js";
7
+ import type { ConsoleEntry, ConsoleLevel } from "../Console.js";
8
+ import { type Result } from "../Result.js";
9
+ import type { NonEmptyReadonlySet } from "../Set.js";
10
+ import { type AbortError, type Task } from "../Task.js";
11
+ import { type Id, type Name } from "../Type.js";
12
+ import type { ExtractType } from "../Types.js";
13
+ import type { CreateWebSocketDep } from "../WebSocket.js";
14
+ import type { SharedWorker as CommonSharedWorker, NativeMessagePort, SharedWorkerSelf, WorkerDeps } from "../Worker.js";
15
+ import type { EvoluError } from "./Error.js";
16
+ import type { Owner, OwnerId, SyncOwner } from "./Owner.js";
17
+ import { type ApplyProtocolMessageAsClientResult, type ProtocolError, type ProtocolMessage } from "./Protocol.js";
18
+ import { type Patch, type Query, type RowsByQueryMap } from "./Query.js";
19
+ import type { MutationChange } from "./Schema.js";
20
+ import type { CrdtMessage } from "./Storage.js";
21
+ export type SharedWorker = CommonSharedWorker<SharedWorkerInput>;
22
+ export interface SharedWorkerDep {
23
+ readonly sharedWorker: SharedWorker;
24
+ }
25
+ export type SharedWorkerDeps = WorkerDeps & CreateWebSocketDep;
26
+ export type SharedWorkerInput = {
27
+ readonly type: "InitTab";
28
+ readonly consoleLevel: ConsoleLevel;
29
+ readonly port: NativeMessagePort<EvoluTabOutput>;
30
+ } | {
31
+ readonly type: "CreateEvolu";
32
+ readonly name: Name;
33
+ readonly evoluPort: NativeMessagePort<EvoluOutput, EvoluInput>;
34
+ readonly dbWorkerPort: NativeMessagePort<DbWorkerInput, DbWorkerOutput>;
35
+ };
36
+ export type EvoluTabOutput = {
37
+ readonly type: "OnConsoleEntry";
38
+ readonly entry: ConsoleEntry;
39
+ } | {
40
+ readonly type: "OnError";
41
+ readonly error: EvoluError;
42
+ };
43
+ export type EvoluInput = {
44
+ readonly type: "Mutate";
45
+ readonly changes: NonEmptyReadonlyArray<MutationChange>;
46
+ readonly onCompleteIds: ReadonlyArray<Id>;
47
+ readonly subscribedQueries: ReadonlySet<Query>;
48
+ } | {
49
+ readonly type: "UseOwner";
50
+ readonly actions: ReadonlyArray<{
51
+ readonly owner: SyncOwner;
52
+ readonly action: "add" | "remove";
53
+ }>;
54
+ } | {
55
+ readonly type: "Query";
56
+ readonly queries: NonEmptyReadonlySet<Query>;
57
+ } | {
58
+ readonly type: "Export";
59
+ } | {
60
+ readonly type: "Dispose";
61
+ };
62
+ export type EvoluOutput = {
63
+ readonly type: "OnPatchesByQuery";
64
+ readonly patchesByQuery: ReadonlyMap<Query, ReadonlyArray<Patch>>;
65
+ readonly onCompleteIds: ReadonlyArray<Id>;
66
+ } | {
67
+ readonly type: "RefreshQueries";
68
+ } | {
69
+ readonly type: "OnExport";
70
+ readonly file: Uint8Array<ArrayBuffer>;
71
+ };
72
+ export declare const initSharedWorker: (self: SharedWorkerSelf<SharedWorkerInput>) => Task<AsyncDisposableStack, never, SharedWorkerDeps>;
73
+ export interface DbWorkerInput {
74
+ readonly callbackId: Id;
75
+ readonly request: {
76
+ readonly type: "ForEvolu";
77
+ readonly evoluPortId: Id;
78
+ readonly message: ExtractType<EvoluInput, "Mutate" | "Query" | "Export">;
79
+ } | {
80
+ readonly type: "ForSharedWorker";
81
+ readonly message: {
82
+ readonly type: "CreateSyncMessages";
83
+ readonly owners: NonEmptyReadonlyArray<Owner>;
84
+ } | {
85
+ readonly type: "ApplySyncMessage";
86
+ readonly owner: Owner;
87
+ readonly inputMessage: Uint8Array<ArrayBuffer>;
88
+ };
89
+ };
90
+ }
91
+ export type DbWorkerOutput = EvoluTabOutput | {
92
+ readonly type: "LeaderAcquired";
93
+ readonly name: Name;
94
+ } | {
95
+ readonly type: "OnQueuedResponse";
96
+ readonly callbackId: Id;
97
+ readonly response: {
98
+ readonly type: "ForEvolu";
99
+ readonly evoluPortId: Id;
100
+ readonly message: {
101
+ readonly type: "Mutate";
102
+ readonly messagesByOwnerId: ReadonlyMap<OwnerId, NonEmptyReadonlyArray<CrdtMessage>>;
103
+ readonly rowsByQuery: RowsByQueryMap;
104
+ } | {
105
+ readonly type: "Query";
106
+ readonly rowsByQuery: RowsByQueryMap;
107
+ } | {
108
+ readonly type: "Export";
109
+ readonly file: Uint8Array<ArrayBuffer>;
110
+ };
111
+ } | {
112
+ readonly type: "ForSharedWorker";
113
+ readonly message: {
114
+ readonly type: "CreateSyncMessages";
115
+ readonly protocolMessagesByOwnerId: ReadonlyMap<OwnerId, ProtocolMessage>;
116
+ } | {
117
+ readonly type: "ApplySyncMessage";
118
+ readonly ownerId: OwnerId;
119
+ readonly didWriteMessages: boolean;
120
+ readonly result: Result<ApplyProtocolMessageAsClientResult, ProtocolError | AbortError>;
121
+ };
122
+ };
123
+ };
124
+ export type SyncState = 123;
125
+ //# sourceMappingURL=Shared.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Shared.d.ts","sourceRoot":"","sources":["../../../src/local-first/Shared.ts"],"names":[],"mappings":"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"}