@foretag/tanstack-db-surrealdb 0.3.0 → 0.3.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/dist/index.mjs CHANGED
@@ -1,109 +1,50 @@
1
- // src/index.ts
2
- import { LoroDoc } from "loro-crdt";
3
- import { Features as Features2, RecordId } from "surrealdb";
1
+ import { queryCollectionOptions } from '@tanstack/query-db-collection';
2
+ import { LoroDoc } from 'loro-crdt';
3
+ import { RecordId, Features, Table, and, eq } from 'surrealdb';
4
4
 
5
- // src/table.ts
6
- import {
7
- and,
8
- eq,
9
- Features,
10
- Table
11
- } from "surrealdb";
12
- function manageTable(db, useLoro, { name, ...args }, syncMode = "eager") {
13
- const rawFields = args.fields ?? "*";
14
- const fields = rawFields === "*" ? ["*"] : [...rawFields];
15
- const cache = /* @__PURE__ */ new Map();
16
- let fullyLoaded = false;
17
- const pageSize = args.pageSize ?? 100;
18
- const initialPageSize = args.initialPageSize ?? Math.min(50, pageSize);
19
- let cursor = 0;
20
- let progressiveTask = null;
21
- const idKey = (id) => typeof id === "string" ? id : id.toString();
22
- const upsertCache = (rows) => {
23
- for (const row of rows) cache.set(idKey(row.id), row);
24
- };
25
- const removeFromCache = (id) => {
26
- cache.delete(idKey(id));
27
- };
28
- const listCached = () => Array.from(cache.values());
29
- const buildWhere = () => {
5
+ // src/index.ts
6
+ var normalizeFields = (raw) => {
7
+ if (!raw || raw === "*") return ["*"];
8
+ return raw;
9
+ };
10
+ var joinOrderBy = (o) => {
11
+ if (!o) return void 0;
12
+ return typeof o === "string" ? o : o.join(", ");
13
+ };
14
+ function manageTable(db, useLoro, { name, ...args }) {
15
+ const fields = normalizeFields(args.fields);
16
+ const baseWhere = () => {
30
17
  if (!useLoro) return args.where;
31
- return args.where ? and(args.where, eq("sync_deleted", false)) : eq("sync_deleted", false);
32
- };
33
- const buildQuery = () => {
34
- let q = db.select(new Table(name));
35
- const cond = buildWhere();
36
- if (cond) q = q.where(cond);
37
- return q;
38
- };
39
- const applyPaging = (q, start, limit) => {
40
- if (typeof start === "number" && q.start) q = q.start(start);
41
- if (typeof limit === "number" && q.limit) q = q.limit(limit);
42
- return q;
43
- };
44
- const fetchAll = async () => {
45
- const rows = await buildQuery().fields(...fields);
46
- upsertCache(rows);
47
- fullyLoaded = true;
48
- return rows;
49
- };
50
- const fetchPage = async (opts) => {
51
- const q = applyPaging(
52
- buildQuery(),
53
- opts?.start ?? 0,
54
- opts?.limit ?? pageSize
55
- );
56
- const rows = await q.fields(...fields);
57
- upsertCache(rows);
58
- if (rows.length < (opts?.limit ?? pageSize)) fullyLoaded = true;
59
- return rows;
60
- };
61
- const fetchById = async (id) => {
62
- const key = idKey(id);
63
- const cached = cache.get(key);
64
- if (cached) return cached;
65
- const res = await db.select(id);
66
- const row = Array.isArray(res) ? res[0] : res;
67
- if (!row) return null;
68
- if (useLoro && row.sync_deleted)
69
- return null;
70
- cache.set(key, row);
71
- return row;
72
- };
73
- const loadMore = async (limit = pageSize) => {
74
- if (fullyLoaded) return { rows: [], done: true };
75
- const rows = await fetchPage({ start: cursor, limit });
76
- cursor += rows.length;
77
- const done = fullyLoaded || rows.length < limit;
78
- args.onProgress?.({
18
+ const alive = eq("sync_deleted", false);
19
+ return args.where ? and(args.where, alive) : alive;
20
+ };
21
+ const listAll = async () => {
22
+ const where = baseWhere();
23
+ const whereSql = where ? " WHERE $where" : "";
24
+ const sql = `SELECT ${fields.join(", ")} FROM type::table($table)${whereSql};`;
25
+ const [res] = await db.query(sql, {
79
26
  table: name,
80
- loaded: cache.size,
81
- lastBatch: rows.length,
82
- done
27
+ where
83
28
  });
84
- return { rows, done };
85
- };
86
- const startProgressive = () => {
87
- if (progressiveTask || fullyLoaded) return;
88
- progressiveTask = (async () => {
89
- if (cache.size === 0) await loadMore(initialPageSize);
90
- while (!fullyLoaded) {
91
- const { done } = await loadMore(pageSize);
92
- if (done) break;
93
- }
94
- })().finally(() => {
95
- progressiveTask = null;
29
+ return res ?? [];
30
+ };
31
+ const loadSubset = async (subset) => {
32
+ const b = baseWhere();
33
+ const w = subset?.where;
34
+ const where = b && w ? and(b, w) : b ?? w;
35
+ const whereSql = where ? " WHERE $where" : "";
36
+ const order = joinOrderBy(subset?.orderBy);
37
+ const orderSql = order ? ` ORDER BY ${order}` : "";
38
+ const limitSql = typeof subset?.limit === "number" ? " LIMIT $limit" : "";
39
+ const startSql = typeof subset?.offset === "number" ? " START $offset" : "";
40
+ const sql = `SELECT ${fields.join(", ")} FROM type::table($table)${whereSql}${orderSql}${limitSql}${startSql};`;
41
+ const [res] = await db.query(sql, {
42
+ table: name,
43
+ where,
44
+ limit: subset?.limit,
45
+ offset: subset?.offset
96
46
  });
97
- };
98
- const listAll = () => fetchAll();
99
- const listActive = async () => {
100
- if (syncMode === "eager") return fetchAll();
101
- if (syncMode === "progressive") {
102
- if (cache.size === 0) await loadMore(initialPageSize);
103
- startProgressive();
104
- return listCached();
105
- }
106
- return listCached();
47
+ return res ?? [];
107
48
  };
108
49
  const create = async (data) => {
109
50
  await db.create(new Table(name)).content(data);
@@ -116,24 +57,21 @@ function manageTable(db, useLoro, { name, ...args }, syncMode = "eager") {
116
57
  await db.update(id).merge({
117
58
  ...data,
118
59
  sync_deleted: false,
119
- updated_at: /* @__PURE__ */ new Date()
60
+ updated_at: Date.now()
120
61
  });
121
62
  };
122
63
  const remove = async (id) => {
123
64
  await db.delete(id);
124
- removeFromCache(id);
125
65
  };
126
66
  const softDelete = async (id) => {
127
67
  if (!useLoro) {
128
68
  await db.delete(id);
129
- removeFromCache(id);
130
69
  return;
131
70
  }
132
71
  await db.upsert(id).merge({
133
72
  sync_deleted: true,
134
- updated_at: /* @__PURE__ */ new Date()
73
+ updated_at: Date.now()
135
74
  });
136
- removeFromCache(id);
137
75
  };
138
76
  const subscribe = (cb) => {
139
77
  let killed = false;
@@ -141,25 +79,10 @@ function manageTable(db, useLoro, { name, ...args }, syncMode = "eager") {
141
79
  const on = (msg) => {
142
80
  const { action, value } = msg;
143
81
  if (action === "KILLED") return;
144
- if (action === "CREATE") {
145
- upsertCache([value]);
146
- cb({ type: "insert", row: value });
147
- return;
148
- }
149
- if (action === "UPDATE") {
150
- if (useLoro && value.sync_deleted) {
151
- removeFromCache(value.id);
152
- cb({ type: "delete", row: { id: value.id } });
153
- return;
154
- }
155
- upsertCache([value]);
156
- cb({ type: "update", row: value });
157
- return;
158
- }
159
- if (action === "DELETE") {
160
- removeFromCache(value.id);
82
+ if (action === "CREATE") cb({ type: "insert", row: value });
83
+ else if (action === "UPDATE") cb({ type: "update", row: value });
84
+ else if (action === "DELETE")
161
85
  cb({ type: "delete", row: { id: value.id } });
162
- }
163
86
  };
164
87
  const start = async () => {
165
88
  if (!db.isFeatureSupported(Features.LiveQueries)) return;
@@ -175,382 +98,169 @@ function manageTable(db, useLoro, { name, ...args }, syncMode = "eager") {
175
98
  };
176
99
  return {
177
100
  listAll,
178
- listActive,
179
- listCached,
180
- fetchPage,
181
- fetchById,
182
- loadMore,
101
+ loadSubset,
183
102
  create,
184
103
  update,
185
104
  remove,
186
105
  softDelete,
187
- subscribe,
188
- get isFullyLoaded() {
189
- return fullyLoaded;
190
- },
191
- get cachedCount() {
192
- return cache.size;
193
- }
106
+ subscribe
194
107
  };
195
108
  }
196
109
 
197
110
  // src/index.ts
198
- var DEFAULT_INITIAL_PAGE_SIZE = 50;
199
- var LOCAL_ID_VERIFY_CHUNK = 500;
200
- var stableStringify = (value) => {
201
- const toJson = (v) => {
202
- if (v === null) return null;
203
- if (typeof v === "string" || typeof v === "number" || typeof v === "boolean")
204
- return v;
205
- if (v instanceof Date) return v.toISOString();
206
- if (Array.isArray(v)) return v.map(toJson);
207
- if (typeof v === "object") {
208
- const o = v;
209
- const keys = Object.keys(o).sort();
210
- const out = {};
211
- for (const k of keys) out[k] = toJson(o[k]);
212
- return out;
213
- }
214
- return String(v);
111
+ function toCleanup(res) {
112
+ if (!res) return () => {
113
+ };
114
+ if (typeof res === "function") {
115
+ return res;
116
+ }
117
+ if (typeof res === "object" && res !== null) {
118
+ const r = res;
119
+ const cleanup = r["cleanup"];
120
+ if (typeof cleanup === "function") return cleanup;
121
+ const unsubscribe = r["unsubscribe"];
122
+ if (typeof unsubscribe === "function") return unsubscribe;
123
+ const dispose = r["dispose"];
124
+ if (typeof dispose === "function") return dispose;
125
+ }
126
+ return () => {
215
127
  };
216
- return JSON.stringify(toJson(value));
217
- };
218
- var chunk = (arr, size) => {
219
- const out = [];
220
- for (let i = 0; i < arr.length; i += size) out.push(arr.slice(i, i + size));
221
- return out;
222
- };
128
+ }
223
129
  function surrealCollectionOptions({
224
130
  id,
225
131
  useLoro = false,
226
132
  onError,
227
133
  db,
228
- syncMode,
134
+ queryClient,
135
+ queryKey,
136
+ syncMode = "eager",
229
137
  ...config
230
138
  }) {
231
139
  let loro;
232
140
  if (useLoro) loro = { doc: new LoroDoc(), key: id };
141
+ const table = manageTable(db, useLoro, config.table);
233
142
  const keyOf = (rid) => typeof rid === "string" ? rid : rid.toString();
234
143
  const getKey = (row) => keyOf(row.id);
235
144
  const loroKey = loro?.key ?? id ?? "surreal";
236
145
  const loroMap = useLoro ? loro?.doc?.getMap?.(loroKey) ?? null : null;
237
- const loroToArray = () => {
238
- if (!loroMap) return [];
239
- const json = loroMap.toJSON?.() ?? {};
240
- return Object.values(json);
241
- };
242
- const loroPutMany = (rows) => {
243
- if (!loroMap || rows.length === 0) return;
244
- for (const row of rows) loroMap.set(getKey(row), row);
146
+ const loroPut = (row) => {
147
+ if (!loroMap) return;
148
+ loroMap.set(getKey(row), row);
245
149
  loro?.doc?.commit?.();
246
150
  };
247
- const loroRemoveMany = (ids) => {
248
- if (!loroMap || ids.length === 0) return;
249
- for (const id2 of ids) loroMap.delete(id2);
151
+ const loroRemove = (idStr) => {
152
+ if (!loroMap) return;
153
+ loroMap.delete(idStr);
250
154
  loro?.doc?.commit?.();
251
155
  };
252
- const loroRemove = (id2) => loroRemoveMany([id2]);
253
- const pushQueue = [];
254
- const enqueuePush = (op) => {
255
- if (!useLoro) return;
256
- pushQueue.push(op);
257
- };
258
- const flushPushQueue = async () => {
259
- if (!useLoro) return;
260
- const ops = pushQueue.splice(0, pushQueue.length);
261
- for (const op of ops) {
262
- if (op.kind === "create") {
263
- await table.create(op.row);
264
- } else if (op.kind === "update") {
265
- const rid = new RecordId(
266
- config.table.name,
267
- op.row.id.toString()
268
- );
269
- await table.update(rid, op.row);
270
- } else {
271
- const rid = new RecordId(config.table.name, op.id);
272
- await table.softDelete(rid);
273
- }
274
- }
275
- };
276
- const newer = (a, b) => (a?.getTime() ?? -1) > (b?.getTime() ?? -1);
277
- const fetchServerByLocalIds = async (ids) => {
278
- if (ids.length === 0) return [];
279
- const tableName = config.table.name;
280
- const parts = chunk(ids, LOCAL_ID_VERIFY_CHUNK);
156
+ const mergeLocalOverServer = (serverRows) => {
157
+ if (!useLoro || !loroMap) return serverRows;
158
+ const localJson = loroMap.toJSON?.() ?? {};
159
+ const localById = new Map(
160
+ Object.values(localJson).map((r) => [getKey(r), r])
161
+ );
281
162
  const out = [];
282
- for (const p of parts) {
283
- const [res] = await db.query(
284
- "SELECT * FROM type::table($table) WHERE id IN $ids",
285
- {
286
- table: tableName,
287
- ids: p.map((x) => new RecordId(tableName, x))
288
- }
289
- );
290
- if (res) out.push(...res);
291
- }
292
- return out;
293
- };
294
- const dedupeById = (rows) => {
295
- const m = /* @__PURE__ */ new Map();
296
- for (const r of rows) m.set(getKey(r), r);
297
- return Array.from(m.values());
298
- };
299
- let prevById = /* @__PURE__ */ new Map();
300
- const buildMap = (rows) => new Map(rows.map((r) => [getKey(r), r]));
301
- const same = (a, b) => {
302
- if (useLoro) {
303
- return (a.sync_deleted ?? false) === (b.sync_deleted ?? false) && (a.updated_at?.getTime() ?? 0) === (b.updated_at?.getTime() ?? 0);
304
- }
305
- return stableStringify(a) === stableStringify(b);
306
- };
307
- const diffAndEmit = (currentRows, write) => {
308
- const currById = buildMap(currentRows);
309
- for (const [id2, row] of currById) {
310
- const prev = prevById.get(id2);
311
- if (!prev) write({ type: "insert", value: row });
312
- else if (!same(prev, row)) write({ type: "update", value: row });
313
- }
314
- for (const [id2, prev] of prevById) {
315
- if (!currById.has(id2)) write({ type: "delete", value: prev });
316
- }
317
- prevById = currById;
318
- };
319
- const reconcileBoot = (serverRows, write) => {
320
- const localRows = loroToArray();
321
- const serverById = new Map(serverRows.map((r) => [getKey(r), r]));
322
- const localById = new Map(localRows.map((r) => [getKey(r), r]));
323
- const ids = /* @__PURE__ */ new Set([...serverById.keys(), ...localById.keys()]);
324
- const current = [];
325
- const toRemove = [];
326
- const toPut = [];
327
- const applyLocal = (row) => {
328
- if (!row) return;
329
- if (row.sync_deleted) toRemove.push(getKey(row));
330
- else toPut.push(row);
331
- };
332
- for (const id2 of ids) {
333
- const s = serverById.get(id2);
334
- const l = localById.get(id2);
335
- if (s && l) {
336
- const sDeleted = s.sync_deleted ?? false;
337
- const lDeleted = l.sync_deleted ?? false;
338
- const sUpdated = s.updated_at;
339
- const lUpdated = l.updated_at;
340
- if (sDeleted && lDeleted) {
341
- applyLocal(s);
342
- current.push(s);
343
- } else if (sDeleted && !lDeleted) {
344
- applyLocal(s);
345
- current.push(s);
346
- } else if (!sDeleted && lDeleted) {
347
- if (newer(lUpdated, sUpdated)) {
348
- enqueuePush({
349
- kind: "delete",
350
- id: id2,
351
- updated_at: lUpdated ?? /* @__PURE__ */ new Date()
352
- });
353
- applyLocal(l);
354
- current.push(l);
355
- } else {
356
- applyLocal(s);
357
- current.push(s);
358
- }
359
- } else {
360
- if (newer(lUpdated, sUpdated)) {
361
- enqueuePush({ kind: "update", row: l });
362
- applyLocal(l);
363
- current.push(l);
364
- } else {
365
- applyLocal(s);
366
- current.push(s);
367
- }
368
- }
369
- } else if (s && !l) {
370
- applyLocal(s);
371
- current.push(s);
372
- } else if (!s && l) {
373
- const lDeleted = l.sync_deleted ?? false;
374
- const lUpdated = l.updated_at;
375
- if (lDeleted) {
376
- enqueuePush({
377
- kind: "delete",
378
- id: id2,
379
- updated_at: lUpdated ?? /* @__PURE__ */ new Date()
380
- });
381
- applyLocal(l);
382
- current.push(l);
383
- } else {
384
- enqueuePush({ kind: "create", row: l });
385
- applyLocal(l);
386
- current.push(l);
387
- }
163
+ for (const s of serverRows) {
164
+ const idStr = getKey(s);
165
+ const l = localById.get(idStr);
166
+ if (!l) {
167
+ out.push(s);
168
+ continue;
388
169
  }
170
+ const lDeleted = (l.sync_deleted ?? false) === true;
171
+ if (lDeleted) continue;
172
+ out.push(l);
389
173
  }
390
- loroRemoveMany(toRemove);
391
- loroPutMany(toPut);
392
- diffAndEmit(current, write);
174
+ return out;
393
175
  };
394
- const table = manageTable(db, useLoro, config.table, syncMode);
395
- const now = () => /* @__PURE__ */ new Date();
396
- const sync = ({
397
- begin,
398
- write,
399
- commit,
400
- markReady
401
- }) => {
402
- if (!db.isFeatureSupported(Features2.LiveQueries)) {
403
- markReady();
404
- return () => {
405
- };
406
- }
407
- let offLive = null;
408
- let work = Promise.resolve();
409
- const enqueueWork = (fn) => {
410
- work = work.then(fn).catch((e) => onError?.(e));
411
- return work;
412
- };
413
- const makeTombstone = (id2) => ({
414
- id: new RecordId(config.table.name, id2).toString(),
415
- updated_at: now(),
416
- sync_deleted: true
417
- });
418
- const start = async () => {
176
+ const base = queryCollectionOptions({
177
+ getKey: (row) => getKey(row),
178
+ queryKey,
179
+ queryClient,
180
+ syncMode,
181
+ queryFn: async ({ meta }) => {
419
182
  try {
420
- let serverRows;
421
- if (syncMode === "eager") {
422
- serverRows = await table.listAll();
423
- } else if (syncMode === "progressive") {
424
- const first = await table.loadMore(
425
- config.table.initialPageSize ?? DEFAULT_INITIAL_PAGE_SIZE
426
- );
427
- serverRows = first.rows;
428
- } else {
429
- serverRows = await table.listActive();
430
- }
431
- await enqueueWork(async () => {
432
- begin();
433
- if (useLoro) {
434
- const localIds = loroToArray().map(getKey);
435
- const verifiedServerRows = syncMode === "eager" ? serverRows : dedupeById([
436
- ...serverRows,
437
- ...await fetchServerByLocalIds(
438
- localIds
439
- )
440
- ]);
441
- reconcileBoot(verifiedServerRows, write);
442
- } else {
443
- diffAndEmit(serverRows, write);
444
- }
445
- commit();
446
- markReady();
447
- });
448
- if (syncMode === "progressive") {
449
- void (async () => {
450
- while (!table.isFullyLoaded) {
451
- const { rows } = await table.loadMore();
452
- if (rows.length === 0) break;
453
- await enqueueWork(async () => {
454
- begin();
455
- try {
456
- if (useLoro) loroPutMany(rows);
457
- diffAndEmit(rows, write);
458
- } finally {
459
- commit();
460
- }
461
- });
462
- }
463
- })().catch((e) => onError?.(e));
464
- }
465
- await flushPushQueue();
466
- offLive = table.subscribe((evt) => {
467
- void enqueueWork(async () => {
468
- begin();
469
- try {
470
- if (evt.type === "insert" || evt.type === "update") {
471
- const row = evt.row;
472
- const deleted = useLoro ? row.sync_deleted ?? false : false;
473
- if (deleted) {
474
- if (useLoro) loroRemove(getKey(row));
475
- const prev = prevById.get(getKey(row)) ?? makeTombstone(getKey(row));
476
- write({ type: "delete", value: prev });
477
- prevById.delete(getKey(row));
478
- } else {
479
- if (useLoro) loroPutMany([row]);
480
- const had = prevById.has(getKey(row));
481
- write({
482
- type: had ? "update" : "insert",
483
- value: row
484
- });
485
- prevById.set(getKey(row), row);
486
- }
487
- } else {
488
- const rid = getKey(evt.row);
489
- if (useLoro) loroRemove(rid);
490
- const prev = prevById.get(rid) ?? makeTombstone(rid);
491
- write({ type: "delete", value: prev });
492
- prevById.delete(rid);
493
- }
494
- } finally {
495
- commit();
496
- }
497
- });
498
- });
183
+ const subset = syncMode === "on-demand" ? meta["surrealSubset"] : void 0;
184
+ const rows = syncMode === "eager" ? await table.listAll() : await table.loadSubset(subset);
185
+ return mergeLocalOverServer(rows);
499
186
  } catch (e) {
500
187
  onError?.(e);
501
- markReady();
188
+ return [];
502
189
  }
503
- };
504
- void start();
505
- return () => {
506
- if (offLive) offLive();
507
- };
508
- };
509
- const onInsert = async (p) => {
510
- const resultRows = [];
511
- for (const m of p.transaction.mutations) {
512
- if (m.type !== "insert") continue;
513
- const base = { ...m.modified };
514
- const row = useLoro ? { ...base, updated_at: now(), sync_deleted: false } : base;
515
- if (useLoro) loroPutMany([row]);
516
- await table.create(row);
517
- resultRows.push(row);
518
- }
519
- return resultRows;
520
- };
521
- const onUpdate = async (p) => {
522
- const resultRows = [];
523
- for (const m of p.transaction.mutations) {
524
- if (m.type !== "update") continue;
525
- const id2 = m.key;
526
- const base = { ...m.modified, id: id2 };
527
- const merged = useLoro ? { ...base, updated_at: now() } : base;
528
- if (useLoro) loroPutMany([merged]);
529
- const rid = new RecordId(config.table.name, keyOf(id2));
530
- await table.update(rid, merged);
531
- resultRows.push(merged);
532
- }
533
- return resultRows;
534
- };
535
- const onDelete = async (p) => {
536
- const resultRows = [];
537
- for (const m of p.transaction.mutations) {
538
- if (m.type !== "delete") continue;
539
- const id2 = m.key;
540
- if (useLoro) loroRemove(keyOf(id2));
541
- await table.softDelete(new RecordId(config.table.name, keyOf(id2)));
190
+ },
191
+ onInsert: (async (p) => {
192
+ const now = () => /* @__PURE__ */ new Date();
193
+ const resultRows = [];
194
+ for (const m of p.transaction.mutations) {
195
+ if (m.type !== "insert") continue;
196
+ const baseRow = { ...m.modified };
197
+ const row = useLoro ? {
198
+ ...baseRow,
199
+ updated_at: now(),
200
+ sync_deleted: false
201
+ } : baseRow;
202
+ if (useLoro) loroPut(row);
203
+ await table.create(row);
204
+ resultRows.push(row);
205
+ }
206
+ return resultRows;
207
+ }),
208
+ onUpdate: (async (p) => {
209
+ const now = () => /* @__PURE__ */ new Date();
210
+ const resultRows = [];
211
+ for (const m of p.transaction.mutations) {
212
+ if (m.type !== "update") continue;
213
+ const idKey = m.key;
214
+ const baseRow = { ...m.modified, id: idKey };
215
+ const row = useLoro ? { ...baseRow, updated_at: now() } : baseRow;
216
+ if (useLoro) loroPut(row);
217
+ await table.update(
218
+ new RecordId(config.table.name, keyOf(idKey)),
219
+ row
220
+ );
221
+ resultRows.push(row);
222
+ }
223
+ return resultRows;
224
+ }),
225
+ onDelete: (async (p) => {
226
+ for (const m of p.transaction.mutations) {
227
+ if (m.type !== "delete") continue;
228
+ const idKey = m.key;
229
+ if (useLoro) loroRemove(keyOf(idKey));
230
+ await table.softDelete(
231
+ new RecordId(config.table.name, keyOf(idKey))
232
+ );
233
+ }
234
+ return [];
235
+ })
236
+ });
237
+ const baseSync = base.sync?.sync;
238
+ const sync = baseSync ? {
239
+ sync: (ctx) => {
240
+ const offBase = baseSync(ctx);
241
+ if (!db.isFeatureSupported(Features.LiveQueries))
242
+ return offBase;
243
+ const offLive = table.subscribe((evt) => {
244
+ if (useLoro) {
245
+ if (evt.type === "delete")
246
+ loroRemove(getKey(evt.row));
247
+ else loroPut(evt.row);
248
+ }
249
+ void queryClient.invalidateQueries({ queryKey, exact: false }).catch((e) => onError?.(e));
250
+ });
251
+ const baseCleanup = toCleanup(baseSync(ctx));
252
+ return () => {
253
+ offLive();
254
+ baseCleanup();
255
+ };
542
256
  }
543
- return resultRows;
544
- };
257
+ } : void 0;
545
258
  return {
546
- id,
547
- getKey,
548
- sync: { sync },
549
- onInsert,
550
- onDelete,
551
- onUpdate
259
+ ...base,
260
+ sync: sync ?? base.sync
552
261
  };
553
262
  }
554
- export {
555
- surrealCollectionOptions
556
- };
263
+
264
+ export { surrealCollectionOptions };
265
+ //# sourceMappingURL=index.mjs.map
266
+ //# sourceMappingURL=index.mjs.map