@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-YLXMST5Z.js
DELETED
|
@@ -1,490 +0,0 @@
|
|
|
1
|
-
// src/utils.ts
|
|
2
|
-
function createDeferredPromise() {
|
|
3
|
-
let resolve;
|
|
4
|
-
let reject;
|
|
5
|
-
const promise = new Promise((_resolve, _reject) => {
|
|
6
|
-
resolve = _resolve;
|
|
7
|
-
reject = _reject;
|
|
8
|
-
});
|
|
9
|
-
return { promise, resolve, reject };
|
|
10
|
-
}
|
|
11
|
-
var generateId = () => {
|
|
12
|
-
return crypto.randomUUID();
|
|
13
|
-
};
|
|
14
|
-
function ensureSingletonExecution(fn) {
|
|
15
|
-
let isExecuting = false;
|
|
16
|
-
let shouldReExecute = false;
|
|
17
|
-
const wrappedFn = () => {
|
|
18
|
-
if (isExecuting) {
|
|
19
|
-
shouldReExecute = true;
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
isExecuting = true;
|
|
23
|
-
fn().finally(() => {
|
|
24
|
-
isExecuting = false;
|
|
25
|
-
if (shouldReExecute) {
|
|
26
|
-
shouldReExecute = false;
|
|
27
|
-
wrappedFn();
|
|
28
|
-
}
|
|
29
|
-
});
|
|
30
|
-
};
|
|
31
|
-
wrappedFn.isExecuting = () => isExecuting;
|
|
32
|
-
return wrappedFn;
|
|
33
|
-
}
|
|
34
|
-
function orderBy(inputArray, picker, opts) {
|
|
35
|
-
const array = opts?.inPlace ? inputArray : [...inputArray];
|
|
36
|
-
const direction = opts?.direction ?? "asc";
|
|
37
|
-
return array.sort((a, b) => {
|
|
38
|
-
const aVal = picker(a);
|
|
39
|
-
const bVal = picker(b);
|
|
40
|
-
if (aVal < bVal) return direction === "asc" ? -1 : 1;
|
|
41
|
-
if (aVal > bVal) return direction === "asc" ? 1 : -1;
|
|
42
|
-
return 0;
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
function createAutoFlushBuffer({
|
|
46
|
-
size,
|
|
47
|
-
flush
|
|
48
|
-
}) {
|
|
49
|
-
const buffer = [];
|
|
50
|
-
return {
|
|
51
|
-
add(item) {
|
|
52
|
-
buffer.push(item);
|
|
53
|
-
if (buffer.length >= size) {
|
|
54
|
-
flush(buffer);
|
|
55
|
-
buffer.length = 0;
|
|
56
|
-
}
|
|
57
|
-
},
|
|
58
|
-
flush() {
|
|
59
|
-
flush(buffer);
|
|
60
|
-
buffer.length = 0;
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
function createAsyncAutoFlushBuffer({
|
|
65
|
-
size,
|
|
66
|
-
flush
|
|
67
|
-
}) {
|
|
68
|
-
const buffer = [];
|
|
69
|
-
return {
|
|
70
|
-
async add(item) {
|
|
71
|
-
buffer.push(item);
|
|
72
|
-
if (buffer.length >= size) {
|
|
73
|
-
await this.flush();
|
|
74
|
-
}
|
|
75
|
-
},
|
|
76
|
-
async flush() {
|
|
77
|
-
const itemsToFlush = buffer.splice(0);
|
|
78
|
-
if (itemsToFlush.length === 0) {
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
await flush(itemsToFlush);
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
var TypedBroadcastChannel = class {
|
|
86
|
-
channel;
|
|
87
|
-
constructor(name) {
|
|
88
|
-
this.channel = new BroadcastChannel(name);
|
|
89
|
-
}
|
|
90
|
-
postMessage(message) {
|
|
91
|
-
this.channel.postMessage(message);
|
|
92
|
-
}
|
|
93
|
-
set onmessage(callback) {
|
|
94
|
-
this.channel.onmessage = callback;
|
|
95
|
-
}
|
|
96
|
-
};
|
|
97
|
-
var TypedEvent = class extends Event {
|
|
98
|
-
payload;
|
|
99
|
-
constructor(type, payload) {
|
|
100
|
-
super(type);
|
|
101
|
-
this.payload = payload;
|
|
102
|
-
}
|
|
103
|
-
};
|
|
104
|
-
var createTypedEventTarget = () => {
|
|
105
|
-
const eventTarget = new EventTarget();
|
|
106
|
-
const addEventListener = (type, listener) => {
|
|
107
|
-
eventTarget.addEventListener(type, listener);
|
|
108
|
-
};
|
|
109
|
-
const removeEventListener = (type, listener) => {
|
|
110
|
-
eventTarget.removeEventListener(type, listener);
|
|
111
|
-
};
|
|
112
|
-
const dispatchEvent = (type, payload) => {
|
|
113
|
-
eventTarget.dispatchEvent(new TypedEvent(type, payload));
|
|
114
|
-
};
|
|
115
|
-
return {
|
|
116
|
-
addEventListener,
|
|
117
|
-
removeEventListener,
|
|
118
|
-
dispatchEvent
|
|
119
|
-
};
|
|
120
|
-
};
|
|
121
|
-
function jsonSafeParse(json) {
|
|
122
|
-
try {
|
|
123
|
-
return {
|
|
124
|
-
status: "ok",
|
|
125
|
-
data: JSON.parse(json)
|
|
126
|
-
};
|
|
127
|
-
} catch (error) {
|
|
128
|
-
return {
|
|
129
|
-
status: "error",
|
|
130
|
-
error
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// src/dummy-kysely.ts
|
|
136
|
-
import {
|
|
137
|
-
DummyDriver,
|
|
138
|
-
Kysely,
|
|
139
|
-
SqliteAdapter,
|
|
140
|
-
SqliteIntrospector,
|
|
141
|
-
SqliteQueryCompiler
|
|
142
|
-
} from "kysely";
|
|
143
|
-
var dummyKysely = new Kysely({
|
|
144
|
-
dialect: {
|
|
145
|
-
createAdapter: () => new SqliteAdapter(),
|
|
146
|
-
createDriver: () => new DummyDriver(),
|
|
147
|
-
createQueryCompiler: () => new SqliteQueryCompiler(),
|
|
148
|
-
createIntrospector: (db) => new SqliteIntrospector(db)
|
|
149
|
-
}
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
// src/sqlite-crdt/apply-crdt-event.ts
|
|
153
|
-
function applyCrdtEventMutations({
|
|
154
|
-
db,
|
|
155
|
-
event,
|
|
156
|
-
updateLogTableName
|
|
157
|
-
}) {
|
|
158
|
-
const eventPayload = JSON.parse(event.payload);
|
|
159
|
-
const [metaRow] = db.executePrepared(
|
|
160
|
-
"get-item-crdt-meta",
|
|
161
|
-
{
|
|
162
|
-
item_id: event.item_id,
|
|
163
|
-
dataset: event.dataset
|
|
164
|
-
},
|
|
165
|
-
(db2, params) => {
|
|
166
|
-
return db2.selectFrom(updateLogTableName).select("payload").where("item_id", "=", params("item_id")).where("dataset", "=", params("dataset"));
|
|
167
|
-
}
|
|
168
|
-
);
|
|
169
|
-
const meta = metaRow ? JSON.parse(metaRow.payload) : null;
|
|
170
|
-
const context = {
|
|
171
|
-
db,
|
|
172
|
-
updateLogTableName,
|
|
173
|
-
event,
|
|
174
|
-
meta,
|
|
175
|
-
eventPayload
|
|
176
|
-
};
|
|
177
|
-
switch (event.type) {
|
|
178
|
-
case "item-created": {
|
|
179
|
-
applyItemCreated(context);
|
|
180
|
-
break;
|
|
181
|
-
}
|
|
182
|
-
case "item-updated": {
|
|
183
|
-
applyItemUpdated(context);
|
|
184
|
-
break;
|
|
185
|
-
}
|
|
186
|
-
default:
|
|
187
|
-
event.type;
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
function applyItemCreated(context) {
|
|
191
|
-
if (context.meta) {
|
|
192
|
-
applyItemUpdated(context);
|
|
193
|
-
return;
|
|
194
|
-
}
|
|
195
|
-
const keys = Array.from(Object.keys(context.eventPayload));
|
|
196
|
-
context.db.execute({
|
|
197
|
-
sql: `insert into ${context.event.dataset} (${keys.join(
|
|
198
|
-
","
|
|
199
|
-
)}) values (${keys.map(() => "?").join(",")})`,
|
|
200
|
-
parameters: keys.map((key) => context.eventPayload[key])
|
|
201
|
-
});
|
|
202
|
-
const newUpdateLog = Object.fromEntries(
|
|
203
|
-
keys.map((key) => [key, context.event.timestamp])
|
|
204
|
-
);
|
|
205
|
-
insertCrdtUpdateLog(context, newUpdateLog);
|
|
206
|
-
}
|
|
207
|
-
function insertCrdtUpdateLog(context, log) {
|
|
208
|
-
context.db.executePrepared(
|
|
209
|
-
"insert-crdt-update-log",
|
|
210
|
-
{
|
|
211
|
-
item_id: context.event.item_id,
|
|
212
|
-
dataset: context.event.dataset,
|
|
213
|
-
payload: JSON.stringify(log)
|
|
214
|
-
},
|
|
215
|
-
(db, params) => db.insertInto(context.updateLogTableName).values({
|
|
216
|
-
item_id: params("item_id"),
|
|
217
|
-
dataset: params("dataset"),
|
|
218
|
-
payload: params("payload")
|
|
219
|
-
})
|
|
220
|
-
);
|
|
221
|
-
}
|
|
222
|
-
function applyItemUpdated(context) {
|
|
223
|
-
const meta = context.meta;
|
|
224
|
-
if (!meta) {
|
|
225
|
-
throw new Error(
|
|
226
|
-
`Item ${context.event.item_id} in dataset ${context.event.dataset} not found`
|
|
227
|
-
);
|
|
228
|
-
}
|
|
229
|
-
const keys = Array.from(Object.keys(context.eventPayload)).filter((key) => {
|
|
230
|
-
const lastUpdateTimestamp = meta[key];
|
|
231
|
-
if (!lastUpdateTimestamp) {
|
|
232
|
-
return true;
|
|
233
|
-
}
|
|
234
|
-
const currentUpdateTimestamp = context.event.timestamp;
|
|
235
|
-
return currentUpdateTimestamp > lastUpdateTimestamp;
|
|
236
|
-
});
|
|
237
|
-
if (keys.length > 0) {
|
|
238
|
-
context.db.execute({
|
|
239
|
-
sql: `update ${context.event.dataset} set ${keys.map((key) => `${key} = ?`).join(",")} where id = ?`,
|
|
240
|
-
parameters: [
|
|
241
|
-
...keys.map((key) => context.eventPayload[key]),
|
|
242
|
-
context.event.item_id
|
|
243
|
-
]
|
|
244
|
-
});
|
|
245
|
-
keys.forEach((key) => {
|
|
246
|
-
meta[key] = context.event.timestamp;
|
|
247
|
-
});
|
|
248
|
-
updateCrdtUpdateLog(context, meta);
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
function updateCrdtUpdateLog(context, log) {
|
|
252
|
-
context.db.executePrepared(
|
|
253
|
-
"update-crdt-update-log",
|
|
254
|
-
{
|
|
255
|
-
item_id: context.event.item_id,
|
|
256
|
-
dataset: context.event.dataset,
|
|
257
|
-
payload: JSON.stringify(log)
|
|
258
|
-
},
|
|
259
|
-
(db, params) => db.updateTable(context.updateLogTableName).set({
|
|
260
|
-
payload: params("payload")
|
|
261
|
-
}).where("item_id", "=", params("item_id")).where("dataset", "=", params("dataset"))
|
|
262
|
-
);
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
// src/sqlite-crdt/crdt-table-schema.ts
|
|
266
|
-
var crdtSchema = {
|
|
267
|
-
metaTable: createMetaTableQuery,
|
|
268
|
-
persistedEventsTable: createPersistedEventsTable,
|
|
269
|
-
crdtUpdateLogTable: createCrdtUpdateLogTableQuery
|
|
270
|
-
};
|
|
271
|
-
function createMetaTableQuery(schema, tableName) {
|
|
272
|
-
return schema.createTable(tableName).ifNotExists().addColumn("key", "text", (col) => col.notNull().primaryKey()).addColumn("value", "text", (col) => col.notNull());
|
|
273
|
-
}
|
|
274
|
-
function createPersistedEventsTable(schema, tableName) {
|
|
275
|
-
return schema.createTable(tableName).ifNotExists().addColumn("sync_id", "integer", (col) => col.notNull().primaryKey()).addColumn("status", "text", (col) => col.notNull()).addColumn("type", "text", (col) => col.notNull()).addColumn("timestamp", "text", (col) => col.notNull()).addColumn("origin", "text", (col) => col.notNull()).addColumn("dataset", "text", (col) => col.notNull()).addColumn("item_id", "text", (col) => col.notNull()).addColumn("payload", "text", (col) => col.notNull());
|
|
276
|
-
}
|
|
277
|
-
function createCrdtUpdateLogTableQuery(schema, tableName) {
|
|
278
|
-
return schema.createTable(tableName).ifNotExists().addColumn("dataset", "text", (col) => col.notNull()).addColumn("item_id", "text", (col) => col.notNull()).addColumn("payload", "text", (col) => col.notNull()).addPrimaryKeyConstraint(`pk_${tableName}`, ["item_id", "dataset"]);
|
|
279
|
-
}
|
|
280
|
-
function registerCrdtFunctions({
|
|
281
|
-
db,
|
|
282
|
-
onEventApplied,
|
|
283
|
-
getNextTimestamp,
|
|
284
|
-
getTableSchema,
|
|
285
|
-
updateLogTableName
|
|
286
|
-
}) {
|
|
287
|
-
db.createScalarFunction({
|
|
288
|
-
name: "handle_item_created",
|
|
289
|
-
deterministic: false,
|
|
290
|
-
directOnly: false,
|
|
291
|
-
innocuous: false,
|
|
292
|
-
callback: (dataset, payloadRaw) => {
|
|
293
|
-
const payload = JSON.parse(payloadRaw);
|
|
294
|
-
const event = {
|
|
295
|
-
timestamp: getNextTimestamp(),
|
|
296
|
-
type: "item-created",
|
|
297
|
-
dataset,
|
|
298
|
-
item_id: payload.id,
|
|
299
|
-
payload: payloadRaw
|
|
300
|
-
};
|
|
301
|
-
applyCrdtEventMutations({
|
|
302
|
-
db,
|
|
303
|
-
event,
|
|
304
|
-
updateLogTableName
|
|
305
|
-
});
|
|
306
|
-
onEventApplied(event);
|
|
307
|
-
}
|
|
308
|
-
});
|
|
309
|
-
db.createScalarFunction({
|
|
310
|
-
name: "handle_item_updated",
|
|
311
|
-
deterministic: false,
|
|
312
|
-
directOnly: false,
|
|
313
|
-
innocuous: false,
|
|
314
|
-
callback: (dataset, oldPayloadRaw, newPayloadRaw) => {
|
|
315
|
-
const tableSchema = getTableSchema(dataset);
|
|
316
|
-
const oldPayload = JSON.parse(oldPayloadRaw);
|
|
317
|
-
const newPayload = JSON.parse(newPayloadRaw);
|
|
318
|
-
let hasDiff = false;
|
|
319
|
-
const payload = Object.fromEntries(
|
|
320
|
-
tableSchema.columns.map((column) => {
|
|
321
|
-
const oldValue = oldPayload[column.name];
|
|
322
|
-
const newValue = newPayload[column.name];
|
|
323
|
-
if (oldValue === newValue) {
|
|
324
|
-
return null;
|
|
325
|
-
}
|
|
326
|
-
hasDiff = true;
|
|
327
|
-
return [column.name, newValue];
|
|
328
|
-
}).filter(Boolean)
|
|
329
|
-
);
|
|
330
|
-
const event = {
|
|
331
|
-
timestamp: getNextTimestamp(),
|
|
332
|
-
type: "item-updated",
|
|
333
|
-
dataset,
|
|
334
|
-
item_id: oldPayload.id,
|
|
335
|
-
payload: JSON.stringify(payload)
|
|
336
|
-
};
|
|
337
|
-
if (!hasDiff) {
|
|
338
|
-
return;
|
|
339
|
-
}
|
|
340
|
-
applyCrdtEventMutations({
|
|
341
|
-
db,
|
|
342
|
-
event,
|
|
343
|
-
updateLogTableName
|
|
344
|
-
});
|
|
345
|
-
onEventApplied(event);
|
|
346
|
-
}
|
|
347
|
-
});
|
|
348
|
-
db.createScalarFunction({
|
|
349
|
-
name: "handle_item_deleted",
|
|
350
|
-
deterministic: false,
|
|
351
|
-
directOnly: false,
|
|
352
|
-
innocuous: false,
|
|
353
|
-
callback: (dataset, itemId) => {
|
|
354
|
-
const event = {
|
|
355
|
-
timestamp: getNextTimestamp(),
|
|
356
|
-
type: "item-updated",
|
|
357
|
-
dataset,
|
|
358
|
-
item_id: itemId,
|
|
359
|
-
payload: JSON.stringify({ tombstone: 1 })
|
|
360
|
-
};
|
|
361
|
-
applyCrdtEventMutations({
|
|
362
|
-
db,
|
|
363
|
-
event,
|
|
364
|
-
updateLogTableName
|
|
365
|
-
});
|
|
366
|
-
onEventApplied(event);
|
|
367
|
-
}
|
|
368
|
-
});
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
// src/sqlite-crdt/sync-id-counter.ts
|
|
372
|
-
function createSyncIdCounter({
|
|
373
|
-
initialSyncId,
|
|
374
|
-
saveToStorage
|
|
375
|
-
}) {
|
|
376
|
-
let currentSyncId = initialSyncId;
|
|
377
|
-
return {
|
|
378
|
-
get current() {
|
|
379
|
-
return currentSyncId;
|
|
380
|
-
},
|
|
381
|
-
set current(newSyncId) {
|
|
382
|
-
saveToStorage?.(newSyncId);
|
|
383
|
-
currentSyncId = newSyncId;
|
|
384
|
-
}
|
|
385
|
-
};
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
// src/sqlite-crdt/crdt-storage.ts
|
|
389
|
-
function createCrdtStorage(storage) {
|
|
390
|
-
const eventTarget = createTypedEventTarget();
|
|
391
|
-
const enqueueEvents = (events) => {
|
|
392
|
-
const firstEventSyncId = storage.syncId.current + 1;
|
|
393
|
-
storage.persistEvents(
|
|
394
|
-
events.map((x) => ({
|
|
395
|
-
timestamp: x.timestamp,
|
|
396
|
-
type: x.type,
|
|
397
|
-
dataset: x.dataset,
|
|
398
|
-
item_id: x.item_id,
|
|
399
|
-
origin: x.origin,
|
|
400
|
-
payload: x.payload,
|
|
401
|
-
sync_id: ++storage.syncId.current,
|
|
402
|
-
status: "pending"
|
|
403
|
-
}))
|
|
404
|
-
);
|
|
405
|
-
const lastEventSyncId = storage.syncId.current;
|
|
406
|
-
processEnqueuedEvents();
|
|
407
|
-
return {
|
|
408
|
-
firstEventSyncId,
|
|
409
|
-
lastEventSyncId
|
|
410
|
-
};
|
|
411
|
-
};
|
|
412
|
-
const processEnqueuedEvents = ensureSingletonExecution(async () => {
|
|
413
|
-
await Promise.resolve();
|
|
414
|
-
let hasMore = true;
|
|
415
|
-
while (hasMore) {
|
|
416
|
-
const batch = storage.popPendingEventsBatch();
|
|
417
|
-
const events = batch.events;
|
|
418
|
-
hasMore = batch.hasMore;
|
|
419
|
-
if (events.length === 0) {
|
|
420
|
-
break;
|
|
421
|
-
}
|
|
422
|
-
for (const event of events) {
|
|
423
|
-
try {
|
|
424
|
-
storage.applyCrdtEventMutations(event);
|
|
425
|
-
event.status = "applied";
|
|
426
|
-
} catch (error) {
|
|
427
|
-
console.error("Error applying enqueued CRDT event", error);
|
|
428
|
-
event.status = "failed";
|
|
429
|
-
} finally {
|
|
430
|
-
storage.updateEventStatus(event.sync_id, event.status);
|
|
431
|
-
eventTarget.dispatchEvent("event-applied", event);
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
eventTarget.dispatchEvent("event-processing-done", void 0);
|
|
436
|
-
});
|
|
437
|
-
return {
|
|
438
|
-
enqueueEvents,
|
|
439
|
-
addEventListener: eventTarget.addEventListener,
|
|
440
|
-
removeEventListener: eventTarget.removeEventListener,
|
|
441
|
-
dispatchEvent: eventTarget.dispatchEvent
|
|
442
|
-
};
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
// src/sqlite-crdt/crdt-sync-producer.ts
|
|
446
|
-
var createCrdtSyncProducer = ({
|
|
447
|
-
bufferSize,
|
|
448
|
-
storage,
|
|
449
|
-
broadcastEvents
|
|
450
|
-
}) => {
|
|
451
|
-
const eventsBuffer = createAutoFlushBuffer({
|
|
452
|
-
size: bufferSize,
|
|
453
|
-
flush: (events) => {
|
|
454
|
-
if (events.length === 0) {
|
|
455
|
-
return;
|
|
456
|
-
}
|
|
457
|
-
broadcastEvents({ newSyncId: events[events.length - 1].sync_id });
|
|
458
|
-
}
|
|
459
|
-
});
|
|
460
|
-
storage.addEventListener("event-applied", (event) => {
|
|
461
|
-
if (event.payload.status !== "applied") {
|
|
462
|
-
return;
|
|
463
|
-
}
|
|
464
|
-
eventsBuffer.add(event.payload);
|
|
465
|
-
});
|
|
466
|
-
storage.addEventListener("event-processing-done", () => {
|
|
467
|
-
eventsBuffer.flush();
|
|
468
|
-
});
|
|
469
|
-
};
|
|
470
|
-
|
|
471
|
-
export {
|
|
472
|
-
createDeferredPromise,
|
|
473
|
-
generateId,
|
|
474
|
-
ensureSingletonExecution,
|
|
475
|
-
orderBy,
|
|
476
|
-
createAutoFlushBuffer,
|
|
477
|
-
createAsyncAutoFlushBuffer,
|
|
478
|
-
TypedBroadcastChannel,
|
|
479
|
-
TypedEvent,
|
|
480
|
-
createTypedEventTarget,
|
|
481
|
-
jsonSafeParse,
|
|
482
|
-
dummyKysely,
|
|
483
|
-
applyCrdtEventMutations,
|
|
484
|
-
crdtSchema,
|
|
485
|
-
registerCrdtFunctions,
|
|
486
|
-
createSyncIdCounter,
|
|
487
|
-
createCrdtStorage,
|
|
488
|
-
createCrdtSyncProducer
|
|
489
|
-
};
|
|
490
|
-
//# sourceMappingURL=chunk-YLXMST5Z.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils.ts","../src/dummy-kysely.ts","../src/sqlite-crdt/apply-crdt-event.ts","../src/sqlite-crdt/crdt-table-schema.ts","../src/sqlite-crdt/sync-id-counter.ts","../src/sqlite-crdt/crdt-storage.ts","../src/sqlite-crdt/crdt-sync-producer.ts"],"sourcesContent":["export type DeferredPromise<T> = {\n promise: Promise<T>;\n resolve: (value: T) => void;\n reject: (error: Error) => void;\n};\n\nexport function createDeferredPromise<T>(): DeferredPromise<T> {\n let resolve!: (value: T) => void;\n let reject!: (error: Error) => void;\n const promise = new Promise<T>((_resolve, _reject) => {\n resolve = _resolve;\n reject = _reject;\n });\n return { promise, resolve, reject };\n}\n\nexport const generateId = () => {\n return crypto.randomUUID();\n};\n\nexport type DistributiveOmit<T, K extends keyof T> = T extends any\n ? Omit<T, K>\n : never;\n\nexport function ensureSingletonExecution(fn: () => Promise<void>) {\n let isExecuting = false;\n let shouldReExecute = false;\n\n const wrappedFn = () => {\n if (isExecuting) {\n shouldReExecute = true;\n return;\n }\n\n isExecuting = true;\n fn().finally(() => {\n isExecuting = false;\n\n if (shouldReExecute) {\n shouldReExecute = false;\n wrappedFn();\n }\n });\n };\n\n wrappedFn.isExecuting = () => isExecuting;\n\n return wrappedFn;\n}\n\nexport function orderBy<T>(\n inputArray: T[],\n picker: (item: T) => any,\n opts?: {\n direction?: \"asc\" | \"desc\";\n inPlace?: boolean;\n }\n): T[] {\n const array = opts?.inPlace ? inputArray : [...inputArray];\n const direction = opts?.direction ?? \"asc\";\n return array.sort((a, b) => {\n const aVal = picker(a);\n const bVal = picker(b);\n\n if (aVal < bVal) return direction === \"asc\" ? -1 : 1;\n if (aVal > bVal) return direction === \"asc\" ? 1 : -1;\n return 0;\n });\n}\n\nexport function createAutoFlushBuffer<T>({\n size,\n flush,\n}: {\n size: number;\n flush: (items: T[]) => void;\n}) {\n const buffer: T[] = [];\n\n return {\n add(item: T) {\n buffer.push(item);\n if (buffer.length >= size) {\n flush(buffer);\n buffer.length = 0;\n }\n },\n flush() {\n flush(buffer);\n buffer.length = 0;\n },\n };\n}\n\nexport function createAsyncAutoFlushBuffer<T>({\n size,\n flush,\n}: {\n size: number;\n flush: (items: T[]) => void | Promise<void>;\n}) {\n const buffer: T[] = [];\n\n return {\n async add(item: T) {\n buffer.push(item);\n if (buffer.length >= size) {\n await this.flush();\n }\n },\n async flush() {\n const itemsToFlush = buffer.splice(0);\n if (itemsToFlush.length === 0) {\n return;\n }\n await flush(itemsToFlush);\n },\n };\n}\n\nexport class TypedBroadcastChannel<TMessage> {\n private readonly channel: BroadcastChannel;\n\n constructor(name: string) {\n this.channel = new BroadcastChannel(name);\n }\n\n postMessage(message: TMessage) {\n this.channel.postMessage(message);\n }\n\n set onmessage(callback: (event: MessageEvent<TMessage>) => void) {\n this.channel.onmessage = callback;\n }\n}\n\nexport class TypedEvent<T = unknown> extends Event {\n readonly payload: T;\n constructor(type: string, payload: T) {\n super(type);\n this.payload = payload;\n }\n}\n\nexport const createTypedEventTarget = <T extends Record<string, unknown>>() => {\n const eventTarget = new EventTarget();\n\n const addEventListener = <K extends keyof T & string>(\n type: K,\n listener: (event: TypedEvent<T[K]>) => void\n ) => {\n eventTarget.addEventListener(type, listener as (e: Event) => void);\n };\n\n const removeEventListener = <K extends keyof T & string>(\n type: K,\n listener: (event: TypedEvent<T[K]>) => void\n ) => {\n eventTarget.removeEventListener(type, listener as (e: Event) => void);\n };\n\n const dispatchEvent = <K extends keyof T & string>(\n type: K,\n payload: T[K]\n ) => {\n eventTarget.dispatchEvent(new TypedEvent(type, payload));\n };\n\n return {\n addEventListener,\n removeEventListener,\n dispatchEvent,\n };\n};\n\nexport function jsonSafeParse<T>(json: string):\n | {\n status: \"ok\";\n data: T;\n }\n | {\n status: \"error\";\n error: unknown;\n } {\n try {\n return {\n status: \"ok\",\n data: JSON.parse(json),\n };\n } catch (error) {\n return {\n status: \"error\",\n error,\n };\n }\n}\n\n","import {\n DummyDriver,\n Kysely,\n SqliteAdapter,\n SqliteIntrospector,\n SqliteQueryCompiler,\n} from \"kysely\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport const dummyKysely: Kysely<any> = new Kysely({\n dialect: {\n createAdapter: () => new SqliteAdapter(),\n createDriver: () => new DummyDriver(),\n createQueryCompiler: () => new SqliteQueryCompiler(),\n createIntrospector: (db) => new SqliteIntrospector(db),\n },\n});\n\n","import { type Kysely } from \"kysely\";\nimport type { SQLiteTransactionWrapper } from \"../sqlite-db-wrapper\";\nimport type {\n CrdtEventType,\n CrdtUpdateLogItem,\n CrdtUpdateLogPayload,\n} from \"./crdt-table-schema\";\n\nexport type PendingCrdtEvent = {\n type: CrdtEventType;\n dataset: string;\n item_id: string;\n timestamp: string;\n payload: string;\n};\n\ntype ApplyCrdtParams = {\n updateLogTableName: string;\n db: SQLiteTransactionWrapper<any>;\n event: PendingCrdtEvent;\n};\n\ntype ApplyCrdtContext = {\n db: SQLiteTransactionWrapper<unknown>;\n updateLogTableName: string;\n event: PendingCrdtEvent;\n eventPayload: Record<string, unknown>;\n meta: CrdtUpdateLogPayload | null;\n};\n\nexport function applyCrdtEventMutations({\n db,\n event,\n updateLogTableName,\n}: ApplyCrdtParams) {\n const eventPayload = JSON.parse(event.payload);\n\n const [metaRow] = db.executePrepared(\n \"get-item-crdt-meta\",\n {\n item_id: event.item_id,\n dataset: event.dataset,\n },\n (db, params) => {\n return (db as unknown as Kysely<{ table: CrdtUpdateLogItem }>)\n .selectFrom(updateLogTableName as \"table\")\n .select(\"payload\")\n .where(\"item_id\", \"=\", params(\"item_id\"))\n .where(\"dataset\", \"=\", params(\"dataset\"));\n }\n );\n\n const meta = metaRow\n ? (JSON.parse(metaRow.payload) as CrdtUpdateLogPayload)\n : null;\n\n // TODO Check primary key / unique constraints\n\n const context: ApplyCrdtContext = {\n db: db as SQLiteTransactionWrapper<unknown>,\n updateLogTableName,\n event,\n meta,\n eventPayload,\n };\n\n switch (event.type) {\n case \"item-created\": {\n applyItemCreated(context);\n break;\n }\n case \"item-updated\": {\n applyItemUpdated(context);\n break;\n }\n default:\n event.type satisfies never;\n }\n}\n\nfunction applyItemCreated(context: ApplyCrdtContext) {\n if (context.meta) {\n // Item already exists\n applyItemUpdated(context);\n return;\n }\n\n // TODO SQL sanitization\n\n const keys = Array.from(Object.keys(context.eventPayload));\n context.db.execute({\n sql: `insert into ${context.event.dataset} (${keys.join(\n \",\"\n )}) values (${keys.map(() => \"?\").join(\",\")})`,\n parameters: keys.map((key) => context.eventPayload[key]),\n });\n\n const newUpdateLog = Object.fromEntries(\n keys.map((key) => [key, context.event.timestamp])\n );\n insertCrdtUpdateLog(context, newUpdateLog);\n}\n\nfunction insertCrdtUpdateLog(\n context: ApplyCrdtContext,\n log: Record<string, string>\n) {\n context.db.executePrepared(\n \"insert-crdt-update-log\",\n {\n item_id: context.event.item_id,\n dataset: context.event.dataset,\n payload: JSON.stringify(log),\n },\n (db, params) =>\n (db as unknown as Kysely<{ table: CrdtUpdateLogItem }>)\n .insertInto(context.updateLogTableName as \"table\")\n .values({\n item_id: params(\"item_id\"),\n dataset: params(\"dataset\"),\n payload: params(\"payload\"),\n })\n );\n}\n\nfunction applyItemUpdated(context: ApplyCrdtContext) {\n const meta = context.meta;\n if (!meta) {\n throw new Error(\n `Item ${context.event.item_id} in dataset ${context.event.dataset} not found`\n );\n }\n\n const keys = Array.from(Object.keys(context.eventPayload)).filter((key) => {\n const lastUpdateTimestamp = meta[key];\n if (!lastUpdateTimestamp) {\n return true;\n }\n\n const currentUpdateTimestamp = context.event.timestamp;\n return currentUpdateTimestamp > lastUpdateTimestamp;\n });\n\n if (keys.length > 0) {\n context.db.execute({\n sql: `update ${context.event.dataset} set ${keys\n .map((key) => `${key} = ?`)\n .join(\",\")} where id = ?`,\n parameters: [\n ...keys.map((key) => context.eventPayload[key]),\n context.event.item_id,\n ],\n });\n\n keys.forEach((key) => {\n meta[key] = context.event.timestamp;\n });\n updateCrdtUpdateLog(context, meta);\n }\n}\n\nfunction updateCrdtUpdateLog(\n context: ApplyCrdtContext,\n log: Record<string, string>\n) {\n context.db.executePrepared(\n \"update-crdt-update-log\",\n {\n item_id: context.event.item_id,\n dataset: context.event.dataset,\n payload: JSON.stringify(log),\n },\n (db, params) =>\n (db as unknown as Kysely<{ table: CrdtUpdateLogItem }>)\n .updateTable(context.updateLogTableName as \"table\")\n .set({\n payload: params(\"payload\"),\n })\n .where(\"item_id\", \"=\", params(\"item_id\"))\n .where(\"dataset\", \"=\", params(\"dataset\"))\n );\n}\n\n","import type { SchemaModule } from \"kysely\";\nimport type { SQLiteDbWrapper } from \"../sqlite-db-wrapper\";\nimport type { TableMetadata } from \"../introspection\";\nimport {\n applyCrdtEventMutations,\n type PendingCrdtEvent,\n} from \"./apply-crdt-event\";\n\nexport type CrdtEventType = \"item-created\" | \"item-updated\";\n\nexport type CrdtEventStatus = \"pending\" | \"applied\" | \"failed\";\n\nexport type CrdtEventOrigin = \"remote\" | (string & {});\n\nexport type PersistedCrdtEvent = {\n sync_id: number;\n status: CrdtEventStatus;\n type: CrdtEventType;\n timestamp: string;\n origin: CrdtEventOrigin;\n dataset: string;\n item_id: string;\n payload: string;\n};\n\nexport type CrdtUpdateLogItem = {\n dataset: string;\n item_id: string;\n payload: string;\n};\n\nexport type CrdtUpdateLogPayload = Record<string, string>;\n\nexport type MetaItem = {\n key: string;\n value: string;\n};\n\nexport const crdtSchema = {\n metaTable: createMetaTableQuery,\n persistedEventsTable: createPersistedEventsTable,\n crdtUpdateLogTable: createCrdtUpdateLogTableQuery,\n};\n\nfunction createMetaTableQuery(schema: SchemaModule, tableName: string) {\n return schema\n .createTable(tableName)\n .ifNotExists()\n .addColumn(\"key\", \"text\", (col) => col.notNull().primaryKey())\n .addColumn(\"value\", \"text\", (col) => col.notNull());\n}\n\nfunction createPersistedEventsTable(schema: SchemaModule, tableName: string) {\n return schema\n .createTable(tableName)\n .ifNotExists()\n .addColumn(\"sync_id\", \"integer\", (col) => col.notNull().primaryKey())\n .addColumn(\"status\", \"text\", (col) => col.notNull())\n .addColumn(\"type\", \"text\", (col) => col.notNull())\n .addColumn(\"timestamp\", \"text\", (col) => col.notNull())\n .addColumn(\"origin\", \"text\", (col) => col.notNull())\n .addColumn(\"dataset\", \"text\", (col) => col.notNull())\n .addColumn(\"item_id\", \"text\", (col) => col.notNull())\n .addColumn(\"payload\", \"text\", (col) => col.notNull());\n}\n\nfunction createCrdtUpdateLogTableQuery(\n schema: SchemaModule,\n tableName: string\n) {\n return schema\n .createTable(tableName)\n .ifNotExists()\n .addColumn(\"dataset\", \"text\", (col) => col.notNull())\n .addColumn(\"item_id\", \"text\", (col) => col.notNull())\n .addColumn(\"payload\", \"text\", (col) => col.notNull())\n .addPrimaryKeyConstraint(`pk_${tableName}`, [\"item_id\", \"dataset\"]);\n}\n\nexport function registerCrdtFunctions({\n db,\n onEventApplied,\n getNextTimestamp,\n getTableSchema,\n updateLogTableName,\n}: {\n db: SQLiteDbWrapper<any>;\n onEventApplied: (event: PendingCrdtEvent) => void;\n getNextTimestamp: () => string;\n getTableSchema: (dataset: string) => TableMetadata;\n updateLogTableName: string;\n}) {\n db.createScalarFunction({\n name: \"handle_item_created\",\n deterministic: false,\n directOnly: false,\n innocuous: false,\n callback: (dataset: string, payloadRaw: string) => {\n const payload = JSON.parse(payloadRaw) as { id: string };\n\n const event: PendingCrdtEvent = {\n timestamp: getNextTimestamp(),\n type: \"item-created\",\n dataset,\n item_id: payload.id,\n payload: payloadRaw,\n };\n\n applyCrdtEventMutations({\n db,\n event,\n updateLogTableName,\n });\n\n onEventApplied(event);\n },\n });\n\n db.createScalarFunction({\n name: \"handle_item_updated\",\n deterministic: false,\n directOnly: false,\n innocuous: false,\n callback: (\n dataset: string,\n oldPayloadRaw: string,\n newPayloadRaw: string\n ) => {\n const tableSchema = getTableSchema(dataset);\n const oldPayload = JSON.parse(oldPayloadRaw);\n const newPayload = JSON.parse(newPayloadRaw);\n\n let hasDiff = false;\n const payload = Object.fromEntries(\n tableSchema.columns\n .map((column) => {\n const oldValue = oldPayload[column.name];\n const newValue = newPayload[column.name];\n if (oldValue === newValue) {\n return null as unknown as [string, unknown];\n }\n hasDiff = true;\n return [column.name, newValue] as const;\n })\n .filter(Boolean)\n );\n\n const event: PendingCrdtEvent = {\n timestamp: getNextTimestamp(),\n type: \"item-updated\",\n dataset,\n item_id: oldPayload.id,\n payload: JSON.stringify(payload),\n };\n\n if (!hasDiff) {\n return;\n }\n\n applyCrdtEventMutations({\n db,\n event,\n updateLogTableName,\n });\n onEventApplied(event);\n },\n });\n\n db.createScalarFunction({\n name: \"handle_item_deleted\",\n deterministic: false,\n directOnly: false,\n innocuous: false,\n callback: (dataset: string, itemId: string) => {\n const event: PendingCrdtEvent = {\n timestamp: getNextTimestamp(),\n type: \"item-updated\",\n dataset,\n item_id: itemId,\n payload: JSON.stringify({ tombstone: 1 }),\n };\n\n applyCrdtEventMutations({\n db,\n event,\n updateLogTableName,\n });\n onEventApplied(event);\n },\n });\n}\n\n","export type SyncIdCounter = {\n get current(): number;\n set current(newSyncId: number);\n};\n\nexport function createSyncIdCounter({\n initialSyncId,\n saveToStorage,\n}: {\n initialSyncId: number;\n saveToStorage?: (syncId: number) => void;\n}): SyncIdCounter {\n let currentSyncId = initialSyncId;\n\n return {\n get current() {\n return currentSyncId;\n },\n set current(newSyncId: number) {\n saveToStorage?.(newSyncId);\n currentSyncId = newSyncId;\n },\n };\n}\n\n","import { createTypedEventTarget, ensureSingletonExecution } from \"../utils\";\nimport type {\n CrdtEventOrigin,\n CrdtEventStatus,\n CrdtEventType,\n PersistedCrdtEvent,\n} from \"./crdt-table-schema\";\nimport type { SyncIdCounter } from \"./sync-id-counter\";\n\ntype LocalCrdtEvent = {\n type: CrdtEventType;\n timestamp: string;\n dataset: string;\n item_id: string;\n payload: string;\n origin: CrdtEventOrigin;\n};\n\ntype PendingEventsBatch = {\n events: PersistedCrdtEvent[];\n hasMore: boolean;\n};\n\ntype DbSyncerStorage = {\n syncId: SyncIdCounter;\n persistEvents: (events: PersistedCrdtEvent[]) => void;\n popPendingEventsBatch: () => PendingEventsBatch;\n updateEventStatus: (syncId: number, status: CrdtEventStatus) => void;\n applyCrdtEventMutations: (event: PersistedCrdtEvent) => void;\n};\n\nexport type CrdtStorage = ReturnType<typeof createCrdtStorage>;\n\nexport function createCrdtStorage(storage: DbSyncerStorage) {\n const eventTarget = createTypedEventTarget<{\n \"event-applied\": PersistedCrdtEvent;\n \"event-processing-done\": void;\n }>();\n\n const enqueueEvents = (events: LocalCrdtEvent[]) => {\n const firstEventSyncId = storage.syncId.current + 1;\n storage.persistEvents(\n events.map((x) => ({\n timestamp: x.timestamp,\n type: x.type,\n dataset: x.dataset,\n item_id: x.item_id,\n origin: x.origin,\n payload: x.payload,\n sync_id: ++storage.syncId.current,\n status: \"pending\",\n }))\n );\n const lastEventSyncId = storage.syncId.current;\n\n processEnqueuedEvents();\n\n return {\n firstEventSyncId,\n lastEventSyncId,\n };\n };\n\n const processEnqueuedEvents = ensureSingletonExecution(async () => {\n await Promise.resolve();\n\n let hasMore = true;\n while (hasMore) {\n const batch = storage.popPendingEventsBatch();\n const events = batch.events;\n hasMore = batch.hasMore;\n\n if (events.length === 0) {\n break;\n }\n\n for (const event of events) {\n try {\n storage.applyCrdtEventMutations(event);\n event.status = \"applied\";\n } catch (error) {\n console.error(\"Error applying enqueued CRDT event\", error);\n event.status = \"failed\";\n } finally {\n storage.updateEventStatus(event.sync_id, event.status);\n eventTarget.dispatchEvent(\"event-applied\", event);\n }\n }\n }\n eventTarget.dispatchEvent(\"event-processing-done\", undefined);\n });\n\n return {\n enqueueEvents,\n addEventListener: eventTarget.addEventListener,\n removeEventListener: eventTarget.removeEventListener,\n dispatchEvent: eventTarget.dispatchEvent,\n };\n}\n\n","import { createAutoFlushBuffer } from \"../utils\";\nimport type { CrdtStorage } from \"./crdt-storage\";\nimport type { PersistedCrdtEvent } from \"./crdt-table-schema\";\n\ntype CrdtSyncProducer = {\n bufferSize: number;\n storage: CrdtStorage;\n broadcastEvents: (request: { newSyncId: number }) => void;\n};\n\nexport const createCrdtSyncProducer = ({\n bufferSize,\n storage,\n broadcastEvents,\n}: CrdtSyncProducer) => {\n const eventsBuffer = createAutoFlushBuffer<PersistedCrdtEvent>({\n size: bufferSize,\n flush: (events) => {\n if (events.length === 0) {\n return;\n }\n\n broadcastEvents({ newSyncId: events[events.length - 1].sync_id });\n },\n });\n\n storage.addEventListener(\"event-applied\", (event) => {\n if (event.payload.status !== \"applied\") {\n return;\n }\n eventsBuffer.add(event.payload);\n });\n\n storage.addEventListener(\"event-processing-done\", () => {\n eventsBuffer.flush();\n });\n};\n\n"],"mappings":"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","names":["db"]}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { Kysely } from 'kysely';
|
|
2
|
-
import { m as CrdtStorage } from './crdt-sync-remote-source-rrqinqLn.js';
|
|
3
|
-
|
|
4
|
-
declare const dummyKysely: Kysely<any>;
|
|
5
|
-
|
|
6
|
-
type CrdtSyncProducer = {
|
|
7
|
-
bufferSize: number;
|
|
8
|
-
storage: CrdtStorage;
|
|
9
|
-
broadcastEvents: (request: {
|
|
10
|
-
newSyncId: number;
|
|
11
|
-
}) => void;
|
|
12
|
-
};
|
|
13
|
-
declare const createCrdtSyncProducer: ({ bufferSize, storage, broadcastEvents, }: CrdtSyncProducer) => void;
|
|
14
|
-
|
|
15
|
-
export { createCrdtSyncProducer as c, dummyKysely as d };
|