@helpers4/object 2.0.0-beta.0 → 2.0.0

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
@@ -14,25 +14,31 @@ A set of helpers for working with URLs.
14
14
  <!-- AUTOMATIC-METHODS -->
15
15
  - compact
16
16
  - deepClone
17
- - deepCompare
18
17
  - deepMerge
18
+ - diff
19
+ - equalsDeep
20
+ - equalsShallow
19
21
  - get
22
+ - groupBy
23
+ - invert
24
+ - map
20
25
  - omit
21
26
  - pick
22
27
  - removeUndefinedNull
23
28
  - safeJsonParse
24
29
  - set
25
- - shallowEquals
26
30
  <!-- /AUTOMATIC-METHODS -->
27
31
 
28
32
  ## See
29
33
 
30
34
  <!-- AUTOMATIC-SIBLINGS -->
31
35
  - [array](../array)
36
+ - [ci](../ci)
32
37
  - [commit](../commit)
33
38
  - [date](../date)
34
39
  - [function](../function)
35
- - [math](../math)
40
+ - [id](../id)
41
+ - [markdown](../markdown)
36
42
  - [number](../number)
37
43
  - [observable](../observable)
38
44
  - [promise](../promise)
@@ -48,10 +54,12 @@ A set of helpers for working with URLs.
48
54
  | Name | Package | Source Code | Description |
49
55
  |------|---------|-------------|-------------|
