@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.
- package/dist/.vite/manifest.json +88 -59
- package/dist/AutoFetchCollection.d.ts +3 -3
- package/dist/Collection/Cursor.d.ts +10 -7
- package/dist/Collection/index.d.ts +27 -11
- package/dist/Collection/types.d.ts +1 -0
- package/dist/ReplicatedCollection.d.ts +4 -4
- package/dist/index.cjs.js +26 -27
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +14 -28
- package/dist/index10.cjs.js +265 -0
- package/dist/index10.mjs +263 -28
- package/dist/index11.cjs.js +125 -0
- package/dist/index11.mjs +124 -12
- package/dist/index12.cjs.js +15 -0
- package/dist/index12.mjs +14 -5
- package/dist/index13.cjs.js +23 -0
- package/dist/index13.mjs +22 -133
- package/dist/index14.cjs.js +12 -0
- package/dist/index14.mjs +11 -73
- package/dist/index15.cjs.js +22 -0
- package/dist/index15.mjs +21 -10
- package/dist/index16.cjs.js +33 -0
- package/dist/index16.mjs +32 -27
- package/dist/index17.cjs.js +15 -0
- package/dist/index17.mjs +14 -142
- package/dist/index18.cjs.js +98 -0
- package/dist/index18.mjs +97 -7
- package/dist/index19.cjs.js +11 -0
- package/dist/index19.mjs +10 -41
- package/dist/index2.cjs.js +23 -0
- package/dist/index2.mjs +22 -260
- package/dist/index20.cjs.js +45 -0
- package/dist/index20.mjs +44 -15
- package/dist/index21.cjs.js +45 -0
- package/dist/index21.mjs +44 -26
- package/dist/index22.cjs.js +69 -0
- package/dist/index22.mjs +66 -77
- package/dist/index23.cjs.js +778 -0
- package/dist/index23.mjs +775 -81
- package/dist/index24.cjs.js +11 -0
- package/dist/index24.mjs +10 -18
- package/dist/index25.cjs.js +81 -0
- package/dist/index25.mjs +80 -29
- package/dist/index26.cjs.js +98 -0
- package/dist/index26.mjs +96 -8
- package/dist/index27.cjs.js +154 -0
- package/dist/index27.mjs +153 -7
- package/dist/index28.cjs.js +11 -0
- package/dist/index28.mjs +10 -29
- package/dist/index29.cjs.js +11 -0
- package/dist/index29.mjs +10 -42
- package/dist/index3.cjs.js +19 -0
- package/dist/index3.mjs +18 -788
- package/dist/index4.cjs.js +37 -0
- package/dist/index4.mjs +36 -167
- package/dist/index5.cjs.js +35 -0
- package/dist/index5.mjs +34 -67
- package/dist/index6.cjs.js +47 -0
- package/dist/index6.mjs +46 -5
- package/dist/index7.cjs.js +33 -0
- package/dist/index7.mjs +32 -5
- package/dist/index8.cjs.js +19 -0
- package/dist/index8.mjs +18 -5
- package/dist/index9.cjs.js +139 -0
- package/dist/index9.mjs +138 -5
- package/dist/utils/deepClone.d.ts +1 -1
- package/package.json +3 -3
- package/dist/index.cjs10.js +0 -29
- package/dist/index.cjs11.js +0 -12
- package/dist/index.cjs12.js +0 -5
- package/dist/index.cjs13.js +0 -133
- package/dist/index.cjs14.js +0 -74
- package/dist/index.cjs15.js +0 -10
- package/dist/index.cjs16.js +0 -27
- package/dist/index.cjs17.js +0 -142
- package/dist/index.cjs18.js +0 -7
- package/dist/index.cjs19.js +0 -42
- package/dist/index.cjs2.js +0 -261
- package/dist/index.cjs20.js +0 -15
- package/dist/index.cjs21.js +0 -26
- package/dist/index.cjs22.js +0 -79
- package/dist/index.cjs23.js +0 -84
- package/dist/index.cjs24.js +0 -18
- package/dist/index.cjs25.js +0 -29
- package/dist/index.cjs26.js +0 -9
- package/dist/index.cjs27.js +0 -7
- package/dist/index.cjs28.js +0 -29
- package/dist/index.cjs29.js +0 -42
- package/dist/index.cjs3.js +0 -788
- package/dist/index.cjs4.js +0 -167
- package/dist/index.cjs5.js +0 -68
- package/dist/index.cjs6.js +0 -5
- package/dist/index.cjs7.js +0 -5
- package/dist/index.cjs8.js +0 -5
- 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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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
|
-
|
|
167
|
-
|
|
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
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
-
|
|
35
|
-
|
|
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
|
-
|
|
2
|
-
|
|
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
|
-
|
|
5
|
-
|
|
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
|
-
|
|
2
|
-
|
|
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
|
-
|
|
5
|
-
|
|
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
|
-
|
|
2
|
-
|
|
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
|
-
|
|
5
|
-
|
|
6
|
-
};
|
|
18
|
+
//#endregion
|
|
19
|
+
export { uniqueBy as default };
|