@signaldb/core 2.0.0-beta.4 → 2.0.0-beta.6
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 +27 -21
- package/dist/Collection/Observer.d.ts +2 -0
- package/dist/Collection/index.d.ts +11 -10
- package/dist/Collection/types.d.ts +7 -0
- package/dist/DefaultDataAdapter.d.ts +2 -0
- package/dist/index.cjs.js +8 -5
- package/dist/index.cjs12.js +41 -346
- package/dist/index.cjs13.js +308 -359
- package/dist/index.cjs14.js +387 -177
- package/dist/index.cjs15.js +182 -364
- package/dist/index.cjs16.js +287 -478
- package/dist/index.cjs17.js +563 -136
- package/dist/index.cjs18.js +154 -23
- package/dist/index.cjs19.js +23 -39
- package/dist/index.cjs2.js +1 -1
- package/dist/index.cjs20.js +39 -13
- package/dist/index.cjs21.js +14 -102
- package/dist/index.cjs22.js +93 -118
- package/dist/index.cjs23.js +127 -5
- package/dist/index.cjs24.js +5 -25
- package/dist/index.cjs25.js +24 -7
- package/dist/index.cjs26.js +8 -27
- package/dist/index.cjs27.js +25 -42
- package/dist/index.cjs28.js +44 -6
- package/dist/index.cjs29.js +6 -7
- package/dist/index.cjs3.js +9 -26
- package/dist/index.cjs30.js +7 -3
- package/dist/index.cjs32.js +40 -27
- package/dist/index.cjs33.js +27 -40
- package/dist/index.cjs34.js +5 -0
- package/dist/index.cjs7.js +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.mjs +10 -7
- package/dist/index12.mjs +40 -346
- package/dist/index13.mjs +308 -359
- package/dist/index14.mjs +387 -177
- package/dist/index15.mjs +182 -364
- package/dist/index16.mjs +287 -478
- package/dist/index17.mjs +563 -136
- package/dist/index18.mjs +154 -23
- package/dist/index19.mjs +23 -38
- package/dist/index2.mjs +1 -1
- package/dist/index20.mjs +38 -13
- package/dist/index21.mjs +14 -102
- package/dist/index22.mjs +93 -117
- package/dist/index23.mjs +126 -5
- package/dist/index24.mjs +5 -25
- package/dist/index25.mjs +24 -7
- package/dist/index26.mjs +8 -27
- package/dist/index27.mjs +25 -42
- package/dist/index28.mjs +44 -6
- package/dist/index29.mjs +6 -7
- package/dist/index3.mjs +9 -26
- package/dist/index30.mjs +7 -3
- package/dist/index32.mjs +40 -27
- package/dist/index33.mjs +27 -40
- package/dist/index34.mjs +6 -0
- package/dist/index7.mjs +1 -1
- package/dist/utils/reactiveOrAsync.d.ts +59 -0
- package/package.json +1 -1
package/dist/index.cjs18.js
CHANGED
|
@@ -1,26 +1,157 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
2
|
+
const isEqual = require("./index.cjs6.js");
|
|
3
|
+
const uniqueBy = require("./index.cjs30.js");
|
|
4
|
+
class Observer {
|
|
5
|
+
previousItems = [];
|
|
6
|
+
callbacks;
|
|
7
|
+
unbindEvents;
|
|
8
|
+
/**
|
|
9
|
+
* Creates a new instance of the `Observer` class.
|
|
10
|
+
* Sets up event bindings and initializes the callbacks for tracking changes in a collection.
|
|
11
|
+
* @param bindEvents - A function to bind external events to the observer. Must return a cleanup function to unbind those events.
|
|
12
|
+
*/
|
|
13
|
+
constructor(bindEvents) {
|
|
14
|
+
this.callbacks = {
|
|
15
|
+
added: [],
|
|
16
|
+
addedBefore: [],
|
|
17
|
+
changed: [],
|
|
18
|
+
changedField: [],
|
|
19
|
+
movedBefore: [],
|
|
20
|
+
removed: []
|
|
21
|
+
};
|
|
22
|
+
this.unbindEvents = bindEvents();
|
|
23
|
+
}
|
|
24
|
+
call(event, ...args) {
|
|
25
|
+
this.callbacks[event].forEach(({ callback, options }) => {
|
|
26
|
+
if (!options.skipInitial || !options.isInitial) {
|
|
27
|
+
callback(...args);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
hasCallbacks(events) {
|
|
32
|
+
return events.some((event) => this.callbacks[event].length > 0);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Determines if the observer has no active callbacks registered for any events.
|
|
36
|
+
* @returns A boolean indicating whether the observer is empty (i.e., no callbacks are registered).
|
|
37
|
+
*/
|
|
38
|
+
isEmpty() {
|
|
39
|
+
return !this.hasCallbacks([
|
|
40
|
+
"added",
|
|
41
|
+
"addedBefore",
|
|
42
|
+
"changed",
|
|
43
|
+
"changedField",
|
|
44
|
+
"movedBefore",
|
|
45
|
+
"removed"
|
|
46
|
+
]);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Compares the previous state of items with the new state and triggers the appropriate callbacks
|
|
50
|
+
* for events such as added, removed, changed, or moved items.
|
|
51
|
+
* @param getItems - A function that returns a promise resolving to the new items or the items themselves.
|
|
52
|
+
*/
|
|
53
|
+
runChecks(getItems) {
|
|
54
|
+
const result = getItems();
|
|
55
|
+
if (result instanceof Promise) {
|
|
56
|
+
result.then((newItems) => this.checkItems(newItems)).catch((error) => {
|
|
57
|
+
console.error("Error while asynchronously querying items", error);
|
|
58
|
+
});
|
|
59
|
+
} else {
|
|
60
|
+
this.checkItems(result);
|
|
22
61
|
}
|
|
23
|
-
}
|
|
24
|
-
|
|
62
|
+
}
|
|
63
|
+
checkItems(newItems) {
|
|
64
|
+
const oldItemsMap = new Map(this.previousItems.map((item, index) => [
|
|
65
|
+
item.id,
|
|
66
|
+
{ item, index, beforeItem: this.previousItems[index + 1] || null }
|
|
67
|
+
]));
|
|
68
|
+
const newItemsMap = new Map(newItems.map((item, index) => [
|
|
69
|
+
item.id,
|
|
70
|
+
{ item, index, beforeItem: newItems[index + 1] || null }
|
|
71
|
+
]));
|
|
72
|
+
if (this.hasCallbacks(["changed", "changedField", "movedBefore", "removed"])) {
|
|
73
|
+
oldItemsMap.forEach(({ item: oldItem, index, beforeItem: oldBeforeItem }) => {
|
|
74
|
+
const newItem = newItemsMap.get(oldItem.id);
|
|
75
|
+
if (newItem) {
|
|
76
|
+
if (this.hasCallbacks(["changed", "changedField"]) && !isEqual(newItem.item, oldItem)) {
|
|
77
|
+
this.call("changed", newItem.item);
|
|
78
|
+
if (this.hasCallbacks(["changedField"])) {
|
|
79
|
+
const keys = uniqueBy([
|
|
80
|
+
...Object.keys(newItem.item),
|
|
81
|
+
...Object.keys(oldItem)
|
|
82
|
+
], (value) => value);
|
|
83
|
+
keys.forEach((key) => {
|
|
84
|
+
if (isEqual(newItem.item[key], oldItem[key]))
|
|
85
|
+
return;
|
|
86
|
+
this.call("changedField", newItem.item, key, oldItem[key], newItem.item[key]);
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (newItem.index !== index && newItem.beforeItem?.id !== oldBeforeItem?.id) {
|
|
91
|
+
this.call("movedBefore", newItem.item, newItem.beforeItem);
|
|
92
|
+
}
|
|
93
|
+
} else {
|
|
94
|
+
this.call("removed", oldItem);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
if (this.hasCallbacks(["added", "addedBefore"])) {
|
|
99
|
+
newItems.forEach((newItem, index) => {
|
|
100
|
+
const oldItem = oldItemsMap.get(newItem.id);
|
|
101
|
+
if (oldItem)
|
|
102
|
+
return;
|
|
103
|
+
this.call("added", newItem);
|
|
104
|
+
this.call("addedBefore", newItem, newItems[index + 1] || null);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
this.previousItems = newItems;
|
|
108
|
+
Object.keys(this.callbacks).forEach((key) => {
|
|
109
|
+
const event = key;
|
|
110
|
+
const callbacks = this.callbacks[event];
|
|
111
|
+
this.callbacks[event] = callbacks.map((callback) => ({
|
|
112
|
+
...callback,
|
|
113
|
+
options: {
|
|
114
|
+
...callback.options,
|
|
115
|
+
isInitial: false
|
|
116
|
+
}
|
|
117
|
+
}));
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
stopped = false;
|
|
121
|
+
/**
|
|
122
|
+
* Stops the observer by unbinding all events and cleaning up resources.
|
|
123
|
+
* Safe to call multiple times - will only unbind once.
|
|
124
|
+
*/
|
|
125
|
+
stop() {
|
|
126
|
+
if (this.stopped)
|
|
127
|
+
return;
|
|
128
|
+
this.stopped = true;
|
|
129
|
+
this.unbindEvents();
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Registers callbacks for specific events to observe changes in the collection.
|
|
133
|
+
* @param callbacks - An object containing the callbacks for various events (e.g., 'added', 'removed').
|
|
134
|
+
* @param skipInitial - A boolean indicating whether to skip invoking the callbacks for the initial state of the collection.
|
|
135
|
+
*/
|
|
136
|
+
addCallbacks(callbacks, skipInitial = false) {
|
|
137
|
+
Object.keys(callbacks).forEach((key) => {
|
|
138
|
+
const typedKey = key;
|
|
139
|
+
this.callbacks[typedKey].push({
|
|
140
|
+
callback: callbacks[typedKey],
|
|
141
|
+
options: { skipInitial, isInitial: true }
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Removes the specified callbacks for specific events, unregistering them from the observer.
|
|
147
|
+
* @param callbacks - An object containing the callbacks to be removed for various events.
|
|
148
|
+
*/
|
|
149
|
+
removeCallbacks(callbacks) {
|
|
150
|
+
Object.keys(callbacks).forEach((key) => {
|
|
151
|
+
const typedKey = key;
|
|
152
|
+
const index = this.callbacks[typedKey].findIndex(({ callback }) => callback === callbacks[typedKey]);
|
|
153
|
+
this.callbacks[typedKey].splice(index, 1);
|
|
154
|
+
});
|
|
155
|
+
}
|
|
25
156
|
}
|
|
26
|
-
module.exports =
|
|
157
|
+
module.exports = Observer;
|
package/dist/index.cjs19.js
CHANGED
|
@@ -1,42 +1,26 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
result2.add(clone(currentValue));
|
|
23
|
-
});
|
|
24
|
-
return result2;
|
|
25
|
-
}
|
|
26
|
-
if (value instanceof RegExp)
|
|
27
|
-
return new RegExp(value);
|
|
28
|
-
const result = {};
|
|
29
|
-
for (const key in value) {
|
|
30
|
-
if (Object.hasOwnProperty.call(value, key)) {
|
|
31
|
-
result[key] = clone(value[key]);
|
|
2
|
+
function createSignal(reactivityAdapter, initialValue, isEqual = Object.is) {
|
|
3
|
+
let value = initialValue;
|
|
4
|
+
const dependency = reactivityAdapter?.create();
|
|
5
|
+
const isInReactiveScope = () => {
|
|
6
|
+
if (!reactivityAdapter?.isInScope)
|
|
7
|
+
return true;
|
|
8
|
+
return reactivityAdapter.isInScope();
|
|
9
|
+
};
|
|
10
|
+
const signal = {
|
|
11
|
+
get() {
|
|
12
|
+
if (dependency && isInReactiveScope())
|
|
13
|
+
dependency.depend();
|
|
14
|
+
return value;
|
|
15
|
+
},
|
|
16
|
+
set(newValue) {
|
|
17
|
+
if (isEqual(value, newValue))
|
|
18
|
+
return;
|
|
19
|
+
value = newValue;
|
|
20
|
+
if (dependency)
|
|
21
|
+
dependency.notify();
|
|
32
22
|
}
|
|
33
|
-
}
|
|
34
|
-
return
|
|
23
|
+
};
|
|
24
|
+
return signal;
|
|
35
25
|
}
|
|
36
|
-
|
|
37
|
-
if (typeof structuredClone === "function")
|
|
38
|
-
return structuredClone(object);
|
|
39
|
-
return clone(object);
|
|
40
|
-
}
|
|
41
|
-
exports.clone = clone;
|
|
42
|
-
exports.default = deepClone;
|
|
26
|
+
module.exports = createSignal;
|
package/dist/index.cjs2.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
|
|
3
|
-
const Observer = require("./index.
|
|
3
|
+
const Observer = require("./index.cjs18.js");
|
|
4
4
|
function isInReactiveScope(reactivity) {
|
|
5
5
|
if (!reactivity)
|
|
6
6
|
return false;
|
package/dist/index.cjs20.js
CHANGED
|
@@ -1,16 +1,42 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
|
|
3
|
+
function clone(value) {
|
|
4
|
+
if (typeof value === "function")
|
|
5
|
+
throw new Error("Cloning functions is not supported");
|
|
6
|
+
if (value === null || typeof value !== "object")
|
|
7
|
+
return value;
|
|
8
|
+
if (value instanceof Date)
|
|
9
|
+
return new Date(value);
|
|
10
|
+
if (Array.isArray(value))
|
|
11
|
+
return value.map((item) => clone(item));
|
|
12
|
+
if (value instanceof Map) {
|
|
13
|
+
const result2 = /* @__PURE__ */ new Map();
|
|
14
|
+
value.forEach((currentValue, key) => {
|
|
15
|
+
result2.set(key, clone(currentValue));
|
|
16
|
+
});
|
|
17
|
+
return result2;
|
|
18
|
+
}
|
|
19
|
+
if (value instanceof Set) {
|
|
20
|
+
const result2 = /* @__PURE__ */ new Set();
|
|
21
|
+
value.forEach((currentValue) => {
|
|
22
|
+
result2.add(clone(currentValue));
|
|
23
|
+
});
|
|
24
|
+
return result2;
|
|
25
|
+
}
|
|
26
|
+
if (value instanceof RegExp)
|
|
27
|
+
return new RegExp(value);
|
|
28
|
+
const result = {};
|
|
29
|
+
for (const key in value) {
|
|
30
|
+
if (Object.hasOwnProperty.call(value, key)) {
|
|
31
|
+
result[key] = clone(value[key]);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return result;
|
|
10
35
|
}
|
|
11
|
-
function
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return
|
|
36
|
+
function deepClone(object) {
|
|
37
|
+
if (typeof structuredClone === "function")
|
|
38
|
+
return structuredClone(object);
|
|
39
|
+
return clone(object);
|
|
15
40
|
}
|
|
16
|
-
|
|
41
|
+
exports.clone = clone;
|
|
42
|
+
exports.default = deepClone;
|
package/dist/index.cjs21.js
CHANGED
|
@@ -1,104 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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 isEmptyOptions(options) {
|
|
3
|
+
if (options == null)
|
|
4
|
+
return true;
|
|
5
|
+
if (typeof options !== "object")
|
|
6
|
+
return false;
|
|
7
|
+
if (Array.isArray(options))
|
|
8
|
+
return false;
|
|
9
|
+
return Object.keys(options).length === 0;
|
|
103
10
|
}
|
|
104
|
-
|
|
11
|
+
function queryId(selector, options) {
|
|
12
|
+
const selectorId = JSON.stringify(selector);
|
|
13
|
+
const optionsId = isEmptyOptions(options) ? -1 : JSON.stringify(options);
|
|
14
|
+
return `${selectorId}:${optionsId}`;
|
|
15
|
+
}
|
|
16
|
+
module.exports = queryId;
|
package/dist/index.cjs22.js
CHANGED
|
@@ -1,129 +1,104 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
ids: [...new Set(memo2.matched ? intersection(memo2.ids, result.ids) : result.ids)],
|
|
14
|
-
optimizedSelector
|
|
15
|
-
};
|
|
16
|
-
};
|
|
17
|
-
if (resultOrPromise instanceof Promise) {
|
|
18
|
-
return resultOrPromise.then(async (result) => {
|
|
19
|
-
const memo2 = memoOrPromise instanceof Promise ? await memoOrPromise : memoOrPromise;
|
|
20
|
-
return processResult(memo2, result);
|
|
21
|
-
});
|
|
2
|
+
const createIndexProvider = require("./index.cjs34.js");
|
|
3
|
+
const get = require("./index.cjs10.js");
|
|
4
|
+
const getMatchingKeys = require("./index.cjs27.js");
|
|
5
|
+
const serializeValue = require("./index.cjs11.js");
|
|
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);
|
|
22
13
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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
|
+
}
|
|
41
32
|
}
|
|
42
33
|
} else {
|
|
43
|
-
|
|
44
|
-
|
|
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
|
+
}
|
|
45
42
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
const memo = memoOrPromise;
|
|
58
|
-
if (memo instanceof Promise)
|
|
59
|
-
throw new Error("Mixing async and sync index providers is not supported");
|
|
60
|
-
const optimizedSelector = getSelector(indexInfoOrPromise);
|
|
61
|
-
if (optimizedSelector)
|
|
62
|
-
memo.push(optimizedSelector);
|
|
63
|
-
return memo;
|
|
64
|
-
}, []);
|
|
65
|
-
}
|
|
66
|
-
function getIndexInfo(queryFunctions, selector) {
|
|
67
|
-
if (selector == null || Object.keys(selector).length <= 0) {
|
|
68
|
-
return {
|
|
69
|
-
matched: false,
|
|
70
|
-
ids: [],
|
|
71
|
-
optimizedSelector: selector
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
const { $and, $or, ...rest } = selector;
|
|
75
|
-
const flatInfoOrPromise = getMergedIndexInfo(queryFunctions, rest);
|
|
76
|
-
const processFlatInfo = (flatInfo) => {
|
|
77
|
-
let { matched, ids } = flatInfo;
|
|
78
|
-
const newSelector = flatInfo.optimizedSelector;
|
|
79
|
-
const $andNewOrPromise = Array.isArray($and) ? optimizeLogicGate(queryFunctions, $and, (match, selIds) => {
|
|
80
|
-
if (!match)
|
|
81
|
-
return;
|
|
82
|
-
ids = matched ? intersection(ids, selIds) : selIds;
|
|
83
|
-
matched = true;
|
|
84
|
-
}) : void 0;
|
|
85
|
-
const process$and = ($andNew) => {
|
|
86
|
-
if ($andNew && $andNew.length > 0)
|
|
87
|
-
newSelector.$and = $andNew;
|
|
88
|
-
let hasNonIndexField = false;
|
|
89
|
-
const matchedBefore = matched;
|
|
90
|
-
const idsBefore = ids;
|
|
91
|
-
const process$or = ($orNew) => {
|
|
92
|
-
if ($orNew && $orNew.length > 0)
|
|
93
|
-
newSelector.$or = $orNew;
|
|
94
|
-
if (hasNonIndexField) {
|
|
95
|
-
newSelector.$or = $or;
|
|
96
|
-
matched = matchedBefore;
|
|
97
|
-
ids = idsBefore;
|
|
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
|
+
}
|
|
98
52
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
53
|
+
includedIds = includedIds.filter((pos) => !excludeIds.has(pos));
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
matched: true,
|
|
57
|
+
ids: includedIds,
|
|
58
|
+
fields: [field],
|
|
59
|
+
keepSelector: filteresForNull
|
|
104
60
|
};
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
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);
|
|
111
98
|
}
|
|
112
|
-
|
|
113
|
-
if ($orNewOrPromise instanceof Promise) {
|
|
114
|
-
return $orNewOrPromise.then(($orNew) => process$or($orNew));
|
|
99
|
+
ensureSet(newValue).add(newItem.id);
|
|
115
100
|
}
|
|
116
|
-
return process$or($orNewOrPromise);
|
|
117
|
-
};
|
|
118
|
-
if ($andNewOrPromise instanceof Promise) {
|
|
119
|
-
return $andNewOrPromise.then(($andNew) => process$and($andNew));
|
|
120
101
|
}
|
|
121
|
-
|
|
122
|
-
};
|
|
123
|
-
if (flatInfoOrPromise instanceof Promise) {
|
|
124
|
-
return flatInfoOrPromise.then(processFlatInfo);
|
|
125
|
-
}
|
|
126
|
-
return processFlatInfo(flatInfoOrPromise);
|
|
102
|
+
});
|
|
127
103
|
}
|
|
128
|
-
exports
|
|
129
|
-
exports.getMergedIndexInfo = getMergedIndexInfo;
|
|
104
|
+
module.exports = createIndex;
|