@signaldb/core 2.0.0-beta.13 → 2.0.0-beta.14

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 (82) hide show
  1. package/dist/.vite/manifest.json +72 -46
  2. package/dist/AsyncDataAdapter.d.ts +11 -2
  3. package/dist/Collection/Cursor.d.ts +11 -1
  4. package/dist/Collection/Observer.d.ts +31 -0
  5. package/dist/DataAdapter.d.ts +15 -2
  6. package/dist/WorkerDataAdapter.d.ts +25 -2
  7. package/dist/WorkerDataAdapterHost.d.ts +2 -0
  8. package/dist/index.cjs.js +15 -15
  9. package/dist/index.d.ts +2 -0
  10. package/dist/index.mjs +15 -15
  11. package/dist/index10.cjs.js +7 -19
  12. package/dist/index10.mjs +7 -19
  13. package/dist/index11.cjs.js +19 -41
  14. package/dist/index11.mjs +19 -41
  15. package/dist/index12.cjs.js +41 -18
  16. package/dist/index12.mjs +41 -18
  17. package/dist/index13.cjs.js +18 -41
  18. package/dist/index13.mjs +18 -41
  19. package/dist/index14.cjs.js +39 -80
  20. package/dist/index14.mjs +39 -80
  21. package/dist/index15.cjs.js +82 -11
  22. package/dist/index15.mjs +82 -11
  23. package/dist/index16.cjs.js +11 -132
  24. package/dist/index16.mjs +11 -132
  25. package/dist/index17.cjs.js +127 -38
  26. package/dist/index17.mjs +127 -38
  27. package/dist/index18.cjs.js +43 -11
  28. package/dist/index18.mjs +43 -11
  29. package/dist/index19.cjs.js +10 -18
  30. package/dist/index19.mjs +11 -19
  31. package/dist/index20.cjs.js +19 -33
  32. package/dist/index20.mjs +19 -33
  33. package/dist/index21.cjs.js +33 -31
  34. package/dist/index21.mjs +33 -31
  35. package/dist/index22.cjs.js +31 -21
  36. package/dist/index22.mjs +31 -21
  37. package/dist/index23.cjs.js +16 -14
  38. package/dist/index23.mjs +16 -14
  39. package/dist/index24.cjs.js +15 -338
  40. package/dist/index24.mjs +15 -338
  41. package/dist/index25.cjs.js +122 -554
  42. package/dist/index25.mjs +121 -554
  43. package/dist/index26.cjs.js +34 -7
  44. package/dist/index26.mjs +34 -7
  45. package/dist/index27.cjs.js +339 -7
  46. package/dist/index27.mjs +339 -7
  47. package/dist/index28.cjs.js +550 -83
  48. package/dist/index28.mjs +550 -82
  49. package/dist/index29.cjs.js +8 -422
  50. package/dist/index29.mjs +8 -422
  51. package/dist/index30.cjs.js +7 -68
  52. package/dist/index30.mjs +7 -68
  53. package/dist/index31.cjs.js +86 -28
  54. package/dist/index31.mjs +85 -28
  55. package/dist/index32.cjs.js +446 -278
  56. package/dist/index32.mjs +446 -278
  57. package/dist/index33.cjs.js +68 -17
  58. package/dist/index33.mjs +68 -17
  59. package/dist/index34.cjs.js +460 -304
  60. package/dist/index34.mjs +460 -304
  61. package/dist/index35.cjs.js +14 -532
  62. package/dist/index35.mjs +14 -532
  63. package/dist/index36.cjs.js +389 -0
  64. package/dist/index36.mjs +389 -0
  65. package/dist/index37.cjs.js +539 -0
  66. package/dist/index37.mjs +539 -0
  67. package/dist/index4.cjs.js +199 -140
  68. package/dist/index4.mjs +195 -140
  69. package/dist/index5.cjs.js +152 -253
  70. package/dist/index5.mjs +152 -253
  71. package/dist/index6.cjs.js +267 -89
  72. package/dist/index6.mjs +267 -89
  73. package/dist/index7.cjs.js +121 -29
  74. package/dist/index7.mjs +121 -29
  75. package/dist/index8.cjs.js +29 -8
  76. package/dist/index8.mjs +29 -8
  77. package/dist/index9.cjs.js +8 -7
  78. package/dist/index9.mjs +8 -7
  79. package/dist/utils/incrementalQueryUpdate.d.ts +60 -0
  80. package/dist/utils/projectItems.d.ts +12 -0
  81. package/dist/utils/queryDelta.d.ts +83 -0
  82. package/package.json +1 -1
