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