50
56
  | array | [@helpers4/array](https://www.npmjs.com/package/@helpers4/array) | [Source](https://github.com/helpers4/helpers4/tree/main/helpers/array) | Array manipulation utilities |
57
+ | ci | [@helpers4/ci](https://www.npmjs.com/package/@helpers4/ci) | [Source](https://github.com/helpers4/helpers4/tree/main/helpers/ci) | CI/CD workflow status utilities |
51
58
  | commit | [@helpers4/commit](https://www.npmjs.com/package/@helpers4/commit) | [Source](https://github.com/helpers4/helpers4/tree/main/helpers/commit) | Conventional Commits parsing and analysis |
52
59
  | date | [@helpers4/date](https://www.npmjs.com/package/@helpers4/date) | [Source](https://github.com/helpers4/helpers4/tree/main/helpers/date) | Date and time utility functions |
53
60
  | 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 |
54
- | math | [@helpers4/math](https://www.npmjs.com/package/@helpers4/math) | [Source](https://github.com/helpers4/helpers4/tree/main/helpers/math) | Mathematical utility functions and calculations |
61
+ | id | [@helpers4/id](https://www.npmjs.com/package/@helpers4/id) | [Source](https://github.com/helpers4/helpers4/tree/main/helpers/id) | Unique identifier generation utilities |
62
+ | markdown | [@helpers4/markdown](https://www.npmjs.com/package/@helpers4/markdown) | [Source](https://github.com/helpers4/helpers4/tree/main/helpers/markdown) | Markdown formatting and escaping utilities |
55
63
  | number | [@helpers4/number](https://www.npmjs.com/package/@helpers4/number) | [Source](https://github.com/helpers4/helpers4/tree/main/helpers/number) | Number utility functions and validation |
56
64
  | object | [@helpers4/object](https://www.npmjs.com/package/@helpers4/object) | [Source](https://github.com/helpers4/helpers4/tree/main/helpers/object) | Object manipulation utilities |
57
65
  | 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
@@ -35,21 +35,78 @@ declare function deepClone<T>(obj: T): T;
35
35
  * SPDX-License-Identifier: LGPL-3.0-or-later
36
36
  */
37
37
  /**
38
- * Result type for deep comparison when objects are not identical
38
+ * Merges two or more objects deeply
39
+ * @param target - The target object
40
+ * @param sources - The source objects to merge
41
+ * @returns The merged object
42
+ * @since 1.9.0
43
+ */
44
+ declare function deepMerge<T extends Record<string, unknown>>(target: T, ...sources: Record<string, unknown>[]): T;
45
+ declare function deepMerge(target: undefined, ...sources: Record<string, unknown>[]): undefined;
46
+ declare function deepMerge(target: null, ...sources: Record<string, unknown>[]): null;
47
+
48
+ /**
49
+ * This file is part of helpers4.
50
+ * Copyright (C) 2025 baxyz
51
+ * SPDX-License-Identifier: LGPL-3.0-or-later
52
+ */
53
+ /**
54
+ * Per-key diff result. Each entry tells what differs between the two
55
+ * objects:
56
+ * - `"onlyA"` \u2014 the key exists only on the first input.
57
+ * - `"onlyB"` \u2014 the key exists only on the second input.
58
+ * - `false` \u2014 both inputs have the key but the values differ.
59
+ * - nested `DiffResult` \u2014 plain-object values that differ deeper.
60
+ *
61
+ * @since 2.0.0
62
+ */
63
+ interface DiffResult {
64
+ [key: string]: 'onlyA' | 'onlyB' | false | DiffResult;
65
+ }
66
+ /**
67
+ * Options for {@link diff}.
39
68
  * @since 2.0.0
40
69
  */
41
- interface DeepCompareResult {
42
- [key: string]: "onlyA" | "onlyB" | false | DeepCompareResult;
70
+ interface DiffOptions {
71
+ /**
72
+ * Maximum recursion depth for nested plain objects. Defaults to
73
+ * `Infinity` (full structural diff).
74
+ *
75
+ * - `0` compares values at the top-level only with strict equality.
76
+ * - `1` compares the first level of nested objects with strict equality.
77
+ * - `Infinity` recurses through every plain-object level.
78
+ *
79
+ * Arrays, `Date` and special objects (Map, Set, RegExp\u2026) are always
80
+ * leaf-compared (via {@link arrayDeepEquals}, epoch comparison, or
81
+ * reference equality respectively) regardless of `depth`.
82
+ */
83
+ depth?: number;
43
84
  }
44
85
  /**
45
- * Deep comparison of two objects that returns detailed information about differences.
86
+ * Structural object diff.
87
+ *
88
+ * Returns `true` when both inputs are deeply equal, otherwise a
89
+ * {@link DiffResult} describing the differences key by key.
46
90
  *
47
- * @param objA - First object to compare (can be object, undefined, or null)
48
- * @param objB - Second object to compare (can be object, undefined, or null)
49
- * @returns `true` if objects are identical, `false` if incompatible types, or a `DeepCompareResult` object detailing differences
91
+ * Comparison rules:
92
+ * - Same reference \u2192 `true`.
93
+ * - Either side is `null`/`undefined` (and not both) \u2192 `false`.
94
+ * - Both `Date` \u2192 epoch comparison.
95
+ * - Both arrays \u2192 compared with `array/equalsDeep` (leaf, no diff drill-down).
96
+ * - Special objects (Map, Set, RegExp, Promise, class instances\u2026) \u2192 reference equality.
97
+ * - Plain objects \u2192 key-by-key, recursing up to `options.depth` levels.
98
+ * - Mixed types (e.g. array vs object, Date vs object) \u2192 `false`.
99
+ *
100
+ * For a boolean wrapper see {@link equalsDeep} from this category.
101
+ * For a one-level boolean check see {@link equalsShallow} from this category.
102
+ *
103
+ * @param objA - First value (object, `null`, or `undefined`).
104
+ * @param objB - Second value (object, `null`, or `undefined`).
105
+ * @param options - See {@link DiffOptions}.
106
+ * @returns `true` when equal, otherwise a {@link DiffResult}, or `false` for incompatible types.
50
107
  * @since 2.0.0
51
108
  */
52
- declare function deepCompare(objA: object | undefined | null, objB: object | undefined | null): true | false | DeepCompareResult;
109
+ declare function diff(objA: object | undefined | null, objB: object | undefined | null, options?: DiffOptions): true | false | DiffResult;
53
110
 
54
111
  /**
55
112
  * This file is part of helpers4.
@@ -57,15 +114,48 @@ declare function deepCompare(objA: object | undefined | null, objB: object | und
57
114
  * SPDX-License-Identifier: LGPL-3.0-or-later
58
115
  */
59
116
  /**
60
- * Merges two or more objects deeply
61
- * @param target - The target object
62
- * @param sources - The source objects to merge
63
- * @returns The merged object
64
- * @since 1.9.0
117
+ * Recursive structural object equality.
118
+ *
119
+ * Boolean wrapper around {@link diff} \u2014 returns `true` when the two values
120
+ * are deeply equal according to the same rules. Use this when you only
121
+ * need a yes/no answer; use {@link diff} when you also need to know
122
+ * *what* differs.
123
+ *
124
+ * For a one-level boolean check use {@link equalsShallow}.
125
+ *
126
+ * @param objA - First value (object, `null`, or `undefined`).
127
+ * @param objB - Second value (object, `null`, or `undefined`).
128
+ * @returns `true` if both inputs are deeply equal, `false` otherwise.
129
+ * @since 2.0.0
65
130
  */
66
- declare function deepMerge<T extends Record<string, unknown>>(target: T, ...sources: Record<string, unknown>[]): T;
67
- declare function deepMerge(target: undefined, ...sources: Record<string, unknown>[]): undefined;
68
- declare function deepMerge(target: null, ...sources: Record<string, unknown>[]): null;
131
+ declare function equalsDeep(objA: object | undefined | null, objB: object | undefined | null): boolean;
132
+
133
+ /**
134
+ * This file is part of helpers4.
135
+ * Copyright (C) 2025 baxyz
136
+ * SPDX-License-Identifier: LGPL-3.0-or-later
137
+ */
138
+ /**
139
+ * One-level (shallow) object equality.
140
+ *
141
+ * Two objects are equal when they share the exact same set of own
142
+ * enumerable string keys and each pair of values satisfies strict equality
143
+ * (`===`). No recursion: nested objects/arrays are compared by reference.
144
+ *
145
+ * Falls back to strict equality when either input is `null`, `undefined`
146
+ * or not an object \u2014 so primitives match if and only if they are `===`.
147
+ * Arrays are not supported; they always return `false` (unless identical
148
+ * references). Use `array/equalsShallow` instead.
149
+ *
150
+ * For recursive structural comparison use {@link equalsDeep}. For a diff
151
+ * structure use {@link diff}.
152
+ *
153
+ * @param objA - First value to compare
154
+ * @param objB - Second value to compare
155
+ * @returns `true` if values are shallowly equal, `false` otherwise.
156
+ * @since 2.0.0
157
+ */
158
+ declare function equalsShallow(objA: unknown, objB: unknown): boolean;
69
159
 
70
160
  /**
71
161
  * This file is part of helpers4.
@@ -82,6 +172,82 @@ declare function deepMerge(target: null, ...sources: Record<string, unknown>[]):
82
172
  */
83
173
  declare function get<T = unknown>(obj: unknown, path: string, defaultValue?: T): T | undefined;
84
174
 
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
+ * Groups an array of items by a key derived from each item.
182
+ *
183
+ * A thin, typed wrapper around `Object.groupBy` (ES2024) that works on
184
+ * older targets and provides stricter return-type inference.
185
+ *
186
+ * @param items - The array to group
187
+ * @param keyFn - Function that returns the group key for each item
188
+ * @returns A record mapping each key to the array of items with that key
189
+ * @example
190
+ * groupBy([1, 2, 3, 4], n => n % 2 === 0 ? 'even' : 'odd')
191
+ * // => { odd: [1, 3], even: [2, 4] }
192
+ * @since 2.0.0
193
+ */
194
+ declare function groupBy<T, K extends PropertyKey>(items: readonly T[], keyFn: (item: T) => K): Partial<Record<K, T[]>>;
195
+
196
+ /**
197
+ * This file is part of helpers4.
198
+ * Copyright (C) 2025 baxyz
199
+ * SPDX-License-Identifier: LGPL-3.0-or-later
200
+ */
201
+ /**
202
+ * Returns a new object with keys and values swapped.
203
+ * If multiple keys share the same value, the last one wins.
204
+ *
205
+ * @param obj - The object whose keys and values are to be swapped
206
+ * @returns A new object with values as keys and original keys as values
207
+ * @example
208
+ * invert({ a: 'x', b: 'y', c: 'z' })
209
+ * // => { x: 'a', y: 'b', z: 'c' }
210
+ *
211
+ * invert({ one: 1, two: 2 })
212
+ * // => { 1: 'one', 2: 'two' }
213
+ * @since 2.0.0
214
+ */
215
+ declare function invert<K extends string, V extends PropertyKey>(obj: Record<K, V>): Record<V, K>;
216
+
217
+ /**
218
+ * This file is part of helpers4.
219
+ * Copyright (C) 2025 baxyz
220
+ * SPDX-License-Identifier: LGPL-3.0-or-later
221
+ */
222
+ /**
223
+ * Transforms the values and/or keys of a plain object in a single pass.
224
+ *
225
+ * Both callbacks are optional and default to identity (no transformation).
226
+ * When `mapValue` is omitted the original values are preserved;
227
+ * when `mapKey` is omitted the original keys are preserved.
228
+ *
229
+ * Note: if two different keys map to the same output key the last one wins
230
+ * (insertion order).
231
+ *
232
+ * @param obj - The source object
233
+ * @param mapValue - Callback called with `(value, key)` for each entry.
234
+ * Defaults to identity.
235
+ * @param mapKey - Callback called with `(key, value)` for each entry.
236
+ * Defaults to identity.
237
+ * @returns A new object with transformed keys and/or values
238
+ * @example
239
+ * map({ a: 1, b: 2 }, v => v * 10)
240
+ * // => { a: 10, b: 20 }
241
+ *
242
+ * map({ a: 1, b: 2 }, undefined, k => k.toUpperCase())
243
+ * // => { A: 1, B: 2 }
244
+ *
245
+ * map({ a: 1, b: 2 }, v => v * 10, k => k.toUpperCase())
246
+ * // => { A: 10, B: 20 }
247
+ * @since 2.0.0
248
+ */
249
+ declare function map<TObj extends Record<string, unknown>, TVal = TObj[keyof TObj], TKey extends PropertyKey = keyof TObj>(obj: TObj, mapValue?: (value: TObj[keyof TObj], key: keyof TObj) => TVal, mapKey?: (key: keyof TObj, value: TObj[keyof TObj]) => TKey): Record<TKey, TVal>;
250
+
85
251
  /**
86
252
  * This file is part of helpers4.
87
253
  * Copyright (C) 2025 baxyz
@@ -168,7 +334,7 @@ declare function removeUndefinedNull(obj: undefined): undefined;
168
334
  * safeJsonParse<{ a: number }>('{"a":1}') // => { a: 1 }
169
335
  * safeJsonParse('invalid') // => null
170
336
  * safeJsonParse('invalid', []) // => []
171
- * @since next
337
+ * @since 2.0.0
172
338
  */
173
339
  declare function safeJsonParse<T>(input: string): T | null;
174
340
  declare function safeJsonParse<T>(input: string, fallback: T): T;
@@ -188,21 +354,5 @@ declare function safeJsonParse<T>(input: string, fallback: T): T;
188
354
  */
189
355
  declare function set(obj: Record<string, unknown>, path: string, value: unknown): Record<string, unknown>;
190
356
 
191
- /**
192
- * This file is part of helpers4.
193
- * Copyright (C) 2025 baxyz
194
- * SPDX-License-Identifier: LGPL-3.0-or-later
195
- */
196
- /**
197
- * Quick comparison of two objects using JSON.stringify.
198
- * This is a fast but simple comparison that may not work for all edge cases.
199
- *
200
- * @param objA - First object to compare
201
- * @param objB - Second object to compare
202
- * @returns `true` if objects are identical according to JSON.stringify, `false` otherwise
203
- * @since 2.0.0
204
- */
205
- declare function shallowEquals(objA: unknown, objB: unknown): boolean;
206
-
207
- export { compact, deepClone, deepCompare, deepMerge, get, omit, pick, removeUndefinedNull, safeJsonParse, set, shallowEquals };
208
- export type { DeepCompareResult };
357
+ export { compact, deepClone, deepMerge, diff, equalsDeep, equalsShallow, get, groupBy, invert, map, omit, pick, removeUndefinedNull, safeJsonParse, set };
358
+ export type { DiffOptions, DiffResult };