@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.
Files changed (60) hide show
  1. package/dist/.vite/manifest.json +27 -21
  2. package/dist/Collection/Observer.d.ts +2 -0
  3. package/dist/Collection/index.d.ts +11 -10
  4. package/dist/Collection/types.d.ts +7 -0
  5. package/dist/DefaultDataAdapter.d.ts +2 -0
  6. package/dist/index.cjs.js +8 -5
  7. package/dist/index.cjs12.js +41 -346
  8. package/dist/index.cjs13.js +308 -359
  9. package/dist/index.cjs14.js +387 -177
  10. package/dist/index.cjs15.js +182 -364
  11. package/dist/index.cjs16.js +287 -478
  12. package/dist/index.cjs17.js +563 -136
  13. package/dist/index.cjs18.js +154 -23
  14. package/dist/index.cjs19.js +23 -39
  15. package/dist/index.cjs2.js +1 -1
  16. package/dist/index.cjs20.js +39 -13
  17. package/dist/index.cjs21.js +14 -102
  18. package/dist/index.cjs22.js +93 -118
  19. package/dist/index.cjs23.js +127 -5
  20. package/dist/index.cjs24.js +5 -25
  21. package/dist/index.cjs25.js +24 -7
  22. package/dist/index.cjs26.js +8 -27
  23. package/dist/index.cjs27.js +25 -42
  24. package/dist/index.cjs28.js +44 -6
  25. package/dist/index.cjs29.js +6 -7
  26. package/dist/index.cjs3.js +9 -26
  27. package/dist/index.cjs30.js +7 -3
  28. package/dist/index.cjs32.js +40 -27
  29. package/dist/index.cjs33.js +27 -40
  30. package/dist/index.cjs34.js +5 -0
  31. package/dist/index.cjs7.js +1 -1
  32. package/dist/index.d.ts +2 -1
  33. package/dist/index.mjs +10 -7
  34. package/dist/index12.mjs +40 -346
  35. package/dist/index13.mjs +308 -359
  36. package/dist/index14.mjs +387 -177
  37. package/dist/index15.mjs +182 -364
  38. package/dist/index16.mjs +287 -478
  39. package/dist/index17.mjs +563 -136
  40. package/dist/index18.mjs +154 -23
  41. package/dist/index19.mjs +23 -38
  42. package/dist/index2.mjs +1 -1
  43. package/dist/index20.mjs +38 -13
  44. package/dist/index21.mjs +14 -102
  45. package/dist/index22.mjs +93 -117
  46. package/dist/index23.mjs +126 -5
  47. package/dist/index24.mjs +5 -25
  48. package/dist/index25.mjs +24 -7
  49. package/dist/index26.mjs +8 -27
  50. package/dist/index27.mjs +25 -42
  51. package/dist/index28.mjs +44 -6
  52. package/dist/index29.mjs +6 -7
  53. package/dist/index3.mjs +9 -26
  54. package/dist/index30.mjs +7 -3
  55. package/dist/index32.mjs +40 -27
  56. package/dist/index33.mjs +27 -40
  57. package/dist/index34.mjs +6 -0
  58. package/dist/index7.mjs +1 -1
  59. package/dist/utils/reactiveOrAsync.d.ts +59 -0
  60. package/package.json +1 -1
@@ -1,26 +1,157 @@
1
1
  "use strict";
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();
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
- return signal;
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 = createSignal;
157
+ module.exports = Observer;
@@ -1,42 +1,26 @@
1
1
  "use strict";
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]);
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 result;
23
+ };
24
+ return signal;
35
25
  }
36
- function deepClone(object) {
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;
@@ -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.cjs17.js");
3
+ const Observer = require("./index.cjs18.js");
4
4
  function isInReactiveScope(reactivity) {
5
5
  if (!reactivity)
6
6
  return false;
@@ -1,16 +1,42 @@
1
1
  "use strict";
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;
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 queryId(selector, options) {
12
- const selectorId = JSON.stringify(selector);
13
- const optionsId = isEmptyOptions(options) ? -1 : JSON.stringify(options);
14
- return `${selectorId}:${optionsId}`;
36
+ function deepClone(object) {
37
+ if (typeof structuredClone === "function")
38
+ return structuredClone(object);
39
+ return clone(object);
15
40
  }
16
- module.exports = queryId;
41
+ exports.clone = clone;
42
+ exports.default = deepClone;
@@ -1,104 +1,16 @@
1
1
  "use strict";
2
- const createIndexProvider = require("./index.cjs30.js");
3
- const get = require("./index.cjs10.js");
4
- const getMatchingKeys = require("./index.cjs26.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);
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
- module.exports = createIndex;
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;
@@ -1,129 +1,104 @@
1
1
  "use strict";
2
- Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
3
- const intersection = require("./index.cjs31.js");
4
- function getMergedIndexInfo(queryFunctions, selector) {
5
- return queryFunctions.reduce((memoOrPromise, queryFunction) => {
6
- const resultOrPromise = queryFunction(selector);
7
- const processResult = (memo2, result) => {
8
- if (!result.matched)
9
- return memo2;
10
- const optimizedSelector = result.keepSelector ? memo2.optimizedSelector : Object.fromEntries(Object.entries(memo2.optimizedSelector).filter(([key]) => !result.fields.includes(key)));
11
- return {
12
- matched: true,
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
- const memo = memoOrPromise;
24
- if (memo instanceof Promise)
25
- throw new Error("Mixing async and sync index providers is not supported");
26
- return processResult(memo, resultOrPromise);
27
- }, {
28
- matched: false,
29
- ids: [],
30
- optimizedSelector: { ...selector }
31
- });
32
- }
33
- function optimizeLogicGate(queryFunctions, logicGate, idsCallback) {
34
- return logicGate.reduce((memoOrPromise, sel) => {
35
- const getSelector = (indexInfo) => {
36
- const { matched: selMatched, ids: selIds, optimizedSelector: optimizedSelector2 } = indexInfo;
37
- if (selMatched) {
38
- idsCallback(true, selIds);
39
- if (Object.keys(optimizedSelector2).length > 0) {
40
- return optimizedSelector2;
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
- idsCallback(false, []);
44
- return sel;
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
- const indexInfoOrPromise = getIndexInfo(queryFunctions, sel);
48
- if (indexInfoOrPromise instanceof Promise) {
49
- return indexInfoOrPromise.then(async (indexInfo) => {
50
- const memo2 = memoOrPromise instanceof Promise ? await memoOrPromise : memoOrPromise;
51
- const optimizedSelector2 = getSelector(indexInfo);
52
- if (optimizedSelector2)
53
- memo2.push(optimizedSelector2);
54
- return memo2;
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
- return {
100
- matched,
101
- ids: ids || [],
102
- optimizedSelector: newSelector
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
- const $orNewOrPromise = Array.isArray($or) ? optimizeLogicGate(queryFunctions, $or, (match, selIds) => {
106
- if (match) {
107
- ids = [.../* @__PURE__ */ new Set([...ids, ...selIds])];
108
- matched = true;
109
- } else {
110
- hasNonIndexField = true;
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
- }) : void 0;
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
- return process$and($andNewOrPromise);
122
- };
123
- if (flatInfoOrPromise instanceof Promise) {
124
- return flatInfoOrPromise.then(processFlatInfo);
125
- }
126
- return processFlatInfo(flatInfoOrPromise);
102
+ });
127
103
  }
128
- exports.default = getIndexInfo;
129
- exports.getMergedIndexInfo = getMergedIndexInfo;
104
+ module.exports = createIndex;