@foretag/tanstack-db-surrealdb 0.3.0 → 0.3.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 +20 -19
- package/dist/index.d.ts +20 -19
- package/dist/index.js +1947 -454
- package/dist/index.mjs +1945 -454
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -22,106 +22,1831 @@ __export(index_exports, {
|
|
|
22
22
|
surrealCollectionOptions: () => surrealCollectionOptions
|
|
23
23
|
});
|
|
24
24
|
module.exports = __toCommonJS(index_exports);
|
|
25
|
+
|
|
26
|
+
// node_modules/@tanstack/query-core/build/modern/subscribable.js
|
|
27
|
+
var Subscribable = class {
|
|
28
|
+
constructor() {
|
|
29
|
+
this.listeners = /* @__PURE__ */ new Set();
|
|
30
|
+
this.subscribe = this.subscribe.bind(this);
|
|
31
|
+
}
|
|
32
|
+
subscribe(listener) {
|
|
33
|
+
this.listeners.add(listener);
|
|
34
|
+
this.onSubscribe();
|
|
35
|
+
return () => {
|
|
36
|
+
this.listeners.delete(listener);
|
|
37
|
+
this.onUnsubscribe();
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
hasListeners() {
|
|
41
|
+
return this.listeners.size > 0;
|
|
42
|
+
}
|
|
43
|
+
onSubscribe() {
|
|
44
|
+
}
|
|
45
|
+
onUnsubscribe() {
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
// node_modules/@tanstack/query-core/build/modern/timeoutManager.js
|
|
50
|
+
var defaultTimeoutProvider = {
|
|
51
|
+
// We need the wrapper function syntax below instead of direct references to
|
|
52
|
+
// global setTimeout etc.
|
|
53
|
+
//
|
|
54
|
+
// BAD: `setTimeout: setTimeout`
|
|
55
|
+
// GOOD: `setTimeout: (cb, delay) => setTimeout(cb, delay)`
|
|
56
|
+
//
|
|
57
|
+
// If we use direct references here, then anything that wants to spy on or
|
|
58
|
+
// replace the global setTimeout (like tests) won't work since we'll already
|
|
59
|
+
// have a hard reference to the original implementation at the time when this
|
|
60
|
+
// file was imported.
|
|
61
|
+
setTimeout: (callback, delay) => setTimeout(callback, delay),
|
|
62
|
+
clearTimeout: (timeoutId) => clearTimeout(timeoutId),
|
|
63
|
+
setInterval: (callback, delay) => setInterval(callback, delay),
|
|
64
|
+
clearInterval: (intervalId) => clearInterval(intervalId)
|
|
65
|
+
};
|
|
66
|
+
var TimeoutManager = class {
|
|
67
|
+
// We cannot have TimeoutManager<T> as we must instantiate it with a concrete
|
|
68
|
+
// type at app boot; and if we leave that type, then any new timer provider
|
|
69
|
+
// would need to support ReturnType<typeof setTimeout>, which is infeasible.
|
|
70
|
+
//
|
|
71
|
+
// We settle for type safety for the TimeoutProvider type, and accept that
|
|
72
|
+
// this class is unsafe internally to allow for extension.
|
|
73
|
+
#provider = defaultTimeoutProvider;
|
|
74
|
+
#providerCalled = false;
|
|
75
|
+
setTimeoutProvider(provider) {
|
|
76
|
+
if (process.env.NODE_ENV !== "production") {
|
|
77
|
+
if (this.#providerCalled && provider !== this.#provider) {
|
|
78
|
+
console.error(
|
|
79
|
+
`[timeoutManager]: Switching provider after calls to previous provider might result in unexpected behavior.`,
|
|
80
|
+
{ previous: this.#provider, provider }
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
this.#provider = provider;
|
|
85
|
+
if (process.env.NODE_ENV !== "production") {
|
|
86
|
+
this.#providerCalled = false;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
setTimeout(callback, delay) {
|
|
90
|
+
if (process.env.NODE_ENV !== "production") {
|
|
91
|
+
this.#providerCalled = true;
|
|
92
|
+
}
|
|
93
|
+
return this.#provider.setTimeout(callback, delay);
|
|
94
|
+
}
|
|
95
|
+
clearTimeout(timeoutId) {
|
|
96
|
+
this.#provider.clearTimeout(timeoutId);
|
|
97
|
+
}
|
|
98
|
+
setInterval(callback, delay) {
|
|
99
|
+
if (process.env.NODE_ENV !== "production") {
|
|
100
|
+
this.#providerCalled = true;
|
|
101
|
+
}
|
|
102
|
+
return this.#provider.setInterval(callback, delay);
|
|
103
|
+
}
|
|
104
|
+
clearInterval(intervalId) {
|
|
105
|
+
this.#provider.clearInterval(intervalId);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
var timeoutManager = new TimeoutManager();
|
|
109
|
+
function systemSetTimeoutZero(callback) {
|
|
110
|
+
setTimeout(callback, 0);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// node_modules/@tanstack/query-core/build/modern/utils.js
|
|
114
|
+
var isServer = typeof window === "undefined" || "Deno" in globalThis;
|
|
115
|
+
function noop() {
|
|
116
|
+
}
|
|
117
|
+
function isValidTimeout(value) {
|
|
118
|
+
return typeof value === "number" && value >= 0 && value !== Infinity;
|
|
119
|
+
}
|
|
120
|
+
function timeUntilStale(updatedAt, staleTime) {
|
|
121
|
+
return Math.max(updatedAt + (staleTime || 0) - Date.now(), 0);
|
|
122
|
+
}
|
|
123
|
+
function resolveStaleTime(staleTime, query) {
|
|
124
|
+
return typeof staleTime === "function" ? staleTime(query) : staleTime;
|
|
125
|
+
}
|
|
126
|
+
function resolveEnabled(enabled, query) {
|
|
127
|
+
return typeof enabled === "function" ? enabled(query) : enabled;
|
|
128
|
+
}
|
|
129
|
+
function hashKey(queryKey) {
|
|
130
|
+
return JSON.stringify(
|
|
131
|
+
queryKey,
|
|
132
|
+
(_, val) => isPlainObject(val) ? Object.keys(val).sort().reduce((result, key) => {
|
|
133
|
+
result[key] = val[key];
|
|
134
|
+
return result;
|
|
135
|
+
}, {}) : val
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
var hasOwn = Object.prototype.hasOwnProperty;
|
|
139
|
+
function replaceEqualDeep(a, b) {
|
|
140
|
+
if (a === b) {
|
|
141
|
+
return a;
|
|
142
|
+
}
|
|
143
|
+
const array = isPlainArray(a) && isPlainArray(b);
|
|
144
|
+
if (!array && !(isPlainObject(a) && isPlainObject(b))) return b;
|
|
145
|
+
const aItems = array ? a : Object.keys(a);
|
|
146
|
+
const aSize = aItems.length;
|
|
147
|
+
const bItems = array ? b : Object.keys(b);
|
|
148
|
+
const bSize = bItems.length;
|
|
149
|
+
const copy = array ? new Array(bSize) : {};
|
|
150
|
+
let equalItems = 0;
|
|
151
|
+
for (let i = 0; i < bSize; i++) {
|
|
152
|
+
const key = array ? i : bItems[i];
|
|
153
|
+
const aItem = a[key];
|
|
154
|
+
const bItem = b[key];
|
|
155
|
+
if (aItem === bItem) {
|
|
156
|
+
copy[key] = aItem;
|
|
157
|
+
if (array ? i < aSize : hasOwn.call(a, key)) equalItems++;
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
if (aItem === null || bItem === null || typeof aItem !== "object" || typeof bItem !== "object") {
|
|
161
|
+
copy[key] = bItem;
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
const v = replaceEqualDeep(aItem, bItem);
|
|
165
|
+
copy[key] = v;
|
|
166
|
+
if (v === aItem) equalItems++;
|
|
167
|
+
}
|
|
168
|
+
return aSize === bSize && equalItems === aSize ? a : copy;
|
|
169
|
+
}
|
|
170
|
+
function shallowEqualObjects(a, b) {
|
|
171
|
+
if (!b || Object.keys(a).length !== Object.keys(b).length) {
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
for (const key in a) {
|
|
175
|
+
if (a[key] !== b[key]) {
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return true;
|
|
180
|
+
}
|
|
181
|
+
function isPlainArray(value) {
|
|
182
|
+
return Array.isArray(value) && value.length === Object.keys(value).length;
|
|
183
|
+
}
|
|
184
|
+
function isPlainObject(o) {
|
|
185
|
+
if (!hasObjectPrototype(o)) {
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
const ctor = o.constructor;
|
|
189
|
+
if (ctor === void 0) {
|
|
190
|
+
return true;
|
|
191
|
+
}
|
|
192
|
+
const prot = ctor.prototype;
|
|
193
|
+
if (!hasObjectPrototype(prot)) {
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
if (!prot.hasOwnProperty("isPrototypeOf")) {
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
199
|
+
if (Object.getPrototypeOf(o) !== Object.prototype) {
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
return true;
|
|
203
|
+
}
|
|
204
|
+
function hasObjectPrototype(o) {
|
|
205
|
+
return Object.prototype.toString.call(o) === "[object Object]";
|
|
206
|
+
}
|
|
207
|
+
function replaceData(prevData, data, options) {
|
|
208
|
+
if (typeof options.structuralSharing === "function") {
|
|
209
|
+
return options.structuralSharing(prevData, data);
|
|
210
|
+
} else if (options.structuralSharing !== false) {
|
|
211
|
+
if (process.env.NODE_ENV !== "production") {
|
|
212
|
+
try {
|
|
213
|
+
return replaceEqualDeep(prevData, data);
|
|
214
|
+
} catch (error) {
|
|
215
|
+
console.error(
|
|
216
|
+
`Structural sharing requires data to be JSON serializable. To fix this, turn off structuralSharing or return JSON-serializable data from your queryFn. [${options.queryHash}]: ${error}`
|
|
217
|
+
);
|
|
218
|
+
throw error;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return replaceEqualDeep(prevData, data);
|
|
222
|
+
}
|
|
223
|
+
return data;
|
|
224
|
+
}
|
|
225
|
+
var skipToken = Symbol();
|
|
226
|
+
|
|
227
|
+
// node_modules/@tanstack/query-core/build/modern/focusManager.js
|
|
228
|
+
var FocusManager = class extends Subscribable {
|
|
229
|
+
#focused;
|
|
230
|
+
#cleanup;
|
|
231
|
+
#setup;
|
|
232
|
+
constructor() {
|
|
233
|
+
super();
|
|
234
|
+
this.#setup = (onFocus) => {
|
|
235
|
+
if (!isServer && window.addEventListener) {
|
|
236
|
+
const listener = () => onFocus();
|
|
237
|
+
window.addEventListener("visibilitychange", listener, false);
|
|
238
|
+
return () => {
|
|
239
|
+
window.removeEventListener("visibilitychange", listener);
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
return;
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
onSubscribe() {
|
|
246
|
+
if (!this.#cleanup) {
|
|
247
|
+
this.setEventListener(this.#setup);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
onUnsubscribe() {
|
|
251
|
+
if (!this.hasListeners()) {
|
|
252
|
+
this.#cleanup?.();
|
|
253
|
+
this.#cleanup = void 0;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
setEventListener(setup) {
|
|
257
|
+
this.#setup = setup;
|
|
258
|
+
this.#cleanup?.();
|
|
259
|
+
this.#cleanup = setup((focused) => {
|
|
260
|
+
if (typeof focused === "boolean") {
|
|
261
|
+
this.setFocused(focused);
|
|
262
|
+
} else {
|
|
263
|
+
this.onFocus();
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
setFocused(focused) {
|
|
268
|
+
const changed = this.#focused !== focused;
|
|
269
|
+
if (changed) {
|
|
270
|
+
this.#focused = focused;
|
|
271
|
+
this.onFocus();
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
onFocus() {
|
|
275
|
+
const isFocused = this.isFocused();
|
|
276
|
+
this.listeners.forEach((listener) => {
|
|
277
|
+
listener(isFocused);
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
isFocused() {
|
|
281
|
+
if (typeof this.#focused === "boolean") {
|
|
282
|
+
return this.#focused;
|
|
283
|
+
}
|
|
284
|
+
return globalThis.document?.visibilityState !== "hidden";
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
var focusManager = new FocusManager();
|
|
288
|
+
|
|
289
|
+
// node_modules/@tanstack/query-core/build/modern/thenable.js
|
|
290
|
+
function pendingThenable() {
|
|
291
|
+
let resolve;
|
|
292
|
+
let reject;
|
|
293
|
+
const thenable = new Promise((_resolve, _reject) => {
|
|
294
|
+
resolve = _resolve;
|
|
295
|
+
reject = _reject;
|
|
296
|
+
});
|
|
297
|
+
thenable.status = "pending";
|
|
298
|
+
thenable.catch(() => {
|
|
299
|
+
});
|
|
300
|
+
function finalize(data) {
|
|
301
|
+
Object.assign(thenable, data);
|
|
302
|
+
delete thenable.resolve;
|
|
303
|
+
delete thenable.reject;
|
|
304
|
+
}
|
|
305
|
+
thenable.resolve = (value) => {
|
|
306
|
+
finalize({
|
|
307
|
+
status: "fulfilled",
|
|
308
|
+
value
|
|
309
|
+
});
|
|
310
|
+
resolve(value);
|
|
311
|
+
};
|
|
312
|
+
thenable.reject = (reason) => {
|
|
313
|
+
finalize({
|
|
314
|
+
status: "rejected",
|
|
315
|
+
reason
|
|
316
|
+
});
|
|
317
|
+
reject(reason);
|
|
318
|
+
};
|
|
319
|
+
return thenable;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// node_modules/@tanstack/query-core/build/modern/notifyManager.js
|
|
323
|
+
var defaultScheduler = systemSetTimeoutZero;
|
|
324
|
+
function createNotifyManager() {
|
|
325
|
+
let queue = [];
|
|
326
|
+
let transactions = 0;
|
|
327
|
+
let notifyFn = (callback) => {
|
|
328
|
+
callback();
|
|
329
|
+
};
|
|
330
|
+
let batchNotifyFn = (callback) => {
|
|
331
|
+
callback();
|
|
332
|
+
};
|
|
333
|
+
let scheduleFn = defaultScheduler;
|
|
334
|
+
const schedule = (callback) => {
|
|
335
|
+
if (transactions) {
|
|
336
|
+
queue.push(callback);
|
|
337
|
+
} else {
|
|
338
|
+
scheduleFn(() => {
|
|
339
|
+
notifyFn(callback);
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
const flush = () => {
|
|
344
|
+
const originalQueue = queue;
|
|
345
|
+
queue = [];
|
|
346
|
+
if (originalQueue.length) {
|
|
347
|
+
scheduleFn(() => {
|
|
348
|
+
batchNotifyFn(() => {
|
|
349
|
+
originalQueue.forEach((callback) => {
|
|
350
|
+
notifyFn(callback);
|
|
351
|
+
});
|
|
352
|
+
});
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
};
|
|
356
|
+
return {
|
|
357
|
+
batch: (callback) => {
|
|
358
|
+
let result;
|
|
359
|
+
transactions++;
|
|
360
|
+
try {
|
|
361
|
+
result = callback();
|
|
362
|
+
} finally {
|
|
363
|
+
transactions--;
|
|
364
|
+
if (!transactions) {
|
|
365
|
+
flush();
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
return result;
|
|
369
|
+
},
|
|
370
|
+
/**
|
|
371
|
+
* All calls to the wrapped function will be batched.
|
|
372
|
+
*/
|
|
373
|
+
batchCalls: (callback) => {
|
|
374
|
+
return (...args) => {
|
|
375
|
+
schedule(() => {
|
|
376
|
+
callback(...args);
|
|
377
|
+
});
|
|
378
|
+
};
|
|
379
|
+
},
|
|
380
|
+
schedule,
|
|
381
|
+
/**
|
|
382
|
+
* Use this method to set a custom notify function.
|
|
383
|
+
* This can be used to for example wrap notifications with `React.act` while running tests.
|
|
384
|
+
*/
|
|
385
|
+
setNotifyFunction: (fn) => {
|
|
386
|
+
notifyFn = fn;
|
|
387
|
+
},
|
|
388
|
+
/**
|
|
389
|
+
* Use this method to set a custom function to batch notifications together into a single tick.
|
|
390
|
+
* By default React Query will use the batch function provided by ReactDOM or React Native.
|
|
391
|
+
*/
|
|
392
|
+
setBatchNotifyFunction: (fn) => {
|
|
393
|
+
batchNotifyFn = fn;
|
|
394
|
+
},
|
|
395
|
+
setScheduler: (fn) => {
|
|
396
|
+
scheduleFn = fn;
|
|
397
|
+
}
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
var notifyManager = createNotifyManager();
|
|
401
|
+
|
|
402
|
+
// node_modules/@tanstack/query-core/build/modern/onlineManager.js
|
|
403
|
+
var OnlineManager = class extends Subscribable {
|
|
404
|
+
#online = true;
|
|
405
|
+
#cleanup;
|
|
406
|
+
#setup;
|
|
407
|
+
constructor() {
|
|
408
|
+
super();
|
|
409
|
+
this.#setup = (onOnline) => {
|
|
410
|
+
if (!isServer && window.addEventListener) {
|
|
411
|
+
const onlineListener = () => onOnline(true);
|
|
412
|
+
const offlineListener = () => onOnline(false);
|
|
413
|
+
window.addEventListener("online", onlineListener, false);
|
|
414
|
+
window.addEventListener("offline", offlineListener, false);
|
|
415
|
+
return () => {
|
|
416
|
+
window.removeEventListener("online", onlineListener);
|
|
417
|
+
window.removeEventListener("offline", offlineListener);
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
return;
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
onSubscribe() {
|
|
424
|
+
if (!this.#cleanup) {
|
|
425
|
+
this.setEventListener(this.#setup);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
onUnsubscribe() {
|
|
429
|
+
if (!this.hasListeners()) {
|
|
430
|
+
this.#cleanup?.();
|
|
431
|
+
this.#cleanup = void 0;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
setEventListener(setup) {
|
|
435
|
+
this.#setup = setup;
|
|
436
|
+
this.#cleanup?.();
|
|
437
|
+
this.#cleanup = setup(this.setOnline.bind(this));
|
|
438
|
+
}
|
|
439
|
+
setOnline(online) {
|
|
440
|
+
const changed = this.#online !== online;
|
|
441
|
+
if (changed) {
|
|
442
|
+
this.#online = online;
|
|
443
|
+
this.listeners.forEach((listener) => {
|
|
444
|
+
listener(online);
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
isOnline() {
|
|
449
|
+
return this.#online;
|
|
450
|
+
}
|
|
451
|
+
};
|
|
452
|
+
var onlineManager = new OnlineManager();
|
|
453
|
+
|
|
454
|
+
// node_modules/@tanstack/query-core/build/modern/retryer.js
|
|
455
|
+
function canFetch(networkMode) {
|
|
456
|
+
return (networkMode ?? "online") === "online" ? onlineManager.isOnline() : true;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// node_modules/@tanstack/query-core/build/modern/query.js
|
|
460
|
+
function fetchState(data, options) {
|
|
461
|
+
return {
|
|
462
|
+
fetchFailureCount: 0,
|
|
463
|
+
fetchFailureReason: null,
|
|
464
|
+
fetchStatus: canFetch(options.networkMode) ? "fetching" : "paused",
|
|
465
|
+
...data === void 0 && {
|
|
466
|
+
error: null,
|
|
467
|
+
status: "pending"
|
|
468
|
+
}
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// node_modules/@tanstack/query-core/build/modern/queryObserver.js
|
|
473
|
+
var QueryObserver = class extends Subscribable {
|
|
474
|
+
constructor(client, options) {
|
|
475
|
+
super();
|
|
476
|
+
this.options = options;
|
|
477
|
+
this.#client = client;
|
|
478
|
+
this.#selectError = null;
|
|
479
|
+
this.#currentThenable = pendingThenable();
|
|
480
|
+
this.bindMethods();
|
|
481
|
+
this.setOptions(options);
|
|
482
|
+
}
|
|
483
|
+
#client;
|
|
484
|
+
#currentQuery = void 0;
|
|
485
|
+
#currentQueryInitialState = void 0;
|
|
486
|
+
#currentResult = void 0;
|
|
487
|
+
#currentResultState;
|
|
488
|
+
#currentResultOptions;
|
|
489
|
+
#currentThenable;
|
|
490
|
+
#selectError;
|
|
491
|
+
#selectFn;
|
|
492
|
+
#selectResult;
|
|
493
|
+
// This property keeps track of the last query with defined data.
|
|
494
|
+
// It will be used to pass the previous data and query to the placeholder function between renders.
|
|
495
|
+
#lastQueryWithDefinedData;
|
|
496
|
+
#staleTimeoutId;
|
|
497
|
+
#refetchIntervalId;
|
|
498
|
+
#currentRefetchInterval;
|
|
499
|
+
#trackedProps = /* @__PURE__ */ new Set();
|
|
500
|
+
bindMethods() {
|
|
501
|
+
this.refetch = this.refetch.bind(this);
|
|
502
|
+
}
|
|
503
|
+
onSubscribe() {
|
|
504
|
+
if (this.listeners.size === 1) {
|
|
505
|
+
this.#currentQuery.addObserver(this);
|
|
506
|
+
if (shouldFetchOnMount(this.#currentQuery, this.options)) {
|
|
507
|
+
this.#executeFetch();
|
|
508
|
+
} else {
|
|
509
|
+
this.updateResult();
|
|
510
|
+
}
|
|
511
|
+
this.#updateTimers();
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
onUnsubscribe() {
|
|
515
|
+
if (!this.hasListeners()) {
|
|
516
|
+
this.destroy();
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
shouldFetchOnReconnect() {
|
|
520
|
+
return shouldFetchOn(
|
|
521
|
+
this.#currentQuery,
|
|
522
|
+
this.options,
|
|
523
|
+
this.options.refetchOnReconnect
|
|
524
|
+
);
|
|
525
|
+
}
|
|
526
|
+
shouldFetchOnWindowFocus() {
|
|
527
|
+
return shouldFetchOn(
|
|
528
|
+
this.#currentQuery,
|
|
529
|
+
this.options,
|
|
530
|
+
this.options.refetchOnWindowFocus
|
|
531
|
+
);
|
|
532
|
+
}
|
|
533
|
+
destroy() {
|
|
534
|
+
this.listeners = /* @__PURE__ */ new Set();
|
|
535
|
+
this.#clearStaleTimeout();
|
|
536
|
+
this.#clearRefetchInterval();
|
|
537
|
+
this.#currentQuery.removeObserver(this);
|
|
538
|
+
}
|
|
539
|
+
setOptions(options) {
|
|
540
|
+
const prevOptions = this.options;
|
|
541
|
+
const prevQuery = this.#currentQuery;
|
|
542
|
+
this.options = this.#client.defaultQueryOptions(options);
|
|
543
|
+
if (this.options.enabled !== void 0 && typeof this.options.enabled !== "boolean" && typeof this.options.enabled !== "function" && typeof resolveEnabled(this.options.enabled, this.#currentQuery) !== "boolean") {
|
|
544
|
+
throw new Error(
|
|
545
|
+
"Expected enabled to be a boolean or a callback that returns a boolean"
|
|
546
|
+
);
|
|
547
|
+
}
|
|
548
|
+
this.#updateQuery();
|
|
549
|
+
this.#currentQuery.setOptions(this.options);
|
|
550
|
+
if (prevOptions._defaulted && !shallowEqualObjects(this.options, prevOptions)) {
|
|
551
|
+
this.#client.getQueryCache().notify({
|
|
552
|
+
type: "observerOptionsUpdated",
|
|
553
|
+
query: this.#currentQuery,
|
|
554
|
+
observer: this
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
const mounted = this.hasListeners();
|
|
558
|
+
if (mounted && shouldFetchOptionally(
|
|
559
|
+
this.#currentQuery,
|
|
560
|
+
prevQuery,
|
|
561
|
+
this.options,
|
|
562
|
+
prevOptions
|
|
563
|
+
)) {
|
|
564
|
+
this.#executeFetch();
|
|
565
|
+
}
|
|
566
|
+
this.updateResult();
|
|
567
|
+
if (mounted && (this.#currentQuery !== prevQuery || resolveEnabled(this.options.enabled, this.#currentQuery) !== resolveEnabled(prevOptions.enabled, this.#currentQuery) || resolveStaleTime(this.options.staleTime, this.#currentQuery) !== resolveStaleTime(prevOptions.staleTime, this.#currentQuery))) {
|
|
568
|
+
this.#updateStaleTimeout();
|
|
569
|
+
}
|
|
570
|
+
const nextRefetchInterval = this.#computeRefetchInterval();
|
|
571
|
+
if (mounted && (this.#currentQuery !== prevQuery || resolveEnabled(this.options.enabled, this.#currentQuery) !== resolveEnabled(prevOptions.enabled, this.#currentQuery) || nextRefetchInterval !== this.#currentRefetchInterval)) {
|
|
572
|
+
this.#updateRefetchInterval(nextRefetchInterval);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
getOptimisticResult(options) {
|
|
576
|
+
const query = this.#client.getQueryCache().build(this.#client, options);
|
|
577
|
+
const result = this.createResult(query, options);
|
|
578
|
+
if (shouldAssignObserverCurrentProperties(this, result)) {
|
|
579
|
+
this.#currentResult = result;
|
|
580
|
+
this.#currentResultOptions = this.options;
|
|
581
|
+
this.#currentResultState = this.#currentQuery.state;
|
|
582
|
+
}
|
|
583
|
+
return result;
|
|
584
|
+
}
|
|
585
|
+
getCurrentResult() {
|
|
586
|
+
return this.#currentResult;
|
|
587
|
+
}
|
|
588
|
+
trackResult(result, onPropTracked) {
|
|
589
|
+
return new Proxy(result, {
|
|
590
|
+
get: (target, key) => {
|
|
591
|
+
this.trackProp(key);
|
|
592
|
+
onPropTracked?.(key);
|
|
593
|
+
if (key === "promise") {
|
|
594
|
+
this.trackProp("data");
|
|
595
|
+
if (!this.options.experimental_prefetchInRender && this.#currentThenable.status === "pending") {
|
|
596
|
+
this.#currentThenable.reject(
|
|
597
|
+
new Error(
|
|
598
|
+
"experimental_prefetchInRender feature flag is not enabled"
|
|
599
|
+
)
|
|
600
|
+
);
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
return Reflect.get(target, key);
|
|
604
|
+
}
|
|
605
|
+
});
|
|
606
|
+
}
|
|
607
|
+
trackProp(key) {
|
|
608
|
+
this.#trackedProps.add(key);
|
|
609
|
+
}
|
|
610
|
+
getCurrentQuery() {
|
|
611
|
+
return this.#currentQuery;
|
|
612
|
+
}
|
|
613
|
+
refetch({ ...options } = {}) {
|
|
614
|
+
return this.fetch({
|
|
615
|
+
...options
|
|
616
|
+
});
|
|
617
|
+
}
|
|
618
|
+
fetchOptimistic(options) {
|
|
619
|
+
const defaultedOptions = this.#client.defaultQueryOptions(options);
|
|
620
|
+
const query = this.#client.getQueryCache().build(this.#client, defaultedOptions);
|
|
621
|
+
return query.fetch().then(() => this.createResult(query, defaultedOptions));
|
|
622
|
+
}
|
|
623
|
+
fetch(fetchOptions) {
|
|
624
|
+
return this.#executeFetch({
|
|
625
|
+
...fetchOptions,
|
|
626
|
+
cancelRefetch: fetchOptions.cancelRefetch ?? true
|
|
627
|
+
}).then(() => {
|
|
628
|
+
this.updateResult();
|
|
629
|
+
return this.#currentResult;
|
|
630
|
+
});
|
|
631
|
+
}
|
|
632
|
+
#executeFetch(fetchOptions) {
|
|
633
|
+
this.#updateQuery();
|
|
634
|
+
let promise = this.#currentQuery.fetch(
|
|
635
|
+
this.options,
|
|
636
|
+
fetchOptions
|
|
637
|
+
);
|
|
638
|
+
if (!fetchOptions?.throwOnError) {
|
|
639
|
+
promise = promise.catch(noop);
|
|
640
|
+
}
|
|
641
|
+
return promise;
|
|
642
|
+
}
|
|
643
|
+
#updateStaleTimeout() {
|
|
644
|
+
this.#clearStaleTimeout();
|
|
645
|
+
const staleTime = resolveStaleTime(
|
|
646
|
+
this.options.staleTime,
|
|
647
|
+
this.#currentQuery
|
|
648
|
+
);
|
|
649
|
+
if (isServer || this.#currentResult.isStale || !isValidTimeout(staleTime)) {
|
|
650
|
+
return;
|
|
651
|
+
}
|
|
652
|
+
const time = timeUntilStale(this.#currentResult.dataUpdatedAt, staleTime);
|
|
653
|
+
const timeout = time + 1;
|
|
654
|
+
this.#staleTimeoutId = timeoutManager.setTimeout(() => {
|
|
655
|
+
if (!this.#currentResult.isStale) {
|
|
656
|
+
this.updateResult();
|
|
657
|
+
}
|
|
658
|
+
}, timeout);
|
|
659
|
+
}
|
|
660
|
+
#computeRefetchInterval() {
|
|
661
|
+
return (typeof this.options.refetchInterval === "function" ? this.options.refetchInterval(this.#currentQuery) : this.options.refetchInterval) ?? false;
|
|
662
|
+
}
|
|
663
|
+
#updateRefetchInterval(nextInterval) {
|
|
664
|
+
this.#clearRefetchInterval();
|
|
665
|
+
this.#currentRefetchInterval = nextInterval;
|
|
666
|
+
if (isServer || resolveEnabled(this.options.enabled, this.#currentQuery) === false || !isValidTimeout(this.#currentRefetchInterval) || this.#currentRefetchInterval === 0) {
|
|
667
|
+
return;
|
|
668
|
+
}
|
|
669
|
+
this.#refetchIntervalId = timeoutManager.setInterval(() => {
|
|
670
|
+
if (this.options.refetchIntervalInBackground || focusManager.isFocused()) {
|
|
671
|
+
this.#executeFetch();
|
|
672
|
+
}
|
|
673
|
+
}, this.#currentRefetchInterval);
|
|
674
|
+
}
|
|
675
|
+
#updateTimers() {
|
|
676
|
+
this.#updateStaleTimeout();
|
|
677
|
+
this.#updateRefetchInterval(this.#computeRefetchInterval());
|
|
678
|
+
}
|
|
679
|
+
#clearStaleTimeout() {
|
|
680
|
+
if (this.#staleTimeoutId) {
|
|
681
|
+
timeoutManager.clearTimeout(this.#staleTimeoutId);
|
|
682
|
+
this.#staleTimeoutId = void 0;
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
#clearRefetchInterval() {
|
|
686
|
+
if (this.#refetchIntervalId) {
|
|
687
|
+
timeoutManager.clearInterval(this.#refetchIntervalId);
|
|
688
|
+
this.#refetchIntervalId = void 0;
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
createResult(query, options) {
|
|
692
|
+
const prevQuery = this.#currentQuery;
|
|
693
|
+
const prevOptions = this.options;
|
|
694
|
+
const prevResult = this.#currentResult;
|
|
695
|
+
const prevResultState = this.#currentResultState;
|
|
696
|
+
const prevResultOptions = this.#currentResultOptions;
|
|
697
|
+
const queryChange = query !== prevQuery;
|
|
698
|
+
const queryInitialState = queryChange ? query.state : this.#currentQueryInitialState;
|
|
699
|
+
const { state } = query;
|
|
700
|
+
let newState = { ...state };
|
|
701
|
+
let isPlaceholderData = false;
|
|
702
|
+
let data;
|
|
703
|
+
if (options._optimisticResults) {
|
|
704
|
+
const mounted = this.hasListeners();
|
|
705
|
+
const fetchOnMount = !mounted && shouldFetchOnMount(query, options);
|
|
706
|
+
const fetchOptionally = mounted && shouldFetchOptionally(query, prevQuery, options, prevOptions);
|
|
707
|
+
if (fetchOnMount || fetchOptionally) {
|
|
708
|
+
newState = {
|
|
709
|
+
...newState,
|
|
710
|
+
...fetchState(state.data, query.options)
|
|
711
|
+
};
|
|
712
|
+
}
|
|
713
|
+
if (options._optimisticResults === "isRestoring") {
|
|
714
|
+
newState.fetchStatus = "idle";
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
let { error, errorUpdatedAt, status } = newState;
|
|
718
|
+
data = newState.data;
|
|
719
|
+
let skipSelect = false;
|
|
720
|
+
if (options.placeholderData !== void 0 && data === void 0 && status === "pending") {
|
|
721
|
+
let placeholderData;
|
|
722
|
+
if (prevResult?.isPlaceholderData && options.placeholderData === prevResultOptions?.placeholderData) {
|
|
723
|
+
placeholderData = prevResult.data;
|
|
724
|
+
skipSelect = true;
|
|
725
|
+
} else {
|
|
726
|
+
placeholderData = typeof options.placeholderData === "function" ? options.placeholderData(
|
|
727
|
+
this.#lastQueryWithDefinedData?.state.data,
|
|
728
|
+
this.#lastQueryWithDefinedData
|
|
729
|
+
) : options.placeholderData;
|
|
730
|
+
}
|
|
731
|
+
if (placeholderData !== void 0) {
|
|
732
|
+
status = "success";
|
|
733
|
+
data = replaceData(
|
|
734
|
+
prevResult?.data,
|
|
735
|
+
placeholderData,
|
|
736
|
+
options
|
|
737
|
+
);
|
|
738
|
+
isPlaceholderData = true;
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
if (options.select && data !== void 0 && !skipSelect) {
|
|
742
|
+
if (prevResult && data === prevResultState?.data && options.select === this.#selectFn) {
|
|
743
|
+
data = this.#selectResult;
|
|
744
|
+
} else {
|
|
745
|
+
try {
|
|
746
|
+
this.#selectFn = options.select;
|
|
747
|
+
data = options.select(data);
|
|
748
|
+
data = replaceData(prevResult?.data, data, options);
|
|
749
|
+
this.#selectResult = data;
|
|
750
|
+
this.#selectError = null;
|
|
751
|
+
} catch (selectError) {
|
|
752
|
+
this.#selectError = selectError;
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
if (this.#selectError) {
|
|
757
|
+
error = this.#selectError;
|
|
758
|
+
data = this.#selectResult;
|
|
759
|
+
errorUpdatedAt = Date.now();
|
|
760
|
+
status = "error";
|
|
761
|
+
}
|
|
762
|
+
const isFetching = newState.fetchStatus === "fetching";
|
|
763
|
+
const isPending = status === "pending";
|
|
764
|
+
const isError = status === "error";
|
|
765
|
+
const isLoading = isPending && isFetching;
|
|
766
|
+
const hasData = data !== void 0;
|
|
767
|
+
const result = {
|
|
768
|
+
status,
|
|
769
|
+
fetchStatus: newState.fetchStatus,
|
|
770
|
+
isPending,
|
|
771
|
+
isSuccess: status === "success",
|
|
772
|
+
isError,
|
|
773
|
+
isInitialLoading: isLoading,
|
|
774
|
+
isLoading,
|
|
775
|
+
data,
|
|
776
|
+
dataUpdatedAt: newState.dataUpdatedAt,
|
|
777
|
+
error,
|
|
778
|
+
errorUpdatedAt,
|
|
779
|
+
failureCount: newState.fetchFailureCount,
|
|
780
|
+
failureReason: newState.fetchFailureReason,
|
|
781
|
+
errorUpdateCount: newState.errorUpdateCount,
|
|
782
|
+
isFetched: newState.dataUpdateCount > 0 || newState.errorUpdateCount > 0,
|
|
783
|
+
isFetchedAfterMount: newState.dataUpdateCount > queryInitialState.dataUpdateCount || newState.errorUpdateCount > queryInitialState.errorUpdateCount,
|
|
784
|
+
isFetching,
|
|
785
|
+
isRefetching: isFetching && !isPending,
|
|
786
|
+
isLoadingError: isError && !hasData,
|
|
787
|
+
isPaused: newState.fetchStatus === "paused",
|
|
788
|
+
isPlaceholderData,
|
|
789
|
+
isRefetchError: isError && hasData,
|
|
790
|
+
isStale: isStale(query, options),
|
|
791
|
+
refetch: this.refetch,
|
|
792
|
+
promise: this.#currentThenable,
|
|
793
|
+
isEnabled: resolveEnabled(options.enabled, query) !== false
|
|
794
|
+
};
|
|
795
|
+
const nextResult = result;
|
|
796
|
+
if (this.options.experimental_prefetchInRender) {
|
|
797
|
+
const finalizeThenableIfPossible = (thenable) => {
|
|
798
|
+
if (nextResult.status === "error") {
|
|
799
|
+
thenable.reject(nextResult.error);
|
|
800
|
+
} else if (nextResult.data !== void 0) {
|
|
801
|
+
thenable.resolve(nextResult.data);
|
|
802
|
+
}
|
|
803
|
+
};
|
|
804
|
+
const recreateThenable = () => {
|
|
805
|
+
const pending = this.#currentThenable = nextResult.promise = pendingThenable();
|
|
806
|
+
finalizeThenableIfPossible(pending);
|
|
807
|
+
};
|
|
808
|
+
const prevThenable = this.#currentThenable;
|
|
809
|
+
switch (prevThenable.status) {
|
|
810
|
+
case "pending":
|
|
811
|
+
if (query.queryHash === prevQuery.queryHash) {
|
|
812
|
+
finalizeThenableIfPossible(prevThenable);
|
|
813
|
+
}
|
|
814
|
+
break;
|
|
815
|
+
case "fulfilled":
|
|
816
|
+
if (nextResult.status === "error" || nextResult.data !== prevThenable.value) {
|
|
817
|
+
recreateThenable();
|
|
818
|
+
}
|
|
819
|
+
break;
|
|
820
|
+
case "rejected":
|
|
821
|
+
if (nextResult.status !== "error" || nextResult.error !== prevThenable.reason) {
|
|
822
|
+
recreateThenable();
|
|
823
|
+
}
|
|
824
|
+
break;
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
return nextResult;
|
|
828
|
+
}
|
|
829
|
+
updateResult() {
|
|
830
|
+
const prevResult = this.#currentResult;
|
|
831
|
+
const nextResult = this.createResult(this.#currentQuery, this.options);
|
|
832
|
+
this.#currentResultState = this.#currentQuery.state;
|
|
833
|
+
this.#currentResultOptions = this.options;
|
|
834
|
+
if (this.#currentResultState.data !== void 0) {
|
|
835
|
+
this.#lastQueryWithDefinedData = this.#currentQuery;
|
|
836
|
+
}
|
|
837
|
+
if (shallowEqualObjects(nextResult, prevResult)) {
|
|
838
|
+
return;
|
|
839
|
+
}
|
|
840
|
+
this.#currentResult = nextResult;
|
|
841
|
+
const shouldNotifyListeners = () => {
|
|
842
|
+
if (!prevResult) {
|
|
843
|
+
return true;
|
|
844
|
+
}
|
|
845
|
+
const { notifyOnChangeProps } = this.options;
|
|
846
|
+
const notifyOnChangePropsValue = typeof notifyOnChangeProps === "function" ? notifyOnChangeProps() : notifyOnChangeProps;
|
|
847
|
+
if (notifyOnChangePropsValue === "all" || !notifyOnChangePropsValue && !this.#trackedProps.size) {
|
|
848
|
+
return true;
|
|
849
|
+
}
|
|
850
|
+
const includedProps = new Set(
|
|
851
|
+
notifyOnChangePropsValue ?? this.#trackedProps
|
|
852
|
+
);
|
|
853
|
+
if (this.options.throwOnError) {
|
|
854
|
+
includedProps.add("error");
|
|
855
|
+
}
|
|
856
|
+
return Object.keys(this.#currentResult).some((key) => {
|
|
857
|
+
const typedKey = key;
|
|
858
|
+
const changed = this.#currentResult[typedKey] !== prevResult[typedKey];
|
|
859
|
+
return changed && includedProps.has(typedKey);
|
|
860
|
+
});
|
|
861
|
+
};
|
|
862
|
+
this.#notify({ listeners: shouldNotifyListeners() });
|
|
863
|
+
}
|
|
864
|
+
#updateQuery() {
|
|
865
|
+
const query = this.#client.getQueryCache().build(this.#client, this.options);
|
|
866
|
+
if (query === this.#currentQuery) {
|
|
867
|
+
return;
|
|
868
|
+
}
|
|
869
|
+
const prevQuery = this.#currentQuery;
|
|
870
|
+
this.#currentQuery = query;
|
|
871
|
+
this.#currentQueryInitialState = query.state;
|
|
872
|
+
if (this.hasListeners()) {
|
|
873
|
+
prevQuery?.removeObserver(this);
|
|
874
|
+
query.addObserver(this);
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
onQueryUpdate() {
|
|
878
|
+
this.updateResult();
|
|
879
|
+
if (this.hasListeners()) {
|
|
880
|
+
this.#updateTimers();
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
#notify(notifyOptions) {
|
|
884
|
+
notifyManager.batch(() => {
|
|
885
|
+
if (notifyOptions.listeners) {
|
|
886
|
+
this.listeners.forEach((listener) => {
|
|
887
|
+
listener(this.#currentResult);
|
|
888
|
+
});
|
|
889
|
+
}
|
|
890
|
+
this.#client.getQueryCache().notify({
|
|
891
|
+
query: this.#currentQuery,
|
|
892
|
+
type: "observerResultsUpdated"
|
|
893
|
+
});
|
|
894
|
+
});
|
|
895
|
+
}
|
|
896
|
+
};
|
|
897
|
+
function shouldLoadOnMount(query, options) {
|
|
898
|
+
return resolveEnabled(options.enabled, query) !== false && query.state.data === void 0 && !(query.state.status === "error" && options.retryOnMount === false);
|
|
899
|
+
}
|
|
900
|
+
function shouldFetchOnMount(query, options) {
|
|
901
|
+
return shouldLoadOnMount(query, options) || query.state.data !== void 0 && shouldFetchOn(query, options, options.refetchOnMount);
|
|
902
|
+
}
|
|
903
|
+
function shouldFetchOn(query, options, field) {
|
|
904
|
+
if (resolveEnabled(options.enabled, query) !== false && resolveStaleTime(options.staleTime, query) !== "static") {
|
|
905
|
+
const value = typeof field === "function" ? field(query) : field;
|
|
906
|
+
return value === "always" || value !== false && isStale(query, options);
|
|
907
|
+
}
|
|
908
|
+
return false;
|
|
909
|
+
}
|
|
910
|
+
function shouldFetchOptionally(query, prevQuery, options, prevOptions) {
|
|
911
|
+
return (query !== prevQuery || resolveEnabled(prevOptions.enabled, query) === false) && (!options.suspense || query.state.status !== "error") && isStale(query, options);
|
|
912
|
+
}
|
|
913
|
+
function isStale(query, options) {
|
|
914
|
+
return resolveEnabled(options.enabled, query) !== false && query.isStaleByTime(resolveStaleTime(options.staleTime, query));
|
|
915
|
+
}
|
|
916
|
+
function shouldAssignObserverCurrentProperties(observer, optimisticResult) {
|
|
917
|
+
if (!shallowEqualObjects(observer.getCurrentResult(), optimisticResult)) {
|
|
918
|
+
return true;
|
|
919
|
+
}
|
|
920
|
+
return false;
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
// node_modules/@tanstack/query-db-collection/dist/esm/query.js
|
|
924
|
+
var import_db2 = require("@tanstack/db");
|
|
925
|
+
|
|
926
|
+
// node_modules/@tanstack/query-db-collection/dist/esm/errors.js
|
|
927
|
+
var import_db = require("@tanstack/db");
|
|
928
|
+
var QueryCollectionError = class extends import_db.TanStackDBError {
|
|
929
|
+
constructor(message) {
|
|
930
|
+
super(message);
|
|
931
|
+
this.name = `QueryCollectionError`;
|
|
932
|
+
}
|
|
933
|
+
};
|
|
934
|
+
var QueryKeyRequiredError = class extends QueryCollectionError {
|
|
935
|
+
constructor() {
|
|
936
|
+
super(`[QueryCollection] queryKey must be provided.`);
|
|
937
|
+
this.name = `QueryKeyRequiredError`;
|
|
938
|
+
}
|
|
939
|
+
};
|
|
940
|
+
var QueryFnRequiredError = class extends QueryCollectionError {
|
|
941
|
+
constructor() {
|
|
942
|
+
super(`[QueryCollection] queryFn must be provided.`);
|
|
943
|
+
this.name = `QueryFnRequiredError`;
|
|
944
|
+
}
|
|
945
|
+
};
|
|
946
|
+
var QueryClientRequiredError = class extends QueryCollectionError {
|
|
947
|
+
constructor() {
|
|
948
|
+
super(`[QueryCollection] queryClient must be provided.`);
|
|
949
|
+
this.name = `QueryClientRequiredError`;
|
|
950
|
+
}
|
|
951
|
+
};
|
|
952
|
+
var GetKeyRequiredError = class extends QueryCollectionError {
|
|
953
|
+
constructor() {
|
|
954
|
+
super(`[QueryCollection] getKey must be provided.`);
|
|
955
|
+
this.name = `GetKeyRequiredError`;
|
|
956
|
+
}
|
|
957
|
+
};
|
|
958
|
+
var SyncNotInitializedError = class extends QueryCollectionError {
|
|
959
|
+
constructor() {
|
|
960
|
+
super(
|
|
961
|
+
`Collection must be in 'ready' state for manual sync operations. Sync not initialized yet.`
|
|
962
|
+
);
|
|
963
|
+
this.name = `SyncNotInitializedError`;
|
|
964
|
+
}
|
|
965
|
+
};
|
|
966
|
+
var DuplicateKeyInBatchError = class extends QueryCollectionError {
|
|
967
|
+
constructor(key) {
|
|
968
|
+
super(`Duplicate key '${key}' found within batch operations`);
|
|
969
|
+
this.name = `DuplicateKeyInBatchError`;
|
|
970
|
+
}
|
|
971
|
+
};
|
|
972
|
+
var UpdateOperationItemNotFoundError = class extends QueryCollectionError {
|
|
973
|
+
constructor(key) {
|
|
974
|
+
super(`Update operation: Item with key '${key}' does not exist`);
|
|
975
|
+
this.name = `UpdateOperationItemNotFoundError`;
|
|
976
|
+
}
|
|
977
|
+
};
|
|
978
|
+
var DeleteOperationItemNotFoundError = class extends QueryCollectionError {
|
|
979
|
+
constructor(key) {
|
|
980
|
+
super(`Delete operation: Item with key '${key}' does not exist`);
|
|
981
|
+
this.name = `DeleteOperationItemNotFoundError`;
|
|
982
|
+
}
|
|
983
|
+
};
|
|
984
|
+
|
|
985
|
+
// node_modules/@tanstack/query-db-collection/dist/esm/manual-sync.js
|
|
986
|
+
var activeBatchContexts = /* @__PURE__ */ new WeakMap();
|
|
987
|
+
function normalizeOperations(ops, ctx) {
|
|
988
|
+
const operations = Array.isArray(ops) ? ops : [ops];
|
|
989
|
+
const normalized = [];
|
|
990
|
+
for (const op of operations) {
|
|
991
|
+
if (op.type === `delete`) {
|
|
992
|
+
const keys = Array.isArray(op.key) ? op.key : [op.key];
|
|
993
|
+
for (const key of keys) {
|
|
994
|
+
normalized.push({ type: `delete`, key });
|
|
995
|
+
}
|
|
996
|
+
} else {
|
|
997
|
+
const items = Array.isArray(op.data) ? op.data : [op.data];
|
|
998
|
+
for (const item of items) {
|
|
999
|
+
let key;
|
|
1000
|
+
if (op.type === `update`) {
|
|
1001
|
+
key = ctx.getKey(item);
|
|
1002
|
+
} else {
|
|
1003
|
+
const resolved = ctx.collection.validateData(
|
|
1004
|
+
item,
|
|
1005
|
+
op.type === `upsert` ? `insert` : op.type
|
|
1006
|
+
);
|
|
1007
|
+
key = ctx.getKey(resolved);
|
|
1008
|
+
}
|
|
1009
|
+
normalized.push({ type: op.type, key, data: item });
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
return normalized;
|
|
1014
|
+
}
|
|
1015
|
+
function validateOperations(operations, ctx) {
|
|
1016
|
+
const seenKeys = /* @__PURE__ */ new Set();
|
|
1017
|
+
for (const op of operations) {
|
|
1018
|
+
if (seenKeys.has(op.key)) {
|
|
1019
|
+
throw new DuplicateKeyInBatchError(op.key);
|
|
1020
|
+
}
|
|
1021
|
+
seenKeys.add(op.key);
|
|
1022
|
+
if (op.type === `update`) {
|
|
1023
|
+
if (!ctx.collection._state.syncedData.has(op.key)) {
|
|
1024
|
+
throw new UpdateOperationItemNotFoundError(op.key);
|
|
1025
|
+
}
|
|
1026
|
+
} else if (op.type === `delete`) {
|
|
1027
|
+
if (!ctx.collection._state.syncedData.has(op.key)) {
|
|
1028
|
+
throw new DeleteOperationItemNotFoundError(op.key);
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
function performWriteOperations(operations, ctx) {
|
|
1034
|
+
const normalized = normalizeOperations(operations, ctx);
|
|
1035
|
+
validateOperations(normalized, ctx);
|
|
1036
|
+
ctx.begin();
|
|
1037
|
+
for (const op of normalized) {
|
|
1038
|
+
switch (op.type) {
|
|
1039
|
+
case `insert`: {
|
|
1040
|
+
const resolved = ctx.collection.validateData(op.data, `insert`);
|
|
1041
|
+
ctx.write({
|
|
1042
|
+
type: `insert`,
|
|
1043
|
+
value: resolved
|
|
1044
|
+
});
|
|
1045
|
+
break;
|
|
1046
|
+
}
|
|
1047
|
+
case `update`: {
|
|
1048
|
+
const currentItem = ctx.collection._state.syncedData.get(op.key);
|
|
1049
|
+
const updatedItem = {
|
|
1050
|
+
...currentItem,
|
|
1051
|
+
...op.data
|
|
1052
|
+
};
|
|
1053
|
+
const resolved = ctx.collection.validateData(
|
|
1054
|
+
updatedItem,
|
|
1055
|
+
`update`,
|
|
1056
|
+
op.key
|
|
1057
|
+
);
|
|
1058
|
+
ctx.write({
|
|
1059
|
+
type: `update`,
|
|
1060
|
+
value: resolved
|
|
1061
|
+
});
|
|
1062
|
+
break;
|
|
1063
|
+
}
|
|
1064
|
+
case `delete`: {
|
|
1065
|
+
const currentItem = ctx.collection._state.syncedData.get(op.key);
|
|
1066
|
+
ctx.write({
|
|
1067
|
+
type: `delete`,
|
|
1068
|
+
value: currentItem
|
|
1069
|
+
});
|
|
1070
|
+
break;
|
|
1071
|
+
}
|
|
1072
|
+
case `upsert`: {
|
|
1073
|
+
const existsInSyncedStore = ctx.collection._state.syncedData.has(op.key);
|
|
1074
|
+
const resolved = ctx.collection.validateData(
|
|
1075
|
+
op.data,
|
|
1076
|
+
existsInSyncedStore ? `update` : `insert`,
|
|
1077
|
+
op.key
|
|
1078
|
+
);
|
|
1079
|
+
if (existsInSyncedStore) {
|
|
1080
|
+
ctx.write({
|
|
1081
|
+
type: `update`,
|
|
1082
|
+
value: resolved
|
|
1083
|
+
});
|
|
1084
|
+
} else {
|
|
1085
|
+
ctx.write({
|
|
1086
|
+
type: `insert`,
|
|
1087
|
+
value: resolved
|
|
1088
|
+
});
|
|
1089
|
+
}
|
|
1090
|
+
break;
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
ctx.commit();
|
|
1095
|
+
const updatedData = Array.from(ctx.collection._state.syncedData.values());
|
|
1096
|
+
if (ctx.updateCacheData) {
|
|
1097
|
+
ctx.updateCacheData(updatedData);
|
|
1098
|
+
} else {
|
|
1099
|
+
ctx.queryClient.setQueryData(ctx.queryKey, updatedData);
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
function createWriteUtils(getContext) {
|
|
1103
|
+
function ensureContext() {
|
|
1104
|
+
const context = getContext();
|
|
1105
|
+
if (!context) {
|
|
1106
|
+
throw new SyncNotInitializedError();
|
|
1107
|
+
}
|
|
1108
|
+
return context;
|
|
1109
|
+
}
|
|
1110
|
+
return {
|
|
1111
|
+
writeInsert(data) {
|
|
1112
|
+
const operation = {
|
|
1113
|
+
type: `insert`,
|
|
1114
|
+
data
|
|
1115
|
+
};
|
|
1116
|
+
const ctx = ensureContext();
|
|
1117
|
+
const batchContext = activeBatchContexts.get(ctx);
|
|
1118
|
+
if (batchContext?.isActive) {
|
|
1119
|
+
batchContext.operations.push(operation);
|
|
1120
|
+
return;
|
|
1121
|
+
}
|
|
1122
|
+
performWriteOperations(operation, ctx);
|
|
1123
|
+
},
|
|
1124
|
+
writeUpdate(data) {
|
|
1125
|
+
const operation = {
|
|
1126
|
+
type: `update`,
|
|
1127
|
+
data
|
|
1128
|
+
};
|
|
1129
|
+
const ctx = ensureContext();
|
|
1130
|
+
const batchContext = activeBatchContexts.get(ctx);
|
|
1131
|
+
if (batchContext?.isActive) {
|
|
1132
|
+
batchContext.operations.push(operation);
|
|
1133
|
+
return;
|
|
1134
|
+
}
|
|
1135
|
+
performWriteOperations(operation, ctx);
|
|
1136
|
+
},
|
|
1137
|
+
writeDelete(key) {
|
|
1138
|
+
const operation = {
|
|
1139
|
+
type: `delete`,
|
|
1140
|
+
key
|
|
1141
|
+
};
|
|
1142
|
+
const ctx = ensureContext();
|
|
1143
|
+
const batchContext = activeBatchContexts.get(ctx);
|
|
1144
|
+
if (batchContext?.isActive) {
|
|
1145
|
+
batchContext.operations.push(operation);
|
|
1146
|
+
return;
|
|
1147
|
+
}
|
|
1148
|
+
performWriteOperations(operation, ctx);
|
|
1149
|
+
},
|
|
1150
|
+
writeUpsert(data) {
|
|
1151
|
+
const operation = {
|
|
1152
|
+
type: `upsert`,
|
|
1153
|
+
data
|
|
1154
|
+
};
|
|
1155
|
+
const ctx = ensureContext();
|
|
1156
|
+
const batchContext = activeBatchContexts.get(ctx);
|
|
1157
|
+
if (batchContext?.isActive) {
|
|
1158
|
+
batchContext.operations.push(operation);
|
|
1159
|
+
return;
|
|
1160
|
+
}
|
|
1161
|
+
performWriteOperations(operation, ctx);
|
|
1162
|
+
},
|
|
1163
|
+
writeBatch(callback) {
|
|
1164
|
+
const ctx = ensureContext();
|
|
1165
|
+
const existingBatch = activeBatchContexts.get(ctx);
|
|
1166
|
+
if (existingBatch?.isActive) {
|
|
1167
|
+
throw new Error(
|
|
1168
|
+
`Cannot nest writeBatch calls. Complete the current batch before starting a new one.`
|
|
1169
|
+
);
|
|
1170
|
+
}
|
|
1171
|
+
const batchContext = {
|
|
1172
|
+
operations: [],
|
|
1173
|
+
isActive: true
|
|
1174
|
+
};
|
|
1175
|
+
activeBatchContexts.set(ctx, batchContext);
|
|
1176
|
+
try {
|
|
1177
|
+
const result = callback();
|
|
1178
|
+
if (
|
|
1179
|
+
// @ts-expect-error - Runtime check for async callback, callback is typed as () => void but user might pass async
|
|
1180
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
1181
|
+
result && typeof result === `object` && `then` in result && // @ts-expect-error - Runtime check for async callback, callback is typed as () => void but user might pass async
|
|
1182
|
+
typeof result.then === `function`
|
|
1183
|
+
) {
|
|
1184
|
+
throw new Error(
|
|
1185
|
+
`writeBatch does not support async callbacks. The callback must be synchronous.`
|
|
1186
|
+
);
|
|
1187
|
+
}
|
|
1188
|
+
if (batchContext.operations.length > 0) {
|
|
1189
|
+
performWriteOperations(batchContext.operations, ctx);
|
|
1190
|
+
}
|
|
1191
|
+
} finally {
|
|
1192
|
+
batchContext.isActive = false;
|
|
1193
|
+
activeBatchContexts.delete(ctx);
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
};
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
// node_modules/@tanstack/query-db-collection/dist/esm/serialization.js
|
|
1200
|
+
function serializeLoadSubsetOptions(options) {
|
|
1201
|
+
if (!options) {
|
|
1202
|
+
return void 0;
|
|
1203
|
+
}
|
|
1204
|
+
const result = {};
|
|
1205
|
+
if (options.where) {
|
|
1206
|
+
result.where = serializeExpression(options.where);
|
|
1207
|
+
}
|
|
1208
|
+
if (options.orderBy?.length) {
|
|
1209
|
+
result.orderBy = options.orderBy.map((clause) => {
|
|
1210
|
+
const baseOrderBy = {
|
|
1211
|
+
expression: serializeExpression(clause.expression),
|
|
1212
|
+
direction: clause.compareOptions.direction,
|
|
1213
|
+
nulls: clause.compareOptions.nulls,
|
|
1214
|
+
stringSort: clause.compareOptions.stringSort
|
|
1215
|
+
};
|
|
1216
|
+
if (clause.compareOptions.stringSort === `locale`) {
|
|
1217
|
+
return {
|
|
1218
|
+
...baseOrderBy,
|
|
1219
|
+
locale: clause.compareOptions.locale,
|
|
1220
|
+
localeOptions: clause.compareOptions.localeOptions
|
|
1221
|
+
};
|
|
1222
|
+
}
|
|
1223
|
+
return baseOrderBy;
|
|
1224
|
+
});
|
|
1225
|
+
}
|
|
1226
|
+
if (options.limit !== void 0) {
|
|
1227
|
+
result.limit = options.limit;
|
|
1228
|
+
}
|
|
1229
|
+
if (options.offset !== void 0) {
|
|
1230
|
+
result.offset = options.offset;
|
|
1231
|
+
}
|
|
1232
|
+
return Object.keys(result).length === 0 ? void 0 : JSON.stringify(result);
|
|
1233
|
+
}
|
|
1234
|
+
function serializeExpression(expr) {
|
|
1235
|
+
if (!expr) {
|
|
1236
|
+
return null;
|
|
1237
|
+
}
|
|
1238
|
+
switch (expr.type) {
|
|
1239
|
+
case `val`:
|
|
1240
|
+
return {
|
|
1241
|
+
type: `val`,
|
|
1242
|
+
value: serializeValue(expr.value)
|
|
1243
|
+
};
|
|
1244
|
+
case `ref`:
|
|
1245
|
+
return {
|
|
1246
|
+
type: `ref`,
|
|
1247
|
+
path: [...expr.path]
|
|
1248
|
+
};
|
|
1249
|
+
case `func`:
|
|
1250
|
+
return {
|
|
1251
|
+
type: `func`,
|
|
1252
|
+
name: expr.name,
|
|
1253
|
+
args: expr.args.map((arg) => serializeExpression(arg))
|
|
1254
|
+
};
|
|
1255
|
+
default:
|
|
1256
|
+
return null;
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
function serializeValue(value) {
|
|
1260
|
+
if (value === void 0) {
|
|
1261
|
+
return { __type: `undefined` };
|
|
1262
|
+
}
|
|
1263
|
+
if (typeof value === `number`) {
|
|
1264
|
+
if (Number.isNaN(value)) {
|
|
1265
|
+
return { __type: `nan` };
|
|
1266
|
+
}
|
|
1267
|
+
if (value === Number.POSITIVE_INFINITY) {
|
|
1268
|
+
return { __type: `infinity`, sign: 1 };
|
|
1269
|
+
}
|
|
1270
|
+
if (value === Number.NEGATIVE_INFINITY) {
|
|
1271
|
+
return { __type: `infinity`, sign: -1 };
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
if (value === null || typeof value === `string` || typeof value === `number` || typeof value === `boolean`) {
|
|
1275
|
+
return value;
|
|
1276
|
+
}
|
|
1277
|
+
if (value instanceof Date) {
|
|
1278
|
+
return { __type: `date`, value: value.toJSON() };
|
|
1279
|
+
}
|
|
1280
|
+
if (Array.isArray(value)) {
|
|
1281
|
+
return value.map((item) => serializeValue(item));
|
|
1282
|
+
}
|
|
1283
|
+
if (typeof value === `object`) {
|
|
1284
|
+
return Object.fromEntries(
|
|
1285
|
+
Object.entries(value).map(([key, val]) => [
|
|
1286
|
+
key,
|
|
1287
|
+
serializeValue(val)
|
|
1288
|
+
])
|
|
1289
|
+
);
|
|
1290
|
+
}
|
|
1291
|
+
return value;
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1294
|
+
// node_modules/@tanstack/query-db-collection/dist/esm/query.js
|
|
1295
|
+
var QueryCollectionUtilsImpl = class {
|
|
1296
|
+
constructor(state, refetch, writeUtils) {
|
|
1297
|
+
this.state = state;
|
|
1298
|
+
this.refetchFn = refetch;
|
|
1299
|
+
this.refetch = refetch;
|
|
1300
|
+
this.writeInsert = writeUtils.writeInsert;
|
|
1301
|
+
this.writeUpdate = writeUtils.writeUpdate;
|
|
1302
|
+
this.writeDelete = writeUtils.writeDelete;
|
|
1303
|
+
this.writeUpsert = writeUtils.writeUpsert;
|
|
1304
|
+
this.writeBatch = writeUtils.writeBatch;
|
|
1305
|
+
}
|
|
1306
|
+
async clearError() {
|
|
1307
|
+
this.state.lastError = void 0;
|
|
1308
|
+
this.state.errorCount = 0;
|
|
1309
|
+
this.state.lastErrorUpdatedAt = 0;
|
|
1310
|
+
await this.refetchFn({ throwOnError: true });
|
|
1311
|
+
}
|
|
1312
|
+
// Getters for error state
|
|
1313
|
+
get lastError() {
|
|
1314
|
+
return this.state.lastError;
|
|
1315
|
+
}
|
|
1316
|
+
get isError() {
|
|
1317
|
+
return !!this.state.lastError;
|
|
1318
|
+
}
|
|
1319
|
+
get errorCount() {
|
|
1320
|
+
return this.state.errorCount;
|
|
1321
|
+
}
|
|
1322
|
+
// Getters for QueryObserver state
|
|
1323
|
+
get isFetching() {
|
|
1324
|
+
return Array.from(this.state.observers.values()).some(
|
|
1325
|
+
(observer) => observer.getCurrentResult().isFetching
|
|
1326
|
+
);
|
|
1327
|
+
}
|
|
1328
|
+
get isRefetching() {
|
|
1329
|
+
return Array.from(this.state.observers.values()).some(
|
|
1330
|
+
(observer) => observer.getCurrentResult().isRefetching
|
|
1331
|
+
);
|
|
1332
|
+
}
|
|
1333
|
+
get isLoading() {
|
|
1334
|
+
return Array.from(this.state.observers.values()).some(
|
|
1335
|
+
(observer) => observer.getCurrentResult().isLoading
|
|
1336
|
+
);
|
|
1337
|
+
}
|
|
1338
|
+
get dataUpdatedAt() {
|
|
1339
|
+
return Math.max(
|
|
1340
|
+
0,
|
|
1341
|
+
...Array.from(this.state.observers.values()).map(
|
|
1342
|
+
(observer) => observer.getCurrentResult().dataUpdatedAt
|
|
1343
|
+
)
|
|
1344
|
+
);
|
|
1345
|
+
}
|
|
1346
|
+
get fetchStatus() {
|
|
1347
|
+
return Array.from(this.state.observers.values()).map(
|
|
1348
|
+
(observer) => observer.getCurrentResult().fetchStatus
|
|
1349
|
+
);
|
|
1350
|
+
}
|
|
1351
|
+
};
|
|
1352
|
+
function queryCollectionOptions(config) {
|
|
1353
|
+
const {
|
|
1354
|
+
queryKey,
|
|
1355
|
+
queryFn,
|
|
1356
|
+
select,
|
|
1357
|
+
queryClient,
|
|
1358
|
+
enabled,
|
|
1359
|
+
refetchInterval,
|
|
1360
|
+
retry,
|
|
1361
|
+
retryDelay,
|
|
1362
|
+
staleTime,
|
|
1363
|
+
getKey,
|
|
1364
|
+
onInsert,
|
|
1365
|
+
onUpdate,
|
|
1366
|
+
onDelete,
|
|
1367
|
+
meta,
|
|
1368
|
+
...baseCollectionConfig
|
|
1369
|
+
} = config;
|
|
1370
|
+
const syncMode = baseCollectionConfig.syncMode ?? `eager`;
|
|
1371
|
+
if (!queryKey) {
|
|
1372
|
+
throw new QueryKeyRequiredError();
|
|
1373
|
+
}
|
|
1374
|
+
if (!queryFn) {
|
|
1375
|
+
throw new QueryFnRequiredError();
|
|
1376
|
+
}
|
|
1377
|
+
if (!queryClient) {
|
|
1378
|
+
throw new QueryClientRequiredError();
|
|
1379
|
+
}
|
|
1380
|
+
if (!getKey) {
|
|
1381
|
+
throw new GetKeyRequiredError();
|
|
1382
|
+
}
|
|
1383
|
+
const state = {
|
|
1384
|
+
lastError: void 0,
|
|
1385
|
+
errorCount: 0,
|
|
1386
|
+
lastErrorUpdatedAt: 0,
|
|
1387
|
+
observers: /* @__PURE__ */ new Map()
|
|
1388
|
+
};
|
|
1389
|
+
const hashToQueryKey = /* @__PURE__ */ new Map();
|
|
1390
|
+
const queryToRows = /* @__PURE__ */ new Map();
|
|
1391
|
+
const rowToQueries = /* @__PURE__ */ new Map();
|
|
1392
|
+
const unsubscribes = /* @__PURE__ */ new Map();
|
|
1393
|
+
const queryRefCounts = /* @__PURE__ */ new Map();
|
|
1394
|
+
const addRow = (rowKey, hashedQueryKey) => {
|
|
1395
|
+
const rowToQueriesSet = rowToQueries.get(rowKey) || /* @__PURE__ */ new Set();
|
|
1396
|
+
rowToQueriesSet.add(hashedQueryKey);
|
|
1397
|
+
rowToQueries.set(rowKey, rowToQueriesSet);
|
|
1398
|
+
const queryToRowsSet = queryToRows.get(hashedQueryKey) || /* @__PURE__ */ new Set();
|
|
1399
|
+
queryToRowsSet.add(rowKey);
|
|
1400
|
+
queryToRows.set(hashedQueryKey, queryToRowsSet);
|
|
1401
|
+
};
|
|
1402
|
+
const removeRow = (rowKey, hashedQuerKey) => {
|
|
1403
|
+
const rowToQueriesSet = rowToQueries.get(rowKey) || /* @__PURE__ */ new Set();
|
|
1404
|
+
rowToQueriesSet.delete(hashedQuerKey);
|
|
1405
|
+
rowToQueries.set(rowKey, rowToQueriesSet);
|
|
1406
|
+
const queryToRowsSet = queryToRows.get(hashedQuerKey) || /* @__PURE__ */ new Set();
|
|
1407
|
+
queryToRowsSet.delete(rowKey);
|
|
1408
|
+
queryToRows.set(hashedQuerKey, queryToRowsSet);
|
|
1409
|
+
return rowToQueriesSet.size === 0;
|
|
1410
|
+
};
|
|
1411
|
+
const internalSync = (params) => {
|
|
1412
|
+
const { begin, write, commit, markReady, collection } = params;
|
|
1413
|
+
let syncStarted = false;
|
|
1414
|
+
const generateQueryKeyFromOptions = (opts) => {
|
|
1415
|
+
if (typeof queryKey === `function`) {
|
|
1416
|
+
return queryKey(opts);
|
|
1417
|
+
} else if (syncMode === `on-demand`) {
|
|
1418
|
+
const serialized = serializeLoadSubsetOptions(opts);
|
|
1419
|
+
return serialized !== void 0 ? [...queryKey, serialized] : queryKey;
|
|
1420
|
+
} else {
|
|
1421
|
+
return queryKey;
|
|
1422
|
+
}
|
|
1423
|
+
};
|
|
1424
|
+
const createQueryFromOpts = (opts = {}, queryFunction = queryFn) => {
|
|
1425
|
+
const key = generateQueryKeyFromOptions(opts);
|
|
1426
|
+
const hashedQueryKey = hashKey(key);
|
|
1427
|
+
const extendedMeta = { ...meta, loadSubsetOptions: opts };
|
|
1428
|
+
if (state.observers.has(hashedQueryKey)) {
|
|
1429
|
+
queryRefCounts.set(
|
|
1430
|
+
hashedQueryKey,
|
|
1431
|
+
(queryRefCounts.get(hashedQueryKey) || 0) + 1
|
|
1432
|
+
);
|
|
1433
|
+
const observer = state.observers.get(hashedQueryKey);
|
|
1434
|
+
const currentResult = observer.getCurrentResult();
|
|
1435
|
+
if (currentResult.isSuccess) {
|
|
1436
|
+
return true;
|
|
1437
|
+
} else if (currentResult.isError) {
|
|
1438
|
+
return Promise.reject(currentResult.error);
|
|
1439
|
+
} else {
|
|
1440
|
+
return new Promise((resolve, reject) => {
|
|
1441
|
+
const unsubscribe = observer.subscribe((result) => {
|
|
1442
|
+
queueMicrotask(() => {
|
|
1443
|
+
if (result.isSuccess) {
|
|
1444
|
+
unsubscribe();
|
|
1445
|
+
resolve();
|
|
1446
|
+
} else if (result.isError) {
|
|
1447
|
+
unsubscribe();
|
|
1448
|
+
reject(result.error);
|
|
1449
|
+
}
|
|
1450
|
+
});
|
|
1451
|
+
});
|
|
1452
|
+
});
|
|
1453
|
+
}
|
|
1454
|
+
}
|
|
1455
|
+
const observerOptions = {
|
|
1456
|
+
queryKey: key,
|
|
1457
|
+
queryFn: queryFunction,
|
|
1458
|
+
meta: extendedMeta,
|
|
1459
|
+
structuralSharing: true,
|
|
1460
|
+
notifyOnChangeProps: `all`,
|
|
1461
|
+
// Only include options that are explicitly defined to allow QueryClient defaultOptions to be used
|
|
1462
|
+
...enabled !== void 0 && { enabled },
|
|
1463
|
+
...refetchInterval !== void 0 && { refetchInterval },
|
|
1464
|
+
...retry !== void 0 && { retry },
|
|
1465
|
+
...retryDelay !== void 0 && { retryDelay },
|
|
1466
|
+
...staleTime !== void 0 && { staleTime }
|
|
1467
|
+
};
|
|
1468
|
+
const localObserver = new QueryObserver(queryClient, observerOptions);
|
|
1469
|
+
hashToQueryKey.set(hashedQueryKey, key);
|
|
1470
|
+
state.observers.set(hashedQueryKey, localObserver);
|
|
1471
|
+
queryRefCounts.set(
|
|
1472
|
+
hashedQueryKey,
|
|
1473
|
+
(queryRefCounts.get(hashedQueryKey) || 0) + 1
|
|
1474
|
+
);
|
|
1475
|
+
const readyPromise = new Promise((resolve, reject) => {
|
|
1476
|
+
const unsubscribe = localObserver.subscribe((result) => {
|
|
1477
|
+
queueMicrotask(() => {
|
|
1478
|
+
if (result.isSuccess) {
|
|
1479
|
+
unsubscribe();
|
|
1480
|
+
resolve();
|
|
1481
|
+
} else if (result.isError) {
|
|
1482
|
+
unsubscribe();
|
|
1483
|
+
reject(result.error);
|
|
1484
|
+
}
|
|
1485
|
+
});
|
|
1486
|
+
});
|
|
1487
|
+
});
|
|
1488
|
+
if (syncStarted || collection.subscriberCount > 0) {
|
|
1489
|
+
subscribeToQuery(localObserver, hashedQueryKey);
|
|
1490
|
+
}
|
|
1491
|
+
return readyPromise;
|
|
1492
|
+
};
|
|
1493
|
+
const makeQueryResultHandler = (queryKey2) => {
|
|
1494
|
+
const hashedQueryKey = hashKey(queryKey2);
|
|
1495
|
+
const handleQueryResult = (result) => {
|
|
1496
|
+
if (result.isSuccess) {
|
|
1497
|
+
state.lastError = void 0;
|
|
1498
|
+
state.errorCount = 0;
|
|
1499
|
+
const rawData = result.data;
|
|
1500
|
+
const newItemsArray = select ? select(rawData) : rawData;
|
|
1501
|
+
if (!Array.isArray(newItemsArray) || newItemsArray.some((item) => typeof item !== `object`)) {
|
|
1502
|
+
const errorMessage = select ? `@tanstack/query-db-collection: select() must return an array of objects. Got: ${typeof newItemsArray} for queryKey ${JSON.stringify(queryKey2)}` : `@tanstack/query-db-collection: queryFn must return an array of objects. Got: ${typeof newItemsArray} for queryKey ${JSON.stringify(queryKey2)}`;
|
|
1503
|
+
console.error(errorMessage);
|
|
1504
|
+
return;
|
|
1505
|
+
}
|
|
1506
|
+
const currentSyncedItems = new Map(
|
|
1507
|
+
collection._state.syncedData.entries()
|
|
1508
|
+
);
|
|
1509
|
+
const newItemsMap = /* @__PURE__ */ new Map();
|
|
1510
|
+
newItemsArray.forEach((item) => {
|
|
1511
|
+
const key = getKey(item);
|
|
1512
|
+
newItemsMap.set(key, item);
|
|
1513
|
+
});
|
|
1514
|
+
begin();
|
|
1515
|
+
currentSyncedItems.forEach((oldItem, key) => {
|
|
1516
|
+
const newItem = newItemsMap.get(key);
|
|
1517
|
+
if (!newItem) {
|
|
1518
|
+
const needToRemove = removeRow(key, hashedQueryKey);
|
|
1519
|
+
if (needToRemove) {
|
|
1520
|
+
write({ type: `delete`, value: oldItem });
|
|
1521
|
+
}
|
|
1522
|
+
} else if (!(0, import_db2.deepEquals)(oldItem, newItem)) {
|
|
1523
|
+
write({ type: `update`, value: newItem });
|
|
1524
|
+
}
|
|
1525
|
+
});
|
|
1526
|
+
newItemsMap.forEach((newItem, key) => {
|
|
1527
|
+
addRow(key, hashedQueryKey);
|
|
1528
|
+
if (!currentSyncedItems.has(key)) {
|
|
1529
|
+
write({ type: `insert`, value: newItem });
|
|
1530
|
+
}
|
|
1531
|
+
});
|
|
1532
|
+
commit();
|
|
1533
|
+
markReady();
|
|
1534
|
+
} else if (result.isError) {
|
|
1535
|
+
if (result.errorUpdatedAt !== state.lastErrorUpdatedAt) {
|
|
1536
|
+
state.lastError = result.error;
|
|
1537
|
+
state.errorCount++;
|
|
1538
|
+
state.lastErrorUpdatedAt = result.errorUpdatedAt;
|
|
1539
|
+
}
|
|
1540
|
+
console.error(
|
|
1541
|
+
`[QueryCollection] Error observing query ${String(queryKey2)}:`,
|
|
1542
|
+
result.error
|
|
1543
|
+
);
|
|
1544
|
+
markReady();
|
|
1545
|
+
}
|
|
1546
|
+
};
|
|
1547
|
+
return handleQueryResult;
|
|
1548
|
+
};
|
|
1549
|
+
const isSubscribed = (hashedQueryKey) => {
|
|
1550
|
+
return unsubscribes.has(hashedQueryKey);
|
|
1551
|
+
};
|
|
1552
|
+
const subscribeToQuery = (observer, hashedQueryKey) => {
|
|
1553
|
+
if (!isSubscribed(hashedQueryKey)) {
|
|
1554
|
+
const cachedQueryKey = hashToQueryKey.get(hashedQueryKey);
|
|
1555
|
+
const handleQueryResult = makeQueryResultHandler(cachedQueryKey);
|
|
1556
|
+
const unsubscribeFn = observer.subscribe(handleQueryResult);
|
|
1557
|
+
unsubscribes.set(hashedQueryKey, unsubscribeFn);
|
|
1558
|
+
const currentResult = observer.getCurrentResult();
|
|
1559
|
+
if (currentResult.isSuccess || currentResult.isError) {
|
|
1560
|
+
handleQueryResult(currentResult);
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
};
|
|
1564
|
+
const subscribeToQueries = () => {
|
|
1565
|
+
state.observers.forEach(subscribeToQuery);
|
|
1566
|
+
};
|
|
1567
|
+
const unsubscribeFromQueries = () => {
|
|
1568
|
+
unsubscribes.forEach((unsubscribeFn) => {
|
|
1569
|
+
unsubscribeFn();
|
|
1570
|
+
});
|
|
1571
|
+
unsubscribes.clear();
|
|
1572
|
+
};
|
|
1573
|
+
syncStarted = true;
|
|
1574
|
+
const unsubscribeFromCollectionEvents = collection.on(
|
|
1575
|
+
`subscribers:change`,
|
|
1576
|
+
({ subscriberCount }) => {
|
|
1577
|
+
if (subscriberCount > 0) {
|
|
1578
|
+
subscribeToQueries();
|
|
1579
|
+
} else if (subscriberCount === 0) {
|
|
1580
|
+
unsubscribeFromQueries();
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
);
|
|
1584
|
+
if (syncMode === `eager`) {
|
|
1585
|
+
const initialResult = createQueryFromOpts({});
|
|
1586
|
+
if (initialResult instanceof Promise) {
|
|
1587
|
+
initialResult.catch(() => {
|
|
1588
|
+
});
|
|
1589
|
+
}
|
|
1590
|
+
} else {
|
|
1591
|
+
markReady();
|
|
1592
|
+
}
|
|
1593
|
+
subscribeToQueries();
|
|
1594
|
+
state.observers.forEach((observer, hashedQueryKey) => {
|
|
1595
|
+
const cachedQueryKey = hashToQueryKey.get(hashedQueryKey);
|
|
1596
|
+
const handleQueryResult = makeQueryResultHandler(cachedQueryKey);
|
|
1597
|
+
handleQueryResult(observer.getCurrentResult());
|
|
1598
|
+
});
|
|
1599
|
+
const cleanupQueryInternal = (hashedQueryKey) => {
|
|
1600
|
+
unsubscribes.get(hashedQueryKey)?.();
|
|
1601
|
+
unsubscribes.delete(hashedQueryKey);
|
|
1602
|
+
const rowKeys = queryToRows.get(hashedQueryKey) ?? /* @__PURE__ */ new Set();
|
|
1603
|
+
const rowsToDelete = [];
|
|
1604
|
+
rowKeys.forEach((rowKey) => {
|
|
1605
|
+
const queries = rowToQueries.get(rowKey);
|
|
1606
|
+
if (!queries) {
|
|
1607
|
+
return;
|
|
1608
|
+
}
|
|
1609
|
+
queries.delete(hashedQueryKey);
|
|
1610
|
+
if (queries.size === 0) {
|
|
1611
|
+
rowToQueries.delete(rowKey);
|
|
1612
|
+
if (collection.has(rowKey)) {
|
|
1613
|
+
rowsToDelete.push(collection.get(rowKey));
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
});
|
|
1617
|
+
if (rowsToDelete.length > 0) {
|
|
1618
|
+
begin();
|
|
1619
|
+
rowsToDelete.forEach((row) => {
|
|
1620
|
+
write({ type: `delete`, value: row });
|
|
1621
|
+
});
|
|
1622
|
+
commit();
|
|
1623
|
+
}
|
|
1624
|
+
state.observers.delete(hashedQueryKey);
|
|
1625
|
+
queryToRows.delete(hashedQueryKey);
|
|
1626
|
+
hashToQueryKey.delete(hashedQueryKey);
|
|
1627
|
+
queryRefCounts.delete(hashedQueryKey);
|
|
1628
|
+
};
|
|
1629
|
+
const cleanupQueryIfIdle = (hashedQueryKey) => {
|
|
1630
|
+
const refcount = queryRefCounts.get(hashedQueryKey) || 0;
|
|
1631
|
+
const observer = state.observers.get(hashedQueryKey);
|
|
1632
|
+
if (refcount <= 0) {
|
|
1633
|
+
unsubscribes.get(hashedQueryKey)?.();
|
|
1634
|
+
unsubscribes.delete(hashedQueryKey);
|
|
1635
|
+
}
|
|
1636
|
+
const hasListeners = observer?.hasListeners() ?? false;
|
|
1637
|
+
if (hasListeners) {
|
|
1638
|
+
queryRefCounts.set(hashedQueryKey, 0);
|
|
1639
|
+
return;
|
|
1640
|
+
}
|
|
1641
|
+
if (refcount > 0) {
|
|
1642
|
+
console.warn(
|
|
1643
|
+
`[cleanupQueryIfIdle] Invariant violation: refcount=${refcount} but no listeners. Cleaning up to prevent leak.`,
|
|
1644
|
+
{ hashedQueryKey }
|
|
1645
|
+
);
|
|
1646
|
+
}
|
|
1647
|
+
cleanupQueryInternal(hashedQueryKey);
|
|
1648
|
+
};
|
|
1649
|
+
const forceCleanupQuery = (hashedQueryKey) => {
|
|
1650
|
+
cleanupQueryInternal(hashedQueryKey);
|
|
1651
|
+
};
|
|
1652
|
+
const unsubscribeQueryCache = queryClient.getQueryCache().subscribe((event) => {
|
|
1653
|
+
const hashedKey = event.query.queryHash;
|
|
1654
|
+
if (event.type === `removed`) {
|
|
1655
|
+
if (hashToQueryKey.has(hashedKey)) {
|
|
1656
|
+
cleanupQueryIfIdle(hashedKey);
|
|
1657
|
+
}
|
|
1658
|
+
}
|
|
1659
|
+
});
|
|
1660
|
+
const cleanup = async () => {
|
|
1661
|
+
unsubscribeFromCollectionEvents();
|
|
1662
|
+
unsubscribeFromQueries();
|
|
1663
|
+
const allQueryKeys = [...hashToQueryKey.values()];
|
|
1664
|
+
const allHashedKeys = [...state.observers.keys()];
|
|
1665
|
+
for (const hashedKey of allHashedKeys) {
|
|
1666
|
+
forceCleanupQuery(hashedKey);
|
|
1667
|
+
}
|
|
1668
|
+
unsubscribeQueryCache();
|
|
1669
|
+
await Promise.all(
|
|
1670
|
+
allQueryKeys.map(async (qKey) => {
|
|
1671
|
+
await queryClient.cancelQueries({ queryKey: qKey, exact: true });
|
|
1672
|
+
queryClient.removeQueries({ queryKey: qKey, exact: true });
|
|
1673
|
+
})
|
|
1674
|
+
);
|
|
1675
|
+
};
|
|
1676
|
+
const unloadSubset = (options) => {
|
|
1677
|
+
const key = generateQueryKeyFromOptions(options);
|
|
1678
|
+
const hashedQueryKey = hashKey(key);
|
|
1679
|
+
const currentCount = queryRefCounts.get(hashedQueryKey) || 0;
|
|
1680
|
+
const newCount = currentCount - 1;
|
|
1681
|
+
if (newCount <= 0) {
|
|
1682
|
+
queryRefCounts.set(hashedQueryKey, 0);
|
|
1683
|
+
cleanupQueryIfIdle(hashedQueryKey);
|
|
1684
|
+
} else {
|
|
1685
|
+
queryRefCounts.set(hashedQueryKey, newCount);
|
|
1686
|
+
}
|
|
1687
|
+
};
|
|
1688
|
+
const loadSubsetDedupe = syncMode === `eager` ? void 0 : createQueryFromOpts;
|
|
1689
|
+
return {
|
|
1690
|
+
loadSubset: loadSubsetDedupe,
|
|
1691
|
+
unloadSubset: syncMode === `eager` ? void 0 : unloadSubset,
|
|
1692
|
+
cleanup
|
|
1693
|
+
};
|
|
1694
|
+
};
|
|
1695
|
+
const refetch = async (opts) => {
|
|
1696
|
+
const allQueryKeys = [...hashToQueryKey.values()];
|
|
1697
|
+
const refetchPromises = allQueryKeys.map((qKey) => {
|
|
1698
|
+
const queryObserver = state.observers.get(hashKey(qKey));
|
|
1699
|
+
return queryObserver.refetch({
|
|
1700
|
+
throwOnError: opts?.throwOnError
|
|
1701
|
+
});
|
|
1702
|
+
});
|
|
1703
|
+
await Promise.all(refetchPromises);
|
|
1704
|
+
};
|
|
1705
|
+
const updateCacheData = (items) => {
|
|
1706
|
+
const key = typeof queryKey === `function` ? queryKey({}) : queryKey;
|
|
1707
|
+
if (select) {
|
|
1708
|
+
queryClient.setQueryData(key, (oldData) => {
|
|
1709
|
+
if (!oldData || typeof oldData !== `object`) {
|
|
1710
|
+
return oldData;
|
|
1711
|
+
}
|
|
1712
|
+
if (Array.isArray(oldData)) {
|
|
1713
|
+
return items;
|
|
1714
|
+
}
|
|
1715
|
+
const selectedArray = select(oldData);
|
|
1716
|
+
if (Array.isArray(selectedArray)) {
|
|
1717
|
+
for (const propKey of Object.keys(oldData)) {
|
|
1718
|
+
if (oldData[propKey] === selectedArray) {
|
|
1719
|
+
return { ...oldData, [propKey]: items };
|
|
1720
|
+
}
|
|
1721
|
+
}
|
|
1722
|
+
}
|
|
1723
|
+
if (Array.isArray(oldData.data)) {
|
|
1724
|
+
return { ...oldData, data: items };
|
|
1725
|
+
}
|
|
1726
|
+
if (Array.isArray(oldData.items)) {
|
|
1727
|
+
return { ...oldData, items };
|
|
1728
|
+
}
|
|
1729
|
+
if (Array.isArray(oldData.results)) {
|
|
1730
|
+
return { ...oldData, results: items };
|
|
1731
|
+
}
|
|
1732
|
+
for (const propKey of Object.keys(oldData)) {
|
|
1733
|
+
if (Array.isArray(oldData[propKey])) {
|
|
1734
|
+
return { ...oldData, [propKey]: items };
|
|
1735
|
+
}
|
|
1736
|
+
}
|
|
1737
|
+
return oldData;
|
|
1738
|
+
});
|
|
1739
|
+
} else {
|
|
1740
|
+
queryClient.setQueryData(key, items);
|
|
1741
|
+
}
|
|
1742
|
+
};
|
|
1743
|
+
let writeContext = null;
|
|
1744
|
+
const enhancedInternalSync = (params) => {
|
|
1745
|
+
const { begin, write, commit, collection } = params;
|
|
1746
|
+
const contextQueryKey = typeof queryKey === `function` ? queryKey({}) : queryKey;
|
|
1747
|
+
writeContext = {
|
|
1748
|
+
collection,
|
|
1749
|
+
queryClient,
|
|
1750
|
+
queryKey: contextQueryKey,
|
|
1751
|
+
getKey,
|
|
1752
|
+
begin,
|
|
1753
|
+
write,
|
|
1754
|
+
commit,
|
|
1755
|
+
updateCacheData
|
|
1756
|
+
};
|
|
1757
|
+
return internalSync(params);
|
|
1758
|
+
};
|
|
1759
|
+
const writeUtils = createWriteUtils(
|
|
1760
|
+
() => writeContext
|
|
1761
|
+
);
|
|
1762
|
+
const wrappedOnInsert = onInsert ? async (params) => {
|
|
1763
|
+
const handlerResult = await onInsert(params) ?? {};
|
|
1764
|
+
const shouldRefetch = handlerResult.refetch !== false;
|
|
1765
|
+
if (shouldRefetch) {
|
|
1766
|
+
await refetch();
|
|
1767
|
+
}
|
|
1768
|
+
return handlerResult;
|
|
1769
|
+
} : void 0;
|
|
1770
|
+
const wrappedOnUpdate = onUpdate ? async (params) => {
|
|
1771
|
+
const handlerResult = await onUpdate(params) ?? {};
|
|
1772
|
+
const shouldRefetch = handlerResult.refetch !== false;
|
|
1773
|
+
if (shouldRefetch) {
|
|
1774
|
+
await refetch();
|
|
1775
|
+
}
|
|
1776
|
+
return handlerResult;
|
|
1777
|
+
} : void 0;
|
|
1778
|
+
const wrappedOnDelete = onDelete ? async (params) => {
|
|
1779
|
+
const handlerResult = await onDelete(params) ?? {};
|
|
1780
|
+
const shouldRefetch = handlerResult.refetch !== false;
|
|
1781
|
+
if (shouldRefetch) {
|
|
1782
|
+
await refetch();
|
|
1783
|
+
}
|
|
1784
|
+
return handlerResult;
|
|
1785
|
+
} : void 0;
|
|
1786
|
+
const utils = new QueryCollectionUtilsImpl(state, refetch, writeUtils);
|
|
1787
|
+
return {
|
|
1788
|
+
...baseCollectionConfig,
|
|
1789
|
+
getKey,
|
|
1790
|
+
syncMode,
|
|
1791
|
+
sync: { sync: enhancedInternalSync },
|
|
1792
|
+
onInsert: wrappedOnInsert,
|
|
1793
|
+
onUpdate: wrappedOnUpdate,
|
|
1794
|
+
onDelete: wrappedOnDelete,
|
|
1795
|
+
utils
|
|
1796
|
+
};
|
|
1797
|
+
}
|
|
1798
|
+
|
|
1799
|
+
// node_modules/@tanstack/query-db-collection/dist/esm/index.js
|
|
1800
|
+
var import_db3 = require("@tanstack/db");
|
|
1801
|
+
|
|
1802
|
+
// src/index.ts
|
|
25
1803
|
var import_loro_crdt = require("loro-crdt");
|
|
26
1804
|
var import_surrealdb2 = require("surrealdb");
|
|
27
1805
|
|
|
28
1806
|
// src/table.ts
|
|
29
1807
|
var import_surrealdb = require("surrealdb");
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
for (const row of rows) cache.set(idKey(row.id), row);
|
|
42
|
-
};
|
|
43
|
-
const removeFromCache = (id) => {
|
|
44
|
-
cache.delete(idKey(id));
|
|
45
|
-
};
|
|
46
|
-
const listCached = () => Array.from(cache.values());
|
|
47
|
-
const buildWhere = () => {
|
|
1808
|
+
var normalizeFields = (raw) => {
|
|
1809
|
+
if (!raw || raw === "*") return ["*"];
|
|
1810
|
+
return raw;
|
|
1811
|
+
};
|
|
1812
|
+
var joinOrderBy = (o) => {
|
|
1813
|
+
if (!o) return void 0;
|
|
1814
|
+
return typeof o === "string" ? o : o.join(", ");
|
|
1815
|
+
};
|
|
1816
|
+
function manageTable(db, useLoro, { name, ...args }) {
|
|
1817
|
+
const fields = normalizeFields(args.fields);
|
|
1818
|
+
const baseWhere = () => {
|
|
48
1819
|
if (!useLoro) return args.where;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const applyPaging = (q, start, limit) => {
|
|
58
|
-
if (typeof start === "number" && q.start) q = q.start(start);
|
|
59
|
-
if (typeof limit === "number" && q.limit) q = q.limit(limit);
|
|
60
|
-
return q;
|
|
61
|
-
};
|
|
62
|
-
const fetchAll = async () => {
|
|
63
|
-
const rows = await buildQuery().fields(...fields);
|
|
64
|
-
upsertCache(rows);
|
|
65
|
-
fullyLoaded = true;
|
|
66
|
-
return rows;
|
|
67
|
-
};
|
|
68
|
-
const fetchPage = async (opts) => {
|
|
69
|
-
const q = applyPaging(
|
|
70
|
-
buildQuery(),
|
|
71
|
-
opts?.start ?? 0,
|
|
72
|
-
opts?.limit ?? pageSize
|
|
73
|
-
);
|
|
74
|
-
const rows = await q.fields(...fields);
|
|
75
|
-
upsertCache(rows);
|
|
76
|
-
if (rows.length < (opts?.limit ?? pageSize)) fullyLoaded = true;
|
|
77
|
-
return rows;
|
|
78
|
-
};
|
|
79
|
-
const fetchById = async (id) => {
|
|
80
|
-
const key = idKey(id);
|
|
81
|
-
const cached = cache.get(key);
|
|
82
|
-
if (cached) return cached;
|
|
83
|
-
const res = await db.select(id);
|
|
84
|
-
const row = Array.isArray(res) ? res[0] : res;
|
|
85
|
-
if (!row) return null;
|
|
86
|
-
if (useLoro && row.sync_deleted)
|
|
87
|
-
return null;
|
|
88
|
-
cache.set(key, row);
|
|
89
|
-
return row;
|
|
90
|
-
};
|
|
91
|
-
const loadMore = async (limit = pageSize) => {
|
|
92
|
-
if (fullyLoaded) return { rows: [], done: true };
|
|
93
|
-
const rows = await fetchPage({ start: cursor, limit });
|
|
94
|
-
cursor += rows.length;
|
|
95
|
-
const done = fullyLoaded || rows.length < limit;
|
|
96
|
-
args.onProgress?.({
|
|
1820
|
+
const alive = (0, import_surrealdb.eq)("sync_deleted", false);
|
|
1821
|
+
return args.where ? (0, import_surrealdb.and)(args.where, alive) : alive;
|
|
1822
|
+
};
|
|
1823
|
+
const listAll = async () => {
|
|
1824
|
+
const where = baseWhere();
|
|
1825
|
+
const whereSql = where ? " WHERE $where" : "";
|
|
1826
|
+
const sql = `SELECT ${fields.join(", ")} FROM type::table($table)${whereSql};`;
|
|
1827
|
+
const [res] = await db.query(sql, {
|
|
97
1828
|
table: name,
|
|
98
|
-
|
|
99
|
-
lastBatch: rows.length,
|
|
100
|
-
done
|
|
101
|
-
});
|
|
102
|
-
return { rows, done };
|
|
103
|
-
};
|
|
104
|
-
const startProgressive = () => {
|
|
105
|
-
if (progressiveTask || fullyLoaded) return;
|
|
106
|
-
progressiveTask = (async () => {
|
|
107
|
-
if (cache.size === 0) await loadMore(initialPageSize);
|
|
108
|
-
while (!fullyLoaded) {
|
|
109
|
-
const { done } = await loadMore(pageSize);
|
|
110
|
-
if (done) break;
|
|
111
|
-
}
|
|
112
|
-
})().finally(() => {
|
|
113
|
-
progressiveTask = null;
|
|
1829
|
+
where
|
|
114
1830
|
});
|
|
1831
|
+
return res ?? [];
|
|
115
1832
|
};
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
1833
|
+
const loadSubset = async (subset) => {
|
|
1834
|
+
const b = baseWhere();
|
|
1835
|
+
const w = subset?.where;
|
|
1836
|
+
const where = b && w ? (0, import_surrealdb.and)(b, w) : b ?? w;
|
|
1837
|
+
const whereSql = where ? " WHERE $where" : "";
|
|
1838
|
+
const order = joinOrderBy(subset?.orderBy);
|
|
1839
|
+
const orderSql = order ? ` ORDER BY ${order}` : "";
|
|
1840
|
+
const limitSql = typeof subset?.limit === "number" ? " LIMIT $limit" : "";
|
|
1841
|
+
const startSql = typeof subset?.offset === "number" ? " START $offset" : "";
|
|
1842
|
+
const sql = `SELECT ${fields.join(", ")} FROM type::table($table)${whereSql}${orderSql}${limitSql}${startSql};`;
|
|
1843
|
+
const [res] = await db.query(sql, {
|
|
1844
|
+
table: name,
|
|
1845
|
+
where,
|
|
1846
|
+
limit: subset?.limit,
|
|
1847
|
+
offset: subset?.offset
|
|
1848
|
+
});
|
|
1849
|
+
return res ?? [];
|
|
125
1850
|
};
|
|
126
1851
|
const create = async (data) => {
|
|
127
1852
|
await db.create(new import_surrealdb.Table(name)).content(data);
|
|
@@ -134,24 +1859,21 @@ function manageTable(db, useLoro, { name, ...args }, syncMode = "eager") {
|
|
|
134
1859
|
await db.update(id).merge({
|
|
135
1860
|
...data,
|
|
136
1861
|
sync_deleted: false,
|
|
137
|
-
updated_at:
|
|
1862
|
+
updated_at: Date.now()
|
|
138
1863
|
});
|
|
139
1864
|
};
|
|
140
1865
|
const remove = async (id) => {
|
|
141
1866
|
await db.delete(id);
|
|
142
|
-
removeFromCache(id);
|
|
143
1867
|
};
|
|
144
1868
|
const softDelete = async (id) => {
|
|
145
1869
|
if (!useLoro) {
|
|
146
1870
|
await db.delete(id);
|
|
147
|
-
removeFromCache(id);
|
|
148
1871
|
return;
|
|
149
1872
|
}
|
|
150
1873
|
await db.upsert(id).merge({
|
|
151
1874
|
sync_deleted: true,
|
|
152
|
-
updated_at:
|
|
1875
|
+
updated_at: Date.now()
|
|
153
1876
|
});
|
|
154
|
-
removeFromCache(id);
|
|
155
1877
|
};
|
|
156
1878
|
const subscribe = (cb) => {
|
|
157
1879
|
let killed = false;
|
|
@@ -159,25 +1881,10 @@ function manageTable(db, useLoro, { name, ...args }, syncMode = "eager") {
|
|
|
159
1881
|
const on = (msg) => {
|
|
160
1882
|
const { action, value } = msg;
|
|
161
1883
|
if (action === "KILLED") return;
|
|
162
|
-
if (action === "CREATE") {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
return;
|
|
166
|
-
}
|
|
167
|
-
if (action === "UPDATE") {
|
|
168
|
-
if (useLoro && value.sync_deleted) {
|
|
169
|
-
removeFromCache(value.id);
|
|
170
|
-
cb({ type: "delete", row: { id: value.id } });
|
|
171
|
-
return;
|
|
172
|
-
}
|
|
173
|
-
upsertCache([value]);
|
|
174
|
-
cb({ type: "update", row: value });
|
|
175
|
-
return;
|
|
176
|
-
}
|
|
177
|
-
if (action === "DELETE") {
|
|
178
|
-
removeFromCache(value.id);
|
|
1884
|
+
if (action === "CREATE") cb({ type: "insert", row: value });
|
|
1885
|
+
else if (action === "UPDATE") cb({ type: "update", row: value });
|
|
1886
|
+
else if (action === "DELETE")
|
|
179
1887
|
cb({ type: "delete", row: { id: value.id } });
|
|
180
|
-
}
|
|
181
1888
|
};
|
|
182
1889
|
const start = async () => {
|
|
183
1890
|
if (!db.isFeatureSupported(import_surrealdb.Features.LiveQueries)) return;
|
|
@@ -193,380 +1900,166 @@ function manageTable(db, useLoro, { name, ...args }, syncMode = "eager") {
|
|
|
193
1900
|
};
|
|
194
1901
|
return {
|
|
195
1902
|
listAll,
|
|
196
|
-
|
|
197
|
-
listCached,
|
|
198
|
-
fetchPage,
|
|
199
|
-
fetchById,
|
|
200
|
-
loadMore,
|
|
1903
|
+
loadSubset,
|
|
201
1904
|
create,
|
|
202
1905
|
update,
|
|
203
1906
|
remove,
|
|
204
1907
|
softDelete,
|
|
205
|
-
subscribe
|
|
206
|
-
get isFullyLoaded() {
|
|
207
|
-
return fullyLoaded;
|
|
208
|
-
},
|
|
209
|
-
get cachedCount() {
|
|
210
|
-
return cache.size;
|
|
211
|
-
}
|
|
1908
|
+
subscribe
|
|
212
1909
|
};
|
|
213
1910
|
}
|
|
214
1911
|
|
|
215
1912
|
// src/index.ts
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
if (typeof
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
return JSON.stringify(toJson(value));
|
|
235
|
-
};
|
|
236
|
-
var chunk = (arr, size) => {
|
|
237
|
-
const out = [];
|
|
238
|
-
for (let i = 0; i < arr.length; i += size) out.push(arr.slice(i, i + size));
|
|
239
|
-
return out;
|
|
240
|
-
};
|
|
1913
|
+
function toCleanup(res) {
|
|
1914
|
+
if (!res) return () => {
|
|
1915
|
+
};
|
|
1916
|
+
if (typeof res === "function") {
|
|
1917
|
+
return res;
|
|
1918
|
+
}
|
|
1919
|
+
if (typeof res === "object" && res !== null) {
|
|
1920
|
+
const r = res;
|
|
1921
|
+
const cleanup = r["cleanup"];
|
|
1922
|
+
if (typeof cleanup === "function") return cleanup;
|
|
1923
|
+
const unsubscribe = r["unsubscribe"];
|
|
1924
|
+
if (typeof unsubscribe === "function") return unsubscribe;
|
|
1925
|
+
const dispose = r["dispose"];
|
|
1926
|
+
if (typeof dispose === "function") return dispose;
|
|
1927
|
+
}
|
|
1928
|
+
return () => {
|
|
1929
|
+
};
|
|
1930
|
+
}
|
|
241
1931
|
function surrealCollectionOptions({
|
|
242
1932
|
id,
|
|
243
1933
|
useLoro = false,
|
|
244
1934
|
onError,
|
|
245
1935
|
db,
|
|
246
|
-
|
|
1936
|
+
queryClient,
|
|
1937
|
+
queryKey,
|
|
1938
|
+
syncMode = "eager",
|
|
247
1939
|
...config
|
|
248
1940
|
}) {
|
|
249
1941
|
let loro;
|
|
250
1942
|
if (useLoro) loro = { doc: new import_loro_crdt.LoroDoc(), key: id };
|
|
1943
|
+
const table = manageTable(db, useLoro, config.table);
|
|
251
1944
|
const keyOf = (rid) => typeof rid === "string" ? rid : rid.toString();
|
|
252
1945
|
const getKey = (row) => keyOf(row.id);
|
|
253
1946
|
const loroKey = loro?.key ?? id ?? "surreal";
|
|
254
1947
|
const loroMap = useLoro ? loro?.doc?.getMap?.(loroKey) ?? null : null;
|
|
255
|
-
const
|
|
256
|
-
if (!loroMap) return
|
|
257
|
-
|
|
258
|
-
return Object.values(json);
|
|
259
|
-
};
|
|
260
|
-
const loroPutMany = (rows) => {
|
|
261
|
-
if (!loroMap || rows.length === 0) return;
|
|
262
|
-
for (const row of rows) loroMap.set(getKey(row), row);
|
|
1948
|
+
const loroPut = (row) => {
|
|
1949
|
+
if (!loroMap) return;
|
|
1950
|
+
loroMap.set(getKey(row), row);
|
|
263
1951
|
loro?.doc?.commit?.();
|
|
264
1952
|
};
|
|
265
|
-
const
|
|
266
|
-
if (!loroMap
|
|
267
|
-
|
|
1953
|
+
const loroRemove = (idStr) => {
|
|
1954
|
+
if (!loroMap) return;
|
|
1955
|
+
loroMap.delete(idStr);
|
|
268
1956
|
loro?.doc?.commit?.();
|
|
269
1957
|
};
|
|
270
|
-
const
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
const flushPushQueue = async () => {
|
|
277
|
-
if (!useLoro) return;
|
|
278
|
-
const ops = pushQueue.splice(0, pushQueue.length);
|
|
279
|
-
for (const op of ops) {
|
|
280
|
-
if (op.kind === "create") {
|
|
281
|
-
await table.create(op.row);
|
|
282
|
-
} else if (op.kind === "update") {
|
|
283
|
-
const rid = new import_surrealdb2.RecordId(
|
|
284
|
-
config.table.name,
|
|
285
|
-
op.row.id.toString()
|
|
286
|
-
);
|
|
287
|
-
await table.update(rid, op.row);
|
|
288
|
-
} else {
|
|
289
|
-
const rid = new import_surrealdb2.RecordId(config.table.name, op.id);
|
|
290
|
-
await table.softDelete(rid);
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
};
|
|
294
|
-
const newer = (a, b) => (a?.getTime() ?? -1) > (b?.getTime() ?? -1);
|
|
295
|
-
const fetchServerByLocalIds = async (ids) => {
|
|
296
|
-
if (ids.length === 0) return [];
|
|
297
|
-
const tableName = config.table.name;
|
|
298
|
-
const parts = chunk(ids, LOCAL_ID_VERIFY_CHUNK);
|
|
1958
|
+
const mergeLocalOverServer = (serverRows) => {
|
|
1959
|
+
if (!useLoro || !loroMap) return serverRows;
|
|
1960
|
+
const localJson = loroMap.toJSON?.() ?? {};
|
|
1961
|
+
const localById = new Map(
|
|
1962
|
+
Object.values(localJson).map((r) => [getKey(r), r])
|
|
1963
|
+
);
|
|
299
1964
|
const out = [];
|
|
300
|
-
for (const
|
|
301
|
-
const
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
}
|
|
307
|
-
);
|
|
308
|
-
if (res) out.push(...res);
|
|
309
|
-
}
|
|
310
|
-
return out;
|
|
311
|
-
};
|
|
312
|
-
const dedupeById = (rows) => {
|
|
313
|
-
const m = /* @__PURE__ */ new Map();
|
|
314
|
-
for (const r of rows) m.set(getKey(r), r);
|
|
315
|
-
return Array.from(m.values());
|
|
316
|
-
};
|
|
317
|
-
let prevById = /* @__PURE__ */ new Map();
|
|
318
|
-
const buildMap = (rows) => new Map(rows.map((r) => [getKey(r), r]));
|
|
319
|
-
const same = (a, b) => {
|
|
320
|
-
if (useLoro) {
|
|
321
|
-
return (a.sync_deleted ?? false) === (b.sync_deleted ?? false) && (a.updated_at?.getTime() ?? 0) === (b.updated_at?.getTime() ?? 0);
|
|
322
|
-
}
|
|
323
|
-
return stableStringify(a) === stableStringify(b);
|
|
324
|
-
};
|
|
325
|
-
const diffAndEmit = (currentRows, write) => {
|
|
326
|
-
const currById = buildMap(currentRows);
|
|
327
|
-
for (const [id2, row] of currById) {
|
|
328
|
-
const prev = prevById.get(id2);
|
|
329
|
-
if (!prev) write({ type: "insert", value: row });
|
|
330
|
-
else if (!same(prev, row)) write({ type: "update", value: row });
|
|
331
|
-
}
|
|
332
|
-
for (const [id2, prev] of prevById) {
|
|
333
|
-
if (!currById.has(id2)) write({ type: "delete", value: prev });
|
|
334
|
-
}
|
|
335
|
-
prevById = currById;
|
|
336
|
-
};
|
|
337
|
-
const reconcileBoot = (serverRows, write) => {
|
|
338
|
-
const localRows = loroToArray();
|
|
339
|
-
const serverById = new Map(serverRows.map((r) => [getKey(r), r]));
|
|
340
|
-
const localById = new Map(localRows.map((r) => [getKey(r), r]));
|
|
341
|
-
const ids = /* @__PURE__ */ new Set([...serverById.keys(), ...localById.keys()]);
|
|
342
|
-
const current = [];
|
|
343
|
-
const toRemove = [];
|
|
344
|
-
const toPut = [];
|
|
345
|
-
const applyLocal = (row) => {
|
|
346
|
-
if (!row) return;
|
|
347
|
-
if (row.sync_deleted) toRemove.push(getKey(row));
|
|
348
|
-
else toPut.push(row);
|
|
349
|
-
};
|
|
350
|
-
for (const id2 of ids) {
|
|
351
|
-
const s = serverById.get(id2);
|
|
352
|
-
const l = localById.get(id2);
|
|
353
|
-
if (s && l) {
|
|
354
|
-
const sDeleted = s.sync_deleted ?? false;
|
|
355
|
-
const lDeleted = l.sync_deleted ?? false;
|
|
356
|
-
const sUpdated = s.updated_at;
|
|
357
|
-
const lUpdated = l.updated_at;
|
|
358
|
-
if (sDeleted && lDeleted) {
|
|
359
|
-
applyLocal(s);
|
|
360
|
-
current.push(s);
|
|
361
|
-
} else if (sDeleted && !lDeleted) {
|
|
362
|
-
applyLocal(s);
|
|
363
|
-
current.push(s);
|
|
364
|
-
} else if (!sDeleted && lDeleted) {
|
|
365
|
-
if (newer(lUpdated, sUpdated)) {
|
|
366
|
-
enqueuePush({
|
|
367
|
-
kind: "delete",
|
|
368
|
-
id: id2,
|
|
369
|
-
updated_at: lUpdated ?? /* @__PURE__ */ new Date()
|
|
370
|
-
});
|
|
371
|
-
applyLocal(l);
|
|
372
|
-
current.push(l);
|
|
373
|
-
} else {
|
|
374
|
-
applyLocal(s);
|
|
375
|
-
current.push(s);
|
|
376
|
-
}
|
|
377
|
-
} else {
|
|
378
|
-
if (newer(lUpdated, sUpdated)) {
|
|
379
|
-
enqueuePush({ kind: "update", row: l });
|
|
380
|
-
applyLocal(l);
|
|
381
|
-
current.push(l);
|
|
382
|
-
} else {
|
|
383
|
-
applyLocal(s);
|
|
384
|
-
current.push(s);
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
} else if (s && !l) {
|
|
388
|
-
applyLocal(s);
|
|
389
|
-
current.push(s);
|
|
390
|
-
} else if (!s && l) {
|
|
391
|
-
const lDeleted = l.sync_deleted ?? false;
|
|
392
|
-
const lUpdated = l.updated_at;
|
|
393
|
-
if (lDeleted) {
|
|
394
|
-
enqueuePush({
|
|
395
|
-
kind: "delete",
|
|
396
|
-
id: id2,
|
|
397
|
-
updated_at: lUpdated ?? /* @__PURE__ */ new Date()
|
|
398
|
-
});
|
|
399
|
-
applyLocal(l);
|
|
400
|
-
current.push(l);
|
|
401
|
-
} else {
|
|
402
|
-
enqueuePush({ kind: "create", row: l });
|
|
403
|
-
applyLocal(l);
|
|
404
|
-
current.push(l);
|
|
405
|
-
}
|
|
1965
|
+
for (const s of serverRows) {
|
|
1966
|
+
const idStr = getKey(s);
|
|
1967
|
+
const l = localById.get(idStr);
|
|
1968
|
+
if (!l) {
|
|
1969
|
+
out.push(s);
|
|
1970
|
+
continue;
|
|
406
1971
|
}
|
|
1972
|
+
const lDeleted = (l.sync_deleted ?? false) === true;
|
|
1973
|
+
if (lDeleted) continue;
|
|
1974
|
+
out.push(l);
|
|
407
1975
|
}
|
|
408
|
-
|
|
409
|
-
loroPutMany(toPut);
|
|
410
|
-
diffAndEmit(current, write);
|
|
1976
|
+
return out;
|
|
411
1977
|
};
|
|
412
|
-
const
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
markReady
|
|
419
|
-
}) => {
|
|
420
|
-
if (!db.isFeatureSupported(import_surrealdb2.Features.LiveQueries)) {
|
|
421
|
-
markReady();
|
|
422
|
-
return () => {
|
|
423
|
-
};
|
|
424
|
-
}
|
|
425
|
-
let offLive = null;
|
|
426
|
-
let work = Promise.resolve();
|
|
427
|
-
const enqueueWork = (fn) => {
|
|
428
|
-
work = work.then(fn).catch((e) => onError?.(e));
|
|
429
|
-
return work;
|
|
430
|
-
};
|
|
431
|
-
const makeTombstone = (id2) => ({
|
|
432
|
-
id: new import_surrealdb2.RecordId(config.table.name, id2).toString(),
|
|
433
|
-
updated_at: now(),
|
|
434
|
-
sync_deleted: true
|
|
435
|
-
});
|
|
436
|
-
const start = async () => {
|
|
1978
|
+
const base = queryCollectionOptions({
|
|
1979
|
+
getKey: (row) => getKey(row),
|
|
1980
|
+
queryKey,
|
|
1981
|
+
queryClient,
|
|
1982
|
+
syncMode,
|
|
1983
|
+
queryFn: async ({ meta }) => {
|
|
437
1984
|
try {
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
} else if (syncMode === "progressive") {
|
|
442
|
-
const first = await table.loadMore(
|
|
443
|
-
config.table.initialPageSize ?? DEFAULT_INITIAL_PAGE_SIZE
|
|
444
|
-
);
|
|
445
|
-
serverRows = first.rows;
|
|
446
|
-
} else {
|
|
447
|
-
serverRows = await table.listActive();
|
|
448
|
-
}
|
|
449
|
-
await enqueueWork(async () => {
|
|
450
|
-
begin();
|
|
451
|
-
if (useLoro) {
|
|
452
|
-
const localIds = loroToArray().map(getKey);
|
|
453
|
-
const verifiedServerRows = syncMode === "eager" ? serverRows : dedupeById([
|
|
454
|
-
...serverRows,
|
|
455
|
-
...await fetchServerByLocalIds(
|
|
456
|
-
localIds
|
|
457
|
-
)
|
|
458
|
-
]);
|
|
459
|
-
reconcileBoot(verifiedServerRows, write);
|
|
460
|
-
} else {
|
|
461
|
-
diffAndEmit(serverRows, write);
|
|
462
|
-
}
|
|
463
|
-
commit();
|
|
464
|
-
markReady();
|
|
465
|
-
});
|
|
466
|
-
if (syncMode === "progressive") {
|
|
467
|
-
void (async () => {
|
|
468
|
-
while (!table.isFullyLoaded) {
|
|
469
|
-
const { rows } = await table.loadMore();
|
|
470
|
-
if (rows.length === 0) break;
|
|
471
|
-
await enqueueWork(async () => {
|
|
472
|
-
begin();
|
|
473
|
-
try {
|
|
474
|
-
if (useLoro) loroPutMany(rows);
|
|
475
|
-
diffAndEmit(rows, write);
|
|
476
|
-
} finally {
|
|
477
|
-
commit();
|
|
478
|
-
}
|
|
479
|
-
});
|
|
480
|
-
}
|
|
481
|
-
})().catch((e) => onError?.(e));
|
|
482
|
-
}
|
|
483
|
-
await flushPushQueue();
|
|
484
|
-
offLive = table.subscribe((evt) => {
|
|
485
|
-
void enqueueWork(async () => {
|
|
486
|
-
begin();
|
|
487
|
-
try {
|
|
488
|
-
if (evt.type === "insert" || evt.type === "update") {
|
|
489
|
-
const row = evt.row;
|
|
490
|
-
const deleted = useLoro ? row.sync_deleted ?? false : false;
|
|
491
|
-
if (deleted) {
|
|
492
|
-
if (useLoro) loroRemove(getKey(row));
|
|
493
|
-
const prev = prevById.get(getKey(row)) ?? makeTombstone(getKey(row));
|
|
494
|
-
write({ type: "delete", value: prev });
|
|
495
|
-
prevById.delete(getKey(row));
|
|
496
|
-
} else {
|
|
497
|
-
if (useLoro) loroPutMany([row]);
|
|
498
|
-
const had = prevById.has(getKey(row));
|
|
499
|
-
write({
|
|
500
|
-
type: had ? "update" : "insert",
|
|
501
|
-
value: row
|
|
502
|
-
});
|
|
503
|
-
prevById.set(getKey(row), row);
|
|
504
|
-
}
|
|
505
|
-
} else {
|
|
506
|
-
const rid = getKey(evt.row);
|
|
507
|
-
if (useLoro) loroRemove(rid);
|
|
508
|
-
const prev = prevById.get(rid) ?? makeTombstone(rid);
|
|
509
|
-
write({ type: "delete", value: prev });
|
|
510
|
-
prevById.delete(rid);
|
|
511
|
-
}
|
|
512
|
-
} finally {
|
|
513
|
-
commit();
|
|
514
|
-
}
|
|
515
|
-
});
|
|
516
|
-
});
|
|
1985
|
+
const subset = syncMode === "on-demand" ? meta["surrealSubset"] : void 0;
|
|
1986
|
+
const rows = syncMode === "eager" ? await table.listAll() : await table.loadSubset(subset);
|
|
1987
|
+
return mergeLocalOverServer(rows);
|
|
517
1988
|
} catch (e) {
|
|
518
1989
|
onError?.(e);
|
|
519
|
-
|
|
1990
|
+
return [];
|
|
520
1991
|
}
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
const
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
1992
|
+
},
|
|
1993
|
+
onInsert: (async (p) => {
|
|
1994
|
+
const now = () => /* @__PURE__ */ new Date();
|
|
1995
|
+
const resultRows = [];
|
|
1996
|
+
for (const m of p.transaction.mutations) {
|
|
1997
|
+
if (m.type !== "insert") continue;
|
|
1998
|
+
const baseRow = { ...m.modified };
|
|
1999
|
+
const row = useLoro ? {
|
|
2000
|
+
...baseRow,
|
|
2001
|
+
updated_at: now(),
|
|
2002
|
+
sync_deleted: false
|
|
2003
|
+
} : baseRow;
|
|
2004
|
+
if (useLoro) loroPut(row);
|
|
2005
|
+
await table.create(row);
|
|
2006
|
+
resultRows.push(row);
|
|
2007
|
+
}
|
|
2008
|
+
return resultRows;
|
|
2009
|
+
}),
|
|
2010
|
+
onUpdate: (async (p) => {
|
|
2011
|
+
const now = () => /* @__PURE__ */ new Date();
|
|
2012
|
+
const resultRows = [];
|
|
2013
|
+
for (const m of p.transaction.mutations) {
|
|
2014
|
+
if (m.type !== "update") continue;
|
|
2015
|
+
const idKey = m.key;
|
|
2016
|
+
const baseRow = { ...m.modified, id: idKey };
|
|
2017
|
+
const row = useLoro ? { ...baseRow, updated_at: now() } : baseRow;
|
|
2018
|
+
if (useLoro) loroPut(row);
|
|
2019
|
+
await table.update(
|
|
2020
|
+
new import_surrealdb2.RecordId(config.table.name, keyOf(idKey)),
|
|
2021
|
+
row
|
|
2022
|
+
);
|
|
2023
|
+
resultRows.push(row);
|
|
2024
|
+
}
|
|
2025
|
+
return resultRows;
|
|
2026
|
+
}),
|
|
2027
|
+
onDelete: (async (p) => {
|
|
2028
|
+
for (const m of p.transaction.mutations) {
|
|
2029
|
+
if (m.type !== "delete") continue;
|
|
2030
|
+
const idKey = m.key;
|
|
2031
|
+
if (useLoro) loroRemove(keyOf(idKey));
|
|
2032
|
+
await table.softDelete(
|
|
2033
|
+
new import_surrealdb2.RecordId(config.table.name, keyOf(idKey))
|
|
2034
|
+
);
|
|
2035
|
+
}
|
|
2036
|
+
return [];
|
|
2037
|
+
})
|
|
2038
|
+
});
|
|
2039
|
+
const baseSync = base.sync?.sync;
|
|
2040
|
+
const sync = baseSync ? {
|
|
2041
|
+
sync: (ctx) => {
|
|
2042
|
+
const offBase = baseSync(ctx);
|
|
2043
|
+
if (!db.isFeatureSupported(import_surrealdb2.Features.LiveQueries))
|
|
2044
|
+
return offBase;
|
|
2045
|
+
const offLive = table.subscribe((evt) => {
|
|
2046
|
+
if (useLoro) {
|
|
2047
|
+
if (evt.type === "delete")
|
|
2048
|
+
loroRemove(getKey(evt.row));
|
|
2049
|
+
else loroPut(evt.row);
|
|
2050
|
+
}
|
|
2051
|
+
void queryClient.invalidateQueries({ queryKey, exact: false }).catch((e) => onError?.(e));
|
|
2052
|
+
});
|
|
2053
|
+
const baseCleanup = toCleanup(baseSync(ctx));
|
|
2054
|
+
return () => {
|
|
2055
|
+
offLive();
|
|
2056
|
+
baseCleanup();
|
|
2057
|
+
};
|
|
2058
|
+
}
|
|
2059
|
+
} : void 0;
|
|
563
2060
|
return {
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
sync: { sync },
|
|
567
|
-
onInsert,
|
|
568
|
-
onDelete,
|
|
569
|
-
onUpdate
|
|
2061
|
+
...base,
|
|
2062
|
+
sync: sync ?? base.sync
|
|
570
2063
|
};
|
|
571
2064
|
}
|
|
572
2065
|
// Annotate the CommonJS export names for ESM import in node:
|