@signaldb/core 2.0.0-beta.0 → 2.0.0-beta.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/.vite/manifest.json +25 -12
- package/dist/AutoFetchDataAdapter.d.ts +0 -1
- package/dist/Collection/index.d.ts +2 -0
- package/dist/DataAdapter.d.ts +7 -6
- package/dist/DefaultDataAdapter.d.ts +1 -0
- package/dist/WorkerDataAdapter.d.ts +4 -1
- package/dist/WorkerDataAdapterHost.d.ts +9 -6
- package/dist/index.cjs12.js +32 -21
- package/dist/index.cjs13.js +25 -13
- package/dist/index.cjs14.js +31 -37
- package/dist/index.cjs15.js +120 -75
- package/dist/index.cjs16.js +45 -36
- package/dist/index.cjs17.js +1 -1
- package/dist/index.cjs2.js +5 -2
- package/dist/index.cjs20.js +5 -102
- package/dist/index.cjs21.js +93 -118
- package/dist/index.cjs22.js +127 -5
- package/dist/index.cjs23.js +5 -25
- package/dist/index.cjs24.js +25 -5
- package/dist/index.cjs26.js +1 -1
- package/dist/index.cjs27.js +44 -3
- package/dist/index.cjs28.js +6 -5
- package/dist/index.cjs29.js +7 -27
- package/dist/index.cjs3.js +25 -21
- package/dist/index.cjs30.js +3 -40
- package/dist/index.cjs31.js +5 -7
- package/dist/index.cjs32.js +29 -0
- package/dist/index.cjs33.js +42 -0
- package/dist/index.d.ts +1 -0
- package/dist/index12.mjs +32 -21
- package/dist/index13.mjs +25 -13
- package/dist/index14.mjs +31 -37
- package/dist/index15.mjs +120 -75
- package/dist/index16.mjs +45 -36
- package/dist/index17.mjs +1 -1
- package/dist/index2.mjs +5 -2
- package/dist/index20.mjs +5 -102
- package/dist/index21.mjs +93 -117
- package/dist/index22.mjs +126 -5
- package/dist/index23.mjs +5 -25
- package/dist/index24.mjs +25 -5
- package/dist/index26.mjs +1 -1
- package/dist/index27.mjs +44 -3
- package/dist/index28.mjs +6 -5
- package/dist/index29.mjs +7 -27
- package/dist/index3.mjs +25 -21
- package/dist/index30.mjs +3 -40
- package/dist/index31.mjs +5 -7
- package/dist/index32.mjs +30 -0
- package/dist/index33.mjs +43 -0
- package/dist/utils/batchOnNextTick.d.ts +16 -0
- package/package.json +1 -1
package/dist/index.cjs15.js
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const deepClone = require("./index.cjs19.js");
|
|
3
|
-
const match = require("./index.
|
|
3
|
+
const match = require("./index.cjs23.js");
|
|
4
4
|
const modify = require("./index.cjs7.js");
|
|
5
|
-
const queryId = require("./index.
|
|
5
|
+
const queryId = require("./index.cjs20.js");
|
|
6
6
|
const isEqual = require("./index.cjs6.js");
|
|
7
|
-
const getIndexInfo = require("./index.
|
|
7
|
+
const getIndexInfo = require("./index.cjs22.js");
|
|
8
8
|
const getMatchingKeys = require("./index.cjs26.js");
|
|
9
9
|
const sortItems = require("./index.cjs25.js");
|
|
10
|
-
const project = require("./index.
|
|
10
|
+
const project = require("./index.cjs24.js");
|
|
11
|
+
const compact = require("./index.cjs28.js");
|
|
11
12
|
class WorkerDataAdapterHost {
|
|
12
13
|
workerContext;
|
|
13
14
|
options;
|
|
14
15
|
id;
|
|
16
|
+
log = () => {
|
|
17
|
+
};
|
|
15
18
|
storageAdapters = /* @__PURE__ */ new Map();
|
|
16
19
|
storageAdapterReady = /* @__PURE__ */ new Map();
|
|
17
20
|
collectionIndices = /* @__PURE__ */ new Map();
|
|
@@ -26,6 +29,8 @@ class WorkerDataAdapterHost {
|
|
|
26
29
|
if (this.options.onError) {
|
|
27
30
|
this.onError = this.options.onError;
|
|
28
31
|
}
|
|
32
|
+
if (this.options.log)
|
|
33
|
+
this.log = this.options.log;
|
|
29
34
|
if (typeof addEventListener === "undefined" || typeof postMessage === "undefined") {
|
|
30
35
|
throw new TypeError("WorkerDataAdapterHost can only be used in a Web Worker context");
|
|
31
36
|
}
|
|
@@ -50,6 +55,8 @@ class WorkerDataAdapterHost {
|
|
|
50
55
|
this.respond(id, null, new Error(`Method ${method} not found`));
|
|
51
56
|
return;
|
|
52
57
|
}
|
|
58
|
+
this.log(method, ...args);
|
|
59
|
+
await this.isReady(args[0]);
|
|
53
60
|
try {
|
|
54
61
|
const result = await fn.apply(this, args);
|
|
55
62
|
this.respond(id, result);
|
|
@@ -64,7 +71,7 @@ class WorkerDataAdapterHost {
|
|
|
64
71
|
if (selector != null && Object.keys(selector).length === 1 && "id" in selector && typeof selector.id !== "object") {
|
|
65
72
|
return {
|
|
66
73
|
matched: true,
|
|
67
|
-
ids: [selector.id],
|
|
74
|
+
ids: compact([selector.id]),
|
|
68
75
|
optimizedSelector: {}
|
|
69
76
|
};
|
|
70
77
|
}
|
|
@@ -214,10 +221,7 @@ class WorkerDataAdapterHost {
|
|
|
214
221
|
if (!storageAdapter)
|
|
215
222
|
throw new Error(`No persistence adapter for collection ${collectionName}`);
|
|
216
223
|
const setupPromise = (async () => {
|
|
217
|
-
await Promise.all(
|
|
218
|
-
storageAdapter.createIndex("id"),
|
|
219
|
-
...indices.map((index) => storageAdapter.createIndex(index))
|
|
220
|
-
]);
|
|
224
|
+
await Promise.all(indices.map((index) => storageAdapter.createIndex(index)));
|
|
221
225
|
await storageAdapter.setup();
|
|
222
226
|
})();
|
|
223
227
|
this.storageAdapterReady.set(collectionName, setupPromise);
|
|
@@ -238,101 +242,142 @@ class WorkerDataAdapterHost {
|
|
|
238
242
|
throw new Error(`Collection ${collectionName} not initialized!`);
|
|
239
243
|
this.queries.get(collectionName)?.delete(id);
|
|
240
244
|
};
|
|
241
|
-
insert = async (collectionName,
|
|
242
|
-
const storageAdapter = this.storageAdapters.get(collectionName);
|
|
243
|
-
if (!storageAdapter)
|
|
244
|
-
throw new Error(`No persistence adapter for collection ${collectionName}`);
|
|
245
|
-
const existingItems = await this.executeQuery(collectionName, { id: newItem.id }, { limit: 1 });
|
|
246
|
-
if (existingItems.length > 0) {
|
|
247
|
-
throw new Error(`Item with id ${newItem.id} already exists`);
|
|
248
|
-
}
|
|
249
|
-
await storageAdapter.insert([newItem]);
|
|
250
|
-
await this.checkQueryUpdates(collectionName, [newItem]);
|
|
251
|
-
return newItem;
|
|
252
|
-
};
|
|
253
|
-
updateOne = async (collectionName, selector, modifier) => {
|
|
245
|
+
insert = async (collectionName, input) => {
|
|
254
246
|
const storageAdapter = this.storageAdapters.get(collectionName);
|
|
255
247
|
if (!storageAdapter)
|
|
256
248
|
throw new Error(`No persistence adapter for collection ${collectionName}`);
|
|
257
|
-
const
|
|
258
|
-
const
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
const existingItems = await this.executeQuery(collectionName, { id: modifiedItem.id }, { limit: 1 });
|
|
264
|
-
if (existingItems.length > 0) {
|
|
265
|
-
throw new Error(`Item with id ${modifiedItem.id} already exists`);
|
|
249
|
+
const existingItems = await this.executeQuery(collectionName, { id: { $in: input.map((i) => i[0].id) } });
|
|
250
|
+
const result = input.map(([item]) => {
|
|
251
|
+
if (item.id == null)
|
|
252
|
+
throw new Error("Item must have an id");
|
|
253
|
+
if (existingItems.some((existing) => existing.id === item.id)) {
|
|
254
|
+
return new Error(`Item with id ${item.id} already exists`);
|
|
266
255
|
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
256
|
+
return item;
|
|
257
|
+
});
|
|
258
|
+
const newItems = result.filter((item) => !(item instanceof Error));
|
|
259
|
+
await storageAdapter.insert(newItems);
|
|
260
|
+
await this.checkQueryUpdates(collectionName, newItems);
|
|
261
|
+
return result;
|
|
271
262
|
};
|
|
272
|
-
|
|
263
|
+
updateOne = async (collectionName, parameters) => {
|
|
273
264
|
const storageAdapter = this.storageAdapters.get(collectionName);
|
|
274
265
|
if (!storageAdapter)
|
|
275
266
|
throw new Error(`No persistence adapter for collection ${collectionName}`);
|
|
276
|
-
const
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
267
|
+
const previousItems = [];
|
|
268
|
+
const result = await Promise.all(parameters.map(async ([selector, modifier]) => {
|
|
269
|
+
const item = await this.executeQuery(collectionName, selector, { limit: 1 }).then((items) => items[0] ?? null);
|
|
270
|
+
const { $setOnInsert, ...restModifier } = modifier;
|
|
271
|
+
if (item == null)
|
|
272
|
+
return [];
|
|
273
|
+
previousItems.push(item);
|
|
281
274
|
const modifiedItem = modify(deepClone.default(item), restModifier);
|
|
282
275
|
if (item.id !== modifiedItem.id) {
|
|
283
276
|
const existingItems = await this.executeQuery(collectionName, { id: modifiedItem.id }, { limit: 1 });
|
|
284
277
|
if (existingItems.length > 0) {
|
|
285
|
-
|
|
278
|
+
return new Error(`Item with id ${modifiedItem.id} already exists`);
|
|
286
279
|
}
|
|
287
280
|
}
|
|
288
|
-
return modifiedItem;
|
|
281
|
+
return [modifiedItem];
|
|
289
282
|
}));
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
283
|
+
const modifiedItems = compact(result.filter((item) => !(item instanceof Error)).flat());
|
|
284
|
+
if (modifiedItems.length > 0) {
|
|
285
|
+
await storageAdapter.replace(modifiedItems);
|
|
286
|
+
await this.checkQueryUpdates(collectionName, [...modifiedItems, ...previousItems]);
|
|
287
|
+
}
|
|
288
|
+
return result;
|
|
293
289
|
};
|
|
294
|
-
|
|
290
|
+
updateMany = async (collectionName, parameters) => {
|
|
295
291
|
const storageAdapter = this.storageAdapters.get(collectionName);
|
|
296
292
|
if (!storageAdapter)
|
|
297
293
|
throw new Error(`No persistence adapter for collection ${collectionName}`);
|
|
298
|
-
const
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
294
|
+
const previousItems = [];
|
|
295
|
+
const result = await Promise.all(parameters.map(async ([selector, modifier]) => {
|
|
296
|
+
const items = await this.executeQuery(collectionName, selector);
|
|
297
|
+
if (items.length === 0)
|
|
298
|
+
return [];
|
|
299
|
+
const { $setOnInsert, ...restModifier } = modifier;
|
|
300
|
+
try {
|
|
301
|
+
const changedItems = await Promise.all(items.map(async (item) => {
|
|
302
|
+
const modifiedItem = modify(deepClone.default(item), restModifier);
|
|
303
|
+
if (item.id !== modifiedItem.id) {
|
|
304
|
+
const existingItems = await this.executeQuery(collectionName, { id: modifiedItem.id }, { limit: 1 });
|
|
305
|
+
if (existingItems.length > 0) {
|
|
306
|
+
throw new Error(`Item with id ${modifiedItem.id} already exists`);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
previousItems.push(item);
|
|
310
|
+
return modifiedItem;
|
|
311
|
+
}));
|
|
312
|
+
return changedItems;
|
|
313
|
+
} catch (error) {
|
|
314
|
+
return error;
|
|
315
|
+
}
|
|
316
|
+
}));
|
|
317
|
+
const modifiedItems = compact(result.filter((item) => !(item instanceof Error)).flat());
|
|
318
|
+
if (modifiedItems.length > 0) {
|
|
319
|
+
await storageAdapter.replace(modifiedItems);
|
|
320
|
+
await this.checkQueryUpdates(collectionName, [...modifiedItems, ...previousItems]);
|
|
321
|
+
}
|
|
322
|
+
return result;
|
|
323
|
+
};
|
|
324
|
+
replaceOne = async (collectionName, parameters) => {
|
|
325
|
+
const storageAdapter = this.storageAdapters.get(collectionName);
|
|
326
|
+
if (!storageAdapter)
|
|
327
|
+
throw new Error(`No persistence adapter for collection ${collectionName}`);
|
|
328
|
+
const previousItems = [];
|
|
329
|
+
const result = await Promise.all(parameters.map(async ([selector, replacement]) => {
|
|
330
|
+
const item = await this.executeQuery(collectionName, selector, { limit: 1 }).then((items) => items[0] ?? null);
|
|
331
|
+
if (item == null)
|
|
332
|
+
return [];
|
|
333
|
+
previousItems.push(item);
|
|
334
|
+
const modifiedItem = {
|
|
335
|
+
...replacement,
|
|
336
|
+
id: replacement.id ?? item.id
|
|
337
|
+
};
|
|
338
|
+
if (item.id !== modifiedItem.id) {
|
|
339
|
+
const existingItems = await this.executeQuery(collectionName, { id: modifiedItem.id }, { limit: 1 });
|
|
340
|
+
if (existingItems.length > 0) {
|
|
341
|
+
return new Error(`Item with id ${modifiedItem.id} already exists`);
|
|
342
|
+
}
|
|
309
343
|
}
|
|
344
|
+
return [modifiedItem];
|
|
345
|
+
}));
|
|
346
|
+
const modifiedItems = compact(result.filter((item) => !(item instanceof Error)).flat());
|
|
347
|
+
if (modifiedItems.length > 0) {
|
|
348
|
+
await storageAdapter.replace(modifiedItems);
|
|
349
|
+
await this.checkQueryUpdates(collectionName, [...modifiedItems, ...previousItems]);
|
|
310
350
|
}
|
|
311
|
-
|
|
312
|
-
await this.checkQueryUpdates(collectionName, [modifiedItem]);
|
|
313
|
-
return [modifiedItem];
|
|
351
|
+
return result;
|
|
314
352
|
};
|
|
315
|
-
removeOne = async (collectionName,
|
|
353
|
+
removeOne = async (collectionName, selectors) => {
|
|
316
354
|
const storageAdapter = this.storageAdapters.get(collectionName);
|
|
317
355
|
if (!storageAdapter)
|
|
318
356
|
throw new Error(`No persistence adapter for collection ${collectionName}`);
|
|
319
|
-
const
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
357
|
+
const result = await Promise.all(selectors.map(async ([selector]) => {
|
|
358
|
+
const item = await this.executeQuery(collectionName, selector, { limit: 1 }).then((items2) => items2[0] ?? null);
|
|
359
|
+
if (item == null)
|
|
360
|
+
return [];
|
|
361
|
+
return [item];
|
|
362
|
+
}));
|
|
363
|
+
const items = result.flat();
|
|
364
|
+
if (items.length > 0) {
|
|
365
|
+
await storageAdapter.remove(items);
|
|
366
|
+
await this.checkQueryUpdates(collectionName, items);
|
|
367
|
+
}
|
|
368
|
+
return result;
|
|
325
369
|
};
|
|
326
|
-
removeMany = async (collectionName,
|
|
370
|
+
removeMany = async (collectionName, selectors) => {
|
|
327
371
|
const storageAdapter = this.storageAdapters.get(collectionName);
|
|
328
372
|
if (!storageAdapter)
|
|
329
373
|
throw new Error(`No persistence adapter for collection ${collectionName}`);
|
|
330
|
-
const
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
374
|
+
const result = await Promise.all(selectors.map(async ([selector]) => this.executeQuery(collectionName, selector)));
|
|
375
|
+
const items = result.flat();
|
|
376
|
+
if (items.length > 0) {
|
|
377
|
+
await storageAdapter.remove(items);
|
|
378
|
+
await this.checkQueryUpdates(collectionName, items);
|
|
379
|
+
}
|
|
380
|
+
return result;
|
|
336
381
|
};
|
|
337
382
|
isReady = async (collectionName) => {
|
|
338
383
|
return this.storageAdapterReady.get(collectionName);
|
package/dist/index.cjs16.js
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const deepClone = require("./index.cjs19.js");
|
|
3
|
-
const match = require("./index.
|
|
3
|
+
const match = require("./index.cjs23.js");
|
|
4
4
|
const modify = require("./index.cjs7.js");
|
|
5
|
-
const queryId = require("./index.
|
|
5
|
+
const queryId = require("./index.cjs20.js");
|
|
6
6
|
const isEqual = require("./index.cjs6.js");
|
|
7
|
-
const getIndexInfo = require("./index.
|
|
7
|
+
const getIndexInfo = require("./index.cjs22.js");
|
|
8
8
|
const getMatchingKeys = require("./index.cjs26.js");
|
|
9
9
|
const sortItems = require("./index.cjs25.js");
|
|
10
|
-
const project = require("./index.
|
|
10
|
+
const project = require("./index.cjs24.js");
|
|
11
11
|
function defaultMergeItems(a, b) {
|
|
12
12
|
return { ...a, ...b };
|
|
13
13
|
}
|
|
14
|
+
function selectorId(selector) {
|
|
15
|
+
return JSON.stringify(selector ?? {});
|
|
16
|
+
}
|
|
14
17
|
class AutoFetchDataAdapter {
|
|
15
18
|
options;
|
|
16
19
|
id;
|
|
@@ -74,7 +77,7 @@ class AutoFetchDataAdapter {
|
|
|
74
77
|
state: "active",
|
|
75
78
|
error: null
|
|
76
79
|
});
|
|
77
|
-
const key =
|
|
80
|
+
const key = selectorId(selector);
|
|
78
81
|
const perColObservers = this.activeObservers.get(collection.name);
|
|
79
82
|
const current = perColObservers?.get(key)?.count ?? 0;
|
|
80
83
|
perColObservers?.set(key, { selector, count: current + 1 });
|
|
@@ -91,7 +94,7 @@ class AutoFetchDataAdapter {
|
|
|
91
94
|
const qid = queryId(selector, options);
|
|
92
95
|
const registry = this.queries.get(collection.name);
|
|
93
96
|
registry?.delete(qid);
|
|
94
|
-
const key =
|
|
97
|
+
const key = selectorId(selector);
|
|
95
98
|
const perColObservers = this.activeObservers.get(collection.name);
|
|
96
99
|
const current = perColObservers?.get(key)?.count ?? 0;
|
|
97
100
|
const remaining = Math.max(0, current - 1);
|
|
@@ -141,7 +144,9 @@ class AutoFetchDataAdapter {
|
|
|
141
144
|
});
|
|
142
145
|
}
|
|
143
146
|
registry.get(qid)?.listeners.add(callback);
|
|
144
|
-
return () =>
|
|
147
|
+
return () => {
|
|
148
|
+
registry.get(qid)?.listeners.delete(callback);
|
|
149
|
+
};
|
|
145
150
|
};
|
|
146
151
|
return {
|
|
147
152
|
insert: async (item) => {
|
|
@@ -175,6 +180,23 @@ class AutoFetchDataAdapter {
|
|
|
175
180
|
getQueryError,
|
|
176
181
|
getQueryResult,
|
|
177
182
|
onQueryStateChange,
|
|
183
|
+
executeQuery: async (selector, options) => {
|
|
184
|
+
await ready;
|
|
185
|
+
registerQuery(selector, options);
|
|
186
|
+
await new Promise((resolve) => {
|
|
187
|
+
let stop = () => {
|
|
188
|
+
};
|
|
189
|
+
stop = onQueryStateChange(selector, options, (state) => {
|
|
190
|
+
if (state === "active")
|
|
191
|
+
return;
|
|
192
|
+
resolve();
|
|
193
|
+
stop();
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
const result = getQueryResult(selector, options);
|
|
197
|
+
unregisterQuery(selector, options);
|
|
198
|
+
return result;
|
|
199
|
+
},
|
|
178
200
|
dispose: async () => {
|
|
179
201
|
this.storageAdapters.delete(collection.name);
|
|
180
202
|
this.queries.delete(collection.name);
|
|
@@ -192,9 +214,6 @@ class AutoFetchDataAdapter {
|
|
|
192
214
|
};
|
|
193
215
|
}
|
|
194
216
|
// ===== Auto-fetch mechanics =====
|
|
195
|
-
selectorKey(selector) {
|
|
196
|
-
return JSON.stringify(selector ?? {});
|
|
197
|
-
}
|
|
198
217
|
async forceRefetchAll() {
|
|
199
218
|
const tasks = [];
|
|
200
219
|
for (const [collectionName, observers] of this.activeObservers.entries()) {
|
|
@@ -213,7 +232,7 @@ class AutoFetchDataAdapter {
|
|
|
213
232
|
throw new Error("AutoFetchDataAdapter: fetchQueryItems must resolve to { items: T[] }");
|
|
214
233
|
}
|
|
215
234
|
const ids = items.map((i) => i.id);
|
|
216
|
-
const selectorKey =
|
|
235
|
+
const selectorKey = selectorId(selector);
|
|
217
236
|
const selMap = this.selectorIds.get(collectionName);
|
|
218
237
|
const previous = selMap?.get(selectorKey) ?? /* @__PURE__ */ new Set();
|
|
219
238
|
ids.forEach((id) => previous.add(id));
|
|
@@ -226,7 +245,7 @@ class AutoFetchDataAdapter {
|
|
|
226
245
|
}
|
|
227
246
|
}
|
|
228
247
|
async purgeSelector(collectionName, selector) {
|
|
229
|
-
const selectorKey =
|
|
248
|
+
const selectorKey = selectorId(selector);
|
|
230
249
|
const selMap = this.selectorIds.get(collectionName);
|
|
231
250
|
const ids = selMap?.get(selectorKey);
|
|
232
251
|
selMap?.delete(selectorKey);
|
|
@@ -263,10 +282,7 @@ class AutoFetchDataAdapter {
|
|
|
263
282
|
const storage = this.storageAdapters.get(collectionName);
|
|
264
283
|
if (!storage)
|
|
265
284
|
throw new Error(`No persistence adapter for collection ${collectionName}`);
|
|
266
|
-
await Promise.all(
|
|
267
|
-
storage.createIndex("id"),
|
|
268
|
-
...indices.map((field) => storage.createIndex(field))
|
|
269
|
-
]);
|
|
285
|
+
await Promise.all(indices.map((field) => storage.createIndex(field)));
|
|
270
286
|
await storage.setup();
|
|
271
287
|
}
|
|
272
288
|
ensureStorageAdapter(name) {
|
|
@@ -284,24 +300,16 @@ class AutoFetchDataAdapter {
|
|
|
284
300
|
for (const query of registry.values()) {
|
|
285
301
|
if (!isEqual(query.selector, selector))
|
|
286
302
|
continue;
|
|
287
|
-
query.
|
|
288
|
-
query.error = error;
|
|
289
|
-
for (const callback of query.listeners) {
|
|
290
|
-
try {
|
|
291
|
-
callback(state);
|
|
292
|
-
} catch (error_) {
|
|
293
|
-
this.onError(error_);
|
|
294
|
-
}
|
|
295
|
-
}
|
|
303
|
+
this.publishState(collectionName, queryId(query.selector, query.options), state, error);
|
|
296
304
|
}
|
|
297
305
|
}
|
|
298
306
|
publishState(collectionName, qid, state, error) {
|
|
299
|
-
const
|
|
300
|
-
if (!
|
|
307
|
+
const query = this.queries.get(collectionName)?.get(qid);
|
|
308
|
+
if (!query)
|
|
301
309
|
return;
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
for (const callback of
|
|
310
|
+
query.state = state;
|
|
311
|
+
query.error = error;
|
|
312
|
+
for (const callback of query.listeners) {
|
|
305
313
|
try {
|
|
306
314
|
callback(state);
|
|
307
315
|
} catch (error_) {
|
|
@@ -310,10 +318,11 @@ class AutoFetchDataAdapter {
|
|
|
310
318
|
}
|
|
311
319
|
}
|
|
312
320
|
publishResult(collectionName, qid, items) {
|
|
313
|
-
const
|
|
314
|
-
if (!
|
|
321
|
+
const query = this.queries.get(collectionName)?.get(qid);
|
|
322
|
+
if (!query)
|
|
315
323
|
return;
|
|
316
|
-
|
|
324
|
+
query.items = items;
|
|
325
|
+
this.queries.get(collectionName)?.set(qid, query);
|
|
317
326
|
}
|
|
318
327
|
async fulfillQuery(collectionName, selector, options) {
|
|
319
328
|
const qid = queryId(selector, options);
|
|
@@ -472,7 +481,7 @@ class AutoFetchDataAdapter {
|
|
|
472
481
|
throw new Error(`Item with id ${String(modified.id)} already exists`);
|
|
473
482
|
}
|
|
474
483
|
await storage.replace([modified]);
|
|
475
|
-
await this.checkQueryUpdates(collectionName, [modified]);
|
|
484
|
+
await this.checkQueryUpdates(collectionName, [item, modified]);
|
|
476
485
|
return [modified];
|
|
477
486
|
}
|
|
478
487
|
async updateMany(collectionName, selector, modifier) {
|
|
@@ -493,7 +502,7 @@ class AutoFetchDataAdapter {
|
|
|
493
502
|
return modified;
|
|
494
503
|
}));
|
|
495
504
|
await storage.replace(changed);
|
|
496
|
-
await this.checkQueryUpdates(collectionName, changed);
|
|
505
|
+
await this.checkQueryUpdates(collectionName, [...items, ...changed]);
|
|
497
506
|
return changed;
|
|
498
507
|
}
|
|
499
508
|
async replaceOne(collectionName, selector, replacement) {
|
|
@@ -511,7 +520,7 @@ class AutoFetchDataAdapter {
|
|
|
511
520
|
throw new Error(`Item with id ${String(modified.id)} already exists`);
|
|
512
521
|
}
|
|
513
522
|
await storage.replace([modified]);
|
|
514
|
-
await this.checkQueryUpdates(collectionName, [modified]);
|
|
523
|
+
await this.checkQueryUpdates(collectionName, [item, modified]);
|
|
515
524
|
return [modified];
|
|
516
525
|
}
|
|
517
526
|
async removeOne(collectionName, selector) {
|
package/dist/index.cjs17.js
CHANGED
package/dist/index.cjs2.js
CHANGED
|
@@ -62,9 +62,12 @@ class Cursor {
|
|
|
62
62
|
return this.options.transform(item);
|
|
63
63
|
}
|
|
64
64
|
depend(changeEvents) {
|
|
65
|
-
if (
|
|
65
|
+
if (this.options?.async)
|
|
66
66
|
return;
|
|
67
|
-
if (!isInReactiveScope(this.options.reactive))
|
|
67
|
+
if (!isInReactiveScope(this.options.reactive)) {
|
|
68
|
+
console.warn("Cursor.depend() called outside of a reactive scope without async option; consider using { async: true } or wrapping in a reactive scope");
|
|
69
|
+
}
|
|
70
|
+
if (!this.options.reactive)
|
|
68
71
|
return;
|
|
69
72
|
const signal = this.options.reactive.create();
|
|
70
73
|
signal.depend();
|
package/dist/index.cjs20.js
CHANGED
|
@@ -1,104 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
function createIndex(field) {
|
|
7
|
-
const index = /* @__PURE__ */ new Map();
|
|
8
|
-
const ensureSet = (key) => {
|
|
9
|
-
let set = index.get(key);
|
|
10
|
-
if (!set) {
|
|
11
|
-
set = /* @__PURE__ */ new Set();
|
|
12
|
-
index.set(key, set);
|
|
13
|
-
}
|
|
14
|
-
return set;
|
|
15
|
-
};
|
|
16
|
-
return createIndexProvider({
|
|
17
|
-
query(selector) {
|
|
18
|
-
if (!Object.hasOwnProperty.call(selector, field)) {
|
|
19
|
-
return { matched: false };
|
|
20
|
-
}
|
|
21
|
-
const fieldSelector = selector[field];
|
|
22
|
-
const filteresForNull = fieldSelector == null || fieldSelector.$exists === false;
|
|
23
|
-
const keys = filteresForNull ? { include: null, exclude: [...index.keys()].filter((key) => key != null) } : getMatchingKeys(field, selector);
|
|
24
|
-
if (keys.include == null && keys.exclude == null)
|
|
25
|
-
return { matched: false };
|
|
26
|
-
let includedIds = [];
|
|
27
|
-
if (keys.include == null) {
|
|
28
|
-
for (const set of index.values()) {
|
|
29
|
-
for (const pos of set) {
|
|
30
|
-
includedIds.push(pos);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
} else {
|
|
34
|
-
for (const key of keys.include) {
|
|
35
|
-
const posSet = index.get(key);
|
|
36
|
-
if (posSet) {
|
|
37
|
-
for (const pos of posSet) {
|
|
38
|
-
includedIds.push(pos);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
if (keys.exclude != null) {
|
|
44
|
-
const excludeIds = /* @__PURE__ */ new Set();
|
|
45
|
-
for (const key of keys.exclude) {
|
|
46
|
-
const posSet = index.get(key);
|
|
47
|
-
if (posSet) {
|
|
48
|
-
for (const pos of posSet) {
|
|
49
|
-
excludeIds.add(pos);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
includedIds = includedIds.filter((pos) => !excludeIds.has(pos));
|
|
54
|
-
}
|
|
55
|
-
return {
|
|
56
|
-
matched: true,
|
|
57
|
-
ids: includedIds,
|
|
58
|
-
fields: [field],
|
|
59
|
-
keepSelector: filteresForNull
|
|
60
|
-
};
|
|
61
|
-
},
|
|
62
|
-
rebuild(items) {
|
|
63
|
-
index.clear();
|
|
64
|
-
items.forEach((item) => {
|
|
65
|
-
const value = serializeValue(get(item, field));
|
|
66
|
-
ensureSet(value).add(item.id);
|
|
67
|
-
});
|
|
68
|
-
},
|
|
69
|
-
// NEW: delta methods
|
|
70
|
-
insert(items) {
|
|
71
|
-
for (const item of items) {
|
|
72
|
-
const value = serializeValue(get(item, field));
|
|
73
|
-
ensureSet(value).add(item.id);
|
|
74
|
-
}
|
|
75
|
-
},
|
|
76
|
-
remove(items) {
|
|
77
|
-
for (const item of items) {
|
|
78
|
-
const value = serializeValue(get(item, field));
|
|
79
|
-
const set = index.get(value);
|
|
80
|
-
if (!set)
|
|
81
|
-
continue;
|
|
82
|
-
set.delete(item.id);
|
|
83
|
-
if (set.size === 0)
|
|
84
|
-
index.delete(value);
|
|
85
|
-
}
|
|
86
|
-
},
|
|
87
|
-
update(pairs) {
|
|
88
|
-
for (const { oldItem, newItem } of pairs) {
|
|
89
|
-
const oldValue = serializeValue(get(oldItem, field));
|
|
90
|
-
const newValue = serializeValue(get(newItem, field));
|
|
91
|
-
if (oldValue === newValue)
|
|
92
|
-
continue;
|
|
93
|
-
const oldSet = index.get(oldValue);
|
|
94
|
-
if (oldSet) {
|
|
95
|
-
oldSet.delete(oldItem.id);
|
|
96
|
-
if (oldSet.size === 0)
|
|
97
|
-
index.delete(oldValue);
|
|
98
|
-
}
|
|
99
|
-
ensureSet(newValue).add(newItem.id);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
});
|
|
2
|
+
function queryId(selector, options) {
|
|
3
|
+
const selectorId = JSON.stringify(selector);
|
|
4
|
+
const optionsId = options == null ? -1 : JSON.stringify(options);
|
|
5
|
+
return `${selectorId}:${optionsId}`;
|
|
103
6
|
}
|
|
104
|
-
module.exports =
|
|
7
|
+
module.exports = queryId;
|