@foretag/tanstack-db-surrealdb 0.1.0 → 0.1.2
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 +3 -4
- package/dist/index.d.mts +10 -9
- package/dist/index.d.ts +10 -9
- package/dist/index.js +24 -26
- package/dist/index.mjs +24 -26
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -51,13 +51,12 @@ type Product = {
|
|
|
51
51
|
|
|
52
52
|
export const products = createCollection(
|
|
53
53
|
surrealCollection<Product>({
|
|
54
|
-
|
|
54
|
+
db,
|
|
55
55
|
useLoro: true, // Optional if you need CRDTs
|
|
56
|
-
getKey: (collection) => collection.id,
|
|
57
56
|
table: {
|
|
58
|
-
db,
|
|
59
57
|
name: 'products',
|
|
60
|
-
where: expr(eq('store', '123'))
|
|
58
|
+
where: expr(eq('store', '123')),
|
|
59
|
+
fields: ['name', 'price'] // Optional or defaults to *
|
|
61
60
|
},
|
|
62
61
|
});
|
|
63
62
|
)
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CollectionConfig } from '@tanstack/db';
|
|
1
|
+
import { CollectionConfig, UtilsRecord } from '@tanstack/db';
|
|
2
2
|
import { Container } from 'loro-crdt';
|
|
3
3
|
import { Surreal, Expr } from 'surrealdb';
|
|
4
4
|
|
|
@@ -6,25 +6,26 @@ type Id = string;
|
|
|
6
6
|
type SurrealObject<T> = T & {
|
|
7
7
|
id: Id;
|
|
8
8
|
};
|
|
9
|
+
type SurrealField<I> = keyof I;
|
|
9
10
|
type SyncedRow = SurrealObject<{
|
|
10
|
-
sync_deleted
|
|
11
|
-
updated_at
|
|
11
|
+
sync_deleted?: boolean;
|
|
12
|
+
updated_at?: Date;
|
|
12
13
|
}>;
|
|
13
|
-
type TableOptions = {
|
|
14
|
-
db: Surreal;
|
|
14
|
+
type TableOptions<T> = {
|
|
15
15
|
name: string;
|
|
16
16
|
where?: Expr;
|
|
17
|
+
fields?: SurrealField<T>[];
|
|
17
18
|
};
|
|
18
|
-
type SurrealCollectionConfig<T extends
|
|
19
|
+
type SurrealCollectionConfig<T extends SurrealObject<object>> = {
|
|
19
20
|
id?: string;
|
|
20
|
-
|
|
21
|
-
table: TableOptions
|
|
21
|
+
db: Surreal;
|
|
22
|
+
table: TableOptions<T>;
|
|
22
23
|
useLoro?: boolean;
|
|
23
24
|
onError?: (e: unknown) => void;
|
|
24
25
|
};
|
|
25
26
|
|
|
26
27
|
declare function surrealCollectionOptions<T extends SyncedRow, S extends Record<string, Container> = {
|
|
27
28
|
[k: string]: never;
|
|
28
|
-
}>({ id,
|
|
29
|
+
}>({ id, useLoro, onError, db, ...config }: SurrealCollectionConfig<T>): CollectionConfig<T, Id, never, UtilsRecord>;
|
|
29
30
|
|
|
30
31
|
export { surrealCollectionOptions };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CollectionConfig } from '@tanstack/db';
|
|
1
|
+
import { CollectionConfig, UtilsRecord } from '@tanstack/db';
|
|
2
2
|
import { Container } from 'loro-crdt';
|
|
3
3
|
import { Surreal, Expr } from 'surrealdb';
|
|
4
4
|
|
|
@@ -6,25 +6,26 @@ type Id = string;
|
|
|
6
6
|
type SurrealObject<T> = T & {
|
|
7
7
|
id: Id;
|
|
8
8
|
};
|
|
9
|
+
type SurrealField<I> = keyof I;
|
|
9
10
|
type SyncedRow = SurrealObject<{
|
|
10
|
-
sync_deleted
|
|
11
|
-
updated_at
|
|
11
|
+
sync_deleted?: boolean;
|
|
12
|
+
updated_at?: Date;
|
|
12
13
|
}>;
|
|
13
|
-
type TableOptions = {
|
|
14
|
-
db: Surreal;
|
|
14
|
+
type TableOptions<T> = {
|
|
15
15
|
name: string;
|
|
16
16
|
where?: Expr;
|
|
17
|
+
fields?: SurrealField<T>[];
|
|
17
18
|
};
|
|
18
|
-
type SurrealCollectionConfig<T extends
|
|
19
|
+
type SurrealCollectionConfig<T extends SurrealObject<object>> = {
|
|
19
20
|
id?: string;
|
|
20
|
-
|
|
21
|
-
table: TableOptions
|
|
21
|
+
db: Surreal;
|
|
22
|
+
table: TableOptions<T>;
|
|
22
23
|
useLoro?: boolean;
|
|
23
24
|
onError?: (e: unknown) => void;
|
|
24
25
|
};
|
|
25
26
|
|
|
26
27
|
declare function surrealCollectionOptions<T extends SyncedRow, S extends Record<string, Container> = {
|
|
27
28
|
[k: string]: never;
|
|
28
|
-
}>({ id,
|
|
29
|
+
}>({ id, useLoro, onError, db, ...config }: SurrealCollectionConfig<T>): CollectionConfig<T, Id, never, UtilsRecord>;
|
|
29
30
|
|
|
30
31
|
export { surrealCollectionOptions };
|
package/dist/index.js
CHANGED
|
@@ -27,20 +27,13 @@ var import_surrealdb2 = require("surrealdb");
|
|
|
27
27
|
|
|
28
28
|
// src/table.ts
|
|
29
29
|
var import_surrealdb = require("surrealdb");
|
|
30
|
-
function manageTable({
|
|
31
|
-
|
|
32
|
-
name,
|
|
33
|
-
where
|
|
34
|
-
}) {
|
|
30
|
+
function manageTable(db, { name, ...args }) {
|
|
31
|
+
const fields = args.fields?.join(", ") ?? "*";
|
|
35
32
|
const listAll = async () => {
|
|
36
|
-
|
|
37
|
-
const res = await db.select(new import_surrealdb.Table(name)) ?? [];
|
|
38
|
-
return Array.isArray(res) ? res : [res];
|
|
39
|
-
}
|
|
40
|
-
return await db.select(new import_surrealdb.Table(name)).where(where);
|
|
33
|
+
return await db.select(new import_surrealdb.Table(name)).where(args.where).fields(fields);
|
|
41
34
|
};
|
|
42
35
|
const listActive = async () => {
|
|
43
|
-
return await db.select(new import_surrealdb.Table(name)).where((0, import_surrealdb.and)(where, (0, import_surrealdb.eq)("sync_deleted", false)));
|
|
36
|
+
return await db.select(new import_surrealdb.Table(name)).where((0, import_surrealdb.and)(args.where, (0, import_surrealdb.eq)("sync_deleted", false))).fields(fields);
|
|
44
37
|
};
|
|
45
38
|
const upsert = async (id, data) => {
|
|
46
39
|
await db.upsert(id).merge({
|
|
@@ -70,7 +63,7 @@ function manageTable({
|
|
|
70
63
|
cb({ type: "delete", row: { id: value.id } });
|
|
71
64
|
};
|
|
72
65
|
const start = async () => {
|
|
73
|
-
if (!where) {
|
|
66
|
+
if (!args.where) {
|
|
74
67
|
live = await db.live(new import_surrealdb.Table(name));
|
|
75
68
|
live.subscribe(on);
|
|
76
69
|
} else {
|
|
@@ -80,7 +73,7 @@ function manageTable({
|
|
|
80
73
|
}
|
|
81
74
|
};
|
|
82
75
|
const [id] = await db.query(
|
|
83
|
-
`LIVE SELECT * FROM ${name} WHERE ${where.toSQL(ctx)}`
|
|
76
|
+
`LIVE SELECT * FROM ${name} WHERE ${args.where.toSQL(ctx)}`
|
|
84
77
|
).collect();
|
|
85
78
|
live = await db.liveOf(new import_surrealdb.Uuid(id));
|
|
86
79
|
live.subscribe(on);
|
|
@@ -106,33 +99,30 @@ function manageTable({
|
|
|
106
99
|
// src/index.ts
|
|
107
100
|
function surrealCollectionOptions({
|
|
108
101
|
id,
|
|
109
|
-
getKey,
|
|
110
102
|
useLoro = false,
|
|
111
103
|
onError,
|
|
104
|
+
db,
|
|
112
105
|
...config
|
|
113
106
|
}) {
|
|
114
|
-
var _a, _b;
|
|
115
107
|
let loro;
|
|
116
108
|
if (useLoro) loro = { doc: new import_loro_crdt.LoroDoc(), key: id };
|
|
117
|
-
const
|
|
118
|
-
const
|
|
109
|
+
const getKey = (row) => row.id;
|
|
110
|
+
const loroKey = loro?.key ?? id ?? "surreal";
|
|
111
|
+
const loroMap = useLoro ? loro?.doc?.getMap?.(loroKey) ?? null : null;
|
|
119
112
|
const loroToArray = () => {
|
|
120
|
-
var _a2;
|
|
121
113
|
if (!loroMap) return [];
|
|
122
|
-
const json =
|
|
114
|
+
const json = loroMap.toJSON?.() ?? {};
|
|
123
115
|
return Object.values(json);
|
|
124
116
|
};
|
|
125
117
|
const loroPut = (row) => {
|
|
126
|
-
var _a2, _b2;
|
|
127
118
|
if (!loroMap) return;
|
|
128
119
|
loroMap.set(String(getKey(row)), row);
|
|
129
|
-
|
|
120
|
+
loro?.doc?.commit?.();
|
|
130
121
|
};
|
|
131
122
|
const loroRemove = (id2) => {
|
|
132
|
-
var _a2, _b2;
|
|
133
123
|
if (!loroMap) return;
|
|
134
124
|
loroMap.delete(String(id2));
|
|
135
|
-
|
|
125
|
+
loro?.doc?.commit?.();
|
|
136
126
|
};
|
|
137
127
|
const flushPushQueue = async () => {
|
|
138
128
|
const ops = pushQueue.splice(0, pushQueue.length);
|
|
@@ -148,7 +138,7 @@ function surrealCollectionOptions({
|
|
|
148
138
|
};
|
|
149
139
|
const pushQueue = [];
|
|
150
140
|
const enqueuePush = (op) => pushQueue.push(op);
|
|
151
|
-
const newer = (a, b) => (
|
|
141
|
+
const newer = (a, b) => (a?.getTime() ?? -1) > (b?.getTime() ?? -1);
|
|
152
142
|
const reconcileBoot = (serverRows, write) => {
|
|
153
143
|
const localRows = useLoro ? loroToArray() : [];
|
|
154
144
|
const serverById = new Map(
|
|
@@ -244,7 +234,7 @@ function surrealCollectionOptions({
|
|
|
244
234
|
}
|
|
245
235
|
prevById = currById;
|
|
246
236
|
};
|
|
247
|
-
const table = manageTable(config.table);
|
|
237
|
+
const table = manageTable(db, config.table);
|
|
248
238
|
const sync = ({
|
|
249
239
|
begin,
|
|
250
240
|
write,
|
|
@@ -293,7 +283,7 @@ function surrealCollectionOptions({
|
|
|
293
283
|
}
|
|
294
284
|
});
|
|
295
285
|
} catch (e) {
|
|
296
|
-
onError
|
|
286
|
+
onError?.(e);
|
|
297
287
|
markReady();
|
|
298
288
|
}
|
|
299
289
|
};
|
|
@@ -304,6 +294,7 @@ function surrealCollectionOptions({
|
|
|
304
294
|
};
|
|
305
295
|
const now = () => Date.now();
|
|
306
296
|
const onInsert = async (p) => {
|
|
297
|
+
const resultRows = [];
|
|
307
298
|
for (const m of p.transaction.mutations) {
|
|
308
299
|
if (m.type !== "insert") continue;
|
|
309
300
|
const row = {
|
|
@@ -314,9 +305,12 @@ function surrealCollectionOptions({
|
|
|
314
305
|
if (useLoro) loroPut(row);
|
|
315
306
|
const rid = new import_surrealdb2.RecordId(config.table.name, row.id);
|
|
316
307
|
await table.upsert(rid, row);
|
|
308
|
+
resultRows.push(row);
|
|
317
309
|
}
|
|
310
|
+
return resultRows;
|
|
318
311
|
};
|
|
319
312
|
const onUpdate = async (p) => {
|
|
313
|
+
const resultRows = [];
|
|
320
314
|
for (const m of p.transaction.mutations) {
|
|
321
315
|
if (m.type !== "update") continue;
|
|
322
316
|
const id2 = m.key;
|
|
@@ -324,15 +318,19 @@ function surrealCollectionOptions({
|
|
|
324
318
|
if (useLoro) loroPut(merged);
|
|
325
319
|
const rid = new import_surrealdb2.RecordId(config.table.name, id2);
|
|
326
320
|
await table.upsert(rid, merged);
|
|
321
|
+
resultRows.push(merged);
|
|
327
322
|
}
|
|
323
|
+
return resultRows;
|
|
328
324
|
};
|
|
329
325
|
const onDelete = async (p) => {
|
|
326
|
+
const resultRows = [];
|
|
330
327
|
for (const m of p.transaction.mutations) {
|
|
331
328
|
if (m.type !== "delete") continue;
|
|
332
329
|
const id2 = m.key;
|
|
333
330
|
if (useLoro) loroRemove(id2);
|
|
334
331
|
await table.softDelete(new import_surrealdb2.RecordId(config.table.name, id2));
|
|
335
332
|
}
|
|
333
|
+
return resultRows;
|
|
336
334
|
};
|
|
337
335
|
return {
|
|
338
336
|
id,
|
package/dist/index.mjs
CHANGED
|
@@ -9,20 +9,13 @@ import {
|
|
|
9
9
|
Table,
|
|
10
10
|
Uuid
|
|
11
11
|
} from "surrealdb";
|
|
12
|
-
function manageTable({
|
|
13
|
-
|
|
14
|
-
name,
|
|
15
|
-
where
|
|
16
|
-
}) {
|
|
12
|
+
function manageTable(db, { name, ...args }) {
|
|
13
|
+
const fields = args.fields?.join(", ") ?? "*";
|
|
17
14
|
const listAll = async () => {
|
|
18
|
-
|
|
19
|
-
const res = await db.select(new Table(name)) ?? [];
|
|
20
|
-
return Array.isArray(res) ? res : [res];
|
|
21
|
-
}
|
|
22
|
-
return await db.select(new Table(name)).where(where);
|
|
15
|
+
return await db.select(new Table(name)).where(args.where).fields(fields);
|
|
23
16
|
};
|
|
24
17
|
const listActive = async () => {
|
|
25
|
-
return await db.select(new Table(name)).where(and(where, eq("sync_deleted", false)));
|
|
18
|
+
return await db.select(new Table(name)).where(and(args.where, eq("sync_deleted", false))).fields(fields);
|
|
26
19
|
};
|
|
27
20
|
const upsert = async (id, data) => {
|
|
28
21
|
await db.upsert(id).merge({
|
|
@@ -52,7 +45,7 @@ function manageTable({
|
|
|
52
45
|
cb({ type: "delete", row: { id: value.id } });
|
|
53
46
|
};
|
|
54
47
|
const start = async () => {
|
|
55
|
-
if (!where) {
|
|
48
|
+
if (!args.where) {
|
|
56
49
|
live = await db.live(new Table(name));
|
|
57
50
|
live.subscribe(on);
|
|
58
51
|
} else {
|
|
@@ -62,7 +55,7 @@ function manageTable({
|
|
|
62
55
|
}
|
|
63
56
|
};
|
|
64
57
|
const [id] = await db.query(
|
|
65
|
-
`LIVE SELECT * FROM ${name} WHERE ${where.toSQL(ctx)}`
|
|
58
|
+
`LIVE SELECT * FROM ${name} WHERE ${args.where.toSQL(ctx)}`
|
|
66
59
|
).collect();
|
|
67
60
|
live = await db.liveOf(new Uuid(id));
|
|
68
61
|
live.subscribe(on);
|
|
@@ -88,33 +81,30 @@ function manageTable({
|
|
|
88
81
|
// src/index.ts
|
|
89
82
|
function surrealCollectionOptions({
|
|
90
83
|
id,
|
|
91
|
-
getKey,
|
|
92
84
|
useLoro = false,
|
|
93
85
|
onError,
|
|
86
|
+
db,
|
|
94
87
|
...config
|
|
95
88
|
}) {
|
|
96
|
-
var _a, _b;
|
|
97
89
|
let loro;
|
|
98
90
|
if (useLoro) loro = { doc: new LoroDoc(), key: id };
|
|
99
|
-
const
|
|
100
|
-
const
|
|
91
|
+
const getKey = (row) => row.id;
|
|
92
|
+
const loroKey = loro?.key ?? id ?? "surreal";
|
|
93
|
+
const loroMap = useLoro ? loro?.doc?.getMap?.(loroKey) ?? null : null;
|
|
101
94
|
const loroToArray = () => {
|
|
102
|
-
var _a2;
|
|
103
95
|
if (!loroMap) return [];
|
|
104
|
-
const json =
|
|
96
|
+
const json = loroMap.toJSON?.() ?? {};
|
|
105
97
|
return Object.values(json);
|
|
106
98
|
};
|
|
107
99
|
const loroPut = (row) => {
|
|
108
|
-
var _a2, _b2;
|
|
109
100
|
if (!loroMap) return;
|
|
110
101
|
loroMap.set(String(getKey(row)), row);
|
|
111
|
-
|
|
102
|
+
loro?.doc?.commit?.();
|
|
112
103
|
};
|
|
113
104
|
const loroRemove = (id2) => {
|
|
114
|
-
var _a2, _b2;
|
|
115
105
|
if (!loroMap) return;
|
|
116
106
|
loroMap.delete(String(id2));
|
|
117
|
-
|
|
107
|
+
loro?.doc?.commit?.();
|
|
118
108
|
};
|
|
119
109
|
const flushPushQueue = async () => {
|
|
120
110
|
const ops = pushQueue.splice(0, pushQueue.length);
|
|
@@ -130,7 +120,7 @@ function surrealCollectionOptions({
|
|
|
130
120
|
};
|
|
131
121
|
const pushQueue = [];
|
|
132
122
|
const enqueuePush = (op) => pushQueue.push(op);
|
|
133
|
-
const newer = (a, b) => (
|
|
123
|
+
const newer = (a, b) => (a?.getTime() ?? -1) > (b?.getTime() ?? -1);
|
|
134
124
|
const reconcileBoot = (serverRows, write) => {
|
|
135
125
|
const localRows = useLoro ? loroToArray() : [];
|
|
136
126
|
const serverById = new Map(
|
|
@@ -226,7 +216,7 @@ function surrealCollectionOptions({
|
|
|
226
216
|
}
|
|
227
217
|
prevById = currById;
|
|
228
218
|
};
|
|
229
|
-
const table = manageTable(config.table);
|
|
219
|
+
const table = manageTable(db, config.table);
|
|
230
220
|
const sync = ({
|
|
231
221
|
begin,
|
|
232
222
|
write,
|
|
@@ -275,7 +265,7 @@ function surrealCollectionOptions({
|
|
|
275
265
|
}
|
|
276
266
|
});
|
|
277
267
|
} catch (e) {
|
|
278
|
-
onError
|
|
268
|
+
onError?.(e);
|
|
279
269
|
markReady();
|
|
280
270
|
}
|
|
281
271
|
};
|
|
@@ -286,6 +276,7 @@ function surrealCollectionOptions({
|
|
|
286
276
|
};
|
|
287
277
|
const now = () => Date.now();
|
|
288
278
|
const onInsert = async (p) => {
|
|
279
|
+
const resultRows = [];
|
|
289
280
|
for (const m of p.transaction.mutations) {
|
|
290
281
|
if (m.type !== "insert") continue;
|
|
291
282
|
const row = {
|
|
@@ -296,9 +287,12 @@ function surrealCollectionOptions({
|
|
|
296
287
|
if (useLoro) loroPut(row);
|
|
297
288
|
const rid = new RecordId(config.table.name, row.id);
|
|
298
289
|
await table.upsert(rid, row);
|
|
290
|
+
resultRows.push(row);
|
|
299
291
|
}
|
|
292
|
+
return resultRows;
|
|
300
293
|
};
|
|
301
294
|
const onUpdate = async (p) => {
|
|
295
|
+
const resultRows = [];
|
|
302
296
|
for (const m of p.transaction.mutations) {
|
|
303
297
|
if (m.type !== "update") continue;
|
|
304
298
|
const id2 = m.key;
|
|
@@ -306,15 +300,19 @@ function surrealCollectionOptions({
|
|
|
306
300
|
if (useLoro) loroPut(merged);
|
|
307
301
|
const rid = new RecordId(config.table.name, id2);
|
|
308
302
|
await table.upsert(rid, merged);
|
|
303
|
+
resultRows.push(merged);
|
|
309
304
|
}
|
|
305
|
+
return resultRows;
|
|
310
306
|
};
|
|
311
307
|
const onDelete = async (p) => {
|
|
308
|
+
const resultRows = [];
|
|
312
309
|
for (const m of p.transaction.mutations) {
|
|
313
310
|
if (m.type !== "delete") continue;
|
|
314
311
|
const id2 = m.key;
|
|
315
312
|
if (useLoro) loroRemove(id2);
|
|
316
313
|
await table.softDelete(new RecordId(config.table.name, id2));
|
|
317
314
|
}
|
|
315
|
+
return resultRows;
|
|
318
316
|
};
|
|
319
317
|
return {
|
|
320
318
|
id,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@foretag/tanstack-db-surrealdb",
|
|
3
3
|
"description": "Add Offline / Local First Caching & Syncing to your SurrealDB app with TanstackDB and Loro (CRDTs)",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.2",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist"
|
|
7
7
|
],
|
|
@@ -40,13 +40,13 @@
|
|
|
40
40
|
"build": "tsup src/index.ts --dts --format esm,cjs"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@tanstack/db": "^0.4.
|
|
44
|
-
"loro-crdt": "^1.8.
|
|
45
|
-
"surrealdb": "2.0.0-alpha.
|
|
43
|
+
"@tanstack/db": "^0.4.10",
|
|
44
|
+
"loro-crdt": "^1.8.4",
|
|
45
|
+
"surrealdb": "2.0.0-alpha.9"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"@biomejs/biome": "^2.2.
|
|
49
|
-
"
|
|
48
|
+
"@biomejs/biome": "^2.2.6",
|
|
49
|
+
"@tanstack/svelte-db": "^0.1.32",
|
|
50
50
|
"tsup": "^8.5.0"
|
|
51
51
|
}
|
|
52
52
|
}
|