package/dist/index14.mjs CHANGED
@@ -1,86 +1,45 @@
1
- import createIndexProvider from "./index9.mjs";
2
- import get from "./index10.mjs";
3
- import serializeValue from "./index12.mjs";
4
- import getMatchingKeys from "./index13.mjs";
5
- //#region src/createIndex.ts
1
+ import isFieldExpression from "./index12.mjs";
2
+ import serializeValue from "./index13.mjs";
3
+ //#region src/utils/getMatchingKeys.ts
6
4
  /**
7
- * creates an index for a specific field
8
- * @param field name of the field
9
- * @returns an index provider to pass to the `indices` option of the collection constructor
5
+ * Extracts the matching and excluded keys for a given field in a selector.
6
+ * Supports serialized values and `$in`/`$nin` field expressions for optimization.
7
+ * Returns `null` for include/exclude if the field cannot be optimized.
8
+ * @template T - The type of the items in the selector.
9
+ * @template I - The type of the unique identifier for the items.
10
+ * @param field - The name of the field to extract matching keys for.
11
+ * @param selector - The selector object containing query criteria.
12
+ * @returns An object containing arrays of serialized included and excluded keys,
13
+ * or `null` if the field cannot be optimized.
10
14
  */
11
- function createIndex(field) {
12
- const index = /* @__PURE__ */ new Map();
13
- const ensureSet = (key) => {
14
- let set = index.get(key);
15
- if (!set) {
16
- set = /* @__PURE__ */ new Set();
17
- index.set(key, set);
18
- }
19
- return set;
15
+ function getMatchingKeys(field, selector) {
16
+ const result = {
17
+ include: null,
18
+ exclude: null
20
19
  };
21
- return createIndexProvider({
22
- query(selector) {
23
- if (!Object.hasOwnProperty.call(selector, field)) return { matched: false };
24
- const fieldSelector = selector[field];
25
- const filteresForNull = fieldSelector == null || fieldSelector.$exists === false;
26
- const keys = filteresForNull ? {
27
- include: null,
28
- exclude: [...index.keys()].filter((key) => key != null)
29
- } : getMatchingKeys(field, selector);
30
- if (keys.include == null && keys.exclude == null) return { matched: false };
31
- let includedIds = [];
32
- if (keys.include == null) for (const set of index.values()) for (const pos of set) includedIds.push(pos);
33
- else for (const key of keys.include) {
34
- const posSet = index.get(key);
35
- if (posSet) for (const pos of posSet) includedIds.push(pos);
36
- }
37
- if (keys.exclude != null) {
38
- const excludeIds = /* @__PURE__ */ new Set();
39
- for (const key of keys.exclude) {
40
- const posSet = index.get(key);
41
- if (posSet) for (const pos of posSet) excludeIds.add(pos);
42
- }
43
- includedIds = includedIds.filter((pos) => !excludeIds.has(pos));
44
- }
45
- return {
46
- matched: true,
47
- ids: includedIds,
48
- fields: [field],
49
- keepSelector: filteresForNull
50
- };
51
- },
52
- rebuild(items) {
53
- index.clear();
54
- items.forEach((item) => {
55
- ensureSet(serializeValue(get(item, field))).add(item.id);
56
- });
57
- },
58
- insert(items) {
59
- for (const item of items) ensureSet(serializeValue(get(item, field))).add(item.id);
60
- },
61
- remove(items) {
62
- for (const item of items) {
63
- const value = serializeValue(get(item, field));
64
- const set = index.get(value);
65
- if (!set) continue;
66
- set.delete(item.id);
67
- if (set.size === 0) index.delete(value);
68
- }
69
- },
70
- update(pairs) {
71
- for (const { oldItem, newItem } of pairs) {
72
- const oldValue = serializeValue(get(oldItem, field));
73
- const newValue = serializeValue(get(newItem, field));
74
- if (oldValue === newValue) continue;
75
- const oldSet = index.get(oldValue);
76
- if (oldSet) {
77
- oldSet.delete(oldItem.id);
78
- if (oldSet.size === 0) index.delete(oldValue);
79
- }
80
- ensureSet(newValue).add(newItem.id);
81
- }
20
+ const fieldSelector = selector[field];
21
+ if (fieldSelector instanceof RegExp) return result;
22
+ if (fieldSelector == null) return result;
23
+ if (isFieldExpression(fieldSelector)) {
24
+ if (fieldSelector.$ne != null) {
25
+ result.exclude = [serializeValue(fieldSelector.$ne)];
26
+ return result;
27
+ }
28
+ if (Array.isArray(fieldSelector.$in) && fieldSelector.$in.length > 0) {
29
+ result.include = fieldSelector.$in.map(serializeValue);
30
+ return result;
31
+ }
32
+ if (Array.isArray(fieldSelector.$nin) && fieldSelector.$nin.length > 0) {
33
+ result.exclude = fieldSelector.$nin.map(serializeValue);
34
+ return result;
82
35
  }
83
- });
36
+ return {
37
+ include: null,
38
+ exclude: null
39
+ };
40
+ }
41
+ result.include = [serializeValue(fieldSelector)];
42
+ return result;
84
43
  }
85
44
  //#endregion
86
- export { createIndex as default };
45
+ export { getMatchingKeys as default };
@@ -1,15 +1,86 @@
1
- //#region src/utils/intersection.ts
1
+ const require_createIndexProvider = require("./index10.cjs.js");
2
+ const require_get = require("./index11.cjs.js");
3
+ const require_serializeValue = require("./index13.cjs.js");
4
+ const require_getMatchingKeys = require("./index14.cjs.js");
5
+ //#region src/createIndex.ts
2
6
  /**
3
- * Computes the intersection of multiple arrays, returning an array of unique elements
4
- * that are present in all the input arrays.
5
- * @template T - The type of elements in the arrays.
6
- * @param arrays - A variable number of arrays to compute the intersection of.
7
- * @returns An array containing the unique elements found in all the input arrays.
8
- * - If no arrays are provided, returns an empty array.
7
+ * creates an index for a specific field
8
+ * @param field name of the field
9
+ * @returns an index provider to pass to the `indices` option of the collection constructor
9
10
  */
10
- function intersection(...arrays) {
11
- if (arrays.length === 0) return [];
12
- return [...new Set(arrays.reduce((a, b) => a.filter((c) => b.includes(c))))];
11
+ function createIndex(field) {
12
+ const index = /* @__PURE__ */ new Map();
13
+ const ensureSet = (key) => {
14
+ let set = index.get(key);
15
+ if (!set) {
16
+ set = /* @__PURE__ */ new Set();
17
+ index.set(key, set);
18
+ }
19
+ return set;
20
+ };
21
+ return require_createIndexProvider.default({
22
+ query(selector) {
23
+ if (!Object.hasOwnProperty.call(selector, field)) return { matched: false };
24
+ const fieldSelector = selector[field];
25
+ const filteresForNull = fieldSelector == null || fieldSelector.$exists === false;
26
+ const keys = filteresForNull ? {
27
+ include: null,
28
+ exclude: [...index.keys()].filter((key) => key != null)
29
+ } : require_getMatchingKeys.default(field, selector);
30
+ if (keys.include == null && keys.exclude == null) return { matched: false };
31
+ let includedIds = [];
32
+ if (keys.include == null) for (const set of index.values()) for (const pos of set) includedIds.push(pos);
33
+ else for (const key of keys.include) {
34
+ const posSet = index.get(key);
35
+ if (posSet) for (const pos of posSet) includedIds.push(pos);
36
+ }
37
+ if (keys.exclude != null) {
38
+ const excludeIds = /* @__PURE__ */ new Set();
39
+ for (const key of keys.exclude) {
40
+ const posSet = index.get(key);
41
+ if (posSet) for (const pos of posSet) excludeIds.add(pos);
42
+ }
43
+ includedIds = includedIds.filter((pos) => !excludeIds.has(pos));
44
+ }
45
+ return {
46
+ matched: true,
47
+ ids: includedIds,
48
+ fields: [field],
49
+ keepSelector: filteresForNull
50
+ };
51
+ },
52
+ rebuild(items) {
53
+ index.clear();
54
+ items.forEach((item) => {
55
+ ensureSet(require_serializeValue.default(require_get.default(item, field))).add(item.id);
56
+ });
57
+ },
58
+ insert(items) {
59
+ for (const item of items) ensureSet(require_serializeValue.default(require_get.default(item, field))).add(item.id);
60
+ },
61
+ remove(items) {
62
+ for (const item of items) {
63
+ const value = require_serializeValue.default(require_get.default(item, field));
64
+ const set = index.get(value);
65
+ if (!set) continue;
66
+ set.delete(item.id);
67
+ if (set.size === 0) index.delete(value);
68
+ }
69
+ },
70
+ update(pairs) {
71
+ for (const { oldItem, newItem } of pairs) {
72
+ const oldValue = require_serializeValue.default(require_get.default(oldItem, field));
73
+ const newValue = require_serializeValue.default(require_get.default(newItem, field));
74
+ if (oldValue === newValue) continue;
75
+ const oldSet = index.get(oldValue);
76
+ if (oldSet) {
77
+ oldSet.delete(oldItem.id);
78
+ if (oldSet.size === 0) index.delete(oldValue);
79
+ }
80
+ ensureSet(newValue).add(newItem.id);
81
+ }
82
+ }
83
+ });
13
84
  }
14
85
  //#endregion
15
- exports.default = intersection;
86
+ exports.default = createIndex;
package/dist/index15.mjs CHANGED
@@ -1,15 +1,86 @@
1
- //#region src/utils/intersection.ts
1
+ import createIndexProvider from "./index10.mjs";
2
+ import get from "./index11.mjs";
3
+ import serializeValue from "./index13.mjs";
4
+ import getMatchingKeys from "./index14.mjs";
5
+ //#region src/createIndex.ts
2
6
  /**
3
- * Computes the intersection of multiple arrays, returning an array of unique elements
4
- * that are present in all the input arrays.
5
- * @template T - The type of elements in the arrays.
6
- * @param arrays - A variable number of arrays to compute the intersection of.
7
- * @returns An array containing the unique elements found in all the input arrays.
8
- * - If no arrays are provided, returns an empty array.
7
+ * creates an index for a specific field
8
+ * @param field name of the field
9
+ * @returns an index provider to pass to the `indices` option of the collection constructor
9
10
  */
10
- function intersection(...arrays) {
11
- if (arrays.length === 0) return [];
12
- return [...new Set(arrays.reduce((a, b) => a.filter((c) => b.includes(c))))];
11
+ function createIndex(field) {
12
+ const index = /* @__PURE__ */ new Map();
13
+ const ensureSet = (key) => {
14
+ let set = index.get(key);
15
+ if (!set) {
16
+ set = /* @__PURE__ */ new Set();
17
+ index.set(key, set);
18
+ }
19
+ return set;
20
+ };
21
+ return createIndexProvider({
22
+ query(selector) {
23
+ if (!Object.hasOwnProperty.call(selector, field)) return { matched: false };
24
+ const fieldSelector = selector[field];
25
+ const filteresForNull = fieldSelector == null || fieldSelector.$exists === false;
26
+ const keys = filteresForNull ? {
27
+ include: null,
28
+ exclude: [...index.keys()].filter((key) => key != null)
29
+ } : getMatchingKeys(field, selector);
30
+ if (keys.include == null && keys.exclude == null) return { matched: false };
31
+ let includedIds = [];
32
+ if (keys.include == null) for (const set of index.values()) for (const pos of set) includedIds.push(pos);
33
+ else for (const key of keys.include) {
34
+ const posSet = index.get(key);
35
+ if (posSet) for (const pos of posSet) includedIds.push(pos);
36
+ }
37
+ if (keys.exclude != null) {
38
+ const excludeIds = /* @__PURE__ */ new Set();
39
+ for (const key of keys.exclude) {
40
+ const posSet = index.get(key);
41
+ if (posSet) for (const pos of posSet) excludeIds.add(pos);
42
+ }
43
+ includedIds = includedIds.filter((pos) => !excludeIds.has(pos));
44
+ }
45
+ return {
46
+ matched: true,
47
+ ids: includedIds,
48
+ fields: [field],
49
+ keepSelector: filteresForNull
50
+ };
51
+ },
52
+ rebuild(items) {
53
+ index.clear();
54
+ items.forEach((item) => {
55
+ ensureSet(serializeValue(get(item, field))).add(item.id);
56
+ });
57
+ },
58
+ insert(items) {
59
+ for (const item of items) ensureSet(serializeValue(get(item, field))).add(item.id);
60
+ },
61
+ remove(items) {
62
+ for (const item of items) {
63
+ const value = serializeValue(get(item, field));
64
+ const set = index.get(value);
65
+ if (!set) continue;
66
+ set.delete(item.id);
67
+ if (set.size === 0) index.delete(value);
68
+ }
69
+ },
70
+ update(pairs) {
71
+ for (const { oldItem, newItem } of pairs) {
72
+ const oldValue = serializeValue(get(oldItem, field));
73
+ const newValue = serializeValue(get(newItem, field));
74
+ if (oldValue === newValue) continue;
75
+ const oldSet = index.get(oldValue);
76
+ if (oldSet) {
77
+ oldSet.delete(oldItem.id);
78
+ if (oldSet.size === 0) index.delete(oldValue);
79
+ }
80
+ ensureSet(newValue).add(newItem.id);
81
+ }
82
+ }
83
+ });
13
84
  }
14
85
  //#endregion
15
- export { intersection as default };
86
+ export { createIndex as default };
@@ -1,136 +1,15 @@
1
- const require_intersection = require("./index15.cjs.js");
2
- //#region src/getIndexInfo.ts
1
+ //#region src/utils/intersection.ts
3
2
  /**
4
- * Retrieves merged index information for a given flat selector by querying multiple
5
- * index providers. Combines results from all index providers to determine matched ids
6
- * and an optimized selector.
7
- * @template T - The type of the items in the collection.
8
- * @template I - The type of the unique identifier for the items.
9
- * @param queryFunctions - An array of index providers to query.
10
- * @param selector - The flat selector used to filter items.
11
- * @returns An object containing:
12
- * - `matched`: A boolean indicating if the selector matched any items.
13
- * - `ids`: An array of matched item ids.
14
- * - `optimizedSelector`: A flat selector optimized based on the index results.
3
+ * Computes the intersection of multiple arrays, returning an array of unique elements
4
+ * that are present in all the input arrays.
5
+ * @template T - The type of elements in the arrays.
6
+ * @param arrays - A variable number of arrays to compute the intersection of.
7
+ * @returns An array containing the unique elements found in all the input arrays.
8
+ * - If no arrays are provided, returns an empty array.
15
9
  */
16
- function getMergedIndexInfo(queryFunctions, selector) {
17
- return queryFunctions.reduce((memoOrPromise, queryFunction) => {
18
- const resultOrPromise = queryFunction(selector);
19
- const processResult = (memo, result) => {
20
- if (!result.matched) return memo;
21
- const optimizedSelector = result.keepSelector ? memo.optimizedSelector : Object.fromEntries(Object.entries(memo.optimizedSelector).filter(([key]) => !result.fields.includes(key)));
22
- return {
23
- matched: true,
24
- ids: [...new Set(memo.matched ? require_intersection.default(memo.ids, result.ids) : result.ids)],
25
- optimizedSelector
26
- };
27
- };
28
- if (resultOrPromise instanceof Promise) return resultOrPromise.then(async (result) => {
29
- return processResult(memoOrPromise instanceof Promise ? await memoOrPromise : memoOrPromise, result);
30
- });
31
- const memo = memoOrPromise;
32
- if (memo instanceof Promise) throw new Error("Mixing async and sync index providers is not supported");
33
- return processResult(memo, resultOrPromise);
34
- }, {
35
- matched: false,
36
- ids: [],
37
- optimizedSelector: { ...selector }
38
- });
39
- }
40
- /**
41
- * Optimizes a logic gate ($and/$or) of selectors by querying multiple index providers.
42
- * @param queryFunctions - An array of index providers to query.
43
- * @param logicGate - An array of selectors representing the logic gate.
44
- * @param idsCallback - A callback function called with matched ids.
45
- * @returns An array of optimized selectors or a promise that resolves to such an array.
46
- */
47
- function optimizeLogicGate(queryFunctions, logicGate, idsCallback) {
48
- return logicGate.reduce((memoOrPromise, sel) => {
49
- const getSelector = (indexInfo) => {
50
- const { matched: selMatched, ids: selIds, optimizedSelector } = indexInfo;
51
- if (selMatched) {
52
- idsCallback(true, selIds);
53
- if (Object.keys(optimizedSelector).length > 0) return optimizedSelector;
54
- } else {
55
- idsCallback(false, []);
56
- return sel;
57
- }
58
- };
59
- const indexInfoOrPromise = getIndexInfo(queryFunctions, sel);
60
- if (indexInfoOrPromise instanceof Promise) return indexInfoOrPromise.then(async (indexInfo) => {
61
- const memo = memoOrPromise instanceof Promise ? await memoOrPromise : memoOrPromise;
62
- const optimizedSelector = getSelector(indexInfo);
63
- if (optimizedSelector) memo.push(optimizedSelector);
64
- return memo;
65
- });
66
- const memo = memoOrPromise;
67
- if (memo instanceof Promise) throw new Error("Mixing async and sync index providers is not supported");
68
- const optimizedSelector = getSelector(indexInfoOrPromise);
69
- if (optimizedSelector) memo.push(optimizedSelector);
70
- return memo;
71
- }, []);
72
- }
73
- /**
74
- * Retrieves index information for a given complex selector by querying multiple
75
- * index providers. Handles nested `$and` and `$or` conditions in the selector and
76
- * optimizes the selector to minimize processing overhead.
77
- * @template T - The type of the items in the collection.
78
- * @template I - The type of the unique identifier for the items.
79
- * @param queryFunctions - An array of index providers to query.
80
- * @param selector - The complex selector used to filter items.
81
- * @returns An object containing:
82
- * - `matched`: A boolean indicating if the selector matched any items.
83
- * - `ids`: An array of matched item ids.
84
- * - `optimizedSelector`: A selector optimized based on the index results, with unused
85
- * conditions removed.
86
- */
87
- function getIndexInfo(queryFunctions, selector) {
88
- if (selector == null || Object.keys(selector).length <= 0) return {
89
- matched: false,
90
- ids: [],
91
- optimizedSelector: selector
92
- };
93
- const { $and, $or, ...rest } = selector;
94
- const flatInfoOrPromise = getMergedIndexInfo(queryFunctions, rest);
95
- const processFlatInfo = (flatInfo) => {
96
- let { matched, ids } = flatInfo;
97
- const newSelector = flatInfo.optimizedSelector;
98
- const $andNewOrPromise = Array.isArray($and) ? optimizeLogicGate(queryFunctions, $and, (match, selIds) => {
99
- if (!match) return;
100
- ids = matched ? require_intersection.default(ids, selIds) : selIds;
101
- matched = true;
102
- }) : void 0;
103
- const process$and = ($andNew) => {
104
- if ($andNew && $andNew.length > 0) newSelector.$and = $andNew;
105
- let hasNonIndexField = false;
106
- const matchedBefore = matched;
107
- const idsBefore = ids;
108
- const process$or = ($orNew) => {
109
- if (hasNonIndexField || $orNew && $orNew.length > 0) {
110
- newSelector.$or = $or;
111
- matched = matchedBefore;
112
- ids = idsBefore;
113
- }
114
- return {
115
- matched,
116
- ids: ids || [],
117
- optimizedSelector: newSelector
118
- };
119
- };
120
- const $orNewOrPromise = Array.isArray($or) ? optimizeLogicGate(queryFunctions, $or, (match, selIds) => {
121
- if (match) {
122
- ids = [...new Set([...ids, ...selIds])];
123
- matched = true;
124
- } else hasNonIndexField = true;
125
- }) : void 0;
126
- if ($orNewOrPromise instanceof Promise) return $orNewOrPromise.then(($orNew) => process$or($orNew));
127
- return process$or($orNewOrPromise);
128
- };
129
- if ($andNewOrPromise instanceof Promise) return $andNewOrPromise.then(($andNew) => process$and($andNew));
130
- return process$and($andNewOrPromise);
131
- };
132
- if (flatInfoOrPromise instanceof Promise) return flatInfoOrPromise.then(processFlatInfo);
133
- return processFlatInfo(flatInfoOrPromise);
10
+ function intersection(...arrays) {
11
+ if (arrays.length === 0) return [];
12
+ return [...new Set(arrays.reduce((a, b) => a.filter((c) => b.includes(c))))];
134
13
  }
135
14
  //#endregion
136
- exports.default = getIndexInfo;
15
+ exports.default = intersection;
package/dist/index16.mjs CHANGED
@@ -1,136 +1,15 @@
1
- import intersection from "./index15.mjs";
2
- //#region src/getIndexInfo.ts
1
+ //#region src/utils/intersection.ts
3
2
  /**
4
- * Retrieves merged index information for a given flat selector by querying multiple
5
- * index providers. Combines results from all index providers to determine matched ids
6
- * and an optimized selector.
7
- * @template T - The type of the items in the collection.
8
- * @template I - The type of the unique identifier for the items.
9
- * @param queryFunctions - An array of index providers to query.
10
- * @param selector - The flat selector used to filter items.
11
- * @returns An object containing:
12
- * - `matched`: A boolean indicating if the selector matched any items.
13
- * - `ids`: An array of matched item ids.
14
- * - `optimizedSelector`: A flat selector optimized based on the index results.
3
+ * Computes the intersection of multiple arrays, returning an array of unique elements
4
+ * that are present in all the input arrays.
5
+ * @template T - The type of elements in the arrays.
6
+ * @param arrays - A variable number of arrays to compute the intersection of.
7
+ * @returns An array containing the unique elements found in all the input arrays.
8
+ * - If no arrays are provided, returns an empty array.
15
9
  */
16
- function getMergedIndexInfo(queryFunctions, selector) {
17
- return queryFunctions.reduce((memoOrPromise, queryFunction) => {
18
- const resultOrPromise = queryFunction(selector);
19
- const processResult = (memo, result) => {
20
- if (!result.matched) return memo;
21
- const optimizedSelector = result.keepSelector ? memo.optimizedSelector : Object.fromEntries(Object.entries(memo.optimizedSelector).filter(([key]) => !result.fields.includes(key)));
22
- return {
23
- matched: true,
24
- ids: [...new Set(memo.matched ? intersection(memo.ids, result.ids) : result.ids)],
25
- optimizedSelector
26
- };
27
- };
28
- if (resultOrPromise instanceof Promise) return resultOrPromise.then(async (result) => {
29
- return processResult(memoOrPromise instanceof Promise ? await memoOrPromise : memoOrPromise, result);
30
- });
31
- const memo = memoOrPromise;
32
- if (memo instanceof Promise) throw new Error("Mixing async and sync index providers is not supported");
33
- return processResult(memo, resultOrPromise);
34
- }, {
35
- matched: false,
36
- ids: [],
37
- optimizedSelector: { ...selector }
38
- });
39
- }
40
- /**
41
- * Optimizes a logic gate ($and/$or) of selectors by querying multiple index providers.
42
- * @param queryFunctions - An array of index providers to query.
43
- * @param logicGate - An array of selectors representing the logic gate.
44
- * @param idsCallback - A callback function called with matched ids.
45
- * @returns An array of optimized selectors or a promise that resolves to such an array.
46
- */
47
- function optimizeLogicGate(queryFunctions, logicGate, idsCallback) {
48
- return logicGate.reduce((memoOrPromise, sel) => {
49
- const getSelector = (indexInfo) => {
50
- const { matched: selMatched, ids: selIds, optimizedSelector } = indexInfo;
51
- if (selMatched) {
52
- idsCallback(true, selIds);
53
- if (Object.keys(optimizedSelector).length > 0) return optimizedSelector;
54
- } else {
55
- idsCallback(false, []);
56
- return sel;
57
- }
58
- };
59
- const indexInfoOrPromise = getIndexInfo(queryFunctions, sel);
60
- if (indexInfoOrPromise instanceof Promise) return indexInfoOrPromise.then(async (indexInfo) => {
61
- const memo = memoOrPromise instanceof Promise ? await memoOrPromise : memoOrPromise;
62
- const optimizedSelector = getSelector(indexInfo);
63
- if (optimizedSelector) memo.push(optimizedSelector);
64
- return memo;
65
- });
66
- const memo = memoOrPromise;
67
- if (memo instanceof Promise) throw new Error("Mixing async and sync index providers is not supported");
68
- const optimizedSelector = getSelector(indexInfoOrPromise);
69
- if (optimizedSelector) memo.push(optimizedSelector);
70
- return memo;
71
- }, []);
72
- }
73
- /**
74
- * Retrieves index information for a given complex selector by querying multiple
75
- * index providers. Handles nested `$and` and `$or` conditions in the selector and
76
- * optimizes the selector to minimize processing overhead.
77
- * @template T - The type of the items in the collection.
78
- * @template I - The type of the unique identifier for the items.
79
- * @param queryFunctions - An array of index providers to query.
80
- * @param selector - The complex selector used to filter items.
81
- * @returns An object containing:
82
- * - `matched`: A boolean indicating if the selector matched any items.
83
- * - `ids`: An array of matched item ids.
84
- * - `optimizedSelector`: A selector optimized based on the index results, with unused
85
- * conditions removed.
86
- */
87
- function getIndexInfo(queryFunctions, selector) {
88
- if (selector == null || Object.keys(selector).length <= 0) return {
89
- matched: false,
90
- ids: [],
91
- optimizedSelector: selector
92
- };
93
- const { $and, $or, ...rest } = selector;
94
- const flatInfoOrPromise = getMergedIndexInfo(queryFunctions, rest);
95
- const processFlatInfo = (flatInfo) => {
96
- let { matched, ids } = flatInfo;
97
- const newSelector = flatInfo.optimizedSelector;
98
- const $andNewOrPromise = Array.isArray($and) ? optimizeLogicGate(queryFunctions, $and, (match, selIds) => {
99
- if (!match) return;
100
- ids = matched ? intersection(ids, selIds) : selIds;
101
- matched = true;
102
- }) : void 0;
103
- const process$and = ($andNew) => {
104
- if ($andNew && $andNew.length > 0) newSelector.$and = $andNew;
105
- let hasNonIndexField = false;
106
- const matchedBefore = matched;
107
- const idsBefore = ids;
108
- const process$or = ($orNew) => {
109
- if (hasNonIndexField || $orNew && $orNew.length > 0) {
110
- newSelector.$or = $or;
111
- matched = matchedBefore;
112
- ids = idsBefore;
113
- }
114
- return {
115
- matched,
116
- ids: ids || [],
117
- optimizedSelector: newSelector
118
- };
119
- };
120
- const $orNewOrPromise = Array.isArray($or) ? optimizeLogicGate(queryFunctions, $or, (match, selIds) => {
121
- if (match) {
122
- ids = [...new Set([...ids, ...selIds])];
123
- matched = true;
124
- } else hasNonIndexField = true;
125
- }) : void 0;
126
- if ($orNewOrPromise instanceof Promise) return $orNewOrPromise.then(($orNew) => process$or($orNew));
127
- return process$or($orNewOrPromise);
128
- };
129
- if ($andNewOrPromise instanceof Promise) return $andNewOrPromise.then(($andNew) => process$and($andNew));
130
- return process$and($andNewOrPromise);
131
- };
132
- if (flatInfoOrPromise instanceof Promise) return flatInfoOrPromise.then(processFlatInfo);
133
- return processFlatInfo(flatInfoOrPromise);
10
+ function intersection(...arrays) {
11
+ if (arrays.length === 0) return [];
12
+ return [...new Set(arrays.reduce((a, b) => a.filter((c) => b.includes(c))))];
134
13
  }
135
14
  //#endregion
136
- export { getIndexInfo as default };
15
+ export { intersection as default };