@sqlite-sync/core 0.0.1 → 0.0.3
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/dist/chunk-627DSM2Q.js +1410 -0
- package/dist/chunk-627DSM2Q.js.map +1 -0
- package/dist/chunk-UGF5IU53.js +132 -0
- package/dist/chunk-UGF5IU53.js.map +1 -0
- package/dist/crdt-schema-DQ1cYsFE.d.ts +63 -0
- package/dist/crdt-sync-remote-source-idoIjMcs.d.ts +479 -0
- package/dist/index.d.ts +117 -207
- package/dist/index.js +614 -357
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +50 -26
- package/dist/server.js +28 -36
- package/dist/server.js.map +1 -1
- package/dist/worker.d.ts +13 -11
- package/dist/worker.js +275 -140
- package/dist/worker.js.map +1 -1
- package/package.json +6 -6
- package/dist/chunk-LK5FJCUD.js +0 -522
- package/dist/chunk-LK5FJCUD.js.map +0 -1
- package/dist/chunk-YLXMST5Z.js +0 -490
- package/dist/chunk-YLXMST5Z.js.map +0 -1
- package/dist/crdt-sync-producer-0toEpGf0.d.ts +0 -15
- package/dist/crdt-sync-remote-source-rrqinqLn.d.ts +0 -271
package/dist/chunk-LK5FJCUD.js
DELETED
|
@@ -1,522 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
TypedBroadcastChannel,
|
|
3
|
-
crdtSchema,
|
|
4
|
-
createAsyncAutoFlushBuffer,
|
|
5
|
-
dummyKysely
|
|
6
|
-
} from "./chunk-YLXMST5Z.js";
|
|
7
|
-
|
|
8
|
-
// src/worker-db/worker-common.ts
|
|
9
|
-
var syncDbWorkerLockName = "sync-db-worker-lock";
|
|
10
|
-
var broadcastChannelNames = {
|
|
11
|
-
requests: "sync-db-worker-requests",
|
|
12
|
-
responses: "sync-db-worker-responses"
|
|
13
|
-
};
|
|
14
|
-
var createBroadcastChannels = () => {
|
|
15
|
-
return {
|
|
16
|
-
requests: new TypedBroadcastChannel(broadcastChannelNames.requests),
|
|
17
|
-
responses: new TypedBroadcastChannel(broadcastChannelNames.responses)
|
|
18
|
-
};
|
|
19
|
-
};
|
|
20
|
-
function isWorkerInitMessage(message) {
|
|
21
|
-
return typeof message === "object" && message !== null && "type" in message && message.type === "init";
|
|
22
|
-
}
|
|
23
|
-
function isWorkerInitResponse(message) {
|
|
24
|
-
return typeof message === "object" && message !== null && "type" in message && message.type === "init-ready";
|
|
25
|
-
}
|
|
26
|
-
function isWorkerRequestMessage(message) {
|
|
27
|
-
return typeof message === "object" && message !== null && "type" in message && message.type === "request";
|
|
28
|
-
}
|
|
29
|
-
function isWorkerResponseMessage(message) {
|
|
30
|
-
return typeof message === "object" && message !== null && "type" in message && "requestId" in message && "data" in message;
|
|
31
|
-
}
|
|
32
|
-
function isWorkerNotificationMessage(message) {
|
|
33
|
-
return typeof message === "object" && message !== null && "notificationType" in message && !!message.notificationType;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// src/logger.ts
|
|
37
|
-
var startPerformanceLogger = (logger) => {
|
|
38
|
-
let startTime = performance.now();
|
|
39
|
-
return {
|
|
40
|
-
restart: () => {
|
|
41
|
-
startTime = performance.now();
|
|
42
|
-
},
|
|
43
|
-
logEnd: (type, message, level = "info") => {
|
|
44
|
-
const elapsed = performance.now() - startTime;
|
|
45
|
-
logger(type, `${elapsed.toFixed(2)}ms - ${message}`, level);
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
// src/introspection.ts
|
|
51
|
-
import { sql } from "kysely";
|
|
52
|
-
function tablesQuery(qb) {
|
|
53
|
-
return qb.selectFrom("sqlite_master").where("type", "in", ["table", "view"]).where("name", "not like", "sqlite_%").select(["name", "sql", "type"]).orderBy("name");
|
|
54
|
-
}
|
|
55
|
-
function introspectDb(_db) {
|
|
56
|
-
const db = _db;
|
|
57
|
-
const tables = db.executeKysely(
|
|
58
|
-
(db2) => tablesQuery(db2)
|
|
59
|
-
).rows;
|
|
60
|
-
const tablesMetadata = db.executeKysely(
|
|
61
|
-
(db2) => db2.with(
|
|
62
|
-
"table_list",
|
|
63
|
-
(qb) => tablesQuery(qb)
|
|
64
|
-
).selectFrom([
|
|
65
|
-
"table_list as tl",
|
|
66
|
-
sql`pragma_table_info(tl.name)`.as("p")
|
|
67
|
-
]).select([
|
|
68
|
-
"tl.name as table",
|
|
69
|
-
"p.cid",
|
|
70
|
-
"p.name",
|
|
71
|
-
"p.type",
|
|
72
|
-
"p.notnull",
|
|
73
|
-
"p.dflt_value",
|
|
74
|
-
"p.pk"
|
|
75
|
-
]).orderBy("tl.name").orderBy("p.cid")
|
|
76
|
-
).rows;
|
|
77
|
-
const columnsByTable = {};
|
|
78
|
-
for (const row of tablesMetadata) {
|
|
79
|
-
columnsByTable[row.table] ??= [];
|
|
80
|
-
columnsByTable[row.table].push(row);
|
|
81
|
-
}
|
|
82
|
-
return Object.fromEntries(
|
|
83
|
-
tables.map(({ name, sql: sql2, type }) => {
|
|
84
|
-
let autoIncrementCol = sql2?.split(/[(),]/)?.find((it) => it.toLowerCase().includes("autoincrement"))?.trimStart()?.split(/\s+/)?.[0]?.replace(/["`]/g, "");
|
|
85
|
-
const columns = columnsByTable[name] ?? [];
|
|
86
|
-
if (!autoIncrementCol) {
|
|
87
|
-
const pkCols = columns.filter((r) => r.pk > 0);
|
|
88
|
-
if (pkCols.length === 1 && pkCols[0].type.toLowerCase() === "integer") {
|
|
89
|
-
autoIncrementCol = pkCols[0].name;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
return [
|
|
93
|
-
name,
|
|
94
|
-
{
|
|
95
|
-
name,
|
|
96
|
-
isView: type === "view",
|
|
97
|
-
columns: columns.map((col) => ({
|
|
98
|
-
name: col.name,
|
|
99
|
-
dataType: col.type,
|
|
100
|
-
isNullable: !col.notnull,
|
|
101
|
-
isAutoIncrementing: col.name === autoIncrementCol,
|
|
102
|
-
hasDefaultValue: col.dflt_value != null,
|
|
103
|
-
comment: void 0
|
|
104
|
-
}))
|
|
105
|
-
}
|
|
106
|
-
];
|
|
107
|
-
})
|
|
108
|
-
);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// src/sqlite-db-wrapper.ts
|
|
112
|
-
var SQLiteDbWrapper = class {
|
|
113
|
-
db = null;
|
|
114
|
-
sqlite3;
|
|
115
|
-
logger;
|
|
116
|
-
loggerPrefix;
|
|
117
|
-
loadedDbSchema = null;
|
|
118
|
-
dataPointers = [];
|
|
119
|
-
preparedStatements = [];
|
|
120
|
-
preparedStatementsMap = /* @__PURE__ */ new Map();
|
|
121
|
-
constructor(opts) {
|
|
122
|
-
this.db = opts.db;
|
|
123
|
-
this.sqlite3 = opts.sqlite3;
|
|
124
|
-
this.logger = opts.logger;
|
|
125
|
-
this.loggerPrefix = opts.loggerPrefix;
|
|
126
|
-
}
|
|
127
|
-
get ensureDb() {
|
|
128
|
-
if (!this.db) {
|
|
129
|
-
throw new Error("Database is already closed");
|
|
130
|
-
}
|
|
131
|
-
return this.db;
|
|
132
|
-
}
|
|
133
|
-
get dbSchema() {
|
|
134
|
-
if (!this.loadedDbSchema) {
|
|
135
|
-
this.loadedDbSchema = introspectDb(this);
|
|
136
|
-
}
|
|
137
|
-
return this.loadedDbSchema;
|
|
138
|
-
}
|
|
139
|
-
execute(opts) {
|
|
140
|
-
const sql2 = typeof opts === "string" ? opts : opts.sql;
|
|
141
|
-
const bind = typeof opts === "string" ? void 0 : opts.parameters;
|
|
142
|
-
const perf = this.logger ? startPerformanceLogger(this.logger) : void 0;
|
|
143
|
-
const rows = this.ensureDb.exec({
|
|
144
|
-
sql: sql2,
|
|
145
|
-
bind,
|
|
146
|
-
returnValue: "resultRows",
|
|
147
|
-
rowMode: "object"
|
|
148
|
-
});
|
|
149
|
-
perf?.logEnd(`${this.loggerPrefix ?? ""}:query`, sql2, "info");
|
|
150
|
-
return { rows };
|
|
151
|
-
}
|
|
152
|
-
executeTransaction(callback) {
|
|
153
|
-
return this.ensureDb.transaction(() => callback(this));
|
|
154
|
-
}
|
|
155
|
-
prepare(sql2) {
|
|
156
|
-
const perf = this.logger ? startPerformanceLogger(this.logger) : void 0;
|
|
157
|
-
const stmt = this.ensureDb.prepare(sql2);
|
|
158
|
-
perf?.logEnd(`${this.loggerPrefix ?? ""}:prepare`, sql2, "info");
|
|
159
|
-
let isFinalized = false;
|
|
160
|
-
const execute = (params) => {
|
|
161
|
-
if (isFinalized) {
|
|
162
|
-
throw new Error("Statement is finalized");
|
|
163
|
-
}
|
|
164
|
-
const perf2 = this.logger ? startPerformanceLogger(this.logger) : void 0;
|
|
165
|
-
if (params.length > 0) {
|
|
166
|
-
stmt.bind(params);
|
|
167
|
-
}
|
|
168
|
-
const results = [];
|
|
169
|
-
while (stmt.step()) {
|
|
170
|
-
results.push(stmt.get({}));
|
|
171
|
-
}
|
|
172
|
-
stmt.reset(true);
|
|
173
|
-
perf2?.logEnd(`${this.loggerPrefix ?? ""}:prepare-execute`, sql2, "info");
|
|
174
|
-
return results;
|
|
175
|
-
};
|
|
176
|
-
const finalize = () => {
|
|
177
|
-
isFinalized = true;
|
|
178
|
-
stmt.finalize();
|
|
179
|
-
};
|
|
180
|
-
const preparedStatement = {
|
|
181
|
-
execute,
|
|
182
|
-
finalize,
|
|
183
|
-
get isFinalized() {
|
|
184
|
-
return isFinalized;
|
|
185
|
-
}
|
|
186
|
-
};
|
|
187
|
-
this.preparedStatements.push(
|
|
188
|
-
preparedStatement
|
|
189
|
-
);
|
|
190
|
-
return preparedStatement;
|
|
191
|
-
}
|
|
192
|
-
prepareKysely() {
|
|
193
|
-
return (factory) => {
|
|
194
|
-
const query = factory(dummyKysely, (key) => key).compile();
|
|
195
|
-
const statement = this.prepare(query.sql);
|
|
196
|
-
return {
|
|
197
|
-
execute: (parameters) => {
|
|
198
|
-
const params = query.parameters.map(
|
|
199
|
-
(param) => parameters[param]
|
|
200
|
-
);
|
|
201
|
-
const result = statement.execute(params);
|
|
202
|
-
return result;
|
|
203
|
-
}
|
|
204
|
-
};
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
executeKysely(factory) {
|
|
208
|
-
const query = factory(dummyKysely).compile();
|
|
209
|
-
return this.execute(query);
|
|
210
|
-
}
|
|
211
|
-
executePrepared(key, params, factory) {
|
|
212
|
-
let statement = this.preparedStatementsMap.get(key);
|
|
213
|
-
if (!statement) {
|
|
214
|
-
statement = this.prepareKysely()(factory);
|
|
215
|
-
this.preparedStatementsMap.set(
|
|
216
|
-
key,
|
|
217
|
-
statement
|
|
218
|
-
);
|
|
219
|
-
}
|
|
220
|
-
return statement.execute(params);
|
|
221
|
-
}
|
|
222
|
-
sql(templateOrString, ...parameters) {
|
|
223
|
-
if (typeof templateOrString === "string") {
|
|
224
|
-
return this.execute({
|
|
225
|
-
sql: templateOrString,
|
|
226
|
-
parameters
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
return this.execute({
|
|
230
|
-
sql: templateOrString.join("?"),
|
|
231
|
-
parameters
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
createScalarFunction({
|
|
235
|
-
name,
|
|
236
|
-
callback,
|
|
237
|
-
deterministic,
|
|
238
|
-
directOnly,
|
|
239
|
-
innocuous
|
|
240
|
-
}) {
|
|
241
|
-
return this.ensureDb.createFunction({
|
|
242
|
-
name,
|
|
243
|
-
xFunc: (_, ...args) => {
|
|
244
|
-
const result = callback(...args);
|
|
245
|
-
return result;
|
|
246
|
-
},
|
|
247
|
-
arity: callback.length,
|
|
248
|
-
deterministic,
|
|
249
|
-
directOnly,
|
|
250
|
-
innocuous
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
|
-
useSnapshot(snapshot) {
|
|
254
|
-
const perf = this.logger ? startPerformanceLogger(this.logger) : void 0;
|
|
255
|
-
const dataPointer = this.sqlite3.wasm.allocFromTypedArray(snapshot);
|
|
256
|
-
this.dataPointers.push(dataPointer);
|
|
257
|
-
const resultCode = this.sqlite3.capi.sqlite3_deserialize(
|
|
258
|
-
this.ensureDb,
|
|
259
|
-
"main",
|
|
260
|
-
dataPointer,
|
|
261
|
-
snapshot.byteLength,
|
|
262
|
-
snapshot.byteLength,
|
|
263
|
-
this.sqlite3.capi.SQLITE_DESERIALIZE_FREEONCLOSE | this.sqlite3.capi.SQLITE_DESERIALIZE_RESIZEABLE
|
|
264
|
-
);
|
|
265
|
-
this.ensureDb.checkRc(resultCode);
|
|
266
|
-
this.invalidateDbSchema();
|
|
267
|
-
perf?.logEnd("useSnapshot", "success", "info");
|
|
268
|
-
}
|
|
269
|
-
createSnapshot() {
|
|
270
|
-
return this.sqlite3.capi.sqlite3_js_db_export(this.ensureDb);
|
|
271
|
-
}
|
|
272
|
-
invalidateDbSchema() {
|
|
273
|
-
this.loadedDbSchema = null;
|
|
274
|
-
}
|
|
275
|
-
cleanup() {
|
|
276
|
-
this.preparedStatements.forEach((stmt) => stmt.finalize());
|
|
277
|
-
this.preparedStatements.splice(0);
|
|
278
|
-
this.preparedStatementsMap.clear();
|
|
279
|
-
}
|
|
280
|
-
close() {
|
|
281
|
-
this.cleanup();
|
|
282
|
-
this.db?.close();
|
|
283
|
-
this.db = null;
|
|
284
|
-
}
|
|
285
|
-
};
|
|
286
|
-
|
|
287
|
-
// src/migrations/system-schema.ts
|
|
288
|
-
function applyWorkerDbSchema(db) {
|
|
289
|
-
db.executeTransaction((db2) => {
|
|
290
|
-
db2.executeKysely(
|
|
291
|
-
(kysely) => crdtSchema.metaTable(kysely.schema, "worker.meta")
|
|
292
|
-
);
|
|
293
|
-
db2.executeKysely(
|
|
294
|
-
(kysely) => crdtSchema.crdtUpdateLogTable(kysely.schema, "crdt_update_log")
|
|
295
|
-
);
|
|
296
|
-
db2.executeKysely(
|
|
297
|
-
(kysely) => crdtSchema.persistedEventsTable(kysely.schema, "worker.crdt_events")
|
|
298
|
-
);
|
|
299
|
-
});
|
|
300
|
-
}
|
|
301
|
-
function applyMemoryDbSchema(db) {
|
|
302
|
-
db.executeKysely(
|
|
303
|
-
(kysely) => crdtSchema.crdtUpdateLogTable(kysely.schema, "crdt_update_log")
|
|
304
|
-
);
|
|
305
|
-
db.executeKysely(
|
|
306
|
-
(kysely) => crdtSchema.persistedEventsTable(kysely.schema, "persisted_crdt_events")
|
|
307
|
-
);
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
// src/sqlite-crdt/crdt-sync-remote-source.ts
|
|
311
|
-
var createCrdtSyncRemoteSource = ({
|
|
312
|
-
bufferSize,
|
|
313
|
-
storage,
|
|
314
|
-
syncId,
|
|
315
|
-
nodeId,
|
|
316
|
-
pullEvents: pullEventsChunk,
|
|
317
|
-
pushEvents
|
|
318
|
-
}) => {
|
|
319
|
-
let pullPromise = null;
|
|
320
|
-
let requestedPullSyncId = null;
|
|
321
|
-
const pullEvents = (request) => {
|
|
322
|
-
const afterSyncId = request?.afterSyncId ?? syncId.current;
|
|
323
|
-
if (pullPromise) {
|
|
324
|
-
if (!requestedPullSyncId || requestedPullSyncId < afterSyncId) {
|
|
325
|
-
requestedPullSyncId = afterSyncId;
|
|
326
|
-
}
|
|
327
|
-
return pullPromise;
|
|
328
|
-
}
|
|
329
|
-
pullPromise = pullAllEvents({
|
|
330
|
-
afterSyncId,
|
|
331
|
-
excludeNodeId: request?.includeSelf ? void 0 : nodeId
|
|
332
|
-
}).finally(() => {
|
|
333
|
-
pullPromise = null;
|
|
334
|
-
if (requestedPullSyncId && requestedPullSyncId > syncId.current) {
|
|
335
|
-
pullEvents({ afterSyncId: requestedPullSyncId });
|
|
336
|
-
requestedPullSyncId = null;
|
|
337
|
-
}
|
|
338
|
-
});
|
|
339
|
-
return pullPromise;
|
|
340
|
-
};
|
|
341
|
-
const pullAllEvents = async (opts) => {
|
|
342
|
-
let hasMore = true;
|
|
343
|
-
let afterSyncId = opts.afterSyncId;
|
|
344
|
-
while (hasMore) {
|
|
345
|
-
const response = await pullEventsChunk({
|
|
346
|
-
...opts,
|
|
347
|
-
afterSyncId
|
|
348
|
-
});
|
|
349
|
-
hasMore = response.hasMore;
|
|
350
|
-
afterSyncId = response.newSyncId;
|
|
351
|
-
if (response.events) {
|
|
352
|
-
storage.enqueueEvents(
|
|
353
|
-
response.events.map((x) => ({
|
|
354
|
-
...x,
|
|
355
|
-
origin: "remote"
|
|
356
|
-
}))
|
|
357
|
-
);
|
|
358
|
-
}
|
|
359
|
-
if (response.newSyncId <= syncId.current) {
|
|
360
|
-
break;
|
|
361
|
-
}
|
|
362
|
-
if (response.newSyncId > syncId.current) {
|
|
363
|
-
syncId.current = response.newSyncId;
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
};
|
|
367
|
-
const pushEventsBuffer = createAsyncAutoFlushBuffer({
|
|
368
|
-
size: bufferSize,
|
|
369
|
-
flush: async (events) => {
|
|
370
|
-
await pushEvents({ nodeId, events });
|
|
371
|
-
}
|
|
372
|
-
});
|
|
373
|
-
storage.addEventListener("event-applied", (event) => {
|
|
374
|
-
if (event.payload.origin === "remote") {
|
|
375
|
-
return;
|
|
376
|
-
}
|
|
377
|
-
pushEventsBuffer.add(event.payload);
|
|
378
|
-
});
|
|
379
|
-
storage.addEventListener("event-processing-done", () => {
|
|
380
|
-
pushEventsBuffer.flush();
|
|
381
|
-
});
|
|
382
|
-
return {
|
|
383
|
-
pullEvents
|
|
384
|
-
};
|
|
385
|
-
};
|
|
386
|
-
|
|
387
|
-
// src/sqlite-kysely.ts
|
|
388
|
-
import {
|
|
389
|
-
CompiledQuery,
|
|
390
|
-
Kysely,
|
|
391
|
-
SqliteAdapter,
|
|
392
|
-
SqliteIntrospector,
|
|
393
|
-
SqliteQueryCompiler
|
|
394
|
-
} from "kysely";
|
|
395
|
-
var SqliteDriver = class {
|
|
396
|
-
#connectionMutex = new ConnectionMutex();
|
|
397
|
-
#db;
|
|
398
|
-
#connection;
|
|
399
|
-
constructor(db) {
|
|
400
|
-
this.#db = db;
|
|
401
|
-
this.#connection = new SqliteConnection(this.#db);
|
|
402
|
-
}
|
|
403
|
-
async init() {
|
|
404
|
-
return Promise.resolve();
|
|
405
|
-
}
|
|
406
|
-
async acquireConnection() {
|
|
407
|
-
await this.#connectionMutex.lock();
|
|
408
|
-
return this.#connection;
|
|
409
|
-
}
|
|
410
|
-
async beginTransaction(connection) {
|
|
411
|
-
await connection.executeQuery(CompiledQuery.raw("begin"));
|
|
412
|
-
}
|
|
413
|
-
async commitTransaction(connection) {
|
|
414
|
-
await connection.executeQuery(CompiledQuery.raw("commit"));
|
|
415
|
-
}
|
|
416
|
-
async rollbackTransaction(connection) {
|
|
417
|
-
await connection.executeQuery(CompiledQuery.raw("rollback"));
|
|
418
|
-
}
|
|
419
|
-
async releaseConnection() {
|
|
420
|
-
this.#connectionMutex.unlock();
|
|
421
|
-
}
|
|
422
|
-
async destroy() {
|
|
423
|
-
this.#db?.close();
|
|
424
|
-
}
|
|
425
|
-
};
|
|
426
|
-
var SqliteConnection = class {
|
|
427
|
-
#db;
|
|
428
|
-
constructor(db) {
|
|
429
|
-
this.#db = db;
|
|
430
|
-
}
|
|
431
|
-
executeQuery(compiledQuery) {
|
|
432
|
-
const stmt = this.#db.execute(compiledQuery);
|
|
433
|
-
return Promise.resolve({
|
|
434
|
-
rows: stmt.rows
|
|
435
|
-
});
|
|
436
|
-
}
|
|
437
|
-
// eslint-disable-next-line require-yield
|
|
438
|
-
async *streamQuery() {
|
|
439
|
-
throw new Error("SQLite3 does not support streaming.");
|
|
440
|
-
}
|
|
441
|
-
};
|
|
442
|
-
var ConnectionMutex = class {
|
|
443
|
-
#promise;
|
|
444
|
-
#resolve;
|
|
445
|
-
async lock() {
|
|
446
|
-
while (this.#promise) {
|
|
447
|
-
await this.#promise;
|
|
448
|
-
}
|
|
449
|
-
this.#promise = new Promise((resolve) => {
|
|
450
|
-
this.#resolve = resolve;
|
|
451
|
-
});
|
|
452
|
-
}
|
|
453
|
-
unlock() {
|
|
454
|
-
const resolve = this.#resolve;
|
|
455
|
-
this.#promise = void 0;
|
|
456
|
-
this.#resolve = void 0;
|
|
457
|
-
resolve?.();
|
|
458
|
-
}
|
|
459
|
-
};
|
|
460
|
-
function createSQLiteKysely(sqliteDb) {
|
|
461
|
-
return new Kysely({
|
|
462
|
-
dialect: {
|
|
463
|
-
createAdapter: () => new SqliteAdapter(),
|
|
464
|
-
createDriver: () => new SqliteDriver(sqliteDb),
|
|
465
|
-
createIntrospector: (db) => new SqliteIntrospector(db),
|
|
466
|
-
createQueryCompiler: () => new SqliteQueryCompiler()
|
|
467
|
-
}
|
|
468
|
-
});
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
// src/migrations/migrator.ts
|
|
472
|
-
import {
|
|
473
|
-
Migrator
|
|
474
|
-
} from "kysely";
|
|
475
|
-
var SyncMigrationsProvider = class {
|
|
476
|
-
migrations;
|
|
477
|
-
constructor(migrations) {
|
|
478
|
-
this.migrations = migrations;
|
|
479
|
-
}
|
|
480
|
-
async getMigrations() {
|
|
481
|
-
return Promise.resolve(this.migrations);
|
|
482
|
-
}
|
|
483
|
-
};
|
|
484
|
-
function createSyncDbMigrator(options) {
|
|
485
|
-
return new Migrator({
|
|
486
|
-
db: options.db,
|
|
487
|
-
provider: new SyncMigrationsProvider(options.migrations),
|
|
488
|
-
allowUnorderedMigrations: false,
|
|
489
|
-
migrationLockTableName: "worker.migration_lock",
|
|
490
|
-
migrationTableName: "worker.migration"
|
|
491
|
-
});
|
|
492
|
-
}
|
|
493
|
-
function createSyncDbMigrations(migrations) {
|
|
494
|
-
return Object.fromEntries(
|
|
495
|
-
Object.entries(migrations).map(([key, value]) => [
|
|
496
|
-
key.toString().padStart(6, "0"),
|
|
497
|
-
value
|
|
498
|
-
])
|
|
499
|
-
);
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
export {
|
|
503
|
-
syncDbWorkerLockName,
|
|
504
|
-
broadcastChannelNames,
|
|
505
|
-
createBroadcastChannels,
|
|
506
|
-
isWorkerInitMessage,
|
|
507
|
-
isWorkerInitResponse,
|
|
508
|
-
isWorkerRequestMessage,
|
|
509
|
-
isWorkerResponseMessage,
|
|
510
|
-
isWorkerNotificationMessage,
|
|
511
|
-
startPerformanceLogger,
|
|
512
|
-
introspectDb,
|
|
513
|
-
SQLiteDbWrapper,
|
|
514
|
-
applyWorkerDbSchema,
|
|
515
|
-
applyMemoryDbSchema,
|
|
516
|
-
createCrdtSyncRemoteSource,
|
|
517
|
-
SqliteDriver,
|
|
518
|
-
createSQLiteKysely,
|
|
519
|
-
createSyncDbMigrator,
|
|
520
|
-
createSyncDbMigrations
|
|
521
|
-
};
|
|
522
|
-
//# sourceMappingURL=chunk-LK5FJCUD.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/worker-db/worker-common.ts","../src/logger.ts","../src/introspection.ts","../src/sqlite-db-wrapper.ts","../src/migrations/system-schema.ts","../src/sqlite-crdt/crdt-sync-remote-source.ts","../src/sqlite-kysely.ts","../src/migrations/migrator.ts"],"sourcesContent":["import type {\n EventsPullRequest,\n EventsPullResponse,\n EventsPushRequest,\n EventsPushResponse,\n} from \"../sqlite-crdt/crdt-sync-remote-source\";\nimport type { ExecuteParams, ExecuteResult } from \"../sqlite-db-wrapper\";\nimport { TypedBroadcastChannel } from \"../utils\";\n\nexport const syncDbWorkerLockName = \"sync-db-worker-lock\";\n\nexport type WorkerNotificationMessage = {\n notificationType: \"new-event-chunk-applied\";\n newSyncId: number;\n};\n\nexport type PushTabEventsResponse = {\n firstEventSyncId: number;\n lastEventSyncId: number;\n};\n\nexport type GetSnapshotResponse = {\n file: Uint8Array<ArrayBufferLike>;\n syncId: number;\n};\n\nexport interface WorkerRpc {\n getSnapshot: () => GetSnapshotResponse;\n pushTabEvents: (request: EventsPushRequest) => EventsPushResponse;\n execute: (query: ExecuteParams) => ExecuteResult<unknown>;\n pullEvents: (params: EventsPullRequest) => EventsPullResponse;\n postInitReady: () => void;\n}\n\nexport type WorkerRequestMethod = keyof WorkerRpc;\n\nexport type WorkerRequestMessage<\n TMethod extends WorkerRequestMethod = WorkerRequestMethod\n> = {\n type: \"request\";\n requestId: string;\n method: TMethod;\n args: Parameters<WorkerRpc[TMethod]>;\n};\n\nexport type WorkerResponseMessage<\n TMethod extends WorkerRequestMethod = WorkerRequestMethod\n> = {\n type: \"response\";\n requestId: string;\n data: ReturnType<WorkerRpc[TMethod]>;\n};\n\nexport type AsyncRpc<T> = {\n [K in keyof T]: T[K] extends (...args: infer U) => infer V\n ? (...args: U) => V extends Promise<infer W> ? Promise<W> : Promise<V>\n : never;\n};\n\nexport const broadcastChannelNames = {\n requests: \"sync-db-worker-requests\",\n responses: \"sync-db-worker-responses\",\n} as const;\n\nexport type WorkerBroadcastChannels = {\n requests: TypedBroadcastChannel<WorkerRequestMessage>;\n responses: TypedBroadcastChannel<\n WorkerResponseMessage | WorkerNotificationMessage | WorkerInitResponse\n >;\n};\n\nexport const createBroadcastChannels = (): WorkerBroadcastChannels => {\n return {\n requests: new TypedBroadcastChannel(broadcastChannelNames.requests),\n responses: new TypedBroadcastChannel(broadcastChannelNames.responses),\n };\n};\n\nexport type WorkerConfig = {\n dbPath: string;\n clientId: string;\n clearOnInit?: boolean;\n syncServer: SyncServerConfig;\n};\n\nexport type SyncServerConfig = {\n host: string;\n room: string;\n};\n\nexport type WorkerInitMessage = {\n type: \"init\";\n config: WorkerConfig;\n};\n\nexport function isWorkerInitMessage(\n message: unknown\n): message is WorkerInitMessage {\n return (\n typeof message === \"object\" &&\n message !== null &&\n \"type\" in message &&\n message.type === \"init\"\n );\n}\n\nexport type WorkerInitResponse = {\n type: \"init-ready\";\n};\n\nexport function isWorkerInitResponse(\n message: unknown\n): message is WorkerInitResponse {\n return (\n typeof message === \"object\" &&\n message !== null &&\n \"type\" in message &&\n message.type === \"init-ready\"\n );\n}\n\nexport function isWorkerRequestMessage(\n message: unknown\n): message is WorkerRequestMessage {\n return (\n typeof message === \"object\" &&\n message !== null &&\n \"type\" in message &&\n message.type === \"request\"\n );\n}\n\nexport function isWorkerResponseMessage(\n message: unknown\n): message is WorkerResponseMessage {\n return (\n typeof message === \"object\" &&\n message !== null &&\n \"type\" in message &&\n \"requestId\" in message &&\n \"data\" in message\n );\n}\n\nexport function isWorkerNotificationMessage(\n message: unknown\n): message is WorkerNotificationMessage {\n return (\n typeof message === \"object\" &&\n message !== null &&\n \"notificationType\" in message &&\n !!message.notificationType\n );\n}\n\n","export type LogLevel = \"info\" | \"warning\" | \"error\" | \"trace\";\n\nexport type Logger = (type: string, message: string, level?: LogLevel) => void;\n\nexport const startPerformanceLogger = (logger: Logger) => {\n let startTime = performance.now();\n\n return {\n restart: () => {\n startTime = performance.now();\n },\n logEnd: (type: string, message: string, level: LogLevel = \"info\") => {\n const elapsed = performance.now() - startTime;\n\n logger(type, `${elapsed.toFixed(2)}ms - ${message}`, level);\n },\n };\n};\n","import type { Kysely } from \"kysely\";\nimport type { QueryCreator } from \"kysely\";\nimport { sql } from \"kysely\";\nimport type { SQLiteDbWrapper } from \"./sqlite-db-wrapper\";\n\ninterface SqliteSystemDatabase {\n // https://www.sqlite.org/schematab.html#alternative_names\n sqlite_master: SQliteMasterTable;\n}\n\n// https://www.sqlite.org/schematab.html#interpretation_of_the_schema_table\ninterface SQliteMasterTable {\n name: string;\n rootpage: number | null;\n sql: string;\n tbl_name: string;\n type: \"index\" | \"table\" | \"trigger\" | \"view\";\n}\n\n// https://www.sqlite.org/pragma.html#pragma_table_info\ninterface PragmaTableInfo {\n cid: number;\n dflt_value: unknown;\n name: string;\n notnull: 0 | 1;\n pk: number;\n type: string;\n}\n\nfunction tablesQuery(\n qb: QueryCreator<SqliteSystemDatabase> | Kysely<SqliteSystemDatabase>\n) {\n return qb\n .selectFrom(\"sqlite_master\")\n .where(\"type\", \"in\", [\"table\", \"view\"])\n .where(\"name\", \"not like\", \"sqlite_%\")\n .select([\"name\", \"sql\", \"type\"])\n .orderBy(\"name\");\n}\n\nexport type TableMetadata = {\n name: string;\n isView: boolean;\n columns: ColumnMetadata[];\n};\n\nexport type DatabaseIntrospection = Record<string, TableMetadata>;\n\ntype ColumnMetadata = {\n name: string;\n dataType: string;\n isNullable: boolean;\n isAutoIncrementing: boolean;\n hasDefaultValue: boolean;\n comment: undefined;\n};\n\nexport function introspectDb<BaseDatabase>(\n _db: SQLiteDbWrapper<BaseDatabase>\n): DatabaseIntrospection {\n const db = _db as unknown as SQLiteDbWrapper<SqliteSystemDatabase>;\n const tables = db.executeKysely((db) =>\n tablesQuery(db as unknown as Kysely<SqliteSystemDatabase>)\n ).rows;\n\n const tablesMetadata = db.executeKysely((db) =>\n db\n .with(\"table_list\", (qb) =>\n tablesQuery(qb as unknown as Kysely<SqliteSystemDatabase>)\n )\n .selectFrom([\n \"table_list as tl\",\n sql<PragmaTableInfo>`pragma_table_info(tl.name)`.as(\"p\"),\n ])\n .select([\n \"tl.name as table\",\n \"p.cid\",\n \"p.name\",\n \"p.type\",\n \"p.notnull\",\n \"p.dflt_value\",\n \"p.pk\",\n ])\n .orderBy(\"tl.name\")\n .orderBy(\"p.cid\")\n ).rows;\n\n const columnsByTable: Record<string, typeof tablesMetadata> = {};\n for (const row of tablesMetadata) {\n columnsByTable[row.table] ??= [];\n columnsByTable[row.table].push(row);\n }\n\n return Object.fromEntries(\n tables.map(({ name, sql, type }) => {\n // // Try to find the name of the column that has `autoincrement` 🤦\n let autoIncrementCol = sql\n ?.split(/[(),]/)\n ?.find((it) => it.toLowerCase().includes(\"autoincrement\"))\n ?.trimStart()\n ?.split(/\\s+/)?.[0]\n ?.replace(/[\"`]/g, \"\");\n\n const columns = columnsByTable[name] ?? [];\n\n // Otherwise, check for an INTEGER PRIMARY KEY\n // https://www.sqlite.org/autoinc.html\n if (!autoIncrementCol) {\n const pkCols = columns.filter((r) => r.pk > 0);\n if (pkCols.length === 1 && pkCols[0].type.toLowerCase() === \"integer\") {\n autoIncrementCol = pkCols[0].name;\n }\n }\n\n return [\n name,\n {\n name: name,\n isView: type === \"view\",\n columns: columns.map((col) => ({\n name: col.name,\n dataType: col.type,\n isNullable: !col.notnull,\n isAutoIncrementing: col.name === autoIncrementCol,\n hasDefaultValue: col.dflt_value != null,\n comment: undefined,\n })),\n },\n ];\n })\n );\n}\n\n","import type {\n BindableValue,\n FunctionOptions,\n Sqlite3Static,\n Database as SQLiteDatabase,\n SqlValue,\n} from \"@sqlite.org/sqlite-wasm\";\nimport { startPerformanceLogger, type Logger } from \"./logger\";\nimport { Kysely, type Compilable, type CompiledQuery } from \"kysely\";\nimport { dummyKysely } from \"./dummy-kysely\";\nimport { introspectDb, type DatabaseIntrospection } from \"./introspection\";\n\nexport type ExecuteParams = {\n sql: string;\n parameters: readonly unknown[];\n};\n\nexport type ExecuteResult<T> = {\n rows: T[];\n};\n\nexport type PreparedStatement<TParams extends SqlValue[], TResult> = {\n execute: (parameters: TParams) => TResult[];\n finalize: () => void;\n isFinalized: boolean;\n};\n\ntype ScalarFunctionOptions<\n TArgs extends readonly SqlValue[],\n TResult extends SqlValue | void\n> = {\n name: string;\n callback: (...args: TArgs) => TResult;\n} & Pick<FunctionOptions, \"deterministic\" | \"directOnly\" | \"innocuous\">;\n\ntype SqliteWrapperOptions = {\n logger?: Logger;\n loggerPrefix?: string;\n sqlite3: Sqlite3Static;\n db: SQLiteDatabase;\n};\n\nexport type SQLiteTransactionWrapper<TDatabase = unknown> = Pick<\n SQLiteDbWrapper<TDatabase>,\n | \"execute\"\n | \"sql\"\n | \"executeKysely\"\n | \"prepare\"\n | \"executePrepared\"\n | \"prepareKysely\"\n>;\n\nexport class SQLiteDbWrapper<TDatabase = unknown> {\n private db: SQLiteDatabase | null = null;\n private sqlite3: Sqlite3Static;\n private logger?: Logger;\n private loggerPrefix?: string;\n\n private loadedDbSchema: DatabaseIntrospection | null = null;\n\n private readonly dataPointers = [] as number[];\n\n private preparedStatements: PreparedStatement<SqlValue[], unknown>[] = [];\n private preparedStatementsMap = new Map<\n string,\n TypedStatement<Record<string, unknown>, unknown>\n >();\n\n constructor(opts: SqliteWrapperOptions) {\n this.db = opts.db;\n this.sqlite3 = opts.sqlite3;\n this.logger = opts.logger;\n this.loggerPrefix = opts.loggerPrefix;\n }\n\n get ensureDb() {\n if (!this.db) {\n throw new Error(\"Database is already closed\");\n }\n return this.db;\n }\n\n get dbSchema() {\n if (!this.loadedDbSchema) {\n this.loadedDbSchema = introspectDb(this);\n }\n return this.loadedDbSchema;\n }\n\n execute<T = unknown>(\n opts: ExecuteParams | string | CompiledQuery<T>\n ): ExecuteResult<T> {\n const sql = typeof opts === \"string\" ? opts : opts.sql;\n const bind = typeof opts === \"string\" ? undefined : opts.parameters;\n\n const perf = this.logger ? startPerformanceLogger(this.logger) : undefined;\n const rows = this.ensureDb.exec({\n sql,\n bind: bind as BindableValue[],\n returnValue: \"resultRows\",\n rowMode: \"object\",\n });\n perf?.logEnd(`${this.loggerPrefix ?? \"\"}:query`, sql, \"info\");\n\n return { rows: rows as T[] };\n }\n\n executeTransaction<T>(\n callback: (db: SQLiteTransactionWrapper<TDatabase>) => T\n ): T {\n return this.ensureDb.transaction(() => callback(this));\n }\n\n prepare<TParams extends SqlValue[], TResult>(sql: string) {\n const perf = this.logger ? startPerformanceLogger(this.logger) : undefined;\n const stmt = this.ensureDb.prepare(sql);\n perf?.logEnd(`${this.loggerPrefix ?? \"\"}:prepare`, sql, \"info\");\n\n let isFinalized = false;\n\n const execute = (params: TParams) => {\n if (isFinalized) {\n throw new Error(\"Statement is finalized\");\n }\n\n const perf = this.logger\n ? startPerformanceLogger(this.logger)\n : undefined;\n if (params.length > 0) {\n stmt.bind(params);\n }\n const results = [] as TResult[];\n while (stmt.step()) {\n results.push(stmt.get({}) as TResult);\n }\n stmt.reset(true);\n perf?.logEnd(`${this.loggerPrefix ?? \"\"}:prepare-execute`, sql, \"info\");\n return results;\n };\n\n const finalize = () => {\n isFinalized = true;\n stmt.finalize();\n };\n\n const preparedStatement: PreparedStatement<TParams, TResult> = {\n execute,\n finalize,\n get isFinalized() {\n return isFinalized;\n },\n };\n\n this.preparedStatements.push(\n preparedStatement as PreparedStatement<SqlValue[], unknown>\n );\n\n return preparedStatement;\n }\n\n prepareKysely<TParams extends Record<string, unknown>>() {\n return <\n TQuery extends Compilable<TResult>,\n TResult = QueryBuilderOutput<TQuery>\n >(\n factory: KyselyStatementFactory<TParams, TDatabase, TQuery, TResult>\n ): TypedStatement<TParams, TResult> => {\n const query = factory(dummyKysely, (key) => key as any).compile();\n const statement = this.prepare<SqlValue[], TResult>(query.sql);\n\n return {\n execute: (parameters) => {\n const params = query.parameters.map(\n (param) => parameters[param as keyof TParams]\n );\n const result = statement.execute(params as SqlValue[]);\n return result;\n },\n };\n };\n }\n\n executeKysely<\n TQuery extends Compilable<TResult>,\n TResult = QueryBuilderOutput<TQuery>\n >(factory: KyselyQueryFactory<TDatabase, TQuery, TResult>) {\n const query = factory(dummyKysely).compile();\n return this.execute(query);\n }\n\n executePrepared<\n TParams extends Record<string, unknown>,\n TQuery extends Compilable<TResult>,\n TResult = QueryBuilderOutput<TQuery>\n >(\n key: string,\n params: TParams,\n factory: KyselyStatementFactory<TParams, TDatabase, TQuery, TResult>\n ) {\n let statement = this.preparedStatementsMap.get(key) as\n | TypedStatement<TParams, TResult>\n | undefined;\n if (!statement) {\n statement = this.prepareKysely<TParams>()(factory);\n this.preparedStatementsMap.set(\n key,\n statement as TypedStatement<Record<string, unknown>, unknown>\n );\n }\n\n return statement.execute(params);\n }\n\n sql<T = unknown>(\n templateOrString: TemplateStringsArray | string,\n ...parameters: unknown[]\n ) {\n if (typeof templateOrString === \"string\") {\n return this.execute<T>({\n sql: templateOrString,\n parameters,\n });\n }\n return this.execute<T>({\n sql: templateOrString.join(\"?\"),\n parameters,\n });\n }\n\n createScalarFunction<\n TArgs extends SqlValue[],\n TResult extends SqlValue | void\n >({\n name,\n callback,\n deterministic,\n directOnly,\n innocuous,\n }: ScalarFunctionOptions<TArgs, TResult>) {\n return this.ensureDb.createFunction({\n name,\n xFunc: (_, ...args) => {\n const result = callback(...(args as TArgs)) as SqlValue;\n return result;\n },\n arity: callback.length,\n deterministic,\n directOnly,\n innocuous,\n });\n }\n\n useSnapshot(snapshot: Uint8Array<ArrayBufferLike>) {\n const perf = this.logger ? startPerformanceLogger(this.logger) : undefined;\n const dataPointer = this.sqlite3.wasm.allocFromTypedArray(snapshot);\n this.dataPointers.push(dataPointer);\n\n const resultCode = this.sqlite3.capi.sqlite3_deserialize(\n this.ensureDb,\n \"main\",\n dataPointer,\n snapshot.byteLength,\n snapshot.byteLength,\n this.sqlite3.capi.SQLITE_DESERIALIZE_FREEONCLOSE |\n this.sqlite3.capi.SQLITE_DESERIALIZE_RESIZEABLE\n );\n\n this.ensureDb.checkRc(resultCode);\n\n this.invalidateDbSchema();\n\n perf?.logEnd(\"useSnapshot\", \"success\", \"info\");\n }\n\n createSnapshot() {\n return this.sqlite3.capi.sqlite3_js_db_export(this.ensureDb);\n }\n\n invalidateDbSchema() {\n this.loadedDbSchema = null;\n }\n\n cleanup() {\n this.preparedStatements.forEach((stmt) => stmt.finalize());\n this.preparedStatements.splice(0);\n this.preparedStatementsMap.clear();\n }\n\n close() {\n this.cleanup();\n\n this.db?.close();\n this.db = null;\n }\n}\n\nexport type QueryBuilderOutput<QB> = QB extends Compilable<infer O> ? O : never;\ntype ParamsGetter<TParams> = <TKey extends keyof TParams>(\n key: TKey\n) => TParams[TKey];\n\ntype TypedStatement<TParams extends Record<string, unknown>, TResult> = {\n execute: (parameters: TParams) => TResult[];\n};\ntype KyselyStatementFactory<\n TParams extends Record<string, unknown>,\n TDatabase,\n TQuery extends Compilable<TResult>,\n TResult = QueryBuilderOutput<TQuery>\n> = (kysely: Kysely<TDatabase>, params: ParamsGetter<TParams>) => TQuery;\nexport type KyselyQueryFactory<\n TDatabase,\n TQuery extends Compilable<TResult>,\n TResult = QueryBuilderOutput<TQuery>\n> = (kysely: Kysely<TDatabase>) => TQuery;\n\n","import {\n crdtSchema,\n type PersistedCrdtEvent,\n type CrdtUpdateLogItem,\n type MetaItem,\n} from \"../sqlite-crdt/crdt-table-schema\";\nimport type { SQLiteDbWrapper } from \"../sqlite-db-wrapper\";\n\nexport type WorkerDbSchema = {\n crdt_update_log: CrdtUpdateLogItem;\n [\"worker.meta\"]: MetaItem;\n [\"worker.crdt_events\"]: PersistedCrdtEvent;\n};\n\nexport function applyWorkerDbSchema(db: SQLiteDbWrapper<any>) {\n db.executeTransaction((db) => {\n db.executeKysely((kysely) =>\n crdtSchema.metaTable(kysely.schema, \"worker.meta\")\n );\n db.executeKysely((kysely) =>\n crdtSchema.crdtUpdateLogTable(kysely.schema, \"crdt_update_log\")\n );\n db.executeKysely((kysely) =>\n crdtSchema.persistedEventsTable(kysely.schema, \"worker.crdt_events\")\n );\n });\n}\n\nexport type MemoryDbSchema = {\n crdt_update_log: CrdtUpdateLogItem;\n persisted_crdt_events: PersistedCrdtEvent;\n};\n\nexport function applyMemoryDbSchema(db: SQLiteDbWrapper<any>) {\n db.executeKysely((kysely) =>\n crdtSchema.crdtUpdateLogTable(kysely.schema, \"crdt_update_log\")\n );\n db.executeKysely((kysely) =>\n crdtSchema.persistedEventsTable(kysely.schema, \"persisted_crdt_events\")\n );\n}\n\n","import { createAsyncAutoFlushBuffer } from \"../utils\";\nimport type { PendingCrdtEvent } from \"./apply-crdt-event\";\nimport type { CrdtStorage } from \"./crdt-storage\";\nimport type { PersistedCrdtEvent } from \"./crdt-table-schema\";\nimport type { SyncIdCounter } from \"./sync-id-counter\";\n\ntype CrdtSyncRemoteSourceConfig = {\n bufferSize: number;\n storage: CrdtStorage;\n syncId: SyncIdCounter;\n nodeId: string;\n pullEvents: (\n request: EventsPullRequest\n ) => EventsPullResponse | Promise<EventsPullResponse>;\n pushEvents: (\n request: EventsPushRequest\n ) => EventsPushResponse | Promise<EventsPushResponse>;\n};\n\nexport type EventsPullRequest = {\n afterSyncId: number;\n excludeNodeId?: string;\n};\nexport type EventsPullResponse = {\n events: PersistedCrdtEvent[];\n newSyncId: number;\n hasMore: boolean;\n};\n\nexport type EventsPushRequest = {\n nodeId: string;\n events: PendingCrdtEvent[];\n};\nexport type EventsPushResponse = {\n ok: boolean;\n};\n\nexport type CrdtSyncRemoteSource = ReturnType<\n typeof createCrdtSyncRemoteSource\n>;\n\nexport const createCrdtSyncRemoteSource = ({\n bufferSize,\n storage,\n syncId,\n nodeId,\n pullEvents: pullEventsChunk,\n pushEvents,\n}: CrdtSyncRemoteSourceConfig) => {\n let pullPromise: Promise<void> | null = null;\n let requestedPullSyncId: number | null = null;\n\n const pullEvents = (request?: {\n afterSyncId?: number;\n includeSelf?: boolean;\n }) => {\n const afterSyncId = request?.afterSyncId ?? syncId.current;\n\n if (pullPromise) {\n if (!requestedPullSyncId || requestedPullSyncId < afterSyncId) {\n requestedPullSyncId = afterSyncId;\n }\n return pullPromise;\n }\n\n pullPromise = pullAllEvents({\n afterSyncId,\n excludeNodeId: request?.includeSelf ? undefined : nodeId,\n }).finally(() => {\n pullPromise = null;\n\n if (requestedPullSyncId && requestedPullSyncId > syncId.current) {\n pullEvents({ afterSyncId: requestedPullSyncId });\n requestedPullSyncId = null;\n }\n });\n return pullPromise;\n };\n\n const pullAllEvents = async (opts: EventsPullRequest) => {\n let hasMore = true;\n let afterSyncId = opts.afterSyncId;\n while (hasMore) {\n const response = await pullEventsChunk({\n ...opts,\n afterSyncId,\n });\n hasMore = response.hasMore;\n afterSyncId = response.newSyncId;\n\n if (response.events) {\n storage.enqueueEvents(\n response.events.map((x) => ({\n ...x,\n origin: \"remote\",\n }))\n );\n }\n if (response.newSyncId <= syncId.current) {\n break;\n }\n if (response.newSyncId > syncId.current) {\n syncId.current = response.newSyncId;\n }\n }\n };\n\n const pushEventsBuffer = createAsyncAutoFlushBuffer<PendingCrdtEvent>({\n size: bufferSize,\n flush: async (events) => {\n await pushEvents({ nodeId, events });\n },\n });\n\n storage.addEventListener(\"event-applied\", (event) => {\n if (event.payload.origin === \"remote\") {\n return;\n }\n pushEventsBuffer.add(event.payload);\n });\n\n storage.addEventListener(\"event-processing-done\", () => {\n pushEventsBuffer.flush();\n });\n\n return {\n pullEvents,\n };\n};\n\n","import {\n CompiledQuery,\n Kysely,\n SqliteAdapter,\n SqliteIntrospector,\n SqliteQueryCompiler,\n type DatabaseConnection,\n type Driver,\n type QueryResult,\n} from \"kysely\";\nimport type {} from \"@sqlite.org/sqlite-wasm\";\n\ntype SqliteDatabase = {\n execute: (opts: { sql: string; parameters: readonly unknown[] }) => {\n rows: unknown[];\n };\n close: () => void;\n};\n\nexport class SqliteDriver implements Driver {\n readonly #connectionMutex = new ConnectionMutex();\n\n #db: SqliteDatabase;\n #connection: DatabaseConnection;\n\n constructor(db: SqliteDatabase) {\n this.#db = db;\n this.#connection = new SqliteConnection(this.#db);\n }\n\n async init(): Promise<void> {\n return Promise.resolve();\n }\n\n async acquireConnection(): Promise<DatabaseConnection> {\n await this.#connectionMutex.lock();\n return this.#connection;\n }\n\n async beginTransaction(connection: DatabaseConnection): Promise<void> {\n await connection.executeQuery(CompiledQuery.raw(\"begin\"));\n }\n\n async commitTransaction(connection: DatabaseConnection): Promise<void> {\n await connection.executeQuery(CompiledQuery.raw(\"commit\"));\n }\n\n async rollbackTransaction(connection: DatabaseConnection): Promise<void> {\n await connection.executeQuery(CompiledQuery.raw(\"rollback\"));\n }\n\n async releaseConnection(): Promise<void> {\n this.#connectionMutex.unlock();\n }\n\n async destroy(): Promise<void> {\n this.#db?.close();\n }\n}\n\nclass SqliteConnection implements DatabaseConnection {\n readonly #db: SqliteDatabase;\n\n constructor(db: SqliteDatabase) {\n this.#db = db;\n }\n\n executeQuery<O>(compiledQuery: CompiledQuery): Promise<QueryResult<O>> {\n const stmt = this.#db.execute(compiledQuery);\n\n return Promise.resolve({\n rows: stmt.rows as O[],\n });\n }\n\n // eslint-disable-next-line require-yield\n async *streamQuery(): AsyncGenerator<never, void, unknown> {\n throw new Error(\"SQLite3 does not support streaming.\");\n }\n}\n\nclass ConnectionMutex {\n #promise?: Promise<void>;\n #resolve?: () => void;\n\n async lock(): Promise<void> {\n while (this.#promise) {\n await this.#promise;\n }\n\n this.#promise = new Promise((resolve) => {\n this.#resolve = resolve;\n });\n }\n\n unlock(): void {\n const resolve = this.#resolve;\n\n this.#promise = undefined;\n this.#resolve = undefined;\n\n resolve?.();\n }\n}\n\nexport function createSQLiteKysely<Database>(sqliteDb: SqliteDatabase) {\n return new Kysely<Database>({\n dialect: {\n createAdapter: () => new SqliteAdapter(),\n createDriver: () => new SqliteDriver(sqliteDb),\n createIntrospector: (db) => new SqliteIntrospector(db),\n createQueryCompiler: () => new SqliteQueryCompiler(),\n },\n });\n}\n\n","import {\n Migrator,\n type MigrationProvider,\n type Migration,\n Kysely,\n} from \"kysely\";\n\nclass SyncMigrationsProvider implements MigrationProvider {\n private migrations: Record<string, Migration>;\n\n constructor(migrations: Record<string, Migration>) {\n this.migrations = migrations;\n }\n\n async getMigrations(): Promise<Record<string, Migration>> {\n return Promise.resolve(this.migrations);\n }\n}\n\ntype SyncDbMigratorOptions = {\n db: Kysely<unknown>;\n migrations: Record<string, Migration>;\n};\nexport function createSyncDbMigrator(options: SyncDbMigratorOptions) {\n return new Migrator({\n db: options.db,\n provider: new SyncMigrationsProvider(options.migrations),\n allowUnorderedMigrations: false,\n migrationLockTableName: \"worker.migration_lock\",\n migrationTableName: \"worker.migration\",\n });\n}\n\nexport function createSyncDbMigrations(\n migrations: Record<number, Migration>\n): Record<number, Migration> {\n return Object.fromEntries(\n Object.entries(migrations).map(([key, value]) => [\n key.toString().padStart(6, \"0\"),\n value,\n ])\n );\n}\n\n"],"mappings":"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","names":["db","sql","sql","perf","db"]}
|