@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.
- package/README.md +4 -61
- package/dist/src/Array.d.ts +343 -102
- package/dist/src/Array.d.ts.map +1 -1
- package/dist/src/Array.js +181 -85
- package/dist/src/Assert.d.ts +57 -11
- package/dist/src/Assert.d.ts.map +1 -1
- package/dist/src/Assert.js +47 -11
- package/dist/src/BigInt.d.ts +6 -1
- package/dist/src/BigInt.d.ts.map +1 -1
- package/dist/src/BigInt.js +5 -0
- package/dist/src/Brand.d.ts +40 -12
- package/dist/src/Brand.d.ts.map +1 -1
- package/dist/src/Brand.js +5 -0
- package/dist/src/Buffer.d.ts +6 -1
- package/dist/src/Buffer.d.ts.map +1 -1
- package/dist/src/Buffer.js +7 -2
- package/dist/src/Cache.d.ts +10 -2
- package/dist/src/Cache.d.ts.map +1 -1
- package/dist/src/Cache.js +6 -0
- package/dist/src/Callbacks.d.ts +10 -7
- package/dist/src/Callbacks.d.ts.map +1 -1
- package/dist/src/Callbacks.js +23 -13
- package/dist/src/Console.d.ts +361 -69
- package/dist/src/Console.d.ts.map +1 -1
- package/dist/src/Console.js +217 -117
- package/dist/src/Crypto.d.ts +70 -21
- package/dist/src/Crypto.d.ts.map +1 -1
- package/dist/src/Crypto.js +72 -27
- package/dist/src/Eq.d.ts +22 -2
- package/dist/src/Eq.d.ts.map +1 -1
- package/dist/src/Eq.js +21 -1
- package/dist/src/Error.d.ts +23 -12
- package/dist/src/Error.d.ts.map +1 -1
- package/dist/src/Error.js +27 -11
- package/dist/src/Function.d.ts +128 -56
- package/dist/src/Function.d.ts.map +1 -1
- package/dist/src/Function.js +118 -14
- package/dist/src/Identicon.d.ts +5 -0
- package/dist/src/Identicon.d.ts.map +1 -1
- package/dist/src/Identicon.js +6 -1
- package/dist/src/Lookup.d.ts +160 -0
- package/dist/src/Lookup.d.ts.map +1 -0
- package/dist/src/Lookup.js +192 -0
- package/dist/src/Microtask.d.ts +21 -0
- package/dist/src/Microtask.d.ts.map +1 -0
- package/dist/src/Microtask.js +37 -0
- package/dist/src/Number.d.ts +18 -4
- package/dist/src/Number.d.ts.map +1 -1
- package/dist/src/Number.js +23 -1
- package/dist/src/Object.d.ts +110 -5
- package/dist/src/Object.d.ts.map +1 -1
- package/dist/src/Object.js +108 -5
- package/dist/src/Option.d.ts +58 -0
- package/dist/src/Option.d.ts.map +1 -0
- package/dist/src/Option.js +43 -0
- package/dist/src/Order.d.ts +5 -0
- package/dist/src/Order.d.ts.map +1 -1
- package/dist/src/Order.js +8 -3
- package/dist/src/Platform.d.ts +36 -2
- package/dist/src/Platform.d.ts.map +1 -1
- package/dist/src/Platform.js +10 -6
- package/dist/src/Polyfills.d.ts +27 -0
- package/dist/src/Polyfills.d.ts.map +1 -0
- package/dist/src/Polyfills.js +299 -0
- package/dist/src/Random.d.ts +18 -7
- package/dist/src/Random.d.ts.map +1 -1
- package/dist/src/Random.js +9 -7
- package/dist/src/Redacted.d.ts +7 -4
- package/dist/src/Redacted.d.ts.map +1 -1
- package/dist/src/Redacted.js +5 -0
- package/dist/src/Ref.d.ts +31 -16
- package/dist/src/Ref.d.ts.map +1 -1
- package/dist/src/Ref.js +35 -7
- package/dist/src/RefCount.d.ts +62 -0
- package/dist/src/RefCount.d.ts.map +1 -0
- package/dist/src/RefCount.js +83 -0
- package/dist/src/Relation.d.ts +84 -29
- package/dist/src/Relation.d.ts.map +1 -1
- package/dist/src/Relation.js +83 -105
- package/dist/src/Resource.d.ts +263 -0
- package/dist/src/Resource.d.ts.map +1 -0
- package/dist/src/Resource.js +389 -0
- package/dist/src/Result.d.ts +390 -374
- package/dist/src/Result.d.ts.map +1 -1
- package/dist/src/Result.js +142 -70
- package/dist/src/Schedule.d.ts +953 -0
- package/dist/src/Schedule.d.ts.map +1 -0
- package/dist/src/Schedule.js +1199 -0
- package/dist/src/Set.d.ts +181 -0
- package/dist/src/Set.d.ts.map +1 -0
- package/dist/src/Set.js +137 -0
- package/dist/src/Skiplist.d.ts +6 -1
- package/dist/src/Skiplist.d.ts.map +1 -1
- package/dist/src/Skiplist.js +5 -0
- package/dist/src/Sqlite.d.ts +160 -60
- package/dist/src/Sqlite.d.ts.map +1 -1
- package/dist/src/Sqlite.js +290 -190
- package/dist/src/Store.d.ts +36 -28
- package/dist/src/Store.d.ts.map +1 -1
- package/dist/src/Store.js +55 -15
- package/dist/src/String.d.ts +5 -0
- package/dist/src/String.d.ts.map +1 -1
- package/dist/src/String.js +5 -0
- package/dist/src/Task.d.ts +2263 -423
- package/dist/src/Task.d.ts.map +1 -1
- package/dist/src/Task.js +1488 -348
- package/dist/src/Test.d.ts +122 -0
- package/dist/src/Test.d.ts.map +1 -0
- package/dist/src/Test.js +66 -0
- package/dist/src/Time.d.ts +201 -48
- package/dist/src/Time.d.ts.map +1 -1
- package/dist/src/Time.js +190 -86
- package/dist/src/Tracer.d.ts +48 -0
- package/dist/src/Tracer.d.ts.map +1 -0
- package/dist/src/Tracer.js +6 -0
- package/dist/src/Type.d.ts +582 -209
- package/dist/src/Type.d.ts.map +1 -1
- package/dist/src/Type.js +362 -240
- package/dist/src/Types.d.ts +160 -6
- package/dist/src/Types.d.ts.map +1 -1
- package/dist/src/Types.js +22 -2
- package/dist/src/WebSocket.d.ts +113 -58
- package/dist/src/WebSocket.d.ts.map +1 -1
- package/dist/src/WebSocket.js +210 -118
- package/dist/src/Worker.d.ts +245 -60
- package/dist/src/Worker.d.ts.map +1 -1
- package/dist/src/Worker.js +220 -64
- package/dist/src/index.d.ts +25 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +19 -3
- package/dist/src/local-first/Db.d.ts +24 -213
- package/dist/src/local-first/Db.d.ts.map +1 -1
- package/dist/src/local-first/Db.js +622 -293
- package/dist/src/local-first/Error.d.ts +12 -0
- package/dist/src/local-first/Error.d.ts.map +1 -0
- package/dist/src/local-first/Error.js +6 -0
- package/dist/src/local-first/Evolu.d.ts +330 -285
- package/dist/src/local-first/Evolu.d.ts.map +1 -1
- package/dist/src/local-first/Evolu.js +472 -402
- package/dist/src/local-first/LocalAuth.d.ts +10 -10
- package/dist/src/local-first/LocalAuth.d.ts.map +1 -1
- package/dist/src/local-first/LocalAuth.js +6 -1
- package/dist/src/local-first/Owner.d.ts +70 -27
- package/dist/src/local-first/Owner.d.ts.map +1 -1
- package/dist/src/local-first/Owner.js +27 -14
- package/dist/src/local-first/Protocol.d.ts +58 -50
- package/dist/src/local-first/Protocol.d.ts.map +1 -1
- package/dist/src/local-first/Protocol.js +253 -155
- package/dist/src/local-first/Query.d.ts +133 -43
- package/dist/src/local-first/Query.d.ts.map +1 -1
- package/dist/src/local-first/Query.js +139 -90
- package/dist/src/local-first/Relay.d.ts +18 -38
- package/dist/src/local-first/Relay.d.ts.map +1 -1
- package/dist/src/local-first/Relay.js +59 -171
- package/dist/src/local-first/Schema.d.ts +139 -144
- package/dist/src/local-first/Schema.d.ts.map +1 -1
- package/dist/src/local-first/Schema.js +78 -163
- package/dist/src/local-first/Shared.d.ts +125 -0
- package/dist/src/local-first/Shared.d.ts.map +1 -0
- package/dist/src/local-first/Shared.js +569 -0
- package/dist/src/local-first/Storage.d.ts +50 -53
- package/dist/src/local-first/Storage.d.ts.map +1 -1
- package/dist/src/local-first/Storage.js +121 -173
- package/dist/src/local-first/Timestamp.d.ts +28 -35
- package/dist/src/local-first/Timestamp.d.ts.map +1 -1
- package/dist/src/local-first/Timestamp.js +24 -25
- package/dist/src/local-first/index.d.ts +2 -15
- package/dist/src/local-first/index.d.ts.map +1 -1
- package/dist/src/local-first/index.js +2 -15
- package/package.json +36 -26
- package/src/Array.ts +467 -106
- package/src/Assert.ts +87 -12
- package/src/BigInt.ts +7 -1
- package/src/Brand.ts +41 -12
- package/src/Buffer.ts +10 -4
- package/src/Cache.ts +11 -2
- package/src/Callbacks.ts +33 -23
- package/src/Console.ts +567 -178
- package/src/Crypto.ts +111 -62
- package/src/Eq.ts +30 -3
- package/src/Error.ts +50 -34
- package/src/Function.ts +140 -68
- package/src/Identicon.ts +7 -1
- package/src/Lookup.ts +415 -0
- package/src/Microtask.ts +58 -0
- package/src/Number.ts +40 -7
- package/src/Object.ts +155 -16
- package/src/Option.ts +74 -0
- package/src/Order.ts +11 -3
- package/src/Platform.ts +43 -7
- package/src/Polyfills.ts +465 -0
- package/src/Random.ts +25 -11
- package/src/Redacted.ts +8 -4
- package/src/Ref.ts +72 -21
- package/src/RefCount.ts +170 -0
- package/src/Relation.ts +188 -136
- package/src/Resource.ts +864 -0
- package/src/Result.ts +548 -381
- package/src/Schedule.ts +1471 -0
- package/src/Set.ts +247 -0
- package/src/Skiplist.ts +7 -1
- package/src/Sqlite.ts +409 -304
- package/src/Store.ts +94 -48
- package/src/String.ts +6 -0
- package/src/Task.ts +3685 -740
- package/src/Test.ts +162 -0
- package/src/Time.ts +348 -145
- package/src/Tracer.ts +54 -0
- package/src/Type.ts +1064 -630
- package/src/Types.ts +202 -7
- package/src/WebSocket.ts +311 -178
- package/src/Worker.ts +527 -147
- package/src/index.ts +74 -3
- package/src/local-first/Db.ts +871 -597
- package/src/local-first/Error.ts +17 -0
- package/src/local-first/Evolu.ts +884 -823
- package/src/local-first/LocalAuth.ts +10 -10
- package/src/local-first/Owner.ts +94 -42
- package/src/local-first/Protocol.ts +440 -303
- package/src/local-first/Query.ts +243 -194
- package/src/local-first/Relay.ts +91 -252
- package/src/local-first/Schema.ts +284 -394
- package/src/local-first/Shared.ts +932 -0
- package/src/local-first/Storage.ts +209 -282
- package/src/local-first/Timestamp.ts +38 -45
- package/src/local-first/index.ts +2 -16
- package/LICENSE +0 -21
- package/dist/src/Instances.d.ts +0 -34
- package/dist/src/Instances.d.ts.map +0 -1
- package/dist/src/Instances.js +0 -44
- package/dist/src/Resources.d.ts +0 -118
- package/dist/src/Resources.d.ts.map +0 -1
- package/dist/src/Resources.js +0 -197
- package/dist/src/local-first/Platform.d.ts +0 -25
- package/dist/src/local-first/Platform.d.ts.map +0 -1
- package/dist/src/local-first/Platform.js +0 -1
- package/dist/src/local-first/Public.d.ts +0 -22
- package/dist/src/local-first/Public.d.ts.map +0 -1
- package/dist/src/local-first/Public.js +0 -15
- package/dist/src/local-first/PublicKysely.d.ts +0 -148
- package/dist/src/local-first/PublicKysely.d.ts.map +0 -1
- package/dist/src/local-first/PublicKysely.js +0 -184
- package/dist/src/local-first/Sync.d.ts +0 -112
- package/dist/src/local-first/Sync.d.ts.map +0 -1
- package/dist/src/local-first/Sync.js +0 -529
- package/src/Instances.ts +0 -90
- package/src/Resources.ts +0 -367
- package/src/local-first/Platform.ts +0 -27
- package/src/local-first/Public.ts +0 -42
- package/src/local-first/PublicKysely.ts +0 -239
- 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 {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
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 {
|
|
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
|
|
22
|
-
* - `updatedAt`: Set by Evolu on every row change, derived from
|
|
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 =
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
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
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
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
|
-
*
|
|
86
|
-
*
|
|
87
|
-
* createdAt, use a different column.
|
|
64
|
+
* // Create a typed query builder (once per schema)
|
|
65
|
+
* const createQuery = createQueryBuilder(Schema);
|
|
88
66
|
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
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
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
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
|
|
83
|
+
return createQuery;
|
|
107
84
|
};
|
|
108
|
-
export const
|
|
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
|
-
|
|
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) =>
|
|
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) =>
|
|
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
|
-
|
|
196
|
-
if (!result.ok)
|
|
197
|
-
return result;
|
|
115
|
+
deps.sqlite.exec(query);
|
|
198
116
|
}
|
|
199
|
-
return ok();
|
|
200
117
|
};
|
|
201
|
-
const
|
|
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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"}
|