@signaldb/core 1.7.2 → 1.8.1

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 (95) hide show
  1. package/dist/.vite/manifest.json +88 -59
  2. package/dist/AutoFetchCollection.d.ts +3 -3
  3. package/dist/Collection/Cursor.d.ts +10 -7
  4. package/dist/Collection/index.d.ts +27 -11
  5. package/dist/Collection/types.d.ts +1 -0
  6. package/dist/ReplicatedCollection.d.ts +4 -4
  7. package/dist/index.cjs.js +26 -27
  8. package/dist/index.d.ts +1 -1
  9. package/dist/index.mjs +14 -28
  10. package/dist/index10.cjs.js +265 -0
  11. package/dist/index10.mjs +263 -28
  12. package/dist/index11.cjs.js +125 -0
  13. package/dist/index11.mjs +124 -12
  14. package/dist/index12.cjs.js +15 -0
  15. package/dist/index12.mjs +14 -5
  16. package/dist/index13.cjs.js +23 -0
  17. package/dist/index13.mjs +22 -133
  18. package/dist/index14.cjs.js +12 -0
  19. package/dist/index14.mjs +11 -73
  20. package/dist/index15.cjs.js +22 -0
  21. package/dist/index15.mjs +21 -10
  22. package/dist/index16.cjs.js +33 -0
  23. package/dist/index16.mjs +32 -27
  24. package/dist/index17.cjs.js +15 -0
  25. package/dist/index17.mjs +14 -142
  26. package/dist/index18.cjs.js +98 -0
  27. package/dist/index18.mjs +97 -7
  28. package/dist/index19.cjs.js +11 -0
  29. package/dist/index19.mjs +10 -41
  30. package/dist/index2.cjs.js +23 -0
  31. package/dist/index2.mjs +22 -260
  32. package/dist/index20.cjs.js +45 -0
  33. package/dist/index20.mjs +44 -15
  34. package/dist/index21.cjs.js +45 -0
  35. package/dist/index21.mjs +44 -26
  36. package/dist/index22.cjs.js +69 -0
  37. package/dist/index22.mjs +66 -77
  38. package/dist/index23.cjs.js +778 -0
  39. package/dist/index23.mjs +775 -81
  40. package/dist/index24.cjs.js +11 -0
  41. package/dist/index24.mjs +10 -18
  42. package/dist/index25.cjs.js +81 -0
  43. package/dist/index25.mjs +80 -29
  44. package/dist/index26.cjs.js +98 -0
  45. package/dist/index26.mjs +96 -8
  46. package/dist/index27.cjs.js +154 -0
  47. package/dist/index27.mjs +153 -7
  48. package/dist/index28.cjs.js +11 -0
  49. package/dist/index28.mjs +10 -29
  50. package/dist/index29.cjs.js +11 -0
  51. package/dist/index29.mjs +10 -42
  52. package/dist/index3.cjs.js +19 -0
  53. package/dist/index3.mjs +18 -788
  54. package/dist/index4.cjs.js +37 -0
  55. package/dist/index4.mjs +36 -167
  56. package/dist/index5.cjs.js +35 -0
  57. package/dist/index5.mjs +34 -67
  58. package/dist/index6.cjs.js +47 -0
  59. package/dist/index6.mjs +46 -5
  60. package/dist/index7.cjs.js +33 -0
  61. package/dist/index7.mjs +32 -5
  62. package/dist/index8.cjs.js +19 -0
  63. package/dist/index8.mjs +18 -5
  64. package/dist/index9.cjs.js +139 -0
  65. package/dist/index9.mjs +138 -5
  66. package/dist/utils/deepClone.d.ts +1 -1
  67. package/package.json +3 -3
  68. package/dist/index.cjs10.js +0 -29
  69. package/dist/index.cjs11.js +0 -12
  70. package/dist/index.cjs12.js +0 -5
  71. package/dist/index.cjs13.js +0 -133
  72. package/dist/index.cjs14.js +0 -74
  73. package/dist/index.cjs15.js +0 -10
  74. package/dist/index.cjs16.js +0 -27
  75. package/dist/index.cjs17.js +0 -142
  76. package/dist/index.cjs18.js +0 -7
  77. package/dist/index.cjs19.js +0 -42
  78. package/dist/index.cjs2.js +0 -261
  79. package/dist/index.cjs20.js +0 -15
  80. package/dist/index.cjs21.js +0 -26
  81. package/dist/index.cjs22.js +0 -79
  82. package/dist/index.cjs23.js +0 -84
  83. package/dist/index.cjs24.js +0 -18
  84. package/dist/index.cjs25.js +0 -29
  85. package/dist/index.cjs26.js +0 -9
  86. package/dist/index.cjs27.js +0 -7
  87. package/dist/index.cjs28.js +0 -29
  88. package/dist/index.cjs29.js +0 -42
  89. package/dist/index.cjs3.js +0 -788
  90. package/dist/index.cjs4.js +0 -167
  91. package/dist/index.cjs5.js +0 -68
  92. package/dist/index.cjs6.js +0 -5
  93. package/dist/index.cjs7.js +0 -5
  94. package/dist/index.cjs8.js +0 -5
  95. package/dist/index.cjs9.js +0 -5
