@evolu/common 4.0.5 → 4.1.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 +6 -0
- package/dist/src/Config.d.ts +18 -0
- package/dist/src/Config.d.ts.map +1 -1
- package/dist/src/Config.js +1 -0
- package/dist/src/Db.d.ts +5 -9
- package/dist/src/Db.d.ts.map +1 -1
- package/dist/src/Db.js +108 -31
- package/dist/src/DbWorker.d.ts +3 -4
- package/dist/src/DbWorker.d.ts.map +1 -1
- package/dist/src/DbWorker.js +42 -22
- package/dist/src/Evolu.d.ts +4 -2
- package/dist/src/Evolu.d.ts.map +1 -1
- package/dist/src/Evolu.js +18 -6
- package/dist/src/Public.d.ts +2 -0
- package/dist/src/Public.d.ts.map +1 -1
- package/dist/src/Public.js +2 -0
- package/dist/src/Sql.d.ts +11 -12
- package/dist/src/Sql.d.ts.map +1 -1
- package/dist/src/Sql.js +30 -106
- package/dist/src/Sqlite.d.ts +29 -3
- package/dist/src/Sqlite.d.ts.map +1 -1
- package/dist/src/Sqlite.js +25 -5
- package/package.json +6 -6
- package/src/Config.ts +20 -0
- package/src/Db.ts +154 -78
- package/src/DbWorker.ts +57 -38
- package/src/Evolu.ts +36 -9
- package/src/Public.ts +2 -0
- package/src/Sql.ts +41 -123
- package/src/Sqlite.ts +65 -7
package/README.md
CHANGED
package/dist/src/Config.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as Context from "effect/Context";
|
|
2
2
|
import * as Layer from "effect/Layer";
|
|
3
|
+
import { CreateIndexBuilder } from "kysely";
|
|
3
4
|
export interface Config {
|
|
4
5
|
/** Alternate URL to Evolu sync and backup server. */
|
|
5
6
|
readonly syncUrl: string;
|
|
@@ -19,6 +20,23 @@ export interface Config {
|
|
|
19
20
|
* default value is: "Evolu".
|
|
20
21
|
*/
|
|
21
22
|
readonly name: string;
|
|
23
|
+
/**
|
|
24
|
+
* Use the `indexes` property to define SQLite indexes.
|
|
25
|
+
*
|
|
26
|
+
* Table and column names are not typed because Kysely doesn't support it.
|
|
27
|
+
*
|
|
28
|
+
* https://medium.com/@JasonWyatt/squeezing-performance-from-sqlite-indexes-indexes-c4e175f3c346
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* const indexes = [
|
|
32
|
+
* createIndex("indexTodoCreatedAt").on("todo").column("createdAt"),
|
|
33
|
+
*
|
|
34
|
+
* createIndex("indexTodoCategoryCreatedAt")
|
|
35
|
+
* .on("todoCategory")
|
|
36
|
+
* .column("createdAt"),
|
|
37
|
+
* ];
|
|
38
|
+
*/
|
|
39
|
+
readonly indexes: ReadonlyArray<CreateIndexBuilder<any>>;
|
|
22
40
|
}
|
|
23
41
|
export declare const Config: Context.Tag<Config, Config>;
|
|
24
42
|
export declare const ConfigLive: (config?: Partial<Config>) => Layer.Layer<Config>;
|
package/dist/src/Config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Config.d.ts","sourceRoot":"","sources":["../../src/Config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"Config.d.ts","sourceRoot":"","sources":["../../src/Config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AAE5C,MAAM,WAAW,MAAM;IACrB,qDAAqD;IACrD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB;;;OAGG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAE3B;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB;;;;;;;;;;;;;;;OAeG;IACH,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC;CAC1D;AAED,eAAO,MAAM,MAAM,6BAAiD,CAAC;AAErE,eAAO,MAAM,UAAU,YAAa,QAAQ,MAAM,CAAC,KAAG,WAAW,CAAC,MAAM,CAWrE,CAAC"}
|
package/dist/src/Config.js
CHANGED
package/dist/src/Db.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ import { Bip39, Mnemonic, NanoIdGenerator } from "./Crypto.js";
|
|
|
11
11
|
import { EvoluTypeError } from "./ErrorStore.js";
|
|
12
12
|
import { Id } from "./Model.js";
|
|
13
13
|
import { Owner } from "./Owner.js";
|
|
14
|
-
import { Sqlite, SqliteQuery, Value } from "./Sqlite.js";
|
|
14
|
+
import { Sqlite, SqliteQuery, SqliteSchema, Table, Value } from "./Sqlite.js";
|
|
15
15
|
import { Store } from "./Store.js";
|
|
16
16
|
export type DatabaseSchema = ReadonlyRecord.ReadonlyRecord<string, TableSchema>;
|
|
17
17
|
type TableSchema = ReadonlyRecord.ReadonlyRecord<string, Value> & {
|
|
@@ -72,7 +72,7 @@ export type Query<R extends Row = Row> = string & Brand.Brand<"Query"> & {
|
|
|
72
72
|
readonly [__queryBrand]: R;
|
|
73
73
|
};
|
|
74
74
|
export type Queries<R extends Row = Row> = ReadonlyArray<Query<R>>;
|
|
75
|
-
export declare const serializeQuery: <R extends Row>({ sql, parameters, }: SqliteQuery) => Query<R>;
|
|
75
|
+
export declare const serializeQuery: <R extends Row>({ sql, parameters, options, }: SqliteQuery) => Query<R>;
|
|
76
76
|
export declare const deserializeQuery: <R extends Row>(query: Query<R>) => SqliteQuery;
|
|
77
77
|
export type Row = {
|
|
78
78
|
[key: string]: Value | Row | ReadonlyArray<Row>;
|
|
@@ -105,12 +105,7 @@ export type QueryResultsPromisesFromQueries<Q extends Queries> = {
|
|
|
105
105
|
[P in keyof Q]: Q[P] extends Query<infer R> ? Promise<QueryResult<R>> : never;
|
|
106
106
|
};
|
|
107
107
|
export declare const queryResultFromRows: <R extends Row>(rows: ReadonlyArray<R>) => QueryResult<R>;
|
|
108
|
-
export
|
|
109
|
-
export interface Table {
|
|
110
|
-
readonly name: string;
|
|
111
|
-
readonly columns: ReadonlyArray<string>;
|
|
112
|
-
}
|
|
113
|
-
export declare const schemaToTables: (schema: S.Schema<any>) => Tables;
|
|
108
|
+
export declare const schemaToTables: (schema: S.Schema<any>) => ReadonlyArray<Table>;
|
|
114
109
|
export declare const transaction: <R, E, A>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Sqlite | R>;
|
|
115
110
|
export interface NoSuchTableOrColumnError {
|
|
116
111
|
readonly _tag: "NoSuchTableOrColumnError";
|
|
@@ -121,7 +116,8 @@ export declare const SqliteNoSuchTableOrColumnError: S.struct<{
|
|
|
121
116
|
export type SqliteNoSuchTableOrColumnError = S.Schema.Type<typeof SqliteNoSuchTableOrColumnError>;
|
|
122
117
|
export declare const someDefectToNoSuchTableOrColumnError: <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, NoSuchTableOrColumnError | E, R>;
|
|
123
118
|
export declare const lazyInit: (mnemonic?: Mnemonic) => Effect.Effect<Owner, never, Sqlite | Bip39 | NanoIdGenerator>;
|
|
124
|
-
export declare const ensureSchema: (
|
|
119
|
+
export declare const ensureSchema: (schema: SqliteSchema) => Effect.Effect<void, never, Sqlite>;
|
|
120
|
+
export declare const dropAllTables: Effect.Effect<void, never, Sqlite>;
|
|
125
121
|
export type RowsStore = Store<RowsStoreValue>;
|
|
126
122
|
export declare const RowsStore: Context.Tag<RowsStore, RowsStore>;
|
|
127
123
|
type RowsStoreValue = ReadonlyMap<Query, ReadonlyArray<Row>>;
|
package/dist/src/Db.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Db.d.ts","sourceRoot":"","sources":["../../src/Db.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,CAAC,MAAM,uBAAuB,CAAC;AAE3C,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAGxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAGtC,OAAO,KAAK,aAAa,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,cAAc,MAAM,uBAAuB,CAAC;AAExD,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AAOjC,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,EAAE,EAA6B,MAAM,YAAY,CAAC;AAC3D,OAAO,EAAE,KAAK,EAAa,MAAM,YAAY,CAAC;AAO9C,OAAO,
|
|
1
|
+
{"version":3,"file":"Db.d.ts","sourceRoot":"","sources":["../../src/Db.ts"],"names":[],"mappings":"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"}
|
package/dist/src/Db.js
CHANGED
|
@@ -15,7 +15,7 @@ import { initialMerkleTree, makeInitialTimestamp, merkleTreeToString, timestampT
|
|
|
15
15
|
import { SqliteBoolean, SqliteDate } from "./Model.js";
|
|
16
16
|
import { makeOwner } from "./Owner.js";
|
|
17
17
|
import { createMessageTable, createMessageTableIndex, createOwnerTable, insertOwner, } from "./Sql.js";
|
|
18
|
-
import { Sqlite, isJsonObjectOrArray, } from "./Sqlite.js";
|
|
18
|
+
import { indexEquivalence, Sqlite, isJsonObjectOrArray, } from "./Sqlite.js";
|
|
19
19
|
import { makeStore } from "./Store.js";
|
|
20
20
|
/**
|
|
21
21
|
* Create table schema.
|
|
@@ -60,16 +60,15 @@ const ReservedColumns = S.struct({
|
|
|
60
60
|
*/
|
|
61
61
|
export const database = S.struct;
|
|
62
62
|
// We use queries as keys, hence JSON.stringify.
|
|
63
|
-
export const serializeQuery = ({ sql, parameters, }) => {
|
|
63
|
+
export const serializeQuery = ({ sql, parameters = [], options, }) => {
|
|
64
64
|
const query = {
|
|
65
65
|
sql,
|
|
66
|
-
parameters: parameters.map((p) =>
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
:
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}),
|
|
66
|
+
parameters: parameters.map((p) => Predicate.isUint8Array(p)
|
|
67
|
+
? Array.from(p)
|
|
68
|
+
: isJsonObjectOrArray(p)
|
|
69
|
+
? { json: p }
|
|
70
|
+
: p),
|
|
71
|
+
...(options && { options }),
|
|
73
72
|
};
|
|
74
73
|
return JSON.stringify(query);
|
|
75
74
|
};
|
|
@@ -95,6 +94,7 @@ export const queryResultFromRows = (rows) => {
|
|
|
95
94
|
}
|
|
96
95
|
return queryResult;
|
|
97
96
|
};
|
|
97
|
+
// TODO: https://discord.com/channels/795981131316985866/1218626687546294386/1218796529725476935
|
|
98
98
|
// https://github.com/Effect-TS/schema/releases/tag/v0.18.0
|
|
99
99
|
const getPropertySignatures = (schema) => {
|
|
100
100
|
const out = {};
|
|
@@ -110,7 +110,9 @@ export const schemaToTables = (schema) => pipe(getPropertySignatures(schema), Re
|
|
|
110
110
|
name,
|
|
111
111
|
columns: Object.keys(getPropertySignatures(schema)),
|
|
112
112
|
})));
|
|
113
|
-
export const transaction = (effect) => Effect.flatMap(Sqlite, (sqlite) => Effect.acquireUseRelease(sqlite.exec("begin"), () => effect, (_, exit) => Exit.isFailure(exit)
|
|
113
|
+
export const transaction = (effect) => Effect.flatMap(Sqlite, (sqlite) => Effect.acquireUseRelease(sqlite.exec({ sql: "begin" }), () => effect, (_, exit) => Exit.isFailure(exit)
|
|
114
|
+
? sqlite.exec({ sql: "rollback" })
|
|
115
|
+
: sqlite.exec({ sql: "end" })));
|
|
114
116
|
export const SqliteNoSuchTableOrColumnError = S.struct({
|
|
115
117
|
message: S.union(S.string.pipe(S.includes("no such table")), S.string.pipe(S.includes("no such column")), S.string.pipe(S.includes("has no column"))),
|
|
116
118
|
});
|
|
@@ -128,7 +130,7 @@ export const lazyInit = (mnemonic) => Effect.gen(function* (_) {
|
|
|
128
130
|
sqlite.exec(createMessageTableIndex),
|
|
129
131
|
sqlite.exec(createOwnerTable),
|
|
130
132
|
sqlite.exec({
|
|
131
|
-
|
|
133
|
+
...insertOwner,
|
|
132
134
|
parameters: [
|
|
133
135
|
owner.id,
|
|
134
136
|
owner.mnemonic,
|
|
@@ -140,27 +142,102 @@ export const lazyInit = (mnemonic) => Effect.gen(function* (_) {
|
|
|
140
142
|
]));
|
|
141
143
|
return owner;
|
|
142
144
|
});
|
|
143
|
-
const
|
|
144
|
-
const
|
|
145
|
+
const getSchema = Effect.gen(function* (_) {
|
|
146
|
+
const sqlite = yield* _(Sqlite);
|
|
147
|
+
const tables = yield* _(sqlite.exec({
|
|
148
|
+
// https://til.simonwillison.net/sqlite/list-all-columns-in-a-database
|
|
149
|
+
sql: `
|
|
150
|
+
select
|
|
151
|
+
sqlite_master.name as tableName,
|
|
152
|
+
table_info.name as columnName
|
|
153
|
+
from
|
|
154
|
+
sqlite_master
|
|
155
|
+
join pragma_table_info(sqlite_master.name) as table_info
|
|
156
|
+
`.trim(),
|
|
157
|
+
}), Effect.map(({ rows }) => {
|
|
158
|
+
const map = new Map();
|
|
159
|
+
rows.forEach((row) => {
|
|
160
|
+
const { tableName, columnName } = row;
|
|
161
|
+
if (!map.has(tableName))
|
|
162
|
+
map.set(tableName, []);
|
|
163
|
+
map.get(tableName)?.push(columnName);
|
|
164
|
+
});
|
|
165
|
+
return Array.from(map, ([name, columns]) => ({
|
|
166
|
+
name,
|
|
167
|
+
columns,
|
|
168
|
+
}));
|
|
169
|
+
}));
|
|
170
|
+
const indexes = yield* _(sqlite.exec({
|
|
171
|
+
sql: `
|
|
172
|
+
select
|
|
173
|
+
name, sql
|
|
174
|
+
from
|
|
175
|
+
sqlite_master
|
|
176
|
+
where
|
|
177
|
+
type='index' and
|
|
178
|
+
name not like 'sqlite_%' and
|
|
179
|
+
name not like 'index_evolu_%'`,
|
|
180
|
+
}), Effect.map((result) => ReadonlyArray.map(result.rows, (row) => ({
|
|
181
|
+
name: row.name,
|
|
182
|
+
/**
|
|
183
|
+
* SQLite returns "CREATE INDEX" for "create index" for some reason.
|
|
184
|
+
* Other keywords remain unchanged. We have to normalize the casing
|
|
185
|
+
* for `indexEquivalence` manually.
|
|
186
|
+
*/
|
|
187
|
+
sql: row.sql.replace("CREATE INDEX", "create index"),
|
|
188
|
+
}))));
|
|
189
|
+
return { tables, indexes };
|
|
190
|
+
});
|
|
191
|
+
export const ensureSchema = (schema) => Effect.gen(function* (_) {
|
|
192
|
+
const sqlite = yield* _(Sqlite);
|
|
193
|
+
const currentSchema = yield* _(getSchema);
|
|
194
|
+
const sql = [];
|
|
195
|
+
schema.tables.forEach((table) => {
|
|
196
|
+
const currentTable = currentSchema.tables.find((t) => t.name === table.name);
|
|
197
|
+
if (!currentTable) {
|
|
198
|
+
sql.push(`
|
|
199
|
+
create table ${table.name} (
|
|
200
|
+
"id" text primary key,
|
|
201
|
+
${table.columns
|
|
202
|
+
.filter((c) => c !== "id")
|
|
203
|
+
// "A column with affinity BLOB does not prefer one storage class over another
|
|
204
|
+
// and no attempt is made to coerce data from one storage class into another."
|
|
205
|
+
// https://www.sqlite.org/datatype3.html
|
|
206
|
+
.map((name) => `"${name}" blob`)
|
|
207
|
+
.join(", ")}
|
|
208
|
+
);
|
|
209
|
+
`);
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
ReadonlyArray.differenceWith(String.Equivalence)(table.columns, currentTable.columns).forEach((newColumn) => {
|
|
213
|
+
sql.push(`alter table "${table.name}" add column "${newColumn}" blob;`);
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
// Remove old indexes.
|
|
218
|
+
ReadonlyArray.differenceWith(indexEquivalence)(currentSchema.indexes, ReadonlyArray.intersectionWith(indexEquivalence)(currentSchema.indexes, schema.indexes)).forEach((indexToDrop) => {
|
|
219
|
+
sql.push(`drop index "${indexToDrop.name}";`);
|
|
220
|
+
});
|
|
221
|
+
// Add new indexes.
|
|
222
|
+
ReadonlyArray.differenceWith(indexEquivalence)(schema.indexes, currentSchema.indexes).forEach((newIndex) => {
|
|
223
|
+
sql.push(`${newIndex.sql};`);
|
|
224
|
+
});
|
|
225
|
+
if (sql.length > 0)
|
|
226
|
+
yield* _(sqlite.exec({
|
|
227
|
+
sql: sql.join(""),
|
|
228
|
+
}));
|
|
229
|
+
});
|
|
230
|
+
export const dropAllTables = Effect.gen(function* (_) {
|
|
145
231
|
const sqlite = yield* _(Sqlite);
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
232
|
+
const schema = yield* _(getSchema);
|
|
233
|
+
const sql = schema.tables
|
|
234
|
+
// The dropped table is completely removed from the database schema and
|
|
235
|
+
// the disk file. The table can not be recovered.
|
|
236
|
+
// All indices and triggers associated with the table are also deleted.
|
|
237
|
+
// https://sqlite.org/lang_droptable.html
|
|
238
|
+
.map((table) => `drop table "${table.name}";`)
|
|
239
|
+
.join("");
|
|
240
|
+
yield* _(sqlite.exec({ sql }));
|
|
149
241
|
});
|
|
150
|
-
const createTable = ({ name, columns, }) => Effect.flatMap(Sqlite, (sqlite) => sqlite.exec(`
|
|
151
|
-
create table ${name} (
|
|
152
|
-
"id" text primary key,
|
|
153
|
-
${columns
|
|
154
|
-
.filter((c) => c !== "id")
|
|
155
|
-
// "A column with affinity BLOB does not prefer one storage class over another
|
|
156
|
-
// and no attempt is made to coerce data from one storage class into another."
|
|
157
|
-
// https://www.sqlite.org/datatype3.html
|
|
158
|
-
.map((name) => `"${name}" blob`)
|
|
159
|
-
.join(", ")}
|
|
160
|
-
);
|
|
161
|
-
`));
|
|
162
|
-
export const ensureSchema = (tables) => Effect.flatMap(getTables, (existingTables) => Effect.forEach(tables, (tableDefinition) => existingTables.includes(tableDefinition.name)
|
|
163
|
-
? updateTable(tableDefinition)
|
|
164
|
-
: createTable(tableDefinition), { discard: true }));
|
|
165
242
|
export const RowsStore = Context.GenericTag("@services/RowsStore");
|
|
166
243
|
export const RowsStoreLive = Layer.effect(RowsStore, makeStore(new Map()));
|
package/dist/src/DbWorker.d.ts
CHANGED
|
@@ -6,14 +6,14 @@ import * as ReadonlyRecord from "effect/ReadonlyRecord";
|
|
|
6
6
|
import { Config } from "./Config.js";
|
|
7
7
|
import { Millis } from "./Crdt.js";
|
|
8
8
|
import { Bip39, Mnemonic, NanoIdGenerator } from "./Crypto.js";
|
|
9
|
-
import { Queries, Query
|
|
9
|
+
import { Queries, Query } from "./Db.js";
|
|
10
10
|
import { QueryPatches } from "./Diff.js";
|
|
11
11
|
import { EvoluError } from "./ErrorStore.js";
|
|
12
12
|
import { Id } from "./Model.js";
|
|
13
13
|
import { OnCompleteId } from "./OnCompletes.js";
|
|
14
14
|
import { Owner } from "./Owner.js";
|
|
15
15
|
import { DbWorkerLock } from "./Platform.js";
|
|
16
|
-
import { Sqlite, Value } from "./Sqlite.js";
|
|
16
|
+
import { Sqlite, SqliteSchema, Value } from "./Sqlite.js";
|
|
17
17
|
import { NewMessage, SyncState, SyncWorker, SyncWorkerOutputSyncResponse } from "./SyncWorker.js";
|
|
18
18
|
import { Messaging } from "./Types.js";
|
|
19
19
|
export interface DbWorker extends Messaging<DbWorkerInput, DbWorkerOutput> {
|
|
@@ -41,9 +41,8 @@ interface DbWorkerInputReset {
|
|
|
41
41
|
readonly _tag: "reset";
|
|
42
42
|
readonly mnemonic?: Mnemonic;
|
|
43
43
|
}
|
|
44
|
-
interface DbWorkerInputEnsureSchema {
|
|
44
|
+
interface DbWorkerInputEnsureSchema extends SqliteSchema {
|
|
45
45
|
readonly _tag: "ensureSchema";
|
|
46
|
-
readonly tables: Tables;
|
|
47
46
|
}
|
|
48
47
|
export type DbWorkerOutput = DbWorkerOutputOnError | DbWorkerOutputOnOwner | DbWorkerOutputOnQuery | DbWorkerOutputOnReceive | DbWorkerOutputOnResetOrRestore | DbWorkerOutputOnSyncState;
|
|
49
48
|
export interface DbWorkerOutputOnError {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DbWorker.d.ts","sourceRoot":"","sources":["../../src/DbWorker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAGxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAGtC,OAAO,KAAK,aAAa,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,cAAc,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,MAAM,EAAc,MAAM,aAAa,CAAC;AACjD,OAAO,EAEL,MAAM,EAiBP,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,EACL,OAAO,EACP,KAAK,
|
|
1
|
+
{"version":3,"file":"DbWorker.d.ts","sourceRoot":"","sources":["../../src/DbWorker.ts"],"names":[],"mappings":"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"}
|
package/dist/src/DbWorker.js
CHANGED
|
@@ -9,14 +9,14 @@ import * as ReadonlyArray from "effect/ReadonlyArray";
|
|
|
9
9
|
import { Config, ConfigLive } from "./Config.js";
|
|
10
10
|
import { Time, TimeLive, diffMerkleTrees, insertIntoMerkleTree, makeSyncTimestamp, merkleTreeToString, receiveTimestamp, sendTimestamp, timestampToString, unsafeTimestampFromString, } from "./Crdt.js";
|
|
11
11
|
import { Bip39, NanoIdGenerator } from "./Crypto.js";
|
|
12
|
-
import { RowsStore, RowsStoreLive, deserializeQuery, ensureSchema, lazyInit, someDefectToNoSuchTableOrColumnError, transaction, } from "./Db.js";
|
|
12
|
+
import { RowsStore, RowsStoreLive, deserializeQuery, dropAllTables, ensureSchema, lazyInit, someDefectToNoSuchTableOrColumnError, transaction, } from "./Db.js";
|
|
13
13
|
import { makePatches } from "./Diff.js";
|
|
14
14
|
import { makeUnexpectedError } from "./ErrorStore.js";
|
|
15
15
|
import { cast } from "./Model.js";
|
|
16
16
|
import { Owner } from "./Owner.js";
|
|
17
17
|
import { DbWorkerLock } from "./Platform.js";
|
|
18
18
|
import * as Sql from "./Sql.js";
|
|
19
|
-
import { Sqlite } from "./Sqlite.js";
|
|
19
|
+
import { Sqlite, drawSqliteQueryPlan as drawExplainQueryPlan, } from "./Sqlite.js";
|
|
20
20
|
import { NewMessageEquivalence, SyncWorker, SyncWorkerPostMessage, } from "./SyncWorker.js";
|
|
21
21
|
export const DbWorker = Context.GenericTag("@services/DbWorker");
|
|
22
22
|
const DbWorkerOnMessage = Context.GenericTag("@services/DbWorkerOnMessage");
|
|
@@ -32,9 +32,23 @@ const query = ({ queries, onCompleteIds = [], }) => Effect.gen(function* (_) {
|
|
|
32
32
|
const sqlite = yield* _(Sqlite);
|
|
33
33
|
const rowsStore = yield* _(RowsStore);
|
|
34
34
|
const dbWorkerOnMessage = yield* _(DbWorkerOnMessage);
|
|
35
|
-
const queriesRows = yield* _(ReadonlyArray.dedupe(queries), Effect.forEach((query) =>
|
|
36
|
-
|
|
37
|
-
.pipe(Effect.map((result) => [query, result.rows]))
|
|
35
|
+
const queriesRows = yield* _(ReadonlyArray.dedupe(queries), Effect.forEach((query) => {
|
|
36
|
+
const sqliteQuery = deserializeQuery(query);
|
|
37
|
+
return sqlite.exec(sqliteQuery).pipe(Effect.map((result) => [query, result.rows]), Effect.tap(() => {
|
|
38
|
+
if (!sqliteQuery.options?.logExplainQueryPlan)
|
|
39
|
+
return;
|
|
40
|
+
return sqlite
|
|
41
|
+
.exec({
|
|
42
|
+
...sqliteQuery,
|
|
43
|
+
sql: `EXPLAIN QUERY PLAN ${sqliteQuery.sql}`,
|
|
44
|
+
})
|
|
45
|
+
.pipe(Effect.tap(() => Effect.log("ExplainQueryPlan")), Effect.tap(({ rows }) => {
|
|
46
|
+
// Not using Effect.log because of formating
|
|
47
|
+
// eslint-disable-next-line no-console
|
|
48
|
+
console.log(drawExplainQueryPlan(rows));
|
|
49
|
+
}));
|
|
50
|
+
}));
|
|
51
|
+
}));
|
|
38
52
|
const previous = rowsStore.getState();
|
|
39
53
|
yield* _(rowsStore.setState(new Map([...previous, ...queriesRows])));
|
|
40
54
|
const queriesPatches = queriesRows.map(([query, rows]) => ({
|
|
@@ -87,13 +101,22 @@ const ensureSchemaByNewMessages = (messages) => Effect.gen(function* (_) {
|
|
|
87
101
|
columns: table.columns.concat(message.column),
|
|
88
102
|
});
|
|
89
103
|
});
|
|
90
|
-
|
|
104
|
+
const tables = Array.from(tablesMap.values());
|
|
105
|
+
yield* _(ensureSchema({ tables, indexes: [] }));
|
|
91
106
|
});
|
|
92
107
|
export const upsertValueIntoTableRowColumn = (message, messages, millis) => Effect.gen(function* (_) {
|
|
93
108
|
const sqlite = yield* _(Sqlite);
|
|
94
109
|
const createdAtOrUpdatedAt = cast(new Date(millis));
|
|
95
110
|
const insert = sqlite.exec({
|
|
96
|
-
sql:
|
|
111
|
+
sql: `
|
|
112
|
+
insert into
|
|
113
|
+
"${message.table}" ("id", "${message.column}", "createdAt", "updatedAt")
|
|
114
|
+
values
|
|
115
|
+
(?, ?, ?, ?)
|
|
116
|
+
on conflict do update set
|
|
117
|
+
"${message.column}" = ?,
|
|
118
|
+
"updatedAt" = ?
|
|
119
|
+
`.trim(),
|
|
97
120
|
parameters: [
|
|
98
121
|
message.row,
|
|
99
122
|
message.value,
|
|
@@ -111,8 +134,8 @@ const applyMessages = ({ merkleTree, messages, }) => Effect.gen(function* (_) {
|
|
|
111
134
|
const sqlite = yield* _(Sqlite);
|
|
112
135
|
for (const message of messages) {
|
|
113
136
|
const timestamp = yield* _(sqlite.exec({
|
|
114
|
-
|
|
115
|
-
parameters: [message.table, message.row, message.column],
|
|
137
|
+
...Sql.selectLastTimestampForTableRowColumn,
|
|
138
|
+
parameters: [message.table, message.row, message.column, 1],
|
|
116
139
|
}), Effect.map((result) => result.rows), Effect.flatMap(ReadonlyArray.head), Effect.map((row) => row.timestamp), Effect.catchTag("NoSuchElementException", () => Effect.succeed(null)));
|
|
117
140
|
if (timestamp == null || timestamp < message.timestamp) {
|
|
118
141
|
const { millis } = unsafeTimestampFromString(message.timestamp);
|
|
@@ -120,7 +143,7 @@ const applyMessages = ({ merkleTree, messages, }) => Effect.gen(function* (_) {
|
|
|
120
143
|
}
|
|
121
144
|
if (timestamp == null || timestamp !== message.timestamp) {
|
|
122
145
|
const { changes } = yield* _(sqlite.exec({
|
|
123
|
-
|
|
146
|
+
...Sql.insertIntoMessagesIfNew,
|
|
124
147
|
parameters: [
|
|
125
148
|
message.timestamp,
|
|
126
149
|
message.table,
|
|
@@ -138,10 +161,10 @@ const applyMessages = ({ merkleTree, messages, }) => Effect.gen(function* (_) {
|
|
|
138
161
|
return merkleTree;
|
|
139
162
|
});
|
|
140
163
|
const writeTimestampAndMerkleTree = ({ timestamp, merkleTree, }) => Effect.flatMap(Sqlite, (sqlite) => sqlite.exec({
|
|
141
|
-
|
|
164
|
+
...Sql.updateOwnerTimestampAndMerkleTree,
|
|
142
165
|
parameters: [
|
|
143
|
-
timestampToString(timestamp),
|
|
144
166
|
merkleTreeToString(merkleTree),
|
|
167
|
+
timestampToString(timestamp),
|
|
145
168
|
],
|
|
146
169
|
}));
|
|
147
170
|
const mutate = ({ mutations, queries, }) => Effect.gen(function* (_) {
|
|
@@ -153,7 +176,10 @@ const mutate = ({ mutations, queries, }) => Effect.gen(function* (_) {
|
|
|
153
176
|
yield* _(upsertValueIntoTableRowColumn(messageToUpsert, toUpsert, now));
|
|
154
177
|
}
|
|
155
178
|
const { exec } = yield* _(Sqlite);
|
|
156
|
-
yield* _(Effect.forEach(toDelete, ({ table, row }) => exec({
|
|
179
|
+
yield* _(Effect.forEach(toDelete, ({ table, row }) => exec({
|
|
180
|
+
sql: `delete from "${table}" where "id" = ?;`,
|
|
181
|
+
parameters: [row],
|
|
182
|
+
})));
|
|
157
183
|
if (toSync.length > 0) {
|
|
158
184
|
let { timestamp, merkleTree } = yield* _(readTimestampAndMerkleTree);
|
|
159
185
|
const messages = yield* _(mutationsToNewMessages(toSync), Effect.forEach((message) => Effect.map(sendTimestamp(timestamp), (nextTimestamp) => {
|
|
@@ -203,7 +229,7 @@ const handleSyncResponse = ({ messages, ...response }) => Effect.gen(function* (
|
|
|
203
229
|
const config = yield* _(Config);
|
|
204
230
|
const owner = yield* _(Owner);
|
|
205
231
|
const messagesToSync = yield* _(sqlite.exec({
|
|
206
|
-
|
|
232
|
+
...Sql.selectMessagesToSync,
|
|
207
233
|
parameters: [timestampToString(makeSyncTimestamp(diff.value))],
|
|
208
234
|
}), Effect.map(({ rows }) => rows));
|
|
209
235
|
if (response.syncLoopCount > 100) {
|
|
@@ -236,13 +262,7 @@ const sync = ({ queries, }) => Effect.gen(function* (_) {
|
|
|
236
262
|
});
|
|
237
263
|
});
|
|
238
264
|
const reset = (input) => Effect.gen(function* (_) {
|
|
239
|
-
|
|
240
|
-
yield* _(sqlite.exec(`SELECT "name" FROM "sqlite_master" WHERE "type" = 'table'`), Effect.map((result) => result.rows), Effect.flatMap(
|
|
241
|
-
// The dropped table is completely removed from the database schema and
|
|
242
|
-
// the disk file. The table can not be recovered.
|
|
243
|
-
// All indices and triggers associated with the table are also deleted.
|
|
244
|
-
// https://sqlite.org/lang_droptable.html
|
|
245
|
-
Effect.forEach(({ name }) => sqlite.exec(`DROP TABLE "${name}"`), { discard: true })));
|
|
265
|
+
yield* _(dropAllTables);
|
|
246
266
|
if (input.mnemonic)
|
|
247
267
|
yield* _(lazyInit(input.mnemonic));
|
|
248
268
|
const onMessage = yield* _(DbWorkerOnMessage);
|
|
@@ -290,7 +310,7 @@ export const DbWorkerCommonLive = Layer.effect(DbWorker, Effect.gen(function* (_
|
|
|
290
310
|
skipAllBecauseOfReset = true;
|
|
291
311
|
return reset(input);
|
|
292
312
|
},
|
|
293
|
-
ensureSchema
|
|
313
|
+
ensureSchema,
|
|
294
314
|
SyncWorkerOutputSyncResponse: handleSyncResponse,
|
|
295
315
|
}), Effect.provide(layer), run);
|
|
296
316
|
};
|
package/dist/src/Evolu.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ import { EvoluError } from "./ErrorStore.js";
|
|
|
10
10
|
import { SqliteBoolean, SqliteDate } from "./Model.js";
|
|
11
11
|
import { Owner } from "./Owner.js";
|
|
12
12
|
import { AppState, FlushSync } from "./Platform.js";
|
|
13
|
+
import { Index, SqliteQueryOptions } from "./Sqlite.js";
|
|
13
14
|
import { Store } from "./Store.js";
|
|
14
15
|
import { SyncState } from "./SyncWorker.js";
|
|
15
16
|
export interface Evolu<S extends DatabaseSchema = DatabaseSchema> {
|
|
@@ -253,7 +254,7 @@ export interface Evolu<S extends DatabaseSchema = DatabaseSchema> {
|
|
|
253
254
|
* Ensure tables and columns defined in {@link DatabaseSchema} exist in the
|
|
254
255
|
* database.
|
|
255
256
|
*/
|
|
256
|
-
readonly ensureSchema: <From, To extends S>(schema: S.Schema<To, From>) => void;
|
|
257
|
+
readonly ensureSchema: <From, To extends S>(schema: S.Schema<To, From>, indexes?: ReadonlyArray<Index>) => void;
|
|
257
258
|
/**
|
|
258
259
|
* Force sync with Evolu Server.
|
|
259
260
|
*
|
|
@@ -264,7 +265,7 @@ export interface Evolu<S extends DatabaseSchema = DatabaseSchema> {
|
|
|
264
265
|
readonly sync: () => void;
|
|
265
266
|
}
|
|
266
267
|
export declare const Evolu: Context.Tag<Evolu<DatabaseSchema>, Evolu<DatabaseSchema>>;
|
|
267
|
-
type CreateQuery<S extends DatabaseSchema> = <R extends Row>(queryCallback: QueryCallback<S, R
|
|
268
|
+
type CreateQuery<S extends DatabaseSchema> = <R extends Row>(queryCallback: QueryCallback<S, R>, options?: SqliteQueryOptions) => Query<R>;
|
|
268
269
|
type QueryCallback<S extends DatabaseSchema, R extends Row> = (db: Pick<Kysely.Kysely<QuerySchema<S>>, "selectFrom" | "fn" | "with" | "withRecursive">) => Kysely.SelectQueryBuilder<any, any, R>;
|
|
269
270
|
type QuerySchema<S extends DatabaseSchema> = {
|
|
270
271
|
readonly [Table in keyof S]: NullableExceptForIdAndAutomaticColumns<{
|
|
@@ -274,6 +275,7 @@ type QuerySchema<S extends DatabaseSchema> = {
|
|
|
274
275
|
type NullableExceptForIdAndAutomaticColumns<T> = {
|
|
275
276
|
readonly [K in keyof T]: K extends "id" | "createdAt" | "updatedAt" ? T[K] : T[K] | null;
|
|
276
277
|
};
|
|
278
|
+
export declare const createIndex: (indexName: string) => Kysely.CreateIndexBuilder<never>;
|
|
277
279
|
export declare const makeCreateQuery: <S extends DatabaseSchema = DatabaseSchema>() => CreateQuery<S>;
|
|
278
280
|
export interface LoadingPromises {
|
|
279
281
|
readonly get: <R extends Row>(query: Query<R>) => {
|
package/dist/src/Evolu.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Evolu.d.ts","sourceRoot":"","sources":["../../src/Evolu.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,uBAAuB,CAAC;AAC3C,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAK1C,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAItC,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AACjC,OAAO,EAAE,MAAM,EAAc,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAwC,MAAM,aAAa,CAAC;AAC7E,OAAO,EACL,cAAc,EACd,OAAO,EACP,KAAK,EACL,WAAW,EACX,+BAA+B,EAC/B,GAAG,EACH,SAAS,EAMV,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,QAAQ,EAAmC,MAAM,eAAe,CAAC;AAE1E,OAAO,EAAE,UAAU,EAAkB,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEvD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"Evolu.d.ts","sourceRoot":"","sources":["../../src/Evolu.ts"],"names":[],"mappings":"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"}
|
package/dist/src/Evolu.js
CHANGED
|
@@ -16,9 +16,10 @@ import { applyPatches } from "./Diff.js";
|
|
|
16
16
|
import { makeErrorStore } from "./ErrorStore.js";
|
|
17
17
|
import { OnCompletes, OnCompletesLive } from "./OnCompletes.js";
|
|
18
18
|
import { AppState, FlushSync } from "./Platform.js";
|
|
19
|
-
import { isSqlMutation } from "./Sqlite.js";
|
|
19
|
+
import { isSqlMutation, } from "./Sqlite.js";
|
|
20
20
|
import { makeStore } from "./Store.js";
|
|
21
21
|
export const Evolu = Context.GenericTag("@services/Evolu");
|
|
22
|
+
// https://kysely.dev/docs/recipes/splitting-query-building-and-execution
|
|
22
23
|
const kysely = new Kysely.Kysely({
|
|
23
24
|
dialect: {
|
|
24
25
|
createAdapter: () => new Kysely.SqliteAdapter(),
|
|
@@ -29,10 +30,16 @@ const kysely = new Kysely.Kysely({
|
|
|
29
30
|
createQueryCompiler: () => new Kysely.SqliteQueryCompiler(),
|
|
30
31
|
},
|
|
31
32
|
});
|
|
32
|
-
export const
|
|
33
|
-
|
|
33
|
+
export const createIndex = kysely.schema.createIndex.bind(kysely.schema);
|
|
34
|
+
export const makeCreateQuery = () => (queryCallback, options) => pipe(queryCallback(kysely).compile(), (compiledQuery) => {
|
|
35
|
+
if (isSqlMutation(compiledQuery.sql))
|
|
34
36
|
throw new Error("SQL mutation (INSERT, UPDATE, DELETE, etc.) isn't allowed in the Evolu `createQuery` function. Kysely suggests it because there is no read-only Kysely yet, and removing such an API is not possible. For mutations, use Evolu mutation API.");
|
|
35
|
-
|
|
37
|
+
const parameters = compiledQuery.parameters;
|
|
38
|
+
return {
|
|
39
|
+
sql: compiledQuery.sql,
|
|
40
|
+
parameters,
|
|
41
|
+
...(options && { options }),
|
|
42
|
+
};
|
|
36
43
|
}, (query) => serializeQuery(query));
|
|
37
44
|
export const LoadingPromises = Context.GenericTag("@services/LoadingPromises");
|
|
38
45
|
export const LoadingPromiseLive = Layer.effect(LoadingPromises, Effect.gen(function* (_) {
|
|
@@ -243,9 +250,10 @@ const EvoluCommon = Layer.effect(Evolu, Effect.gen(function* (_) {
|
|
|
243
250
|
createOrUpdate: mutate,
|
|
244
251
|
resetOwner: () => dbWorker.postMessage({ _tag: "reset" }),
|
|
245
252
|
restoreOwner: (mnemonic) => dbWorker.postMessage({ _tag: "reset", mnemonic }),
|
|
246
|
-
ensureSchema: (schema) => dbWorker.postMessage({
|
|
253
|
+
ensureSchema: (schema, indexes = []) => dbWorker.postMessage({
|
|
247
254
|
_tag: "ensureSchema",
|
|
248
255
|
tables: schemaToTables(schema),
|
|
256
|
+
indexes,
|
|
249
257
|
}),
|
|
250
258
|
sync,
|
|
251
259
|
});
|
|
@@ -264,6 +272,10 @@ export const EvoluCommonLive = EvoluCommon.pipe(Layer.provide(NanoIdGeneratorLiv
|
|
|
264
272
|
export const makeCreateEvolu = (EvoluLive) => (schema, config) => {
|
|
265
273
|
// For https://nextjs.org/docs/architecture/fast-refresh etc.
|
|
266
274
|
const evolu = GlobalValue.globalValue("@evolu/common", () => Evolu.pipe(Effect.provide(EvoluLive), Effect.provide(ConfigLive(config)), Effect.runSync));
|
|
267
|
-
|
|
275
|
+
const indexes = config?.indexes?.map((index) => ({
|
|
276
|
+
name: index.toOperationNode().name.name,
|
|
277
|
+
sql: index.compile().sql,
|
|
278
|
+
}));
|
|
279
|
+
evolu.ensureSchema(schema, indexes);
|
|
268
280
|
return evolu;
|
|
269
281
|
};
|
package/dist/src/Public.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { sql } from "kysely";
|
|
1
2
|
export type { NotNull } from "kysely";
|
|
2
3
|
export { jsonArrayFrom, jsonObjectFrom } from "kysely/helpers/sqlite";
|
|
3
4
|
export type { Timestamp, TimestampError } from "./Crdt.js";
|
|
@@ -5,6 +6,7 @@ export type { InvalidMnemonicError, Mnemonic } from "./Crypto.js";
|
|
|
5
6
|
export { database, table } from "./Db.js";
|
|
6
7
|
export type { ExtractRow, QueryResult } from "./Db.js";
|
|
7
8
|
export type { EvoluError, UnexpectedError } from "./ErrorStore.js";
|
|
9
|
+
export { createIndex } from "./Evolu.js";
|
|
8
10
|
export * from "./Model.js";
|
|
9
11
|
export type { Owner, OwnerId } from "./Owner.js";
|
|
10
12
|
export { canUseDom } from "./Platform.js";
|