@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/index23.mjs CHANGED
@@ -1,8 +1,129 @@
1
- import { Query } from "mingo";
2
- function match(item, selector) {
3
- const query = new Query(selector);
4
- return query.test(item);
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
+ });
20
+ }
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;
39
+ }
40
+ } else {
41
+ idsCallback(false, []);
42
+ return sel;
43
+ }
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;
96
+ }
97
+ return {
98
+ matched,
99
+ ids: ids || [],
100
+ optimizedSelector: newSelector
101
+ };
102
+ };
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;
109
+ }
110
+ }) : void 0;
111
+ if ($orNewOrPromise instanceof Promise) {
112
+ return $orNewOrPromise.then(($orNew) => process$or($orNew));
113
+ }
114
+ return process$or($orNewOrPromise);
115
+ };
116
+ if ($andNewOrPromise instanceof Promise) {
117
+ return $andNewOrPromise.then(($andNew) => process$and($andNew));
118
+ }
119
+ return process$and($andNewOrPromise);
120
+ };
121
+ if (flatInfoOrPromise instanceof Promise) {
122
+ return flatInfoOrPromise.then(processFlatInfo);
123
+ }
124
+ return processFlatInfo(flatInfoOrPromise);
5
125
  }
6
126
  export {
7
- match as default
127
+ getIndexInfo as default,
128
+ getMergedIndexInfo
8
129
  };