@@ -0,0 +1,37 @@
1
+ //#region src/utils/set.ts
2
+ /**
3
+ * Sets a value at a specified path within an object. Creates nested structures
4
+ * (arrays or objects) as needed to set the value at the correct location. Supports
5
+ * deleting the key if the value is `undefined` and the `deleteIfUndefined` flag is set to `true`.
6
+ * @template T - The type of the object to modify.
7
+ * @template K - The type of the value to set.
8
+ * @param object - The object to modify. The object is mutated directly.
9
+ * @param path - The path (dot or bracket notation) where the value should be set.
10
+ * @param value - The value to set at the specified path.
11
+ * @param deleteIfUndefined - A boolean indicating whether to delete the key if the value is `undefined` (default: `false`).
12
+ * @returns The modified object.
13
+ */
14
+ function set(object, path, value, deleteIfUndefined = false) {
15
+ if (object == null) return object;
16
+ const segments = path.split(/[.[\]]/g);
17
+ if (segments[0] === "") segments.shift();
18
+ if (segments.at(-1) === "") segments.pop();
19
+ const apply = (node) => {
20
+ if (segments.length > 1) {
21
+ const key = segments.shift();
22
+ const nextIsNumber = !Number.isNaN(Number.parseInt(segments[0], 10));
23
+ if (node[key] === void 0) node[key] = nextIsNumber ? [] : {};
24
+ apply(node[key]);
25
+ } else {
26
+ if (deleteIfUndefined && value === void 0) {
27
+ delete node[segments[0]];
28
+ return;
29
+ }
30
+ node[segments[0]] = value;
31
+ }
32
+ };
33
+ apply(object);
34
+ return object;
35
+ }
36
+ //#endregion
37
+ exports.default = set;
package/dist/index4.mjs CHANGED
@@ -1,168 +1,37 @@
1
- import ReplicatedCollection from "./index23.mjs";
2
- import createSignal from "./index21.mjs";
3
- class AutoFetchCollection extends ReplicatedCollection {
4
- activeObservers = /* @__PURE__ */ new Map();
5
- observerTimeouts = /* @__PURE__ */ new Map();
6
- purgeDelay;
7
- idQueryCache = /* @__PURE__ */ new Map();
8
- itemsCache = /* @__PURE__ */ new Map();
9
- fetchQueryItems;
10
- triggerReload = null;
11
- reactivityAdapter = null;
12
- loadingSignals = /* @__PURE__ */ new Map();
13
- isFetchingSignal;
14
- mergeItems;
15
- /**
16
- * @param options {Object} - Options for the collection.
17
- * @param options.fetchQueryItems {Function} - A function that fetches items from the server. It takes the selector as an argument and returns a promise that resolves to an object with an `items` property.
18
- * @param options.purgeDelay {Number} - The delay in milliseconds before purging an item from the cache.
19
- */
20
- constructor(options) {
21
- let triggerRemoteChange;
22
- super({
23
- ...options,
24
- pull: () => Promise.resolve({
25
- items: [...this.itemsCache.values()].reduce((memo, items) => {
26
- const newItems = [...memo];
27
- items.forEach((item) => {
28
- const index = newItems.findIndex((i) => i.id === item.id);
29
- if (index === -1) {
30
- newItems.push(item);
31
- return;
32
- }
33
- newItems[index] = this.mergeItems(newItems[index], item);
34
- });
35
- return newItems;
36
- }, [])
37
- }),
38
- registerRemoteChange: async (onChange) => {
39
- triggerRemoteChange = onChange;
40
- }
41
- });
42
- this.mergeItems = options.mergeItems ?? ((itemA, itemB) => ({ ...itemA, ...itemB }));
43
- this.purgeDelay = options.purgeDelay ?? 1e4;
44
- this.isFetchingSignal = createSignal(options.reactivity, false);
45
- if (!triggerRemoteChange)
46
- throw new Error("No triggerRemoteChange method found. Looks like your persistence adapter was not registered");
47
- this.triggerReload = triggerRemoteChange;
48
- this.reactivityAdapter = options.reactivity ?? null;
49
- this.fetchQueryItems = options.fetchQueryItems;
50
- this.on("observer.created", (selector) => this.handleObserverCreation(selector ?? {}));
51
- this.on("observer.disposed", (selector) => setTimeout(() => this.handleObserverDisposal(selector ?? {}), 100));
52
- if (options.registerRemoteChange) {
53
- void options.registerRemoteChange(() => this.forceRefetch());
54
- }
55
- }
56
- /**
57
- * Registers a query manually that items should be fetched for it
58
- * @param selector {Object} Selector of the query
59
- */
60
- registerQuery(selector) {
61
- this.handleObserverCreation(selector);
62
- }
63
- /**
64
- * Unregisters a query manually that items are not fetched anymore for it
65
- * @param selector {Object} Selector of the query
66
- */
67
- unregisterQuery(selector) {
68
- this.handleObserverDisposal(selector);
69
- }
70
- getKeyForSelector(selector) {
71
- return JSON.stringify(selector);
72
- }
73
- async forceRefetch() {
74
- return Promise.all([...this.activeObservers.values()].map(({ selector }) => this.fetchSelector(selector))).then(() => {
75
- });
76
- }
77
- fetchSelector(selector) {
78
- this.isFetchingSignal.set(true);
79
- return this.fetchQueryItems(selector).then((response) => {
80
- if (!response.items)
81
- throw new Error("AutoFetchCollection currently only works with a full item response");
82
- this.itemsCache.set(this.getKeyForSelector(selector), response.items);
83
- response.items.forEach((item) => {
84
- const queries = this.idQueryCache.get(item.id) ?? [];
85
- queries.push(selector);
86
- this.idQueryCache.set(item.id, queries);
87
- });
88
- this.setLoading(selector, true);
89
- this.once("persistence.received", () => {
90
- this.setLoading(selector, false);
91
- });
92
- if (!this.triggerReload)
93
- throw new Error("No triggerReload method found. Looks like your persistence adapter was not registered");
94
- void this.triggerReload();
95
- }).catch((error) => {
96
- this.emit("persistence.error", error);
97
- }).finally(() => {
98
- this.isFetchingSignal.set(false);
99
- });
100
- }
101
- handleObserverCreation(selector) {
102
- const activeObservers = this.activeObservers.get(this.getKeyForSelector(selector))?.count ?? 0;
103
- this.activeObservers.set(this.getKeyForSelector(selector), {
104
- selector,
105
- count: activeObservers + 1
106
- });
107
- const timeout = this.observerTimeouts.get(this.getKeyForSelector(selector));
108
- if (timeout)
109
- clearTimeout(timeout);
110
- if (activeObservers === 0)
111
- void this.fetchSelector(selector);
112
- }
113
- handleObserverDisposal(selector) {
114
- const currentObservers = this.activeObservers.get(this.getKeyForSelector(selector))?.count ?? 0;
115
- const activeObservers = currentObservers - 1;
116
- if (activeObservers > 0) {
117
- this.activeObservers.set(this.getKeyForSelector(selector), {
118
- selector,
119
- count: activeObservers
120
- });
121
- return;
122
- }
123
- const timeout = this.observerTimeouts.get(this.getKeyForSelector(selector));
124
- if (timeout)
125
- clearTimeout(timeout);
126
- const removeObserver = () => {
127
- this.activeObservers.delete(this.getKeyForSelector(selector));
128
- this.itemsCache.delete(this.getKeyForSelector(selector));
129
- if (!this.triggerReload)
130
- throw new Error("No triggerReload method found. Looks like your persistence adapter was not registered");
131
- void this.triggerReload();
132
- };
133
- if (this.purgeDelay === 0) {
134
- removeObserver();
135
- return;
136
- }
137
- this.observerTimeouts.set(this.getKeyForSelector(selector), setTimeout(removeObserver, this.purgeDelay));
138
- }
139
- ensureSignal(selector) {
140
- if (!this.reactivityAdapter)
141
- throw new Error("No reactivity adapter found");
142
- if (!this.loadingSignals.has(this.getKeyForSelector(selector))) {
143
- this.loadingSignals.set(this.getKeyForSelector(selector), createSignal(this.reactivityAdapter, false));
144
- }
145
- return this.loadingSignals.get(this.getKeyForSelector(selector));
146
- }
147
- setLoading(selector, value) {
148
- const signal = this.ensureSignal(selector);
149
- signal.set(value);
150
- }
151
- /**
152
- * Indicates wether a query is currently been loaded
153
- * ⚡️ this function is reactive!
154
- * @param selector {Object} Selector of the query
155
- * @returns The loading state
156
- */
157
- isLoading(selector) {
158
- const isPushing = this.isPushing();
159
- if (!selector) {
160
- return this.isFetchingSignal.get() || isPushing;
161
- }
162
- const signal = this.ensureSignal(selector);
163
- return signal.get() || isPushing;
164
- }
1
+ //#region src/utils/set.ts
2
+ /**
3
+ * Sets a value at a specified path within an object. Creates nested structures
4
+ * (arrays or objects) as needed to set the value at the correct location. Supports
5
+ * deleting the key if the value is `undefined` and the `deleteIfUndefined` flag is set to `true`.
6
+ * @template T - The type of the object to modify.
7
+ * @template K - The type of the value to set.
8
+ * @param object - The object to modify. The object is mutated directly.
9
+ * @param path - The path (dot or bracket notation) where the value should be set.
10
+ * @param value - The value to set at the specified path.
11
+ * @param deleteIfUndefined - A boolean indicating whether to delete the key if the value is `undefined` (default: `false`).
12
+ * @returns The modified object.
13
+ */
14
+ function set(object, path, value, deleteIfUndefined = false) {
15
+ if (object == null) return object;
16
+ const segments = path.split(/[.[\]]/g);
17
+ if (segments[0] === "") segments.shift();
18
+ if (segments.at(-1) === "") segments.pop();
19
+ const apply = (node) => {
20
+ if (segments.length > 1) {
21
+ const key = segments.shift();
22
+ const nextIsNumber = !Number.isNaN(Number.parseInt(segments[0], 10));
23
+ if (node[key] === void 0) node[key] = nextIsNumber ? [] : {};
24
+ apply(node[key]);
25
+ } else {
26
+ if (deleteIfUndefined && value === void 0) {
27
+ delete node[segments[0]];
28
+ return;
29
+ }
30
+ node[segments[0]] = value;
31
+ }
32
+ };
33
+ apply(object);
34
+ return object;
165
35
  }
166
- export {
167
- AutoFetchCollection as default
168
- };
36
+ //#endregion
37
+ export { set as default };
@@ -0,0 +1,35 @@
1
+ const require_get = require("./index2.cjs.js");
2
+ const require_set = require("./index4.cjs.js");
3
+ //#region src/utils/project.ts
4
+ /**
5
+ * Projects the fields of an object based on a specified fields configuration.
6
+ * Supports inclusion (`1`) and exclusion (`0`) of specific fields. Creates a new object
7
+ * with the desired fields included or excluded, based on the configuration.
8
+ * @template T - The type of the object being projected.
9
+ * @param item - The original object to project fields from.
10
+ * @param fields - An object defining the fields to include (`1`) or exclude (`0`).
11
+ * - Keys are the field names, and values are either `1` (include) or `0` (exclude).
12
+ * @returns A new object with the specified fields included or excluded.
13
+ * - If all fields are set to `0`, the excluded fields are removed from the result.
14
+ * - If fields are set to `1`, only the included fields are retained.
15
+ */
16
+ function project(item, fields) {
17
+ if (Object.values(fields).every((value) => value === 0)) {
18
+ const result = { ...item };
19
+ Object.keys(fields).forEach((key) => {
20
+ if (require_get.default(item, key) === void 0) return;
21
+ require_set.default(result, key, void 0, true);
22
+ });
23
+ return result;
24
+ }
25
+ const result = {};
26
+ Object.entries(fields).forEach(([key, value]) => {
27
+ const fieldValue = require_get.default(item, key);
28
+ if (fieldValue === void 0) return;
29
+ if (fieldValue == null && value !== 1) return;
30
+ require_set.default(result, key, value === 1 ? fieldValue : void 0);
31
+ });
32
+ return result;
33
+ }
34
+ //#endregion
35
+ exports.default = project;
package/dist/index5.mjs CHANGED
@@ -1,68 +1,35 @@
1
- import createPersistenceAdapter from "./index8.mjs";
2
- function createTemporaryFallbackExecutor(firstResolvingPromiseFunction, secondResolvingPromiseFunction, options) {
3
- const cacheTimeout = options?.cacheTimeout;
4
- let isResolved = false;
5
- let resolvedValue = null;
6
- let timeout = null;
7
- let secondaryPromise = null;
8
- return (...args) => {
9
- if (secondaryPromise == null) {
10
- if (timeout) {
11
- clearTimeout(timeout);
12
- timeout = null;
13
- }
14
- secondaryPromise = secondResolvingPromiseFunction(...args).then((result) => {
15
- {
16
- timeout = setTimeout(() => {
17
- isResolved = false;
18
- resolvedValue = null;
19
- secondaryPromise = null;
20
- }, cacheTimeout);
21
- }
22
- isResolved = true;
23
- resolvedValue = result;
24
- if (options?.onResolve)
25
- options.onResolve(resolvedValue);
26
- return result;
27
- });
28
- } else if (isResolved) {
29
- return secondaryPromise;
30
- }
31
- return firstResolvingPromiseFunction(...args);
32
- };
1
+ import get from "./index2.mjs";
2
+ import set from "./index4.mjs";
3
+ //#region src/utils/project.ts
4
+ /**
5
+ * Projects the fields of an object based on a specified fields configuration.
6
+ * Supports inclusion (`1`) and exclusion (`0`) of specific fields. Creates a new object
7
+ * with the desired fields included or excluded, based on the configuration.
8
+ * @template T - The type of the object being projected.
9
+ * @param item - The original object to project fields from.
10
+ * @param fields - An object defining the fields to include (`1`) or exclude (`0`).
11
+ * - Keys are the field names, and values are either `1` (include) or `0` (exclude).
12
+ * @returns A new object with the specified fields included or excluded.
13
+ * - If all fields are set to `0`, the excluded fields are removed from the result.
14
+ * - If fields are set to `1`, only the included fields are retained.
15
+ */
16
+ function project(item, fields) {
17
+ if (Object.values(fields).every((value) => value === 0)) {
18
+ const result = { ...item };
19
+ Object.keys(fields).forEach((key) => {
20
+ if (get(item, key) === void 0) return;
21
+ set(result, key, void 0, true);
22
+ });
23
+ return result;
24
+ }
25
+ const result = {};
26
+ Object.entries(fields).forEach(([key, value]) => {
27
+ const fieldValue = get(item, key);
28
+ if (fieldValue === void 0) return;
29
+ if (fieldValue == null && value !== 1) return;
30
+ set(result, key, value === 1 ? fieldValue : void 0);
31
+ });
32
+ return result;
33
33
  }
34
- function combinePersistenceAdapters(slowAdapter, fastAdapter) {
35
- let handleChange = null;
36
- const readExecutor = createTemporaryFallbackExecutor(() => fastAdapter.load(), () => slowAdapter.load(), {
37
- cacheTimeout: 100,
38
- onResolve: (result) => {
39
- if (handleChange)
40
- void handleChange();
41
- void fastAdapter.save(result.items || [], {
42
- added: result.changes?.added || [],
43
- modified: result.changes?.modified || [],
44
- removed: result.changes?.removed || []
45
- });
46
- }
47
- });
48
- return createPersistenceAdapter({
49
- async register(onChange) {
50
- handleChange = onChange;
51
- await Promise.all([slowAdapter.register(onChange), fastAdapter.register(onChange)]);
52
- },
53
- async load() {
54
- const promise = readExecutor();
55
- return promise;
56
- },
57
- async save(items, changes) {
58
- await Promise.all([
59
- fastAdapter.save(items, changes),
60
- slowAdapter.save(items, changes)
61
- ]);
62
- }
63
- });
64
- }
65
- export {
66
- createTemporaryFallbackExecutor,
67
- combinePersistenceAdapters as default
68
- };
34
+ //#endregion
35
+ export { project as default };
@@ -0,0 +1,47 @@
1
+ //#region src/utils/deepClone.ts
2
+ /**
3
+ * Performs a deep clone of a value, supporting various types including arrays, objects,
4
+ * Maps, Sets, Dates, and RegExps. Functions are not supported and will throw an error.
5
+ * @template T - The type of the value to clone.
6
+ * @param value - The value to deep clone.
7
+ * @returns A deep copy of the provided value.
8
+ * @throws {Error} An error if the value is a function, as cloning functions is not supported.
9
+ */
10
+ function clone(value) {
11
+ if (typeof value === "function") throw new Error("Cloning functions is not supported");
12
+ if (value === null || typeof value !== "object") return value;
13
+ if (value instanceof Date) return new Date(value);
14
+ if (Array.isArray(value)) return value.map((item) => clone(item));
15
+ if (value instanceof Map) {
16
+ const result = /* @__PURE__ */ new Map();
17
+ value.forEach((currentValue, key) => {
18
+ result.set(key, clone(currentValue));
19
+ });
20
+ return result;
21
+ }
22
+ if (value instanceof Set) {
23
+ const result = /* @__PURE__ */ new Set();
24
+ value.forEach((currentValue) => {
25
+ result.add(clone(currentValue));
26
+ });
27
+ return result;
28
+ }
29
+ if (value instanceof RegExp) return new RegExp(value);
30
+ const result = {};
31
+ for (const key in value) if (Object.hasOwnProperty.call(value, key)) result[key] = clone(value[key]);
32
+ return result;
33
+ }
34
+ /**
35
+ * Creates a deep clone of an object. Uses the `structuredClone` function if available,
36
+ * otherwise falls back to a manual deep clone implementation.
37
+ * @template T - The type of the object to clone.
38
+ * @param object - The object to deep clone.
39
+ * @returns A deep copy of the provided object.
40
+ */
41
+ function deepClone(object) {
42
+ if (typeof structuredClone === "function") return structuredClone(object);
43
+ /* istanbul ignore next -- @preserve */
44
+ return clone(object);
45
+ }
46
+ //#endregion
47
+ exports.default = deepClone;
package/dist/index6.mjs CHANGED
@@ -1,6 +1,47 @@
1
- function createIndexProvider(definition) {
2
- return definition;
1
+ //#region src/utils/deepClone.ts
2
+ /**
3
+ * Performs a deep clone of a value, supporting various types including arrays, objects,
4
+ * Maps, Sets, Dates, and RegExps. Functions are not supported and will throw an error.
5
+ * @template T - The type of the value to clone.
6
+ * @param value - The value to deep clone.
7
+ * @returns A deep copy of the provided value.
8
+ * @throws {Error} An error if the value is a function, as cloning functions is not supported.
9
+ */
10
+ function clone(value) {
11
+ if (typeof value === "function") throw new Error("Cloning functions is not supported");
12
+ if (value === null || typeof value !== "object") return value;
13
+ if (value instanceof Date) return new Date(value);
14
+ if (Array.isArray(value)) return value.map((item) => clone(item));
15
+ if (value instanceof Map) {
16
+ const result = /* @__PURE__ */ new Map();
17
+ value.forEach((currentValue, key) => {
18
+ result.set(key, clone(currentValue));
19
+ });
20
+ return result;
21
+ }
22
+ if (value instanceof Set) {
23
+ const result = /* @__PURE__ */ new Set();
24
+ value.forEach((currentValue) => {
25
+ result.add(clone(currentValue));
26
+ });
27
+ return result;
28
+ }
29
+ if (value instanceof RegExp) return new RegExp(value);
30
+ const result = {};
31
+ for (const key in value) if (Object.hasOwnProperty.call(value, key)) result[key] = clone(value[key]);
32
+ return result;
3
33
  }
4
- export {
5
- createIndexProvider as default
6
- };
34
+ /**
35
+ * Creates a deep clone of an object. Uses the `structuredClone` function if available,
36
+ * otherwise falls back to a manual deep clone implementation.
37
+ * @template T - The type of the object to clone.
38
+ * @param object - The object to deep clone.
39
+ * @returns A deep copy of the provided object.
40
+ */
41
+ function deepClone(object) {
42
+ if (typeof structuredClone === "function") return structuredClone(object);
43
+ /* istanbul ignore next -- @preserve */
44
+ return clone(object);
45
+ }
46
+ //#endregion
47
+ export { deepClone as default };
@@ -0,0 +1,33 @@
1
+ //#region src/utils/isEqual.ts
2
+ /**
3
+ * Compares two values for deep equality.
4
+ * @param a - The first value to compare.
5
+ * @param b - The second value to compare.
6
+ * @returns - Returns `true` if the two values are deeply equal, otherwise `false`.
7
+ * @example
8
+ * isEqual({ a: 1 }, { a: 1 }); // true
9
+ * isEqual([1, 2], [1, 2]); // true
10
+ * isEqual(new Date(0), new Date(0)); // true
11
+ * isEqual(/abc/, /abc/); // true
12
+ * isEqual({ a: 1 }, { a: 2 }); // false
13
+ * isEqual(null, null); // true
14
+ */
15
+ function isEqual(a, b) {
16
+ if (Object.is(a, b)) return true;
17
+ if (a instanceof RegExp && b instanceof RegExp) return a.toString() === b.toString();
18
+ if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();
19
+ if (typeof a !== "object") return false;
20
+ if (typeof b !== "object") return false;
21
+ if (a === null) return false;
22
+ if (b === null) return false;
23
+ const aKeys = Object.keys(a);
24
+ const bKeys = Object.keys(b);
25
+ if (aKeys.length !== bKeys.length) return false;
26
+ for (const key of aKeys) {
27
+ if (!bKeys.includes(key)) return false;
28
+ if (!isEqual(a[key], b[key])) return false;
29
+ }
30
+ return true;
31
+ }
32
+ //#endregion
33
+ exports.default = isEqual;
package/dist/index7.mjs CHANGED
@@ -1,6 +1,33 @@
1
- function createMemoryAdapter(definition) {
2
- return definition;
1
+ //#region src/utils/isEqual.ts
2
+ /**
3
+ * Compares two values for deep equality.
4
+ * @param a - The first value to compare.
5
+ * @param b - The second value to compare.
6
+ * @returns - Returns `true` if the two values are deeply equal, otherwise `false`.
7
+ * @example
8
+ * isEqual({ a: 1 }, { a: 1 }); // true
9
+ * isEqual([1, 2], [1, 2]); // true
10
+ * isEqual(new Date(0), new Date(0)); // true
11
+ * isEqual(/abc/, /abc/); // true
12
+ * isEqual({ a: 1 }, { a: 2 }); // false
13
+ * isEqual(null, null); // true
14
+ */
15
+ function isEqual(a, b) {
16
+ if (Object.is(a, b)) return true;
17
+ if (a instanceof RegExp && b instanceof RegExp) return a.toString() === b.toString();
18
+ if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();
19
+ if (typeof a !== "object") return false;
20
+ if (typeof b !== "object") return false;
21
+ if (a === null) return false;
22
+ if (b === null) return false;
23
+ const aKeys = Object.keys(a);
24
+ const bKeys = Object.keys(b);
25
+ if (aKeys.length !== bKeys.length) return false;
26
+ for (const key of aKeys) {
27
+ if (!bKeys.includes(key)) return false;
28
+ if (!isEqual(a[key], b[key])) return false;
29
+ }
30
+ return true;
3
31
  }
4
- export {
5
- createMemoryAdapter as default
6
- };
32
+ //#endregion
33
+ export { isEqual as default };
@@ -0,0 +1,19 @@
1
+ //#region src/utils/uniqueBy.ts
2
+ /**
3
+ * Filters an array to ensure unique values based on a specified key or transformation function.
4
+ * @template T - The type of the elements in the array.
5
+ * @param array - The array to filter for unique values.
6
+ * @param fn - A key or transformation function to determine uniqueness.
7
+ * - If a key is provided, it will use the corresponding property of each element for uniqueness.
8
+ * - If a function is provided, it will use the return value of the function applied to each element for uniqueness.
9
+ * @returns A new array containing only unique elements based on the specified key or transformation.
10
+ */
11
+ function uniqueBy(array, fn) {
12
+ const set = /* @__PURE__ */ new Set();
13
+ return array.filter((element) => {
14
+ const value = typeof fn === "function" ? fn(element) : element[fn];
15
+ return !set.has(value) && set.add(value);
16
+ });
17
+ }
18
+ //#endregion
19
+ exports.default = uniqueBy;
package/dist/index8.mjs CHANGED
@@ -1,6 +1,19 @@
1
- function createPersistenceAdapter(definition) {
2
- return definition;
1
+ //#region src/utils/uniqueBy.ts
2
+ /**
3
+ * Filters an array to ensure unique values based on a specified key or transformation function.
4
+ * @template T - The type of the elements in the array.
5
+ * @param array - The array to filter for unique values.
6
+ * @param fn - A key or transformation function to determine uniqueness.
7
+ * - If a key is provided, it will use the corresponding property of each element for uniqueness.
8
+ * - If a function is provided, it will use the return value of the function applied to each element for uniqueness.
9
+ * @returns A new array containing only unique elements based on the specified key or transformation.
10
+ */
11
+ function uniqueBy(array, fn) {
12
+ const set = /* @__PURE__ */ new Set();
13
+ return array.filter((element) => {
14
+ const value = typeof fn === "function" ? fn(element) : element[fn];
15
+ return !set.has(value) && set.add(value);
16
+ });
3
17
  }
4
- export {
5
- createPersistenceAdapter as default
6
- };
18
+ //#endregion
19
+ export { uniqueBy as default };