@foretag/tanstack-db-surrealdb 0.6.0 → 0.6.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/README.md +40 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +121 -79
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +121 -79
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -4,6 +4,66 @@ import { Table, RecordId, Features } from 'surrealdb';
|
|
|
4
4
|
import { parseOrderByExpression, parseWhereExpression } from '@tanstack/db';
|
|
5
5
|
|
|
6
6
|
// src/index.ts
|
|
7
|
+
|
|
8
|
+
// src/crdt.ts
|
|
9
|
+
var toRecord = (value) => typeof value === "object" && value !== null ? value : {};
|
|
10
|
+
var materializeLoroJson = (doc, id) => {
|
|
11
|
+
const root = toRecord(doc.getMap("root").toJSON());
|
|
12
|
+
return {
|
|
13
|
+
id,
|
|
14
|
+
...root
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
var applyLoroJsonChange = (doc, change) => {
|
|
18
|
+
const root = doc.getMap("root");
|
|
19
|
+
if (change.type === "delete") {
|
|
20
|
+
root.set("deleted", true);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const value = toRecord(change.value);
|
|
24
|
+
for (const [key, fieldValue] of Object.entries(value)) {
|
|
25
|
+
if (key === "id") continue;
|
|
26
|
+
root.set(key, fieldValue);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
var materializeLoroRichtext = (doc, id) => {
|
|
30
|
+
const metadata = toRecord(doc.getMap("root").toJSON());
|
|
31
|
+
const content = doc.getText("content").toString();
|
|
32
|
+
return {
|
|
33
|
+
id,
|
|
34
|
+
content,
|
|
35
|
+
...metadata
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
var applyLoroRichtextChange = (doc, change) => {
|
|
39
|
+
const text = doc.getText("content");
|
|
40
|
+
const metadata = doc.getMap("root");
|
|
41
|
+
if (change.type === "delete") {
|
|
42
|
+
metadata.set("deleted", true);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const value = toRecord(change.value);
|
|
46
|
+
for (const [key, fieldValue] of Object.entries(value)) {
|
|
47
|
+
if (key === "id") continue;
|
|
48
|
+
if (key === "content") {
|
|
49
|
+
if (typeof fieldValue === "string") text.update(fieldValue);
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
metadata.set(key, fieldValue);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
var createLoroProfile = (profile) => {
|
|
56
|
+
if (profile === "richtext") {
|
|
57
|
+
return {
|
|
58
|
+
materialize: materializeLoroRichtext,
|
|
59
|
+
applyLocalChange: applyLoroRichtextChange
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
materialize: materializeLoroJson,
|
|
64
|
+
applyLocalChange: applyLoroJsonChange
|
|
65
|
+
};
|
|
66
|
+
};
|
|
7
67
|
var recordIdIdentityPool = /* @__PURE__ */ new Map();
|
|
8
68
|
var nativeRecordIdPool = /* @__PURE__ */ new Map();
|
|
9
69
|
var internRecordIdIdentity = (canonical, preferred) => {
|
|
@@ -191,66 +251,6 @@ var toRecordId = (tableName, id) => {
|
|
|
191
251
|
const key = normalized.startsWith(prefixed) ? normalized.slice(prefixed.length) : normalized;
|
|
192
252
|
return new RecordId(tableName, key);
|
|
193
253
|
};
|
|
194
|
-
|
|
195
|
-
// src/crdt.ts
|
|
196
|
-
var toRecord = (value) => typeof value === "object" && value !== null ? value : {};
|
|
197
|
-
var materializeLoroJson = (doc, id) => {
|
|
198
|
-
const root = toRecord(doc.getMap("root").toJSON());
|
|
199
|
-
return {
|
|
200
|
-
id,
|
|
201
|
-
...root
|
|
202
|
-
};
|
|
203
|
-
};
|
|
204
|
-
var applyLoroJsonChange = (doc, change) => {
|
|
205
|
-
const root = doc.getMap("root");
|
|
206
|
-
if (change.type === "delete") {
|
|
207
|
-
root.set("deleted", true);
|
|
208
|
-
return;
|
|
209
|
-
}
|
|
210
|
-
const value = toRecord(change.value);
|
|
211
|
-
for (const [key, fieldValue] of Object.entries(value)) {
|
|
212
|
-
if (key === "id") continue;
|
|
213
|
-
root.set(key, fieldValue);
|
|
214
|
-
}
|
|
215
|
-
};
|
|
216
|
-
var materializeLoroRichtext = (doc, id) => {
|
|
217
|
-
const metadata = toRecord(doc.getMap("root").toJSON());
|
|
218
|
-
const content = doc.getText("content").toString();
|
|
219
|
-
return {
|
|
220
|
-
id,
|
|
221
|
-
content,
|
|
222
|
-
...metadata
|
|
223
|
-
};
|
|
224
|
-
};
|
|
225
|
-
var applyLoroRichtextChange = (doc, change) => {
|
|
226
|
-
const text = doc.getText("content");
|
|
227
|
-
const metadata = doc.getMap("root");
|
|
228
|
-
if (change.type === "delete") {
|
|
229
|
-
metadata.set("deleted", true);
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
232
|
-
const value = toRecord(change.value);
|
|
233
|
-
for (const [key, fieldValue] of Object.entries(value)) {
|
|
234
|
-
if (key === "id") continue;
|
|
235
|
-
if (key === "content") {
|
|
236
|
-
if (typeof fieldValue === "string") text.update(fieldValue);
|
|
237
|
-
continue;
|
|
238
|
-
}
|
|
239
|
-
metadata.set(key, fieldValue);
|
|
240
|
-
}
|
|
241
|
-
};
|
|
242
|
-
var createLoroProfile = (profile) => {
|
|
243
|
-
if (profile === "richtext") {
|
|
244
|
-
return {
|
|
245
|
-
materialize: materializeLoroRichtext,
|
|
246
|
-
applyLocalChange: applyLoroRichtextChange
|
|
247
|
-
};
|
|
248
|
-
}
|
|
249
|
-
return {
|
|
250
|
-
materialize: materializeLoroJson,
|
|
251
|
-
applyLocalChange: applyLoroJsonChange
|
|
252
|
-
};
|
|
253
|
-
};
|
|
254
254
|
var IDENTIFIER_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
255
255
|
var firstRow = (res) => {
|
|
256
256
|
if (!res) return void 0;
|
|
@@ -289,9 +289,10 @@ var mapRelationPath = (path, relation) => {
|
|
|
289
289
|
return path;
|
|
290
290
|
};
|
|
291
291
|
var normalizeFilterValue = (value) => {
|
|
292
|
-
if (Array.isArray(value))
|
|
292
|
+
if (Array.isArray(value))
|
|
293
293
|
return value.map((item) => normalizeFilterValue(item));
|
|
294
|
-
|
|
294
|
+
if (value && typeof value === "object")
|
|
295
|
+
return normalizeRecordIdLikeValue(value);
|
|
295
296
|
const native = toNativeRecordIdLikeValue(value);
|
|
296
297
|
if (native !== value) return native;
|
|
297
298
|
return normalizeRecordIdLikeValue(value);
|
|
@@ -452,7 +453,8 @@ function manageTable(db, config) {
|
|
|
452
453
|
if (action === "KILLED") return;
|
|
453
454
|
if (action === "CREATE") cb({ type: "insert", row: value });
|
|
454
455
|
else if (action === "UPDATE") cb({ type: "update", row: value });
|
|
455
|
-
else if (action === "DELETE")
|
|
456
|
+
else if (action === "DELETE")
|
|
457
|
+
cb({ type: "delete", row: { id: value.id } });
|
|
456
458
|
};
|
|
457
459
|
const start = async () => {
|
|
458
460
|
if (!db.isFeatureSupported(Features.LiveQueries)) return;
|
|
@@ -685,7 +687,8 @@ function createInsertSchema(tableName) {
|
|
|
685
687
|
const data = normalizeRecordIdLikeFields({
|
|
686
688
|
...value
|
|
687
689
|
});
|
|
688
|
-
if (!data.id)
|
|
690
|
+
if (!data.id)
|
|
691
|
+
data.id = createTempRecordId(tableName);
|
|
689
692
|
return { value: data };
|
|
690
693
|
},
|
|
691
694
|
types: void 0
|
|
@@ -940,7 +943,9 @@ function modernSurrealCollectionOptions(config) {
|
|
|
940
943
|
const ensureBaseLive = async () => {
|
|
941
944
|
if (cleanupBaseLive !== NOOP) return;
|
|
942
945
|
if (!db.isFeatureSupported?.(Features.LiveQueries)) return;
|
|
943
|
-
const live = await db.live(
|
|
946
|
+
const live = await db.live(
|
|
947
|
+
tableResource
|
|
948
|
+
);
|
|
944
949
|
if (killed) {
|
|
945
950
|
await live.kill();
|
|
946
951
|
return;
|
|
@@ -950,14 +955,18 @@ function modernSurrealCollectionOptions(config) {
|
|
|
950
955
|
const row = message.value;
|
|
951
956
|
const id = toRecordKeyString(row.id);
|
|
952
957
|
const wasVisible = activeOnDemandIds.has(id);
|
|
953
|
-
if (isStrictOnDemand && !wasVisible && message.action !== "DELETE")
|
|
958
|
+
if (isStrictOnDemand && !wasVisible && message.action !== "DELETE")
|
|
959
|
+
return;
|
|
954
960
|
if (message.action === "DELETE") {
|
|
955
961
|
for (const ids of subsetIds.values()) ids.delete(id);
|
|
956
962
|
updateActiveOnDemandIds();
|
|
957
963
|
if (isStrictOnDemand && !wasVisible) return;
|
|
958
964
|
ctx.begin();
|
|
959
965
|
try {
|
|
960
|
-
ctx.write({
|
|
966
|
+
ctx.write({
|
|
967
|
+
type: "delete",
|
|
968
|
+
key: `${tableName}:${id}`
|
|
969
|
+
});
|
|
961
970
|
} finally {
|
|
962
971
|
ctx.commit();
|
|
963
972
|
}
|
|
@@ -983,7 +992,9 @@ function modernSurrealCollectionOptions(config) {
|
|
|
983
992
|
if (!crdtEnabled || !updatesTable) return;
|
|
984
993
|
if (cleanupUpdateLive !== NOOP) return;
|
|
985
994
|
if (!db.isFeatureSupported?.(Features.LiveQueries)) return;
|
|
986
|
-
const live = await db.live(
|
|
995
|
+
const live = await db.live(
|
|
996
|
+
updatesTable
|
|
997
|
+
);
|
|
987
998
|
if (killed) {
|
|
988
999
|
await live.kill();
|
|
989
1000
|
return;
|
|
@@ -1035,7 +1046,13 @@ function modernSurrealCollectionOptions(config) {
|
|
|
1035
1046
|
return;
|
|
1036
1047
|
}
|
|
1037
1048
|
for (const id of ids) {
|
|
1038
|
-
await hydrateCrdtDoc(
|
|
1049
|
+
await hydrateCrdtDoc(
|
|
1050
|
+
id,
|
|
1051
|
+
ctx.write,
|
|
1052
|
+
ctx.begin,
|
|
1053
|
+
ctx.commit,
|
|
1054
|
+
"insert"
|
|
1055
|
+
);
|
|
1039
1056
|
}
|
|
1040
1057
|
await ensureUpdateLive();
|
|
1041
1058
|
};
|
|
@@ -1083,13 +1100,19 @@ function modernSurrealCollectionOptions(config) {
|
|
|
1083
1100
|
}
|
|
1084
1101
|
if (!crdtEnabled) {
|
|
1085
1102
|
if (!isOnDemandLike) {
|
|
1086
|
-
const rows2 = await toRecordArray(
|
|
1103
|
+
const rows2 = await toRecordArray(
|
|
1104
|
+
await db.select(tableResource)
|
|
1105
|
+
);
|
|
1087
1106
|
const decoded2 = await Promise.all(
|
|
1088
|
-
rows2.map(
|
|
1107
|
+
rows2.map(
|
|
1108
|
+
(row) => decodeBaseRow(row)
|
|
1109
|
+
)
|
|
1089
1110
|
);
|
|
1090
1111
|
return decoded2;
|
|
1091
1112
|
}
|
|
1092
|
-
const rows = await tableAccess.loadSubset(
|
|
1113
|
+
const rows = await tableAccess.loadSubset(
|
|
1114
|
+
meta?.loadSubsetOptions
|
|
1115
|
+
);
|
|
1093
1116
|
const decoded = await Promise.all(
|
|
1094
1117
|
rows.map(
|
|
1095
1118
|
(row) => decodeBaseRow(row)
|
|
@@ -1175,7 +1198,9 @@ function modernSurrealCollectionOptions(config) {
|
|
|
1175
1198
|
const writeUtils = getWriteUtils(params.collection.utils);
|
|
1176
1199
|
for (const mutation of params.transaction.mutations) {
|
|
1177
1200
|
if (mutation.type !== "update") continue;
|
|
1178
|
-
const mutationId = normalizeMutationId(
|
|
1201
|
+
const mutationId = normalizeMutationId(
|
|
1202
|
+
mutation.key
|
|
1203
|
+
);
|
|
1179
1204
|
const normalizedModified = omitUndefined(
|
|
1180
1205
|
normalizeRecordIdLikeFields({
|
|
1181
1206
|
...mutation.modified
|
|
@@ -1207,7 +1232,9 @@ function modernSurrealCollectionOptions(config) {
|
|
|
1207
1232
|
toRecordKeyString(mutationId)
|
|
1208
1233
|
);
|
|
1209
1234
|
await db.update(mutationId).merge(encoded);
|
|
1210
|
-
writeUtils.writeUpsert?.(
|
|
1235
|
+
writeUtils.writeUpsert?.(
|
|
1236
|
+
normalizeRow({ ...decodedCurrent, ...merged })
|
|
1237
|
+
);
|
|
1211
1238
|
continue;
|
|
1212
1239
|
}
|
|
1213
1240
|
const id = toRecordKeyString(mutationId);
|
|
@@ -1230,7 +1257,9 @@ function modernSurrealCollectionOptions(config) {
|
|
|
1230
1257
|
const writeUtils = getWriteUtils(params.collection.utils);
|
|
1231
1258
|
for (const mutation of params.transaction.mutations) {
|
|
1232
1259
|
if (mutation.type !== "delete") continue;
|
|
1233
|
-
const mutationId = normalizeMutationId(
|
|
1260
|
+
const mutationId = normalizeMutationId(
|
|
1261
|
+
mutation.key
|
|
1262
|
+
);
|
|
1234
1263
|
const id = toRecordKeyString(mutationId);
|
|
1235
1264
|
if (!crdtEnabled) {
|
|
1236
1265
|
await db.delete(mutationId);
|
|
@@ -1257,14 +1286,22 @@ function modernSurrealCollectionOptions(config) {
|
|
|
1257
1286
|
const canRunBaseSync = typeof ctx.collection?.on === "function";
|
|
1258
1287
|
const baseResult = canRunBaseSync ? baseSync(ctx) : void 0;
|
|
1259
1288
|
const baseCleanup = typeof baseResult === "function" ? baseResult : typeof baseResult === "object" && baseResult && "cleanup" in baseResult && typeof baseResult.cleanup === "function" ? baseResult.cleanup : NOOP;
|
|
1260
|
-
const runtime = createSyncRuntime(
|
|
1289
|
+
const runtime = createSyncRuntime(
|
|
1290
|
+
ctx
|
|
1291
|
+
);
|
|
1261
1292
|
const start = async () => {
|
|
1262
1293
|
if (!isOnDemandLike) {
|
|
1263
1294
|
if (!crdtEnabled) {
|
|
1264
1295
|
const rows = toRecordArray(
|
|
1265
1296
|
await db.select(tableResource)
|
|
1266
1297
|
);
|
|
1267
|
-
await hydratePlainRows(
|
|
1298
|
+
await hydratePlainRows(
|
|
1299
|
+
rows,
|
|
1300
|
+
ctx.write,
|
|
1301
|
+
ctx.begin,
|
|
1302
|
+
ctx.commit,
|
|
1303
|
+
"insert"
|
|
1304
|
+
);
|
|
1268
1305
|
await runtime.startRealtime();
|
|
1269
1306
|
ctx.markReady();
|
|
1270
1307
|
return;
|
|
@@ -1278,7 +1315,10 @@ function modernSurrealCollectionOptions(config) {
|
|
|
1278
1315
|
for (const update of updates) {
|
|
1279
1316
|
const id = idFromDocRef(update.doc);
|
|
1280
1317
|
const doc = getDoc(id);
|
|
1281
|
-
const bytes = await decodeUpdateBytes(
|
|
1318
|
+
const bytes = await decodeUpdateBytes(
|
|
1319
|
+
update,
|
|
1320
|
+
"update"
|
|
1321
|
+
);
|
|
1282
1322
|
if (!bytes.byteLength) continue;
|
|
1283
1323
|
doc.import(bytes);
|
|
1284
1324
|
}
|
|
@@ -1287,7 +1327,9 @@ function modernSurrealCollectionOptions(config) {
|
|
|
1287
1327
|
for (const [id, doc] of docs.entries()) {
|
|
1288
1328
|
ctx.write({
|
|
1289
1329
|
type: "insert",
|
|
1290
|
-
value: normalizeRow(
|
|
1330
|
+
value: normalizeRow(
|
|
1331
|
+
materializeCrdt(doc, id)
|
|
1332
|
+
)
|
|
1291
1333
|
});
|
|
1292
1334
|
}
|
|
1293
1335
|
} finally {
|