package/dist/index24.mjs CHANGED
@@ -1,28 +1,8 @@
1
- import get from "./index10.mjs";
2
- import set from "./index32.mjs";
3
- function project(item, fields) {
4
- const allFieldsDeactivated = Object.values(fields).every((value) => value === 0);
5
- if (allFieldsDeactivated) {
6
- const result2 = { ...item };
7
- Object.keys(fields).forEach((key) => {
8
- const fieldValue = get(item, key);
9
- if (fieldValue === void 0)
10
- return;
11
- set(result2, key, void 0, true);
12
- });
13
- return result2;
14
- }
15
- const result = {};
16
- Object.entries(fields).forEach(([key, value]) => {
17
- const fieldValue = get(item, key);
18
- if (fieldValue === void 0)
19
- return;
20
- if (fieldValue == null && value !== 1)
21
- return;
22
- set(result, key, value === 1 ? fieldValue : void 0);
23
- });
24
- return result;
1
+ import { Query } from "mingo";
2
+ function match(item, selector) {
3
+ const query = new Query(selector);
4
+ return query.test(item);
25
5
  }
26
6
  export {
27
- project as default
7
+ match as default
28
8
  };
package/dist/index25.mjs CHANGED
@@ -1,11 +1,28 @@
1
- import { sort } from "fast-sort";
2
1
  import get from "./index10.mjs";
3
- function sortItems(items, sortFields) {
4
- return sort(items).by(Object.entries(sortFields).map(([key, value]) => {
5
- const order = value === 1 ? "asc" : "desc";
6
- return { [order]: (i) => get(i, key) };
7
- }));
2
+ import set from "./index33.mjs";
3
+ function project(item, fields) {
4
+ const allFieldsDeactivated = Object.values(fields).every((value) => value === 0);
5
+ if (allFieldsDeactivated) {
6
+ const result2 = { ...item };
7
+ Object.keys(fields).forEach((key) => {
8
+ const fieldValue = get(item, key);
9
+ if (fieldValue === void 0)
10
+ return;
11
+ set(result2, key, void 0, true);
12
+ });
13
+ return result2;
14
+ }
15
+ const result = {};
16
+ Object.entries(fields).forEach(([key, value]) => {
17
+ const fieldValue = get(item, key);
18
+ if (fieldValue === void 0)
19
+ return;
20
+ if (fieldValue == null && value !== 1)
21
+ return;
22
+ set(result, key, value === 1 ? fieldValue : void 0);
23
+ });
24
+ return result;
8
25
  }
9
26
  export {
10
- sortItems as default
27
+ project as default
11
28
  };
package/dist/index26.mjs CHANGED
@@ -1,30 +1,11 @@
1
- import isFieldExpression from "./index33.mjs";
2
- import serializeValue from "./index11.mjs";
3
- function getMatchingKeys(field, selector) {
4
- const result = { include: null, exclude: null };
5
- const fieldSelector = selector[field];
6
- if (fieldSelector instanceof RegExp)
7
- return result;
8
- if (fieldSelector == null)
9
- return result;
10
- if (isFieldExpression(fieldSelector)) {
11
- if (fieldSelector.$ne != null) {
12
- result.exclude = [serializeValue(fieldSelector.$ne)];
13
- return result;
14
- }
15
- if (Array.isArray(fieldSelector.$in) && fieldSelector.$in.length > 0) {
16
- result.include = fieldSelector.$in.map(serializeValue);
17
- return result;
18
- }
19
- if (Array.isArray(fieldSelector.$nin) && fieldSelector.$nin.length > 0) {
20
- result.exclude = fieldSelector.$nin.map(serializeValue);
21
- return result;
22
- }
23
- return { include: null, exclude: null };
24
- }
25
- result.include = [serializeValue(fieldSelector)];
26
- return result;
1
+ import { sort } from "fast-sort";
2
+ import get from "./index10.mjs";
3
+ function sortItems(items, sortFields) {
4
+ return sort(items).by(Object.entries(sortFields).map(([key, value]) => {
5
+ const order = value === 1 ? "asc" : "desc";
6
+ return { [order]: (i) => get(i, key) };
7
+ }));
27
8
  }
28
9
  export {
29
- getMatchingKeys as default
10
+ sortItems as default
30
11
  };
package/dist/index27.mjs CHANGED
@@ -1,47 +1,30 @@
1
- function batchOnNextTick(onFlush) {
2
- const queues = /* @__PURE__ */ new Map();
3
- function enqueue(key, args) {
4
- return new Promise((resolve, reject) => {
5
- let q = queues.get(key);
6
- if (!q) {
7
- q = {
8
- timer: null,
9
- items: [],
10
- flush: () => flush(key)
11
- };
12
- queues.set(key, q);
13
- }
14
- q.items.push({ args, resolve, reject });
15
- if (q.timer == null) {
16
- q.timer = setTimeout(() => {
17
- q.timer = null;
18
- void q.flush();
19
- }, 0);
20
- }
21
- });
22
- }
23
- async function flush(key) {
24
- const q = queues.get(key);
25
- if (!q || q.items.length === 0)
26
- return;
27
- if (q.timer != null) {
28
- clearTimeout(q.timer);
29
- q.timer = null;
1
+ import isFieldExpression from "./index32.mjs";
2
+ import serializeValue from "./index11.mjs";
3
+ function getMatchingKeys(field, selector) {
4
+ const result = { include: null, exclude: null };
5
+ const fieldSelector = selector[field];
6
+ if (fieldSelector instanceof RegExp)
7
+ return result;
8
+ if (fieldSelector == null)
9
+ return result;
10
+ if (isFieldExpression(fieldSelector)) {
11
+ if (fieldSelector.$ne != null) {
12
+ result.exclude = [serializeValue(fieldSelector.$ne)];
13
+ return result;
14
+ }
15
+ if (Array.isArray(fieldSelector.$in) && fieldSelector.$in.length > 0) {
16
+ result.include = fieldSelector.$in.map(serializeValue);
17
+ return result;
18
+ }
19
+ if (Array.isArray(fieldSelector.$nin) && fieldSelector.$nin.length > 0) {
20
+ result.exclude = fieldSelector.$nin.map(serializeValue);
21
+ return result;
30
22
  }
31
- const items = q.items.splice(0);
32
- onFlush(key, items.map((i) => i.args)).then((results) => {
33
- for (const [index, result] of results.entries()) {
34
- const { resolve } = items[index];
35
- resolve(result);
36
- }
37
- }).catch((error) => {
38
- for (const { reject } of items) {
39
- reject(error);
40
- }
41
- });
23
+ return { include: null, exclude: null };
42
24
  }
43
- return { enqueue, flush };
25
+ result.include = [serializeValue(fieldSelector)];
26
+ return result;
44
27
  }
45
28
  export {
46
- batchOnNextTick as default
29
+ getMatchingKeys as default
47
30
  };
package/dist/index28.mjs CHANGED
@@ -1,9 +1,47 @@
1
- function truthy(value) {
2
- return !!value;
3
- }
4
- function compact(array) {
5
- return array.filter(truthy);
1
+ function batchOnNextTick(onFlush) {
2
+ const queues = /* @__PURE__ */ new Map();
3
+ function enqueue(key, args) {
4
+ return new Promise((resolve, reject) => {
5
+ let q = queues.get(key);
6
+ if (!q) {
7
+ q = {
8
+ timer: null,
9
+ items: [],
10
+ flush: () => flush(key)
11
+ };
12
+ queues.set(key, q);
13
+ }
14
+ q.items.push({ args, resolve, reject });
15
+ if (q.timer == null) {
16
+ q.timer = setTimeout(() => {
17
+ q.timer = null;
18
+ void q.flush();
19
+ }, 0);
20
+ }
21
+ });
22
+ }
23
+ async function flush(key) {
24
+ const q = queues.get(key);
25
+ if (!q || q.items.length === 0)
26
+ return;
27
+ if (q.timer != null) {
28
+ clearTimeout(q.timer);
29
+ q.timer = null;
30
+ }
31
+ const items = q.items.splice(0);
32
+ onFlush(key, items.map((i) => i.args)).then((results) => {
33
+ for (const [index, result] of results.entries()) {
34
+ const { resolve } = items[index];
35
+ resolve(result);
36
+ }
37
+ }).catch((error) => {
38
+ for (const { reject } of items) {
39
+ reject(error);
40
+ }
41
+ });
42
+ }
43
+ return { enqueue, flush };
6
44
  }
7
45
  export {
8
- compact as default
46
+ batchOnNextTick as default
9
47
  };
package/dist/index29.mjs CHANGED
@@ -1,10 +1,9 @@
1
- function uniqueBy(array, fn) {
2
- const set = /* @__PURE__ */ new Set();
3
- return array.filter((element) => {
4
- const value = typeof fn === "function" ? fn(element) : element[fn];
5
- return !set.has(value) && set.add(value);
6
- });
1
+ function truthy(value) {
2
+ return !!value;
3
+ }
4
+ function compact(array) {
5
+ return array.filter(truthy);
7
6
  }
8
7
  export {
9
- uniqueBy as default
8
+ compact as default
10
9
  };
package/dist/index3.mjs CHANGED
@@ -1,10 +1,10 @@
1
1
  import EventEmitter from "./index9.mjs";
2
- import createSignal from "./index18.mjs";
2
+ import createSignal from "./index19.mjs";
3
3
  import randomId from "./index8.mjs";
4
- import DefaultDataAdapter from "./index12.mjs";
4
+ import DefaultDataAdapter from "./index13.mjs";
5
5
  import modify from "./index7.mjs";
6
- import deepClone from "./index19.mjs";
7
- import queryId from "./index20.mjs";
6
+ import deepClone from "./index20.mjs";
7
+ import queryId from "./index21.mjs";
8
8
  import Cursor from "./index2.mjs";
9
9
  class Collection extends EventEmitter {
10
10
  static collections = [];
@@ -244,14 +244,6 @@ class Collection extends EventEmitter {
244
244
  Collection.collections = Collection.collections.filter((collection) => collection !== this);
245
245
  Collection.onDisposeCallbacks.forEach((callback) => callback(this));
246
246
  }
247
- /**
248
- * Finds multiple items in the collection based on a selector and optional options.
249
- * Returns a cursor for reactive data queries.
250
- * @template O - The options type for the find operation.
251
- * @param [selector] - The criteria to select items.
252
- * @param [options] - Options for the find operation, such as limit and sort.
253
- * @returns A cursor to fetch and observe the matching items.
254
- */
255
247
  find(selector = {}, options) {
256
248
  if (this.isDisposed)
257
249
  throw new Error("Collection is disposed");
@@ -281,7 +273,8 @@ class Collection extends EventEmitter {
281
273
  requery();
282
274
  };
283
275
  const listeners = this.queryListeners({ selector, options });
284
- if (listeners === 0)
276
+ const didRegister = listeners === 0;
277
+ if (didRegister)
285
278
  this.backend.registerQuery(selector, options || {});
286
279
  this.queryListeners({ selector, options }, listeners + 1);
287
280
  const queryStateChangeCleanup = this.backend.onQueryStateChange(selector, options || {}, (state) => {
@@ -291,14 +284,14 @@ class Collection extends EventEmitter {
291
284
  });
292
285
  this.emit("observer.created", selector, options);
293
286
  return () => {
294
- setTimeout(() => {
287
+ queueMicrotask(() => {
295
288
  const newListeners = Math.max(0, this.queryListeners({ selector, options }) - 1);
296
- if (newListeners === 0)
289
+ if (newListeners === 0 && didRegister)
297
290
  this.backend.unregisterQuery(selector, options || {});
298
291
  this.queryListeners({ selector, options }, newListeners);
299
292
  queryStateChangeCleanup();
300
293
  this.emit("observer.disposed", selector, options);
301
- }, 0);
294
+ });
302
295
  };
303
296
  }
304
297
  });
@@ -306,16 +299,6 @@ class Collection extends EventEmitter {
306
299
  this.executeInDebugMode((callstack) => this.emit("_debug.find", callstack, selector, options, cursor));
307
300
  return cursor;
308
301
  }
309
- /**
310
- * Finds a single item in the collection based on a selector and optional options.
311
- * ⚡️ this function is reactive!
312
- * Returns the found item or undefined if no item matches.
313
- * @template Async - Whether to perform the operation asynchronously.
314
- * @template O - The options type for the find operation.
315
- * @param selector - The criteria to select the item.
316
- * @param [options] - Options for the find operation, such as projection.
317
- * @returns The found item or `undefined`.
318
- */
319
302
  findOne(selector, options) {
320
303
  if (this.isDisposed)
321
304
  throw new Error("Collection is disposed");
package/dist/index30.mjs CHANGED
@@ -1,6 +1,10 @@
1
- function createIndexProvider(definition) {
2
- return definition;
1
+ function uniqueBy(array, fn) {
2
+ const set = /* @__PURE__ */ new Set();
3
+ return array.filter((element) => {
4
+ const value = typeof fn === "function" ? fn(element) : element[fn];
5
+ return !set.has(value) && set.add(value);
6
+ });
3
7
  }
4
8
  export {
5
- createIndexProvider as default
9
+ uniqueBy as default
6
10
  };
package/dist/index32.mjs CHANGED
@@ -1,30 +1,43 @@
1
- function set(object, path, value, deleteIfUndefined = false) {
2
- if (object == null)
3
- return object;
4
- const segments = path.split(/[.[\]]/g);
5
- if (segments[0] === "")
6
- segments.shift();
7
- if (segments.at(-1) === "")
8
- segments.pop();
9
- const apply = (node) => {
10
- if (segments.length > 1) {
11
- const key = segments.shift();
12
- const nextIsNumber = !Number.isNaN(Number.parseInt(segments[0], 10));
13
- if (node[key] === void 0) {
14
- node[key] = nextIsNumber ? [] : {};
15
- }
16
- apply(node[key]);
17
- } else {
18
- if (deleteIfUndefined && value === void 0) {
19
- delete node[segments[0]];
20
- return;
21
- }
22
- node[segments[0]] = value;
23
- }
24
- };
25
- apply(object);
26
- return object;
1
+ const expressionKeys = /* @__PURE__ */ new Set([
2
+ "$eq",
3
+ "$gt",
4
+ "$gte",
5
+ "$lt",
6
+ "$lte",
7
+ "$in",
8
+ "$nin",
9
+ "$ne",
10
+ "$exists",
11
+ "$not",
12
+ "$expr",
13
+ "$jsonSchema",
14
+ "$mod",
15
+ "$regex",
16
+ "$options",
17
+ "$text",
18
+ "$where",
19
+ "$all",
20
+ "$elemMatch",
21
+ "$size",
22
+ "$bitsAllClear",
23
+ "$bitsAllSet",
24
+ "$bitsAnyClear",
25
+ "$bitsAnySet"
26
+ ]);
27
+ function isFieldExpression(expression) {
28
+ if (typeof expression !== "object" || expression == null) {
29
+ return false;
30
+ }
31
+ const keys = Object.keys(expression);
32
+ if (keys.length === 0) {
33
+ return false;
34
+ }
35
+ const hasInvalidKeys = keys.some((key) => !expressionKeys.has(key));
36
+ if (hasInvalidKeys)
37
+ return false;
38
+ const hasValidKeys = keys.every((key) => expressionKeys.has(key));
39
+ return hasValidKeys;
27
40
  }
28
41
  export {
29
- set as default
42
+ isFieldExpression as default
30
43
  };
package/dist/index33.mjs CHANGED
@@ -1,43 +1,30 @@
1
- const expressionKeys = /* @__PURE__ */ new Set([
2
- "$eq",
3
- "$gt",
4
- "$gte",
5
- "$lt",
6
- "$lte",
7
- "$in",
8
- "$nin",
9
- "$ne",
10
- "$exists",
11
- "$not",
12
- "$expr",
13
- "$jsonSchema",
14
- "$mod",
15
- "$regex",
16
- "$options",
17
- "$text",
18
- "$where",
19
- "$all",
20
- "$elemMatch",
21
- "$size",
22
- "$bitsAllClear",
23
- "$bitsAllSet",
24
- "$bitsAnyClear",
25
- "$bitsAnySet"
26
- ]);
27
- function isFieldExpression(expression) {
28
- if (typeof expression !== "object" || expression == null) {
29
- return false;
30
- }
31
- const keys = Object.keys(expression);
32
- if (keys.length === 0) {
33
- return false;
34
- }
35
- const hasInvalidKeys = keys.some((key) => !expressionKeys.has(key));
36
- if (hasInvalidKeys)
37
- return false;
38
- const hasValidKeys = keys.every((key) => expressionKeys.has(key));
39
- return hasValidKeys;
1
+ function set(object, path, value, deleteIfUndefined = false) {
2
+ if (object == null)
3
+ return object;
4
+ const segments = path.split(/[.[\]]/g);
5
+ if (segments[0] === "")
6
+ segments.shift();
7
+ if (segments.at(-1) === "")
8
+ segments.pop();
9
+ const apply = (node) => {
10
+ if (segments.length > 1) {
11
+ const key = segments.shift();
12
+ const nextIsNumber = !Number.isNaN(Number.parseInt(segments[0], 10));
13
+ if (node[key] === void 0) {
14
+ node[key] = nextIsNumber ? [] : {};
15
+ }
16
+ apply(node[key]);
17
+ } else {
18
+ if (deleteIfUndefined && value === void 0) {
19
+ delete node[segments[0]];
20
+ return;
21
+ }
22
+ node[segments[0]] = value;
23
+ }
24
+ };
25
+ apply(object);
26
+ return object;
40
27
  }
41
28
  export {
42
- isFieldExpression as default
29
+ set as default
43
30
  };
@@ -0,0 +1,6 @@
1
+ function createIndexProvider(definition) {
2
+ return definition;
3
+ }
4
+ export {
5
+ createIndexProvider as default
6
+ };
package/dist/index7.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { update } from "mingo";
2
- import deepClone from "./index19.mjs";
2
+ import deepClone from "./index20.mjs";
3
3
  function modify(item, modifier) {
4
4
  const hasOperators = Object.keys(modifier).some((key) => key.startsWith("$"));
5
5
  if (!hasOperators)