@helpers4/object 2.0.0-alpha.1 → 2.0.0-alpha.11

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/README.md CHANGED
@@ -9,14 +9,19 @@ A set of helpers for working with URLs.
9
9
 
10
10
  ## Documentation
11
11
 
12
- [https://helpers4.js.org/object](https://helpers4.js.org/object)
12
+ [https://helpers4.dev/typescript/categories/object/](https://helpers4.dev/typescript/categories/object/)
13
13
 
14
14
  <!-- AUTOMATIC-METHODS -->
15
+ - compact
16
+ - deepClone
17
+ - deepCompare
15
18
  - deepMerge
16
19
  - get
17
- - deepClone
18
- - set
20
+ - omit
21
+ - pick
19
22
  - removeUndefinedNull
23
+ - set
24
+ - shallowEquals
20
25
  <!-- /AUTOMATIC-METHODS -->
21
26
 
22
27
  ## See
@@ -25,6 +30,7 @@ A set of helpers for working with URLs.
25
30
  - [array](../array)
26
31
  - [date](../date)
27
32
  - [function](../function)
33
+ - [math](../math)
28
34
  - [number](../number)
29
35
  - [observable](../observable)
30
36
  - [promise](../promise)
@@ -42,6 +48,7 @@ A set of helpers for working with URLs.
42
48
  | array | [@helpers4/array](https://www.npmjs.com/package/@helpers4/array) | [Source](https://github.com/helpers4/helpers4/tree/main/helpers/array) | Array manipulation utilities |
43
49
  | date | [@helpers4/date](https://www.npmjs.com/package/@helpers4/date) | [Source](https://github.com/helpers4/helpers4/tree/main/helpers/date) | date utilities |
44
50
  | function | [@helpers4/function](https://www.npmjs.com/package/@helpers4/function) | [Source](https://github.com/helpers4/helpers4/tree/main/helpers/function) | Function utilities and type guards |
51
+ | math | [@helpers4/math](https://www.npmjs.com/package/@helpers4/math) | [Source](https://github.com/helpers4/helpers4/tree/main/helpers/math) | math utilities |
45
52
  | number | [@helpers4/number](https://www.npmjs.com/package/@helpers4/number) | [Source](https://github.com/helpers4/helpers4/tree/main/helpers/number) | number utilities |
46
53
  | object | [@helpers4/object](https://www.npmjs.com/package/@helpers4/object) | [Source](https://github.com/helpers4/helpers4/tree/main/helpers/object) | Object manipulation utilities |
47
54
  | observable | [@helpers4/observable](https://www.npmjs.com/package/@helpers4/observable) | [Source](https://github.com/helpers4/helpers4/tree/main/helpers/observable) | Observable utilities and combinators |
package/lib/index.d.ts CHANGED
@@ -1,5 +1,177 @@
1
- export * from './deepMerge';
2
- export * from './get';
3
- export * from './deepClone';
4
- export * from './set';
5
- export * from './removeUndefinedNull';
1
+ /**
2
+ * This file is part of helpers4.
3
+ * Copyright (C) 2025 baxyz
4
+ * SPDX-License-Identifier: LGPL-3.0-or-later
5
+ */
6
+ /**
7
+ * Removes all entries with falsy values (`false`, `null`, `undefined`, `0`, `""`, `NaN`) from an object.
8
+ * @param obj - The source object
9
+ * @returns A new object containing only entries with truthy values
10
+ * @example
11
+ * compact({ a: 1, b: null, c: '', d: 0, e: 'hello' })
12
+ * // => { a: 1, e: 'hello' }
13
+ * @since 2.0.0
14
+ */
15
+ declare function compact<T extends Record<string, unknown>>(obj: T): Partial<T>;
16
+
17
+ /**
18
+ * This file is part of helpers4.
19
+ * Copyright (C) 2025 baxyz
20
+ * SPDX-License-Identifier: LGPL-3.0-or-later
21
+ */
22
+ /**
23
+ * Creates a deep copy of an object or array
24
+ * @param obj - The object to clone
25
+ * @returns Deep cloned object
26
+ * @since 1.9.0
27
+ */
28
+ declare function deepClone<T>(obj: T): T;
29
+
30
+ /**
31
+ * This file is part of helpers4.
32
+ * Copyright (C) 2025 baxyz
33
+ * SPDX-License-Identifier: LGPL-3.0-or-later
34
+ */
35
+ /**
36
+ * Result type for deep comparison when objects are not identical
37
+ * @since 2.0.0
38
+ */
39
+ interface DeepCompareResult {
40
+ [key: string]: "onlyA" | "onlyB" | false | DeepCompareResult;
41
+ }
42
+ /**
43
+ * Deep comparison of two objects that returns detailed information about differences.
44
+ *
45
+ * @param objA - First object to compare (can be object, undefined, or null)
46
+ * @param objB - Second object to compare (can be object, undefined, or null)
47
+ * @returns `true` if objects are identical, `false` if incompatible types, or a `DeepCompareResult` object detailing differences
48
+ * @since 2.0.0
49
+ */
50
+ declare function deepCompare(objA: object | undefined | null, objB: object | undefined | null): true | false | DeepCompareResult;
51
+
52
+ /**
53
+ * This file is part of helpers4.
54
+ * Copyright (C) 2025 baxyz
55
+ * SPDX-License-Identifier: LGPL-3.0-or-later
56
+ */
57
+ /**
58
+ * Merges two or more objects deeply
59
+ * @param target - The target object
60
+ * @param sources - The source objects to merge
61
+ * @returns The merged object
62
+ * @since 1.9.0
63
+ */
64
+ declare function deepMerge<T extends Record<string, any>>(target: T, ...sources: Record<string, any>[]): T;
65
+
66
+ /**
67
+ * This file is part of helpers4.
68
+ * Copyright (C) 2025 baxyz
69
+ * SPDX-License-Identifier: LGPL-3.0-or-later
70
+ */
71
+ /**
72
+ * Gets a value from an object using a dot-notated path
73
+ * @param obj - The object to get value from
74
+ * @param path - The dot-notated path (e.g., 'a.b.c')
75
+ * @param defaultValue - Default value if path doesn't exist
76
+ * @returns The value at the path or default value
77
+ * @since 1.9.0
78
+ */
79
+ declare function get<T = any>(obj: any, path: string, defaultValue?: T): T | undefined;
80
+
81
+ /**
82
+ * This file is part of helpers4.
83
+ * Copyright (C) 2025 baxyz
84
+ * SPDX-License-Identifier: LGPL-3.0-or-later
85
+ */
86
+ /**
87
+ * Creates a new object without the specified keys.
88
+ * @param obj - The source object
89
+ * @param keys - The keys to omit
90
+ * @returns A new object without the omitted keys
91
+ * @example
92
+ * omit({ a: 1, b: 2, c: 3 }, ['b'])
93
+ * // => { a: 1, c: 3 }
94
+ * @since 2.0.0
95
+ */
96
+ declare function omit<T extends Record<string, unknown>, K extends keyof T>(obj: T, keys: readonly K[]): Omit<T, K>;
97
+
98
+ /**
99
+ * This file is part of helpers4.
100
+ * Copyright (C) 2025 baxyz
101
+ * SPDX-License-Identifier: LGPL-3.0-or-later
102
+ */
103
+ /**
104
+ * Creates a new object with only the specified keys.
105
+ * @param obj - The source object
106
+ * @param keys - The keys to pick
107
+ * @returns A new object with only the picked keys
108
+ * @example
109
+ * pick({ a: 1, b: 2, c: 3 }, ['a', 'c'])
110
+ * // => { a: 1, c: 3 }
111
+ * @since 2.0.0
112
+ */
113
+ declare function pick<T extends Record<string, unknown>, K extends keyof T>(obj: T, keys: readonly K[]): Pick<T, K>;
114
+
115
+ /**
116
+ * This file is part of helpers4.
117
+ * Copyright (C) 2025 baxyz
118
+ * SPDX-License-Identifier: LGPL-3.0-or-later
119
+ */
120
+ /**
121
+ * Remove null and undefined values from an object.
122
+ *
123
+ * @param obj an object
124
+ * @returns A shallow copy of the object without null or undefined values
125
+ * @since 1.0.0
126
+ */
127
+ declare function removeUndefinedNull<T extends Record<string, string | number | boolean | null | undefined>>(obj: T): Partial<T>;
128
+ /**
129
+ * Remove null and undefined values from an object.
130
+ *
131
+ * @param obj a null object
132
+ * @returns null
133
+ * @since 1.0.0
134
+ */
135
+ declare function removeUndefinedNull(obj: null): null;
136
+ /**
137
+ * Remove null and undefined values from an object.
138
+ *
139
+ * @param obj an undefined object
140
+ * @returns undefined
141
+ * @since 1.0.0
142
+ */
143
+ declare function removeUndefinedNull(obj: undefined): undefined;
144
+
145
+ /**
146
+ * This file is part of helpers4.
147
+ * Copyright (C) 2025 baxyz
148
+ * SPDX-License-Identifier: LGPL-3.0-or-later
149
+ */
150
+ /**
151
+ * Sets a value in an object using a dot-notated path
152
+ * @param obj - The object to set value in
153
+ * @param path - The dot-notated path (e.g., 'a.b.c')
154
+ * @param value - The value to set
155
+ * @returns The modified object
156
+ * @since 1.9.0
157
+ */
158
+ declare function set(obj: Record<string, any>, path: string, value: any): Record<string, any>;
159
+
160
+ /**
161
+ * This file is part of helpers4.
162
+ * Copyright (C) 2025 baxyz
163
+ * SPDX-License-Identifier: LGPL-3.0-or-later
164
+ */
165
+ /**
166
+ * Quick comparison of two objects using JSON.stringify.
167
+ * This is a fast but simple comparison that may not work for all edge cases.
168
+ *
169
+ * @param objA - First object to compare
170
+ * @param objB - Second object to compare
171
+ * @returns `true` if objects are identical according to JSON.stringify, `false` otherwise
172
+ * @since 2.0.0
173
+ */
174
+ declare function shallowEquals(objA: unknown, objB: unknown): boolean;
175
+
176
+ export { compact, deepClone, deepCompare, deepMerge, get, omit, pick, removeUndefinedNull, set, shallowEquals };
177
+ export type { DeepCompareResult };
package/lib/index.js CHANGED
@@ -1,6 +1,365 @@
1
- // helpers/object/index.ts
2
- export * from "./deepMerge";
3
- export * from "./get";
4
- export * from "./deepClone";
5
- export * from "./set";
6
- export * from "./removeUndefinedNull";
1
+ //#region helpers/object/compact.ts
2
+ /**
3
+ * This file is part of helpers4.
4
+ * Copyright (C) 2025 baxyz
5
+ * SPDX-License-Identifier: LGPL-3.0-or-later
6
+ */
7
+ /**
8
+ * Removes all entries with falsy values (`false`, `null`, `undefined`, `0`, `""`, `NaN`) from an object.
9
+ * @param obj - The source object
10
+ * @returns A new object containing only entries with truthy values
11
+ * @example
12
+ * compact({ a: 1, b: null, c: '', d: 0, e: 'hello' })
13
+ * // => { a: 1, e: 'hello' }
14
+ * @since 2.0.0
15
+ */
16
+ function compact(obj) {
17
+ const result = {};
18
+ for (const key of Object.keys(obj)) if (obj[key]) result[key] = obj[key];
19
+ return result;
20
+ }
21
+ //#endregion
22
+ //#region helpers/object/deepClone.ts
23
+ /**
24
+ * This file is part of helpers4.
25
+ * Copyright (C) 2025 baxyz
26
+ * SPDX-License-Identifier: LGPL-3.0-or-later
27
+ */
28
+ /**
29
+ * Creates a deep copy of an object or array
30
+ * @param obj - The object to clone
31
+ * @returns Deep cloned object
32
+ * @since 1.9.0
33
+ */
34
+ function deepClone(obj) {
35
+ if (obj === null || typeof obj !== "object") return obj;
36
+ if (obj instanceof Date) return new Date(obj.getTime());
37
+ if (Array.isArray(obj)) return obj.map((item) => deepClone(item));
38
+ const cloned = {};
39
+ for (const key in obj) if (obj.hasOwnProperty(key)) cloned[key] = deepClone(obj[key]);
40
+ return cloned;
41
+ }
42
+ //#endregion
43
+ //#region helpers/array/shallowEquals.ts
44
+ /**
45
+ * This file is part of helpers4.
46
+ * Copyright (C) 2025 baxyz
47
+ * SPDX-License-Identifier: LGPL-3.0-or-later
48
+ */
49
+ /**
50
+ * Quick comparison of two arrays using JSON.stringify.
51
+ * This is a fast but simple comparison that may not work for all edge cases.
52
+ *
53
+ * @param arrA - First array to compare
54
+ * @param arrB - Second array to compare
55
+ * @returns `true` if arrays are identical according to JSON.stringify, `false` otherwise
56
+ * @since 2.0.0
57
+ */
58
+ function shallowEquals$1(arrA, arrB) {
59
+ try {
60
+ return JSON.stringify(arrA) === JSON.stringify(arrB);
61
+ } catch {
62
+ return arrA === arrB;
63
+ }
64
+ }
65
+ //#endregion
66
+ //#region helpers/date/compare.ts
67
+ /**
68
+ * Comparison of two dates.
69
+ *
70
+ * @param dateA - First date to compare
71
+ * @param dateB - Second date to compare
72
+ * @param options - Comparison options
73
+ * @returns `true` if dates are identical according to the specified precision, `false` otherwise
74
+ * @since 2.0.0
75
+ */
76
+ function compare(dateA, dateB, options = {}) {
77
+ const { precision = "milliseconds" } = options;
78
+ if (!(dateA instanceof Date) || !(dateB instanceof Date)) return dateA === dateB;
79
+ if (isNaN(dateA.getTime()) || isNaN(dateB.getTime())) return isNaN(dateA.getTime()) && isNaN(dateB.getTime());
80
+ switch (precision) {
81
+ case "days": return dateA.toDateString() === dateB.toDateString();
82
+ case "hours": return Math.floor(dateA.getTime() / (1e3 * 60 * 60)) === Math.floor(dateB.getTime() / (1e3 * 60 * 60));
83
+ case "minutes": return Math.floor(dateA.getTime() / (1e3 * 60)) === Math.floor(dateB.getTime() / (1e3 * 60));
84
+ case "seconds": return Math.floor(dateA.getTime() / 1e3) === Math.floor(dateB.getTime() / 1e3);
85
+ default: return dateA.getTime() === dateB.getTime();
86
+ }
87
+ }
88
+ //#endregion
89
+ //#region helpers/type/isSpecialObject.ts
90
+ /**
91
+ * This file is part of helpers4.
92
+ * Copyright (C) 2025 baxyz
93
+ * SPDX-License-Identifier: LGPL-3.0-or-later
94
+ */
95
+ /**
96
+ * Determines if a value is a special object that should not have its properties compared deeply.
97
+ * Special objects include: Date, Function, Promise, Observable, RegExp, Error, Map, Set, WeakMap, WeakSet, etc.
98
+ *
99
+ * @param value - The value to check
100
+ * @returns `true` if the value is a special object, `false` otherwise
101
+ * @since 2.0.0
102
+ */
103
+ function isSpecialObject(value) {
104
+ if (value === null || value === void 0) return false;
105
+ if (typeof value === "function") return true;
106
+ if (typeof value !== "object") return false;
107
+ if (Array.isArray(value)) return false;
108
+ if (value instanceof Date || value instanceof Promise || value instanceof RegExp || value instanceof Error || value instanceof Map || value instanceof Set || value instanceof WeakMap || value instanceof WeakSet || value instanceof ArrayBuffer || value instanceof DataView) return true;
109
+ if (value.constructor?.name === "Observable") return true;
110
+ if (typeof HTMLElement !== "undefined" && value instanceof HTMLElement) return true;
111
+ const constructorName = value.constructor?.name;
112
+ if (constructorName && [
113
+ "Buffer",
114
+ "URL",
115
+ "URLSearchParams",
116
+ "File",
117
+ "Blob",
118
+ "FormData",
119
+ "Headers",
120
+ "Request",
121
+ "Response",
122
+ "EventTarget",
123
+ "Symbol"
124
+ ].includes(constructorName)) return true;
125
+ return false;
126
+ }
127
+ //#endregion
128
+ //#region helpers/object/deepCompare.ts
129
+ /**
130
+ * This file is part of helpers4.
131
+ * Copyright (C) 2025 baxyz
132
+ * SPDX-License-Identifier: LGPL-3.0-or-later
133
+ */
134
+ /**
135
+ * Deep comparison of two objects that returns detailed information about differences.
136
+ *
137
+ * @param objA - First object to compare (can be object, undefined, or null)
138
+ * @param objB - Second object to compare (can be object, undefined, or null)
139
+ * @returns `true` if objects are identical, `false` if incompatible types, or a `DeepCompareResult` object detailing differences
140
+ * @since 2.0.0
141
+ */
142
+ function deepCompare(objA, objB) {
143
+ if (objA === objB) return true;
144
+ if (objA == null || objB == null) return false;
145
+ if (objA instanceof Date && objB instanceof Date) return compare(objA, objB);
146
+ if (Array.isArray(objA) && Array.isArray(objB)) return shallowEquals$1(objA, objB);
147
+ if (Array.isArray(objA) || Array.isArray(objB)) return false;
148
+ if (isSpecialObject(objA) || isSpecialObject(objB)) return objA === objB;
149
+ const keys = Array.from(new Set([...Object.keys(objA), ...Object.keys(objB)]));
150
+ const differences = {};
151
+ for (const key of keys) {
152
+ const hasA = key in objA;
153
+ const hasB = key in objB;
154
+ if (!hasA && hasB) differences[key] = "onlyB";
155
+ else if (hasA && !hasB) differences[key] = "onlyA";
156
+ else {
157
+ const valueA = objA[key];
158
+ const valueB = objB[key];
159
+ if (Array.isArray(valueA) && Array.isArray(valueB)) {
160
+ if (!shallowEquals$1(valueA, valueB)) differences[key] = false;
161
+ } else if (valueA instanceof Date && valueB instanceof Date) {
162
+ if (!compare(valueA, valueB)) differences[key] = false;
163
+ } else if (isSpecialObject(valueA) || isSpecialObject(valueB)) {
164
+ if (valueA !== valueB) differences[key] = false;
165
+ } else if (valueA !== null && valueB !== null && valueA !== void 0 && valueB !== void 0 && typeof valueA === "object" && typeof valueB === "object" && !isSpecialObject(valueA) && !isSpecialObject(valueB)) {
166
+ const nestedResult = deepCompare(valueA, valueB);
167
+ if (nestedResult !== true) differences[key] = nestedResult === false ? false : nestedResult;
168
+ } else if (valueA !== valueB) differences[key] = false;
169
+ }
170
+ }
171
+ return Object.keys(differences).length > 0 ? differences : true;
172
+ }
173
+ //#endregion
174
+ //#region helpers/object/deepMerge.ts
175
+ /**
176
+ * This file is part of helpers4.
177
+ * Copyright (C) 2025 baxyz
178
+ * SPDX-License-Identifier: LGPL-3.0-or-later
179
+ */
180
+ /**
181
+ * Merges two or more objects deeply
182
+ * @param target - The target object
183
+ * @param sources - The source objects to merge
184
+ * @returns The merged object
185
+ * @since 1.9.0
186
+ */
187
+ function deepMerge(target, ...sources) {
188
+ if (!sources.length) return target;
189
+ const source = sources.shift();
190
+ if (!source) return deepMerge(target, ...sources);
191
+ for (const key in source) {
192
+ const targetValue = target[key];
193
+ const sourceValue = source[key];
194
+ if (isObject(targetValue) && isObject(sourceValue)) target[key] = deepMerge(targetValue, sourceValue);
195
+ else if (sourceValue !== void 0) target[key] = sourceValue;
196
+ }
197
+ return deepMerge(target, ...sources);
198
+ }
199
+ function isObject(item) {
200
+ return item && typeof item === "object" && !Array.isArray(item);
201
+ }
202
+ //#endregion
203
+ //#region helpers/object/get.ts
204
+ /**
205
+ * This file is part of helpers4.
206
+ * Copyright (C) 2025 baxyz
207
+ * SPDX-License-Identifier: LGPL-3.0-or-later
208
+ */
209
+ /**
210
+ * Gets a value from an object using a dot-notated path
211
+ * @param obj - The object to get value from
212
+ * @param path - The dot-notated path (e.g., 'a.b.c')
213
+ * @param defaultValue - Default value if path doesn't exist
214
+ * @returns The value at the path or default value
215
+ * @since 1.9.0
216
+ */
217
+ function get(obj, path, defaultValue) {
218
+ const keys = path.split(".");
219
+ let result = obj;
220
+ for (const key of keys) {
221
+ if (result == null || typeof result !== "object") return defaultValue;
222
+ result = result[key];
223
+ }
224
+ return result !== void 0 ? result : defaultValue;
225
+ }
226
+ //#endregion
227
+ //#region helpers/object/omit.ts
228
+ /**
229
+ * This file is part of helpers4.
230
+ * Copyright (C) 2025 baxyz
231
+ * SPDX-License-Identifier: LGPL-3.0-or-later
232
+ */
233
+ /**
234
+ * Creates a new object without the specified keys.
235
+ * @param obj - The source object
236
+ * @param keys - The keys to omit
237
+ * @returns A new object without the omitted keys
238
+ * @example
239
+ * omit({ a: 1, b: 2, c: 3 }, ['b'])
240
+ * // => { a: 1, c: 3 }
241
+ * @since 2.0.0
242
+ */
243
+ function omit(obj, keys) {
244
+ const result = { ...obj };
245
+ for (const key of keys) delete result[key];
246
+ return result;
247
+ }
248
+ //#endregion
249
+ //#region helpers/object/pick.ts
250
+ /**
251
+ * This file is part of helpers4.
252
+ * Copyright (C) 2025 baxyz
253
+ * SPDX-License-Identifier: LGPL-3.0-or-later
254
+ */
255
+ /**
256
+ * Creates a new object with only the specified keys.
257
+ * @param obj - The source object
258
+ * @param keys - The keys to pick
259
+ * @returns A new object with only the picked keys
260
+ * @example
261
+ * pick({ a: 1, b: 2, c: 3 }, ['a', 'c'])
262
+ * // => { a: 1, c: 3 }
263
+ * @since 2.0.0
264
+ */
265
+ function pick(obj, keys) {
266
+ const result = {};
267
+ for (const key of keys) if (Object.prototype.hasOwnProperty.call(obj, key)) result[key] = obj[key];
268
+ return result;
269
+ }
270
+ //#endregion
271
+ //#region helpers/type/isNullish.ts
272
+ /**
273
+ * This file is part of helpers4.
274
+ * Copyright (C) 2025 baxyz
275
+ * SPDX-License-Identifier: LGPL-3.0-or-later
276
+ */
277
+ /**
278
+ * Checks if a value is null or undefined (nullish).
279
+ * @param value - The value to check
280
+ * @returns True if value is null or undefined
281
+ * @example
282
+ * isNullish(null) // => true
283
+ * isNullish(undefined) // => true
284
+ * isNullish(0) // => false
285
+ * isNullish('') // => false
286
+ * @since 2.0.0
287
+ */
288
+ function isNullish(value) {
289
+ return value === null || value === void 0;
290
+ }
291
+ //#endregion
292
+ //#region helpers/object/removeUndefinedNull.ts
293
+ /**
294
+ * This file is part of helpers4.
295
+ * Copyright (C) 2025 baxyz
296
+ * SPDX-License-Identifier: LGPL-3.0-or-later
297
+ */
298
+ /**
299
+ * Remove null and undefined values from an object.
300
+ *
301
+ * @param obj an object
302
+ * @returns A shallow copy of the object without null or undefined values
303
+ * @since 1.0.0
304
+ */
305
+ function removeUndefinedNull(obj) {
306
+ return obj ? Object.entries(obj).filter(([_, v]) => !isNullish(v)).reduce((acc, [k, v]) => ({
307
+ ...acc,
308
+ [k]: v
309
+ }), {}) : obj;
310
+ }
311
+ //#endregion
312
+ //#region helpers/object/set.ts
313
+ /**
314
+ * This file is part of helpers4.
315
+ * Copyright (C) 2025 baxyz
316
+ * SPDX-License-Identifier: LGPL-3.0-or-later
317
+ */
318
+ /**
319
+ * Sets a value in an object using a dot-notated path
320
+ * @param obj - The object to set value in
321
+ * @param path - The dot-notated path (e.g., 'a.b.c')
322
+ * @param value - The value to set
323
+ * @returns The modified object
324
+ * @since 1.9.0
325
+ */
326
+ function set(obj, path, value) {
327
+ const keys = path.split(".");
328
+ let current = obj;
329
+ for (let i = 0; i < keys.length - 1; i++) {
330
+ const key = keys[i];
331
+ if (!(key in current) || typeof current[key] !== "object" || current[key] === null) current[key] = {};
332
+ current = current[key];
333
+ }
334
+ current[keys[keys.length - 1]] = value;
335
+ return obj;
336
+ }
337
+ //#endregion
338
+ //#region helpers/object/shallowEquals.ts
339
+ /**
340
+ * This file is part of helpers4.
341
+ * Copyright (C) 2025 baxyz
342
+ * SPDX-License-Identifier: LGPL-3.0-or-later
343
+ */
344
+ /**
345
+ * Quick comparison of two objects using JSON.stringify.
346
+ * This is a fast but simple comparison that may not work for all edge cases.
347
+ *
348
+ * @param objA - First object to compare
349
+ * @param objB - Second object to compare
350
+ * @returns `true` if objects are identical according to JSON.stringify, `false` otherwise
351
+ * @since 2.0.0
352
+ */
353
+ function shallowEquals(objA, objB) {
354
+ if (objA === objB) return true;
355
+ if (typeof objA === "function" || typeof objB === "function") return objA === objB;
356
+ try {
357
+ return JSON.stringify(objA) === JSON.stringify(objB);
358
+ } catch {
359
+ return objA === objB;
360
+ }
361
+ }
362
+ //#endregion
363
+ export { compact, deepClone, deepCompare, deepMerge, get, omit, pick, removeUndefinedNull, set, shallowEquals };
364
+
365
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../helpers/object/compact.ts","../../../helpers/object/deepClone.ts","../../../helpers/array/shallowEquals.ts","../../../helpers/date/compare.ts","../../../helpers/type/isSpecialObject.ts","../../../helpers/object/deepCompare.ts","../../../helpers/object/deepMerge.ts","../../../helpers/object/get.ts","../../../helpers/object/omit.ts","../../../helpers/object/pick.ts","../../../helpers/type/isNullish.ts","../../../helpers/object/removeUndefinedNull.ts","../../../helpers/object/set.ts","../../../helpers/object/shallowEquals.ts"],"sourcesContent":["/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Removes all entries with falsy values (`false`, `null`, `undefined`, `0`, `\"\"`, `NaN`) from an object.\n * @param obj - The source object\n * @returns A new object containing only entries with truthy values\n * @example\n * compact({ a: 1, b: null, c: '', d: 0, e: 'hello' })\n * // => { a: 1, e: 'hello' }\n * @since 2.0.0\n */\nexport function compact<T extends Record<string, unknown>>(obj: T): Partial<T> {\n const result: Partial<T> = {};\n for (const key of Object.keys(obj) as (keyof T)[]) {\n if (obj[key]) {\n result[key] = obj[key];\n }\n }\n return result;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Creates a deep copy of an object or array\n * @param obj - The object to clone\n * @returns Deep cloned object\n * @since 1.9.0\n */\nexport function deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") {\n return obj;\n }\n\n if (obj instanceof Date) {\n return new Date(obj.getTime()) as T;\n }\n\n if (Array.isArray(obj)) {\n return obj.map(item => deepClone(item)) as T;\n }\n\n const cloned = {} as T;\n for (const key in obj) {\n if (obj.hasOwnProperty(key)) {\n cloned[key] = deepClone(obj[key]);\n }\n }\n\n return cloned;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Quick comparison of two arrays using JSON.stringify.\n * This is a fast but simple comparison that may not work for all edge cases.\n *\n * @param arrA - First array to compare\n * @param arrB - Second array to compare\n * @returns `true` if arrays are identical according to JSON.stringify, `false` otherwise\n * @since 2.0.0\n */\nexport function shallowEquals<T>(arrA: T[], arrB: T[]): boolean {\n try {\n return JSON.stringify(arrA) === JSON.stringify(arrB);\n } catch {\n // If JSON.stringify fails (e.g., circular references), fall back to reference equality\n return arrA === arrB;\n }\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Options for date comparison\n * @since 2.0.0\n */\nexport interface DateCompareOptions {\n /** \n * Comparison precision\n * - 'milliseconds': Compare all including milliseconds (default)\n * - 'seconds': Ignore milliseconds, compare to the second\n * - 'minutes': Ignore seconds and milliseconds, compare to the minute\n * - 'hours': Ignore minutes, seconds and milliseconds, compare to the hour\n * - 'days': Compare only the date part (ignore time completely)\n */\n precision?: 'milliseconds' | 'seconds' | 'minutes' | 'hours' | 'days';\n}\n\n/**\n * Comparison of two dates.\n * \n * @param dateA - First date to compare\n * @param dateB - Second date to compare\n * @param options - Comparison options\n * @returns `true` if dates are identical according to the specified precision, `false` otherwise\n * @since 2.0.0\n */\nexport function compare(dateA: Date, dateB: Date, options: DateCompareOptions = {}): boolean {\n const { precision = 'milliseconds' } = options;\n\n if (!(dateA instanceof Date) || !(dateB instanceof Date)) {\n return dateA === dateB;\n }\n\n // Handle invalid dates\n if (isNaN(dateA.getTime()) || isNaN(dateB.getTime())) {\n return isNaN(dateA.getTime()) && isNaN(dateB.getTime());\n }\n\n switch (precision) {\n case 'days':\n return dateA.toDateString() === dateB.toDateString();\n\n case 'hours':\n const hoursA = Math.floor(dateA.getTime() / (1000 * 60 * 60));\n const hoursB = Math.floor(dateB.getTime() / (1000 * 60 * 60));\n return hoursA === hoursB;\n\n case 'minutes':\n const minutesA = Math.floor(dateA.getTime() / (1000 * 60));\n const minutesB = Math.floor(dateB.getTime() / (1000 * 60));\n return minutesA === minutesB;\n\n case 'seconds':\n const secondsA = Math.floor(dateA.getTime() / 1000);\n const secondsB = Math.floor(dateB.getTime() / 1000);\n return secondsA === secondsB;\n\n case 'milliseconds':\n default:\n return dateA.getTime() === dateB.getTime();\n }\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Determines if a value is a special object that should not have its properties compared deeply.\n * Special objects include: Date, Function, Promise, Observable, RegExp, Error, Map, Set, WeakMap, WeakSet, etc.\n * \n * @param value - The value to check\n * @returns `true` if the value is a special object, `false` otherwise\n * @since 2.0.0\n */\nexport function isSpecialObject(value: unknown): boolean {\n if (value === null || value === undefined) {\n return false;\n }\n\n // Functions are special objects\n if (typeof value === 'function') {\n return true;\n }\n\n // Non-objects are not special\n if (typeof value !== 'object') {\n return false;\n }\n\n // Arrays are not considered special objects for our purposes\n if (Array.isArray(value)) {\n return false;\n }\n\n // Check for built-in special objects\n if (\n value instanceof Date ||\n value instanceof Promise ||\n value instanceof RegExp ||\n value instanceof Error ||\n value instanceof Map ||\n value instanceof Set ||\n value instanceof WeakMap ||\n value instanceof WeakSet ||\n value instanceof ArrayBuffer ||\n value instanceof DataView\n ) {\n return true;\n }\n\n // Check for Observable (RxJS or similar)\n if (value.constructor?.name === 'Observable') {\n return true;\n }\n\n // Check for DOM elements (if in browser environment)\n if (typeof HTMLElement !== 'undefined' && value instanceof HTMLElement) {\n return true;\n }\n\n // Check for other built-in types by constructor name\n const constructorName = value.constructor?.name;\n if (constructorName && [\n 'Buffer', // Node.js Buffer\n 'URL', // Web URL API\n 'URLSearchParams',\n 'File', // Web File API\n 'Blob', // Web Blob API\n 'FormData', // Web FormData API\n 'Headers', // Web Headers API\n 'Request', // Web Request API\n 'Response', // Web Response API\n 'EventTarget', // Web EventTarget API\n 'Symbol' // Symbol objects\n ].includes(constructorName)) {\n return true;\n }\n\n return false;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { shallowEquals as shallowEqualsArray } from '../array/shallowEquals';\nimport { compare as compareDate } from '../date/compare';\nimport { isSpecialObject } from '../type/isSpecialObject';\n\n/**\n * Result type for deep comparison when objects are not identical\n * @since 2.0.0\n */\nexport interface DeepCompareResult {\n [key: string]: \"onlyA\" | \"onlyB\" | false | DeepCompareResult;\n}\n\n/**\n * Deep comparison of two objects that returns detailed information about differences.\n *\n * @param objA - First object to compare (can be object, undefined, or null)\n * @param objB - Second object to compare (can be object, undefined, or null)\n * @returns `true` if objects are identical, `false` if incompatible types, or a `DeepCompareResult` object detailing differences\n * @since 2.0.0\n */\nexport function deepCompare(objA: object | undefined | null, objB: object | undefined | null): true | false | DeepCompareResult {\n // Quick reference equality check\n if (objA === objB) {\n return true;\n }\n\n // Handle null/undefined cases\n if (objA == null || objB == null) {\n return false;\n }\n\n // Handle Date objects\n if (objA instanceof Date && objB instanceof Date) {\n return compareDate(objA, objB);\n }\n\n // Handle Arrays at root level - use shallowEquals\n if (Array.isArray(objA) && Array.isArray(objB)) {\n return shallowEqualsArray(objA, objB);\n }\n\n // If one is array and other is not\n if (Array.isArray(objA) || Array.isArray(objB)) {\n return false;\n }\n\n // Handle special objects - compare by reference only\n if (isSpecialObject(objA) || isSpecialObject(objB)) {\n return objA === objB;\n }\n\n // Handle objects - detailed comparison\n const keys = Array.from(new Set([...Object.keys(objA), ...Object.keys(objB)]));\n\n const differences: DeepCompareResult = {};\n\n for (const key of keys) {\n const hasA = key in objA;\n const hasB = key in objB;\n\n if (!hasA && hasB) {\n differences[key] = \"onlyB\";\n } else if (hasA && !hasB) {\n differences[key] = \"onlyA\";\n } else {\n // Both objects have this key - compare values\n const valueA = (objA as any)[key];\n const valueB = (objB as any)[key];\n\n // For arrays, use shallowEquals\n if (Array.isArray(valueA) && Array.isArray(valueB)) {\n if (!shallowEqualsArray(valueA, valueB)) {\n differences[key] = false;\n }\n }\n // For dates, use compareDate\n else if (valueA instanceof Date && valueB instanceof Date) {\n if (!compareDate(valueA, valueB)) {\n differences[key] = false;\n }\n }\n // For special objects, compare by reference only\n else if (isSpecialObject(valueA) || isSpecialObject(valueB)) {\n if (valueA !== valueB) {\n differences[key] = false;\n }\n }\n // For objects, recurse (only plain objects now)\n else if (\n valueA !== null && valueB !== null &&\n valueA !== undefined && valueB !== undefined &&\n typeof valueA === 'object' && typeof valueB === 'object' &&\n !isSpecialObject(valueA) && !isSpecialObject(valueB)\n ) {\n const nestedResult = deepCompare(valueA, valueB);\n if (nestedResult !== true) {\n differences[key] = nestedResult === false ? false : nestedResult;\n }\n }\n // For primitives and other types, check equality\n else if (valueA !== valueB) {\n differences[key] = false;\n }\n }\n }\n\n return Object.keys(differences).length > 0 ? differences : true;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Merges two or more objects deeply\n * @param target - The target object\n * @param sources - The source objects to merge\n * @returns The merged object\n * @since 1.9.0\n */\nexport function deepMerge<T extends Record<string, any>>(target: T, ...sources: Record<string, any>[]): T {\n if (!sources.length) return target;\n const source = sources.shift();\n\n if (!source) return deepMerge(target, ...sources);\n\n for (const key in source) {\n const targetValue = target[key];\n const sourceValue = source[key];\n\n if (isObject(targetValue) && isObject(sourceValue)) {\n (target as any)[key] = deepMerge(targetValue, sourceValue);\n } else if (sourceValue !== undefined) {\n (target as any)[key] = sourceValue;\n }\n }\n\n return deepMerge(target, ...sources);\n}\n\nfunction isObject(item: any): item is object {\n return item && typeof item === 'object' && !Array.isArray(item);\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Gets a value from an object using a dot-notated path\n * @param obj - The object to get value from\n * @param path - The dot-notated path (e.g., 'a.b.c')\n * @param defaultValue - Default value if path doesn't exist\n * @returns The value at the path or default value\n * @since 1.9.0\n */\nexport function get<T = any>(obj: any, path: string, defaultValue?: T): T | undefined {\n const keys = path.split('.');\n let result = obj;\n\n for (const key of keys) {\n if (result == null || typeof result !== 'object') {\n return defaultValue;\n }\n result = result[key];\n }\n\n return result !== undefined ? result : defaultValue;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Creates a new object without the specified keys.\n * @param obj - The source object\n * @param keys - The keys to omit\n * @returns A new object without the omitted keys\n * @example\n * omit({ a: 1, b: 2, c: 3 }, ['b'])\n * // => { a: 1, c: 3 }\n * @since 2.0.0\n */\nexport function omit<T extends Record<string, unknown>, K extends keyof T>(\n obj: T,\n keys: readonly K[]\n): Omit<T, K> {\n const result = { ...obj };\n for (const key of keys) {\n delete result[key];\n }\n return result as Omit<T, K>;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Creates a new object with only the specified keys.\n * @param obj - The source object\n * @param keys - The keys to pick\n * @returns A new object with only the picked keys\n * @example\n * pick({ a: 1, b: 2, c: 3 }, ['a', 'c'])\n * // => { a: 1, c: 3 }\n * @since 2.0.0\n */\nexport function pick<T extends Record<string, unknown>, K extends keyof T>(\n obj: T,\n keys: readonly K[]\n): Pick<T, K> {\n const result = {} as Pick<T, K>;\n for (const key of keys) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result[key] = obj[key];\n }\n }\n return result;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Checks if a value is null or undefined (nullish).\n * @param value - The value to check\n * @returns True if value is null or undefined\n * @example\n * isNullish(null) // => true\n * isNullish(undefined) // => true\n * isNullish(0) // => false\n * isNullish('') // => false\n * @since 2.0.0\n */\nexport function isNullish(value: unknown): value is null | undefined {\n return value === null || value === undefined;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { isNullish } from '../type/isNullish';\n\n/**\n * Remove null and undefined values from an object.\n *\n * @param obj an object\n * @returns A shallow copy of the object without null or undefined values\n * @since 1.0.0\n */\nexport function removeUndefinedNull<T extends Record<string, string | number | boolean | null | undefined>>(obj: T): Partial<T>;\n\n/**\n * Remove null and undefined values from an object.\n *\n * @param obj a null object\n * @returns null\n * @since 1.0.0\n */\nexport function removeUndefinedNull(obj: null): null;\n\n/**\n * Remove null and undefined values from an object.\n *\n * @param obj an undefined object\n * @returns undefined\n * @since 1.0.0\n */\nexport function removeUndefinedNull(obj: undefined): undefined;\n\n/**\n * Remove null and undefined values from an object.\n *\n * @param obj an object\n * @returns A shallow copy of the object without null or undefined values\n * @since 1.0.0\n */\nexport function removeUndefinedNull<T extends Record<string, string | number | boolean | null | undefined>>(obj: T | null | undefined): Partial<T> | null | undefined {\n return obj ? Object.entries(obj)\n .filter(([_, v]) => !isNullish(v))\n .reduce((acc, [k, v]) => ({ ...acc, [k]: v }), {} as Partial<T>) : obj;\n}\n\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Sets a value in an object using a dot-notated path\n * @param obj - The object to set value in\n * @param path - The dot-notated path (e.g., 'a.b.c')\n * @param value - The value to set\n * @returns The modified object\n * @since 1.9.0\n */\nexport function set(obj: Record<string, any>, path: string, value: any): Record<string, any> {\n const keys = path.split('.');\n let current = obj;\n\n for (let i = 0; i < keys.length - 1; i++) {\n const key = keys[i];\n\n if (!(key in current) || typeof current[key] !== 'object' || current[key] === null) {\n current[key] = {};\n }\n\n current = current[key];\n }\n\n current[keys[keys.length - 1]] = value;\n return obj;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Quick comparison of two objects using JSON.stringify.\n * This is a fast but simple comparison that may not work for all edge cases.\n *\n * @param objA - First object to compare\n * @param objB - Second object to compare\n * @returns `true` if objects are identical according to JSON.stringify, `false` otherwise\n * @since 2.0.0\n */\nexport function shallowEquals(objA: unknown, objB: unknown): boolean {\n // Quick reference equality check\n if (objA === objB) {\n return true;\n }\n\n // Handle functions - they can't be JSON.stringified reliably\n if (typeof objA === 'function' || typeof objB === 'function') {\n return objA === objB;\n }\n\n try {\n return JSON.stringify(objA) === JSON.stringify(objB);\n } catch {\n // If JSON.stringify fails (e.g., circular references), fall back to basic comparison\n return objA === objB;\n }\n}\n"],"mappings":"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"}