@signaldb/core 2.0.0-beta.0 → 2.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.vite/manifest.json +24 -11
- package/dist/AsyncDataAdapter.d.ts +1 -1
- package/dist/AutoFetchDataAdapter.d.ts +1 -2
- package/dist/Collection/Cursor.d.ts +3 -2
- package/dist/Collection/index.d.ts +17 -12
- package/dist/Collection/types.d.ts +1 -0
- package/dist/DataAdapter.d.ts +9 -7
- package/dist/DefaultDataAdapter.d.ts +2 -1
- package/dist/WorkerDataAdapter.d.ts +5 -2
- package/dist/WorkerDataAdapterHost.d.ts +9 -6
- package/dist/index.cjs12.js +35 -21
- package/dist/index.cjs13.js +27 -15
- package/dist/index.cjs14.js +72 -56
- package/dist/index.cjs15.js +122 -75
- package/dist/index.cjs16.js +45 -36
- package/dist/index.cjs17.js +4 -2
- package/dist/index.cjs19.js +0 -1
- package/dist/index.cjs2.js +6 -2
- package/dist/index.cjs20.js +14 -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.cjs27.js +44 -3
- package/dist/index.cjs28.js +6 -5
- package/dist/index.cjs29.js +5 -27
- package/dist/index.cjs3.js +41 -22
- package/dist/index.cjs31.js +27 -7
- package/dist/index.cjs32.js +9 -0
- package/dist/index.cjs33.js +5 -0
- package/dist/index.d.ts +2 -1
- package/dist/index12.mjs +35 -21
- package/dist/index13.mjs +27 -15
- package/dist/index14.mjs +72 -56
- package/dist/index15.mjs +122 -75
- package/dist/index16.mjs +45 -36
- package/dist/index17.mjs +4 -2
- package/dist/index19.mjs +0 -1
- package/dist/index2.mjs +6 -2
- package/dist/index20.mjs +14 -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/index27.mjs +44 -3
- package/dist/index28.mjs +6 -5
- package/dist/index29.mjs +5 -27
- package/dist/index3.mjs +41 -22
- package/dist/index31.mjs +27 -7
- package/dist/index32.mjs +10 -0
- package/dist/index33.mjs +6 -0
- package/dist/utils/batchOnNextTick.d.ts +16 -0
- package/dist/utils/deepClone.d.ts +1 -1
- package/package.json +3 -3
package/dist/index16.mjs
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import deepClone from "./index19.mjs";
|
|
2
|
-
import match from "./
|
|
2
|
+
import match from "./index23.mjs";
|
|
3
3
|
import modify from "./index7.mjs";
|
|
4
|
-
import queryId from "./
|
|
4
|
+
import queryId from "./index20.mjs";
|
|
5
5
|
import isEqual from "./index6.mjs";
|
|
6
|
-
import getIndexInfo from "./
|
|
6
|
+
import getIndexInfo from "./index22.mjs";
|
|
7
7
|
import getMatchingKeys from "./index26.mjs";
|
|
8
8
|
import sortItems from "./index25.mjs";
|
|
9
|
-
import project from "./
|
|
9
|
+
import project from "./index24.mjs";
|
|
10
10
|
function defaultMergeItems(a, b) {
|
|
11
11
|
return { ...a, ...b };
|
|
12
12
|
}
|
|
13
|
+
function selectorId(selector) {
|
|
14
|
+
return JSON.stringify(selector ?? {});
|
|
15
|
+
}
|
|
13
16
|
class AutoFetchDataAdapter {
|
|
14
17
|
options;
|
|
15
18
|
id;
|
|
@@ -73,7 +76,7 @@ class AutoFetchDataAdapter {
|
|
|
73
76
|
state: "active",
|
|
74
77
|
error: null
|
|
75
78
|
});
|
|
76
|
-
const key =
|
|
79
|
+
const key = selectorId(selector);
|
|
77
80
|
const perColObservers = this.activeObservers.get(collection.name);
|
|
78
81
|
const current = perColObservers?.get(key)?.count ?? 0;
|
|
79
82
|
perColObservers?.set(key, { selector, count: current + 1 });
|
|
@@ -90,7 +93,7 @@ class AutoFetchDataAdapter {
|
|
|
90
93
|
const qid = queryId(selector, options);
|
|
91
94
|
const registry = this.queries.get(collection.name);
|
|
92
95
|
registry?.delete(qid);
|
|
93
|
-
const key =
|
|
96
|
+
const key = selectorId(selector);
|
|
94
97
|
const perColObservers = this.activeObservers.get(collection.name);
|
|
95
98
|
const current = perColObservers?.get(key)?.count ?? 0;
|
|
96
99
|
const remaining = Math.max(0, current - 1);
|
|
@@ -140,7 +143,9 @@ class AutoFetchDataAdapter {
|
|
|
140
143
|
});
|
|
141
144
|
}
|
|
142
145
|
registry.get(qid)?.listeners.add(callback);
|
|
143
|
-
return () =>
|
|
146
|
+
return () => {
|
|
147
|
+
registry.get(qid)?.listeners.delete(callback);
|
|
148
|
+
};
|
|
144
149
|
};
|
|
145
150
|
return {
|
|
146
151
|
insert: async (item) => {
|
|
@@ -174,6 +179,23 @@ class AutoFetchDataAdapter {
|
|
|
174
179
|
getQueryError,
|
|
175
180
|
getQueryResult,
|
|
176
181
|
onQueryStateChange,
|
|
182
|
+
executeQuery: async (selector, options) => {
|
|
183
|
+
await ready;
|
|
184
|
+
registerQuery(selector, options);
|
|
185
|
+
await new Promise((resolve) => {
|
|
186
|
+
let stop = () => {
|
|
187
|
+
};
|
|
188
|
+
stop = onQueryStateChange(selector, options, (state) => {
|
|
189
|
+
if (state === "active")
|
|
190
|
+
return;
|
|
191
|
+
resolve();
|
|
192
|
+
stop();
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
const result = getQueryResult(selector, options);
|
|
196
|
+
unregisterQuery(selector, options);
|
|
197
|
+
return result;
|
|
198
|
+
},
|
|
177
199
|
dispose: async () => {
|
|
178
200
|
this.storageAdapters.delete(collection.name);
|
|
179
201
|
this.queries.delete(collection.name);
|
|
@@ -191,9 +213,6 @@ class AutoFetchDataAdapter {
|
|
|
191
213
|
};
|
|
192
214
|
}
|
|
193
215
|
// ===== Auto-fetch mechanics =====
|
|
194
|
-
selectorKey(selector) {
|
|
195
|
-
return JSON.stringify(selector ?? {});
|
|
196
|
-
}
|
|
197
216
|
async forceRefetchAll() {
|
|
198
217
|
const tasks = [];
|
|
199
218
|
for (const [collectionName, observers] of this.activeObservers.entries()) {
|
|
@@ -212,7 +231,7 @@ class AutoFetchDataAdapter {
|
|
|
212
231
|
throw new Error("AutoFetchDataAdapter: fetchQueryItems must resolve to { items: T[] }");
|
|
213
232
|
}
|
|
214
233
|
const ids = items.map((i) => i.id);
|
|
215
|
-
const selectorKey =
|
|
234
|
+
const selectorKey = selectorId(selector);
|
|
216
235
|
const selMap = this.selectorIds.get(collectionName);
|
|
217
236
|
const previous = selMap?.get(selectorKey) ?? /* @__PURE__ */ new Set();
|
|
218
237
|
ids.forEach((id) => previous.add(id));
|
|
@@ -225,7 +244,7 @@ class AutoFetchDataAdapter {
|
|
|
225
244
|
}
|
|
226
245
|
}
|
|
227
246
|
async purgeSelector(collectionName, selector) {
|
|
228
|
-
const selectorKey =
|
|
247
|
+
const selectorKey = selectorId(selector);
|
|
229
248
|
const selMap = this.selectorIds.get(collectionName);
|
|
230
249
|
const ids = selMap?.get(selectorKey);
|
|
231
250
|
selMap?.delete(selectorKey);
|
|
@@ -262,10 +281,7 @@ class AutoFetchDataAdapter {
|
|
|
262
281
|
const storage = this.storageAdapters.get(collectionName);
|
|
263
282
|
if (!storage)
|
|
264
283
|
throw new Error(`No persistence adapter for collection ${collectionName}`);
|
|
265
|
-
await Promise.all(
|
|
266
|
-
storage.createIndex("id"),
|
|
267
|
-
...indices.map((field) => storage.createIndex(field))
|
|
268
|
-
]);
|
|
284
|
+
await Promise.all(indices.map((field) => storage.createIndex(field)));
|
|
269
285
|
await storage.setup();
|
|
270
286
|
}
|
|
271
287
|
ensureStorageAdapter(name) {
|
|
@@ -283,24 +299,16 @@ class AutoFetchDataAdapter {
|
|
|
283
299
|
for (const query of registry.values()) {
|
|
284
300
|
if (!isEqual(query.selector, selector))
|
|
285
301
|
continue;
|
|
286
|
-
query.
|
|
287
|
-
query.error = error;
|
|
288
|
-
for (const callback of query.listeners) {
|
|
289
|
-
try {
|
|
290
|
-
callback(state);
|
|
291
|
-
} catch (error_) {
|
|
292
|
-
this.onError(error_);
|
|
293
|
-
}
|
|
294
|
-
}
|
|
302
|
+
this.publishState(collectionName, queryId(query.selector, query.options), state, error);
|
|
295
303
|
}
|
|
296
304
|
}
|
|
297
305
|
publishState(collectionName, qid, state, error) {
|
|
298
|
-
const
|
|
299
|
-
if (!
|
|
306
|
+
const query = this.queries.get(collectionName)?.get(qid);
|
|
307
|
+
if (!query)
|
|
300
308
|
return;
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
for (const callback of
|
|
309
|
+
query.state = state;
|
|
310
|
+
query.error = error;
|
|
311
|
+
for (const callback of query.listeners) {
|
|
304
312
|
try {
|
|
305
313
|
callback(state);
|
|
306
314
|
} catch (error_) {
|
|
@@ -309,10 +317,11 @@ class AutoFetchDataAdapter {
|
|
|
309
317
|
}
|
|
310
318
|
}
|
|
311
319
|
publishResult(collectionName, qid, items) {
|
|
312
|
-
const
|
|
313
|
-
if (!
|
|
320
|
+
const query = this.queries.get(collectionName)?.get(qid);
|
|
321
|
+
if (!query)
|
|
314
322
|
return;
|
|
315
|
-
|
|
323
|
+
query.items = items;
|
|
324
|
+
this.queries.get(collectionName)?.set(qid, query);
|
|
316
325
|
}
|
|
317
326
|
async fulfillQuery(collectionName, selector, options) {
|
|
318
327
|
const qid = queryId(selector, options);
|
|
@@ -471,7 +480,7 @@ class AutoFetchDataAdapter {
|
|
|
471
480
|
throw new Error(`Item with id ${String(modified.id)} already exists`);
|
|
472
481
|
}
|
|
473
482
|
await storage.replace([modified]);
|
|
474
|
-
await this.checkQueryUpdates(collectionName, [modified]);
|
|
483
|
+
await this.checkQueryUpdates(collectionName, [item, modified]);
|
|
475
484
|
return [modified];
|
|
476
485
|
}
|
|
477
486
|
async updateMany(collectionName, selector, modifier) {
|
|
@@ -492,7 +501,7 @@ class AutoFetchDataAdapter {
|
|
|
492
501
|
return modified;
|
|
493
502
|
}));
|
|
494
503
|
await storage.replace(changed);
|
|
495
|
-
await this.checkQueryUpdates(collectionName, changed);
|
|
504
|
+
await this.checkQueryUpdates(collectionName, [...items, ...changed]);
|
|
496
505
|
return changed;
|
|
497
506
|
}
|
|
498
507
|
async replaceOne(collectionName, selector, replacement) {
|
|
@@ -510,7 +519,7 @@ class AutoFetchDataAdapter {
|
|
|
510
519
|
throw new Error(`Item with id ${String(modified.id)} already exists`);
|
|
511
520
|
}
|
|
512
521
|
await storage.replace([modified]);
|
|
513
|
-
await this.checkQueryUpdates(collectionName, [modified]);
|
|
522
|
+
await this.checkQueryUpdates(collectionName, [item, modified]);
|
|
514
523
|
return [modified];
|
|
515
524
|
}
|
|
516
525
|
async removeOne(collectionName, selector) {
|
package/dist/index17.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import isEqual from "./index6.mjs";
|
|
2
|
-
import uniqueBy from "./
|
|
2
|
+
import uniqueBy from "./index32.mjs";
|
|
3
3
|
class Observer {
|
|
4
4
|
previousItems = [];
|
|
5
5
|
callbacks;
|
|
@@ -52,7 +52,9 @@ class Observer {
|
|
|
52
52
|
runChecks(getItems) {
|
|
53
53
|
const result = getItems();
|
|
54
54
|
if (result instanceof Promise) {
|
|
55
|
-
|
|
55
|
+
result.then((newItems) => this.checkItems(newItems)).catch((error) => {
|
|
56
|
+
console.error("Error while asynchronously querying items", error);
|
|
57
|
+
});
|
|
56
58
|
} else {
|
|
57
59
|
this.checkItems(result);
|
|
58
60
|
}
|
package/dist/index19.mjs
CHANGED
package/dist/index2.mjs
CHANGED
|
@@ -26,6 +26,7 @@ class Cursor {
|
|
|
26
26
|
* @param options.limit - The maximum number of items to return in the result set.
|
|
27
27
|
* @param options.reactive - A reactivity adapter to enable observing changes in the cursor's result set.
|
|
28
28
|
* @param options.fieldTracking - A boolean to enable fine-grained field tracking for reactivity.
|
|
29
|
+
* @param options.transformAll - A function that will be able to solve the n+1 problem
|
|
29
30
|
*/
|
|
30
31
|
constructor(getItems, options) {
|
|
31
32
|
this.getItems = getItems;
|
|
@@ -60,9 +61,12 @@ class Cursor {
|
|
|
60
61
|
return this.options.transform(item);
|
|
61
62
|
}
|
|
62
63
|
depend(changeEvents) {
|
|
63
|
-
if (
|
|
64
|
+
if (this.options?.async)
|
|
64
65
|
return;
|
|
65
|
-
if (!isInReactiveScope(this.options.reactive))
|
|
66
|
+
if (!isInReactiveScope(this.options.reactive)) {
|
|
67
|
+
console.warn("Cursor.depend() called outside of a reactive scope without async option; consider using { async: true } or wrapping in a reactive scope");
|
|
68
|
+
}
|
|
69
|
+
if (!this.options.reactive)
|
|
66
70
|
return;
|
|
67
71
|
const signal = this.options.reactive.create();
|
|
68
72
|
signal.depend();
|
package/dist/index20.mjs
CHANGED
|
@@ -1,105 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
};
|
|
15
|
-
return createIndexProvider({
|
|
16
|
-
query(selector) {
|
|
17
|
-
if (!Object.hasOwnProperty.call(selector, field)) {
|
|
18
|
-
return { matched: false };
|
|
19
|
-
}
|
|
20
|
-
const fieldSelector = selector[field];
|
|
21
|
-
const filteresForNull = fieldSelector == null || fieldSelector.$exists === false;
|
|
22
|
-
const keys = filteresForNull ? { include: null, exclude: [...index.keys()].filter((key) => key != null) } : getMatchingKeys(field, selector);
|
|
23
|
-
if (keys.include == null && keys.exclude == null)
|
|
24
|
-
return { matched: false };
|
|
25
|
-
let includedIds = [];
|
|
26
|
-
if (keys.include == null) {
|
|
27
|
-
for (const set of index.values()) {
|
|
28
|
-
for (const pos of set) {
|
|
29
|
-
includedIds.push(pos);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
} else {
|
|
33
|
-
for (const key of keys.include) {
|
|
34
|
-
const posSet = index.get(key);
|
|
35
|
-
if (posSet) {
|
|
36
|
-
for (const pos of posSet) {
|
|
37
|
-
includedIds.push(pos);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
if (keys.exclude != null) {
|
|
43
|
-
const excludeIds = /* @__PURE__ */ new Set();
|
|
44
|
-
for (const key of keys.exclude) {
|
|
45
|
-
const posSet = index.get(key);
|
|
46
|
-
if (posSet) {
|
|
47
|
-
for (const pos of posSet) {
|
|
48
|
-
excludeIds.add(pos);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
includedIds = includedIds.filter((pos) => !excludeIds.has(pos));
|
|
53
|
-
}
|
|
54
|
-
return {
|
|
55
|
-
matched: true,
|
|
56
|
-
ids: includedIds,
|
|
57
|
-
fields: [field],
|
|
58
|
-
keepSelector: filteresForNull
|
|
59
|
-
};
|
|
60
|
-
},
|
|
61
|
-
rebuild(items) {
|
|
62
|
-
index.clear();
|
|
63
|
-
items.forEach((item) => {
|
|
64
|
-
const value = serializeValue(get(item, field));
|
|
65
|
-
ensureSet(value).add(item.id);
|
|
66
|
-
});
|
|
67
|
-
},
|
|
68
|
-
// NEW: delta methods
|
|
69
|
-
insert(items) {
|
|
70
|
-
for (const item of items) {
|
|
71
|
-
const value = serializeValue(get(item, field));
|
|
72
|
-
ensureSet(value).add(item.id);
|
|
73
|
-
}
|
|
74
|
-
},
|
|
75
|
-
remove(items) {
|
|
76
|
-
for (const item of items) {
|
|
77
|
-
const value = serializeValue(get(item, field));
|
|
78
|
-
const set = index.get(value);
|
|
79
|
-
if (!set)
|
|
80
|
-
continue;
|
|
81
|
-
set.delete(item.id);
|
|
82
|
-
if (set.size === 0)
|
|
83
|
-
index.delete(value);
|
|
84
|
-
}
|
|
85
|
-
},
|
|
86
|
-
update(pairs) {
|
|
87
|
-
for (const { oldItem, newItem } of pairs) {
|
|
88
|
-
const oldValue = serializeValue(get(oldItem, field));
|
|
89
|
-
const newValue = serializeValue(get(newItem, field));
|
|
90
|
-
if (oldValue === newValue)
|
|
91
|
-
continue;
|
|
92
|
-
const oldSet = index.get(oldValue);
|
|
93
|
-
if (oldSet) {
|
|
94
|
-
oldSet.delete(oldItem.id);
|
|
95
|
-
if (oldSet.size === 0)
|
|
96
|
-
index.delete(oldValue);
|
|
97
|
-
}
|
|
98
|
-
ensureSet(newValue).add(newItem.id);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
});
|
|
1
|
+
function isEmptyOptions(options) {
|
|
2
|
+
if (options == null)
|
|
3
|
+
return true;
|
|
4
|
+
if (typeof options !== "object")
|
|
5
|
+
return false;
|
|
6
|
+
if (Array.isArray(options))
|
|
7
|
+
return false;
|
|
8
|
+
return Object.keys(options).length === 0;
|
|
9
|
+
}
|
|
10
|
+
function queryId(selector, options) {
|
|
11
|
+
const selectorId = JSON.stringify(selector);
|
|
12
|
+
const optionsId = isEmptyOptions(options) ? -1 : JSON.stringify(options);
|
|
13
|
+
return `${selectorId}:${optionsId}`;
|
|
102
14
|
}
|
|
103
15
|
export {
|
|
104
|
-
|
|
16
|
+
queryId as default
|
|
105
17
|
};
|
package/dist/index21.mjs
CHANGED
|
@@ -1,129 +1,105 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
optimizedSelector
|
|
13
|
-
};
|
|
14
|
-
};
|
|
15
|
-
if (resultOrPromise instanceof Promise) {
|
|
16
|
-
return resultOrPromise.then(async (result) => {
|
|
17
|
-
const memo2 = memoOrPromise instanceof Promise ? await memoOrPromise : memoOrPromise;
|
|
18
|
-
return processResult(memo2, result);
|
|
19
|
-
});
|
|
1
|
+
import createIndexProvider from "./index33.mjs";
|
|
2
|
+
import get from "./index10.mjs";
|
|
3
|
+
import getMatchingKeys from "./index26.mjs";
|
|
4
|
+
import serializeValue from "./index11.mjs";
|
|
5
|
+
function createIndex(field) {
|
|
6
|
+
const index = /* @__PURE__ */ new Map();
|
|
7
|
+
const ensureSet = (key) => {
|
|
8
|
+
let set = index.get(key);
|
|
9
|
+
if (!set) {
|
|
10
|
+
set = /* @__PURE__ */ new Set();
|
|
11
|
+
index.set(key, set);
|
|
20
12
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
13
|
+
return set;
|
|
14
|
+
};
|
|
15
|
+
return createIndexProvider({
|
|
16
|
+
query(selector) {
|
|
17
|
+
if (!Object.hasOwnProperty.call(selector, field)) {
|
|
18
|
+
return { matched: false };
|
|
19
|
+
}
|
|
20
|
+
const fieldSelector = selector[field];
|
|
21
|
+
const filteresForNull = fieldSelector == null || fieldSelector.$exists === false;
|
|
22
|
+
const keys = filteresForNull ? { include: null, exclude: [...index.keys()].filter((key) => key != null) } : getMatchingKeys(field, selector);
|
|
23
|
+
if (keys.include == null && keys.exclude == null)
|
|
24
|
+
return { matched: false };
|
|
25
|
+
let includedIds = [];
|
|
26
|
+
if (keys.include == null) {
|
|
27
|
+
for (const set of index.values()) {
|
|
28
|
+
for (const pos of set) {
|
|
29
|
+
includedIds.push(pos);
|
|
30
|
+
}
|
|
39
31
|
}
|
|
40
32
|
} else {
|
|
41
|
-
|
|
42
|
-
|
|
33
|
+
for (const key of keys.include) {
|
|
34
|
+
const posSet = index.get(key);
|
|
35
|
+
if (posSet) {
|
|
36
|
+
for (const pos of posSet) {
|
|
37
|
+
includedIds.push(pos);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
43
41
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
const memo = memoOrPromise;
|
|
56
|
-
if (memo instanceof Promise)
|
|
57
|
-
throw new Error("Mixing async and sync index providers is not supported");
|
|
58
|
-
const optimizedSelector = getSelector(indexInfoOrPromise);
|
|
59
|
-
if (optimizedSelector)
|
|
60
|
-
memo.push(optimizedSelector);
|
|
61
|
-
return memo;
|
|
62
|
-
}, []);
|
|
63
|
-
}
|
|
64
|
-
function getIndexInfo(queryFunctions, selector) {
|
|
65
|
-
if (selector == null || Object.keys(selector).length <= 0) {
|
|
66
|
-
return {
|
|
67
|
-
matched: false,
|
|
68
|
-
ids: [],
|
|
69
|
-
optimizedSelector: selector
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
const { $and, $or, ...rest } = selector;
|
|
73
|
-
const flatInfoOrPromise = getMergedIndexInfo(queryFunctions, rest);
|
|
74
|
-
const processFlatInfo = (flatInfo) => {
|
|
75
|
-
let { matched, ids } = flatInfo;
|
|
76
|
-
const newSelector = flatInfo.optimizedSelector;
|
|
77
|
-
const $andNewOrPromise = Array.isArray($and) ? optimizeLogicGate(queryFunctions, $and, (match, selIds) => {
|
|
78
|
-
if (!match)
|
|
79
|
-
return;
|
|
80
|
-
ids = matched ? intersection(ids, selIds) : selIds;
|
|
81
|
-
matched = true;
|
|
82
|
-
}) : void 0;
|
|
83
|
-
const process$and = ($andNew) => {
|
|
84
|
-
if ($andNew && $andNew.length > 0)
|
|
85
|
-
newSelector.$and = $andNew;
|
|
86
|
-
let hasNonIndexField = false;
|
|
87
|
-
const matchedBefore = matched;
|
|
88
|
-
const idsBefore = ids;
|
|
89
|
-
const process$or = ($orNew) => {
|
|
90
|
-
if ($orNew && $orNew.length > 0)
|
|
91
|
-
newSelector.$or = $orNew;
|
|
92
|
-
if (hasNonIndexField) {
|
|
93
|
-
newSelector.$or = $or;
|
|
94
|
-
matched = matchedBefore;
|
|
95
|
-
ids = idsBefore;
|
|
42
|
+
if (keys.exclude != null) {
|
|
43
|
+
const excludeIds = /* @__PURE__ */ new Set();
|
|
44
|
+
for (const key of keys.exclude) {
|
|
45
|
+
const posSet = index.get(key);
|
|
46
|
+
if (posSet) {
|
|
47
|
+
for (const pos of posSet) {
|
|
48
|
+
excludeIds.add(pos);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
96
51
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
52
|
+
includedIds = includedIds.filter((pos) => !excludeIds.has(pos));
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
matched: true,
|
|
56
|
+
ids: includedIds,
|
|
57
|
+
fields: [field],
|
|
58
|
+
keepSelector: filteresForNull
|
|
102
59
|
};
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
60
|
+
},
|
|
61
|
+
rebuild(items) {
|
|
62
|
+
index.clear();
|
|
63
|
+
items.forEach((item) => {
|
|
64
|
+
const value = serializeValue(get(item, field));
|
|
65
|
+
ensureSet(value).add(item.id);
|
|
66
|
+
});
|
|
67
|
+
},
|
|
68
|
+
// NEW: delta methods
|
|
69
|
+
insert(items) {
|
|
70
|
+
for (const item of items) {
|
|
71
|
+
const value = serializeValue(get(item, field));
|
|
72
|
+
ensureSet(value).add(item.id);
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
remove(items) {
|
|
76
|
+
for (const item of items) {
|
|
77
|
+
const value = serializeValue(get(item, field));
|
|
78
|
+
const set = index.get(value);
|
|
79
|
+
if (!set)
|
|
80
|
+
continue;
|
|
81
|
+
set.delete(item.id);
|
|
82
|
+
if (set.size === 0)
|
|
83
|
+
index.delete(value);
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
update(pairs) {
|
|
87
|
+
for (const { oldItem, newItem } of pairs) {
|
|
88
|
+
const oldValue = serializeValue(get(oldItem, field));
|
|
89
|
+
const newValue = serializeValue(get(newItem, field));
|
|
90
|
+
if (oldValue === newValue)
|
|
91
|
+
continue;
|
|
92
|
+
const oldSet = index.get(oldValue);
|
|
93
|
+
if (oldSet) {
|
|
94
|
+
oldSet.delete(oldItem.id);
|
|
95
|
+
if (oldSet.size === 0)
|
|
96
|
+
index.delete(oldValue);
|
|
109
97
|
}
|
|
110
|
-
|
|
111
|
-
if ($orNewOrPromise instanceof Promise) {
|
|
112
|
-
return $orNewOrPromise.then(($orNew) => process$or($orNew));
|
|
98
|
+
ensureSet(newValue).add(newItem.id);
|
|
113
99
|
}
|
|
114
|
-
return process$or($orNewOrPromise);
|
|
115
|
-
};
|
|
116
|
-
if ($andNewOrPromise instanceof Promise) {
|
|
117
|
-
return $andNewOrPromise.then(($andNew) => process$and($andNew));
|
|
118
100
|
}
|
|
119
|
-
|
|
120
|
-
};
|
|
121
|
-
if (flatInfoOrPromise instanceof Promise) {
|
|
122
|
-
return flatInfoOrPromise.then(processFlatInfo);
|
|
123
|
-
}
|
|
124
|
-
return processFlatInfo(flatInfoOrPromise);
|
|
101
|
+
});
|
|
125
102
|
}
|
|
126
103
|
export {
|
|
127
|
-
|
|
128
|
-
getMergedIndexInfo
|
|
104
|
+
createIndex as default
|
|
129
105
|
};
|