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