@sqlite-sync/core 0.6.0 → 0.7.1
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-3L4QG3BZ.js → chunk-LBYL5L4O.js} +371 -34
- package/dist/chunk-LBYL5L4O.js.map +1 -0
- package/dist/{crdt-sync-remote-source-CJrVzW-B.d.ts → crdt-sync-remote-source-yXp-iMEd.d.ts} +304 -185
- package/dist/index.d.ts +126 -18
- package/dist/index.js +296 -74
- package/dist/index.js.map +1 -1
- package/dist/reset-state-D6UslXaj.d.ts +19 -0
- package/dist/server.d.ts +2 -2
- package/dist/worker.d.ts +10 -3
- package/dist/worker.js +12 -2
- package/dist/worker.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-3L4QG3BZ.js.map +0 -1
- package/dist/reset-state-Comk7IC0.d.ts +0 -81
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CRDT_EVENT_NO_OP_PAYLOAD,
|
|
3
|
+
CrdtEventValidationError,
|
|
3
4
|
HLCCounter,
|
|
4
5
|
RESET_REQUEST_TTL_MS,
|
|
5
6
|
SQLiteDbWrapper,
|
|
@@ -21,6 +22,7 @@ import {
|
|
|
21
22
|
createSystemDbConfig,
|
|
22
23
|
deserializeHLC,
|
|
23
24
|
dummyKysely,
|
|
25
|
+
formatSchemaVerificationIssues,
|
|
24
26
|
introspectDb,
|
|
25
27
|
isNoOpCrdtEventPayload,
|
|
26
28
|
isWorkerErrorResponseMessage,
|
|
@@ -31,8 +33,10 @@ import {
|
|
|
31
33
|
serializeHLC,
|
|
32
34
|
startPerformanceLogger,
|
|
33
35
|
syncDbClientLockName,
|
|
36
|
+
validateNewCrdtEvent,
|
|
37
|
+
verifySyncSchema,
|
|
34
38
|
xxhash
|
|
35
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-LBYL5L4O.js";
|
|
36
40
|
import {
|
|
37
41
|
TypedBroadcastChannel,
|
|
38
42
|
TypedEvent,
|
|
@@ -46,6 +50,63 @@ import {
|
|
|
46
50
|
tryCatchAsync
|
|
47
51
|
} from "./chunk-NHT3ELMN.js";
|
|
48
52
|
|
|
53
|
+
// src/export-import.ts
|
|
54
|
+
function createExportImport({
|
|
55
|
+
reactiveDb,
|
|
56
|
+
crdtStorage,
|
|
57
|
+
tablesConfig,
|
|
58
|
+
schemaVersion
|
|
59
|
+
}) {
|
|
60
|
+
const crdtTableNames = tablesConfig.map((config) => config.crdtTableName);
|
|
61
|
+
const resolveTables = (requested) => {
|
|
62
|
+
if (!requested) {
|
|
63
|
+
return crdtTableNames;
|
|
64
|
+
}
|
|
65
|
+
for (const name of requested) {
|
|
66
|
+
if (!crdtTableNames.includes(name)) {
|
|
67
|
+
throw new Error(`Unknown table "${name}". Known synced tables: ${crdtTableNames.join(", ")}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return requested;
|
|
71
|
+
};
|
|
72
|
+
const exportData = (opts) => {
|
|
73
|
+
const tables = {};
|
|
74
|
+
for (const crdtTableName of resolveTables(opts?.tables)) {
|
|
75
|
+
const { rows } = reactiveDb.db.execute(`select * from ${quoteId(crdtTableName)}`, {
|
|
76
|
+
loggerLevel: "system"
|
|
77
|
+
});
|
|
78
|
+
tables[crdtTableName] = rows.map(({ tombstone: _tombstone, ...rest }) => rest);
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
schemaVersion,
|
|
82
|
+
exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
83
|
+
tables
|
|
84
|
+
};
|
|
85
|
+
};
|
|
86
|
+
const importData = (data, opts) => {
|
|
87
|
+
const validate = opts?.validate ?? true;
|
|
88
|
+
if (validate && data.schemaVersion !== schemaVersion) {
|
|
89
|
+
throw new Error(
|
|
90
|
+
`Cannot import data from schema version ${data.schemaVersion} into a database at schema version ${schemaVersion}.`
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
const events = [];
|
|
94
|
+
for (const [crdtTableName, rows] of Object.entries(data.tables)) {
|
|
95
|
+
for (const row of rows) {
|
|
96
|
+
events.push({
|
|
97
|
+
type: "item-created",
|
|
98
|
+
dataset: crdtTableName,
|
|
99
|
+
item_id: row.id,
|
|
100
|
+
payload: JSON.stringify(row)
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
crdtStorage.applyOwnEvents(events);
|
|
105
|
+
return { imported: events.length };
|
|
106
|
+
};
|
|
107
|
+
return { exportData, importData };
|
|
108
|
+
}
|
|
109
|
+
|
|
49
110
|
// src/memory-db/sqlite-reactive-db.ts
|
|
50
111
|
import sqlite3InitModule from "@sqlite.org/sqlite-wasm";
|
|
51
112
|
|
|
@@ -458,45 +519,202 @@ function parametersAreEqual(a, b) {
|
|
|
458
519
|
return true;
|
|
459
520
|
}
|
|
460
521
|
|
|
461
|
-
// src/
|
|
462
|
-
function
|
|
463
|
-
|
|
522
|
+
// src/schema/define-sync-schema.ts
|
|
523
|
+
function defineSyncSchema({
|
|
524
|
+
tables,
|
|
525
|
+
migrations
|
|
526
|
+
}) {
|
|
527
|
+
const tablesConfig = Object.entries(tables).map(([crdtTableName, table]) => ({
|
|
528
|
+
crdtTableName,
|
|
529
|
+
baseTableName: table.baseName ?? `_${crdtTableName}`
|
|
530
|
+
}));
|
|
531
|
+
const seenNames = /* @__PURE__ */ new Set();
|
|
532
|
+
for (const { crdtTableName, baseTableName } of tablesConfig) {
|
|
533
|
+
for (const name of [crdtTableName, baseTableName]) {
|
|
534
|
+
if (seenNames.has(name)) {
|
|
535
|
+
throw new Error(`Duplicate table name "${name}" in sync schema`);
|
|
536
|
+
}
|
|
537
|
+
seenNames.add(name);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
return {
|
|
541
|
+
tables,
|
|
542
|
+
get tablesConfig() {
|
|
543
|
+
return tablesConfig;
|
|
544
|
+
},
|
|
545
|
+
get migrations() {
|
|
546
|
+
return migrations;
|
|
547
|
+
},
|
|
548
|
+
get "~clientSchema"() {
|
|
549
|
+
throw new Error("~clientSchema is type-only and cannot be accessed at runtime");
|
|
550
|
+
},
|
|
551
|
+
get "~serverSchema"() {
|
|
552
|
+
throw new Error("~serverSchema is type-only and cannot be accessed at runtime");
|
|
553
|
+
},
|
|
554
|
+
get "~mutationsSchema"() {
|
|
555
|
+
throw new Error("~mutationsSchema is type-only and cannot be accessed at runtime");
|
|
556
|
+
}
|
|
557
|
+
};
|
|
464
558
|
}
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
559
|
+
|
|
560
|
+
// src/schema/table-builder.ts
|
|
561
|
+
var ColumnBuilder = class _ColumnBuilder {
|
|
562
|
+
constructor(meta) {
|
|
563
|
+
this.meta = meta;
|
|
468
564
|
}
|
|
469
|
-
|
|
470
|
-
|
|
565
|
+
/** Allow SQL NULL; widens the value type with `null`. */
|
|
566
|
+
nullable() {
|
|
567
|
+
return new _ColumnBuilder({ ...this.meta, nullable: true });
|
|
471
568
|
}
|
|
472
|
-
|
|
473
|
-
|
|
569
|
+
/** Declare a column default. The value is used both in DDL and when migrating older events. */
|
|
570
|
+
default(value) {
|
|
571
|
+
return new _ColumnBuilder({ ...this.meta, hasDefault: true, defaultValue: value });
|
|
474
572
|
}
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
return
|
|
573
|
+
/** Narrow the TypeScript value type without changing storage, e.g. `t.text().$type<"movie" | "tv">()`. */
|
|
574
|
+
$type() {
|
|
575
|
+
return this;
|
|
478
576
|
}
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
return
|
|
577
|
+
/** Human/AI-readable description, surfaced in generated schema docs. */
|
|
578
|
+
describe(description) {
|
|
579
|
+
return new _ColumnBuilder({ ...this.meta, description });
|
|
580
|
+
}
|
|
581
|
+
};
|
|
582
|
+
var RESERVED_COLUMNS = ["id", "tombstone"];
|
|
583
|
+
var idColumnMeta = {
|
|
584
|
+
kind: "text",
|
|
585
|
+
sqlType: "text",
|
|
586
|
+
nullable: false,
|
|
587
|
+
hasDefault: false,
|
|
588
|
+
description: "Unique immutable item id"
|
|
589
|
+
};
|
|
590
|
+
var tombstoneColumnMeta = {
|
|
591
|
+
kind: "boolean",
|
|
592
|
+
sqlType: "integer",
|
|
593
|
+
nullable: false,
|
|
594
|
+
hasDefault: true,
|
|
595
|
+
defaultValue: false,
|
|
596
|
+
description: "Soft-delete marker"
|
|
597
|
+
};
|
|
598
|
+
var TableBuilder = class _TableBuilder {
|
|
599
|
+
constructor(userColumns, options) {
|
|
600
|
+
this.userColumns = userColumns;
|
|
601
|
+
for (const reserved of RESERVED_COLUMNS) {
|
|
602
|
+
if (reserved in userColumns) {
|
|
603
|
+
throw new Error(`Column "${reserved}" is added automatically to every synced table and cannot be declared`);
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
this.columns = {
|
|
607
|
+
id: idColumnMeta,
|
|
608
|
+
...Object.fromEntries(Object.entries(userColumns).map(([name, column2]) => [name, column2.meta])),
|
|
609
|
+
tombstone: tombstoneColumnMeta
|
|
610
|
+
};
|
|
611
|
+
this.baseName = options?.baseName;
|
|
612
|
+
this.description = options?.description;
|
|
613
|
+
}
|
|
614
|
+
/** All columns in DDL order, including the auto-injected `id` and `tombstone`. */
|
|
615
|
+
columns;
|
|
616
|
+
baseName;
|
|
617
|
+
description;
|
|
618
|
+
describe(description) {
|
|
619
|
+
return new _TableBuilder(this.userColumns, { baseName: this.baseName, description });
|
|
482
620
|
}
|
|
483
|
-
|
|
484
|
-
|
|
621
|
+
/** Type-only: the row shape returned by queries. Do not access at runtime. */
|
|
622
|
+
get $row() {
|
|
485
623
|
return null;
|
|
486
624
|
}
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
625
|
+
/**
|
|
626
|
+
* Validate a CRDT event payload against the declared columns.
|
|
627
|
+
* `item-created` payloads must contain every column without a default (nullable columns may be omitted);
|
|
628
|
+
* `item-updated` payloads are partial and must not touch `id` or set `tombstone` to a deleted value.
|
|
629
|
+
*/
|
|
630
|
+
validatePayload(payload, options) {
|
|
631
|
+
const event = options?.event ?? "item-created";
|
|
632
|
+
const errors = [];
|
|
633
|
+
for (const key of Object.keys(payload)) {
|
|
634
|
+
if (!(key in this.columns)) {
|
|
635
|
+
errors.push(`Unknown column "${key}"`);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
if (event === "item-updated") {
|
|
639
|
+
if ("id" in payload) {
|
|
640
|
+
errors.push(`Column "id" is immutable and cannot appear in an update payload`);
|
|
641
|
+
}
|
|
642
|
+
if (payload.tombstone === true || payload.tombstone === 1) {
|
|
643
|
+
errors.push(`Column "tombstone" cannot be set to true/1 in an update payload; use an item-deleted event`);
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
if (event === "item-created") {
|
|
647
|
+
for (const [name, meta] of Object.entries(this.columns)) {
|
|
648
|
+
if (name in payload || name === "tombstone" || meta.nullable || meta.hasDefault) {
|
|
649
|
+
continue;
|
|
650
|
+
}
|
|
651
|
+
errors.push(`Missing required column "${name}"`);
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
for (const [name, value] of Object.entries(payload)) {
|
|
655
|
+
const meta = this.columns[name];
|
|
656
|
+
if (!meta || event === "item-updated" && name === "id") {
|
|
657
|
+
continue;
|
|
658
|
+
}
|
|
659
|
+
const error = validateValue(name, value, meta);
|
|
660
|
+
if (error) {
|
|
661
|
+
errors.push(error);
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
return errors.length === 0 ? { success: true } : { success: false, errors };
|
|
496
665
|
}
|
|
497
|
-
|
|
498
|
-
|
|
666
|
+
};
|
|
667
|
+
function describeValue(value) {
|
|
668
|
+
if (value === null) return "null";
|
|
669
|
+
if (Array.isArray(value)) return "array";
|
|
670
|
+
return typeof value;
|
|
671
|
+
}
|
|
672
|
+
function validateValue(name, value, meta) {
|
|
673
|
+
if (value === null) {
|
|
674
|
+
return meta.nullable ? null : `Column "${name}" is not nullable, got null`;
|
|
675
|
+
}
|
|
676
|
+
switch (meta.kind) {
|
|
677
|
+
case "text":
|
|
678
|
+
return typeof value === "string" ? null : `Column "${name}" expects text, got ${describeValue(value)}`;
|
|
679
|
+
case "integer":
|
|
680
|
+
return typeof value === "number" && Number.isInteger(value) ? null : `Column "${name}" expects an integer, got ${describeValue(value)}`;
|
|
681
|
+
case "real":
|
|
682
|
+
return typeof value === "number" && Number.isFinite(value) ? null : `Column "${name}" expects a number, got ${describeValue(value)}`;
|
|
683
|
+
case "boolean":
|
|
684
|
+
return typeof value === "boolean" || value === 0 || value === 1 ? null : `Column "${name}" expects a boolean (true/false or 0/1), got ${describeValue(value)}`;
|
|
685
|
+
case "enum": {
|
|
686
|
+
if (typeof value !== "string") {
|
|
687
|
+
return `Column "${name}" expects one of ${formatEnumValues(meta)}, got ${describeValue(value)}`;
|
|
688
|
+
}
|
|
689
|
+
return meta.enumValues?.includes(value) ? null : `Column "${name}" expects one of ${formatEnumValues(meta)}, got "${value}"`;
|
|
690
|
+
}
|
|
499
691
|
}
|
|
692
|
+
}
|
|
693
|
+
function formatEnumValues(meta) {
|
|
694
|
+
return (meta.enumValues ?? []).map((value) => `"${value}"`).join(" | ");
|
|
695
|
+
}
|
|
696
|
+
function column(kind, sqlType) {
|
|
697
|
+
return new ColumnBuilder({ kind, sqlType, nullable: false, hasDefault: false });
|
|
698
|
+
}
|
|
699
|
+
var t = {
|
|
700
|
+
text: () => column("text", "text"),
|
|
701
|
+
integer: () => column("integer", "integer"),
|
|
702
|
+
real: () => column("real", "real"),
|
|
703
|
+
/** Stored as INTEGER 0/1; always bind booleans as 0/1 when writing raw SQL. */
|
|
704
|
+
boolean: () => column("boolean", "integer"),
|
|
705
|
+
/**
|
|
706
|
+
* Union of string literals stored as TEXT, e.g. `t.enum(["movie", "tv"])`. Unlike `$type`, the
|
|
707
|
+
* allowed values are kept as runtime metadata, so payloads are validated against them.
|
|
708
|
+
* For an open-ended set, use `t.text().$type<"idle" | (string & {})>()` instead.
|
|
709
|
+
*/
|
|
710
|
+
enum: (values) => new ColumnBuilder({
|
|
711
|
+
kind: "enum",
|
|
712
|
+
sqlType: "text",
|
|
713
|
+
nullable: false,
|
|
714
|
+
hasDefault: false,
|
|
715
|
+
enumValues: values
|
|
716
|
+
}),
|
|
717
|
+
table: (columns, options) => new TableBuilder(columns, options)
|
|
500
718
|
};
|
|
501
719
|
|
|
502
720
|
// src/sqlite-crdt/crdt-storage-mutator.ts
|
|
@@ -583,7 +801,7 @@ select * from ${quoteId(baseTableName)}
|
|
|
583
801
|
where tombstone = 0;`,
|
|
584
802
|
{ loggerLevel: "system" }
|
|
585
803
|
);
|
|
586
|
-
const allColumnNames = tableSchema.columns.map((
|
|
804
|
+
const allColumnNames = tableSchema.columns.map((column2) => column2.name);
|
|
587
805
|
const jsonPayload = (from) => `'{'||${allColumnNames.map((col) => `'"${col}":'||json_quote(${from}.${quoteId(col)})`).join("||','||")}||'}'`;
|
|
588
806
|
db.execute(
|
|
589
807
|
`
|
|
@@ -636,17 +854,12 @@ function registerCrdtFunctions({
|
|
|
636
854
|
innocuous: false,
|
|
637
855
|
callback: (dataset, payloadRaw) => {
|
|
638
856
|
const payload = JSON.parse(payloadRaw);
|
|
639
|
-
storage.
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
},
|
|
646
|
-
{
|
|
647
|
-
wrapInTransaction: false
|
|
648
|
-
}
|
|
649
|
-
);
|
|
857
|
+
storage.internal.applyOwnEventFromTransaction(reactiveDb.db, {
|
|
858
|
+
type: "item-created",
|
|
859
|
+
dataset,
|
|
860
|
+
item_id: payload.id,
|
|
861
|
+
payload: payloadRaw
|
|
862
|
+
});
|
|
650
863
|
eventApplied = true;
|
|
651
864
|
return void 0;
|
|
652
865
|
}
|
|
@@ -668,34 +881,29 @@ function registerCrdtFunctions({
|
|
|
668
881
|
const newPayload = JSON.parse(newPayloadRaw);
|
|
669
882
|
let hasDiff = false;
|
|
670
883
|
const updatePayload = {};
|
|
671
|
-
for (const
|
|
672
|
-
const oldValue = oldPayload[
|
|
673
|
-
const newValue = newPayload[
|
|
884
|
+
for (const column2 of tableSchema.columns) {
|
|
885
|
+
const oldValue = oldPayload[column2.name];
|
|
886
|
+
const newValue = newPayload[column2.name];
|
|
674
887
|
if (oldValue === newValue) {
|
|
675
888
|
continue;
|
|
676
889
|
}
|
|
677
|
-
if (
|
|
890
|
+
if (column2.name === "id") {
|
|
678
891
|
throw new Error(
|
|
679
892
|
`Cannot update the "id" column of an item. It is used to identify the item and must be immutable.`
|
|
680
893
|
);
|
|
681
894
|
}
|
|
682
895
|
hasDiff = true;
|
|
683
|
-
updatePayload[
|
|
896
|
+
updatePayload[column2.name] = newValue;
|
|
684
897
|
}
|
|
685
898
|
if (!hasDiff) {
|
|
686
899
|
return;
|
|
687
900
|
}
|
|
688
|
-
storage.
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
},
|
|
695
|
-
{
|
|
696
|
-
wrapInTransaction: false
|
|
697
|
-
}
|
|
698
|
-
);
|
|
901
|
+
storage.internal.applyOwnEventFromTransaction(reactiveDb.db, {
|
|
902
|
+
type: "item-updated",
|
|
903
|
+
dataset,
|
|
904
|
+
item_id: oldPayload.id,
|
|
905
|
+
payload: JSON.stringify(updatePayload)
|
|
906
|
+
});
|
|
699
907
|
eventApplied = true;
|
|
700
908
|
return void 0;
|
|
701
909
|
}
|
|
@@ -706,17 +914,12 @@ function registerCrdtFunctions({
|
|
|
706
914
|
directOnly: false,
|
|
707
915
|
innocuous: false,
|
|
708
916
|
callback: (dataset, itemId) => {
|
|
709
|
-
storage.
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
},
|
|
716
|
-
{
|
|
717
|
-
wrapInTransaction: false
|
|
718
|
-
}
|
|
719
|
-
);
|
|
917
|
+
storage.internal.applyOwnEventFromTransaction(reactiveDb.db, {
|
|
918
|
+
type: "item-deleted",
|
|
919
|
+
dataset,
|
|
920
|
+
item_id: itemId,
|
|
921
|
+
payload: "{}"
|
|
922
|
+
});
|
|
720
923
|
eventApplied = true;
|
|
721
924
|
return void 0;
|
|
722
925
|
}
|
|
@@ -724,7 +927,7 @@ function registerCrdtFunctions({
|
|
|
724
927
|
reactiveDb.addEventListener("transaction-committed", () => {
|
|
725
928
|
if (eventApplied) {
|
|
726
929
|
eventApplied = false;
|
|
727
|
-
storage.
|
|
930
|
+
void storage.internal.processEnqueuedEvents();
|
|
728
931
|
}
|
|
729
932
|
});
|
|
730
933
|
reactiveDb.addEventListener("transaction-rolled-back", () => {
|
|
@@ -799,7 +1002,8 @@ async function createMemoryDb({
|
|
|
799
1002
|
crdtTables,
|
|
800
1003
|
initializeSchema = true,
|
|
801
1004
|
initialSyncId,
|
|
802
|
-
eventHlcAccumulator
|
|
1005
|
+
eventHlcAccumulator,
|
|
1006
|
+
syncDbSchema
|
|
803
1007
|
}) {
|
|
804
1008
|
await xxhash.ensureLoaded();
|
|
805
1009
|
const reactiveDb = _reactiveDb;
|
|
@@ -821,7 +1025,8 @@ async function createMemoryDb({
|
|
|
821
1025
|
migrator,
|
|
822
1026
|
db,
|
|
823
1027
|
dbConfig: memoryDbConfig,
|
|
824
|
-
eventHlcAccumulator
|
|
1028
|
+
eventHlcAccumulator,
|
|
1029
|
+
schema: syncDbSchema
|
|
825
1030
|
});
|
|
826
1031
|
registerCrdtFunctions({
|
|
827
1032
|
reactiveDb,
|
|
@@ -1004,7 +1209,8 @@ async function createSyncedDb(options) {
|
|
|
1004
1209
|
migrator: memoryDbMigrator,
|
|
1005
1210
|
reactiveDb,
|
|
1006
1211
|
hlcCounter,
|
|
1007
|
-
crdtTables: options.syncDbSchema.tablesConfig
|
|
1212
|
+
crdtTables: options.syncDbSchema.tablesConfig,
|
|
1213
|
+
syncDbSchema: options.syncDbSchema
|
|
1008
1214
|
});
|
|
1009
1215
|
const pullSyncId = createStoredValue({
|
|
1010
1216
|
initialValue: workerClientSnapshot.syncId
|
|
@@ -1037,6 +1243,12 @@ async function createSyncedDb(options) {
|
|
|
1037
1243
|
globalThis.location?.reload();
|
|
1038
1244
|
});
|
|
1039
1245
|
perf.logEnd("createSyncedDb", "initialized", "info");
|
|
1246
|
+
const { exportData, importData } = createExportImport({
|
|
1247
|
+
reactiveDb,
|
|
1248
|
+
crdtStorage,
|
|
1249
|
+
tablesConfig: options.syncDbSchema.tablesConfig,
|
|
1250
|
+
schemaVersion: workerClientSnapshot.schemaVersion
|
|
1251
|
+
});
|
|
1040
1252
|
let isDisposed = false;
|
|
1041
1253
|
let unregisterDevtools;
|
|
1042
1254
|
const dispose = async () => {
|
|
@@ -1084,6 +1296,8 @@ async function createSyncedDb(options) {
|
|
|
1084
1296
|
setTimeout(() => globalThis.location?.reload(), 250);
|
|
1085
1297
|
},
|
|
1086
1298
|
subscribe: workerClient.subscribe,
|
|
1299
|
+
exportData,
|
|
1300
|
+
importData,
|
|
1087
1301
|
dispose,
|
|
1088
1302
|
_internal: {
|
|
1089
1303
|
executeAsync: workerClient.execute.bind(workerClient),
|
|
@@ -1105,10 +1319,13 @@ async function createSyncedDb(options) {
|
|
|
1105
1319
|
}
|
|
1106
1320
|
export {
|
|
1107
1321
|
CRDT_EVENT_NO_OP_PAYLOAD,
|
|
1322
|
+
ColumnBuilder,
|
|
1323
|
+
CrdtEventValidationError,
|
|
1108
1324
|
HLCCounter,
|
|
1109
1325
|
RESET_REQUEST_TTL_MS,
|
|
1110
1326
|
SQLiteDbWrapper,
|
|
1111
1327
|
SQLiteReactiveDb,
|
|
1328
|
+
TableBuilder,
|
|
1112
1329
|
TypedBroadcastChannel,
|
|
1113
1330
|
TypedEvent,
|
|
1114
1331
|
applyMemoryDbSchema,
|
|
@@ -1121,18 +1338,20 @@ export {
|
|
|
1121
1338
|
createCrdtSyncProducer,
|
|
1122
1339
|
createCrdtSyncRemoteSource,
|
|
1123
1340
|
createDeferredPromise,
|
|
1341
|
+
createExportImport,
|
|
1124
1342
|
createKvStoreTableQuery,
|
|
1125
1343
|
createMigrations,
|
|
1126
1344
|
createMigrator,
|
|
1127
1345
|
createSQLiteCrdtApplyFunction,
|
|
1128
1346
|
createSQLiteKvStore,
|
|
1129
1347
|
createStoredValue,
|
|
1130
|
-
createSyncDbSchema,
|
|
1131
1348
|
createSyncedDb,
|
|
1132
1349
|
createSystemDbConfig,
|
|
1133
1350
|
createTypedEventTarget,
|
|
1351
|
+
defineSyncSchema,
|
|
1134
1352
|
deserializeHLC,
|
|
1135
1353
|
dummyKysely,
|
|
1354
|
+
formatSchemaVerificationIssues,
|
|
1136
1355
|
generateId,
|
|
1137
1356
|
introspectDb,
|
|
1138
1357
|
isNoOpCrdtEventPayload,
|
|
@@ -1143,8 +1362,11 @@ export {
|
|
|
1143
1362
|
runSystemMigrations,
|
|
1144
1363
|
serializeHLC,
|
|
1145
1364
|
startPerformanceLogger,
|
|
1365
|
+
t,
|
|
1146
1366
|
tryCatch,
|
|
1147
1367
|
tryCatchAsync,
|
|
1368
|
+
validateNewCrdtEvent,
|
|
1369
|
+
verifySyncSchema,
|
|
1148
1370
|
xxhash
|
|
1149
1371
|
};
|
|
1150
1372
|
//# sourceMappingURL=index.js.map
|