@ls-stack/utils 3.34.1 → 3.36.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.
@@ -25,6 +25,7 @@ __export(arrayUtils_exports, {
25
25
  arrayWithPrevAndIndex: () => arrayWithPrevAndIndex,
26
26
  filterAndMap: () => filterAndMap,
27
27
  findAfterIndex: () => findAfterIndex,
28
+ findAndMap: () => findAndMap,
28
29
  findBeforeIndex: () => findBeforeIndex,
29
30
  getAscIndexOrder: () => getAscIndexOrder,
30
31
  hasDuplicates: () => hasDuplicates,
@@ -160,11 +161,19 @@ function truncateArray(array, maxLength, appendIfTruncated) {
160
161
  }
161
162
  return result;
162
163
  }
164
+ function findAndMap(array, predicate) {
165
+ for (const item of array) {
166
+ const value = predicate(item);
167
+ if (value !== false) return value;
168
+ }
169
+ return void 0;
170
+ }
163
171
  function arrayOps(array) {
164
172
  return {
165
173
  filterAndMap: (mapFilter) => filterAndMap(array, mapFilter),
166
174
  sortBy: (sortByValue, props) => sortBy(array, sortByValue, props),
167
- rejectDuplicates: (getKey) => rejectDuplicates(array, getKey)
175
+ rejectDuplicates: (getKey) => rejectDuplicates(array, getKey),
176
+ findAndMap: (predicate) => findAndMap(array, predicate)
168
177
  };
169
178
  }
170
179
  // Annotate the CommonJS export names for ESM import in node:
@@ -174,6 +183,7 @@ function arrayOps(array) {
174
183
  arrayWithPrevAndIndex,
175
184
  filterAndMap,
176
185
  findAfterIndex,
186
+ findAndMap,
177
187
  findBeforeIndex,
178
188
  getAscIndexOrder,
179
189
  hasDuplicates,
@@ -94,7 +94,26 @@ type ArrayOps<T> = {
94
94
  filterAndMap: <R>(mapFilter: (item: T, index: number) => false | R) => R[];
95
95
  sortBy: (sortByValue: SortByValue<T>, props: SortByProps) => T[];
96
96
  rejectDuplicates: (getKey: (item: T) => unknown) => T[];
97
+ findAndMap: <R>(predicate: (value: T) => R | false) => R | undefined;
97
98
  };
99
+ /**
100
+ * Finds the first item in an array where the predicate returns a non-false value and returns that mapped value.
101
+ *
102
+ * Combines find and map operations - applies the predicate to each item until one returns
103
+ * a value that is not `false`, then returns that mapped value. If no item matches, returns `undefined`.
104
+ *
105
+ * @param array - The array to search through
106
+ * @param predicate - Function that returns a mapped value or `false` to skip the item
107
+ * @returns The first mapped value that is not `false`, or `undefined` if no item matches
108
+ * @example
109
+ * const users = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }];
110
+ *
111
+ * const foundName = findAndMap(users, (user) =>
112
+ * user.id === 2 ? user.name.toUpperCase() : false
113
+ * );
114
+ * // foundName is 'BOB'
115
+ */
116
+ declare function findAndMap<T, R>(array: T[], predicate: (value: T) => R | false): R | undefined;
98
117
  /**
99
118
  * Enhance an array with extra methods
100
119
  *
@@ -109,4 +128,4 @@ type ArrayOps<T> = {
109
128
  */
110
129
  declare function arrayOps<T>(array: T[]): ArrayOps<T>;
111
130
 
112
- export { type FilterAndMapReturn, arrayOps, arrayWithPrev, arrayWithPrevAndIndex, filterAndMap, findAfterIndex, findBeforeIndex, getAscIndexOrder, hasDuplicates, isInArray, rejectArrayUndefinedValues, rejectDuplicates, sortBy, truncateArray };
131
+ export { type FilterAndMapReturn, arrayOps, arrayWithPrev, arrayWithPrevAndIndex, filterAndMap, findAfterIndex, findAndMap, findBeforeIndex, getAscIndexOrder, hasDuplicates, isInArray, rejectArrayUndefinedValues, rejectDuplicates, sortBy, truncateArray };
@@ -94,7 +94,26 @@ type ArrayOps<T> = {
94
94
  filterAndMap: <R>(mapFilter: (item: T, index: number) => false | R) => R[];
95
95
  sortBy: (sortByValue: SortByValue<T>, props: SortByProps) => T[];
96
96
  rejectDuplicates: (getKey: (item: T) => unknown) => T[];
97
+ findAndMap: <R>(predicate: (value: T) => R | false) => R | undefined;
97
98
  };
99
+ /**
100
+ * Finds the first item in an array where the predicate returns a non-false value and returns that mapped value.
101
+ *
102
+ * Combines find and map operations - applies the predicate to each item until one returns
103
+ * a value that is not `false`, then returns that mapped value. If no item matches, returns `undefined`.
104
+ *
105
+ * @param array - The array to search through
106
+ * @param predicate - Function that returns a mapped value or `false` to skip the item
107
+ * @returns The first mapped value that is not `false`, or `undefined` if no item matches
108
+ * @example
109
+ * const users = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }];
110
+ *
111
+ * const foundName = findAndMap(users, (user) =>
112
+ * user.id === 2 ? user.name.toUpperCase() : false
113
+ * );
114
+ * // foundName is 'BOB'
115
+ */
116
+ declare function findAndMap<T, R>(array: T[], predicate: (value: T) => R | false): R | undefined;
98
117
  /**
99
118
  * Enhance an array with extra methods
100
119
  *
@@ -109,4 +128,4 @@ type ArrayOps<T> = {
109
128
  */
110
129
  declare function arrayOps<T>(array: T[]): ArrayOps<T>;
111
130
 
112
- export { type FilterAndMapReturn, arrayOps, arrayWithPrev, arrayWithPrevAndIndex, filterAndMap, findAfterIndex, findBeforeIndex, getAscIndexOrder, hasDuplicates, isInArray, rejectArrayUndefinedValues, rejectDuplicates, sortBy, truncateArray };
131
+ export { type FilterAndMapReturn, arrayOps, arrayWithPrev, arrayWithPrevAndIndex, filterAndMap, findAfterIndex, findAndMap, findBeforeIndex, getAscIndexOrder, hasDuplicates, isInArray, rejectArrayUndefinedValues, rejectDuplicates, sortBy, truncateArray };
@@ -4,6 +4,7 @@ import {
4
4
  arrayWithPrevAndIndex,
5
5
  filterAndMap,
6
6
  findAfterIndex,
7
+ findAndMap,
7
8
  findBeforeIndex,
8
9
  getAscIndexOrder,
9
10
  hasDuplicates,
@@ -12,7 +13,7 @@ import {
12
13
  rejectDuplicates,
13
14
  sortBy,
14
15
  truncateArray
15
- } from "./chunk-4DVTWCXL.js";
16
+ } from "./chunk-27AL66CH.js";
16
17
  import "./chunk-C2SVCIWE.js";
17
18
  import "./chunk-JF2MDHOJ.js";
18
19
  export {
@@ -21,6 +22,7 @@ export {
21
22
  arrayWithPrevAndIndex,
22
23
  filterAndMap,
23
24
  findAfterIndex,
25
+ findAndMap,
24
26
  findBeforeIndex,
25
27
  getAscIndexOrder,
26
28
  hasDuplicates,
@@ -118,11 +118,19 @@ function truncateArray(array, maxLength, appendIfTruncated) {
118
118
  }
119
119
  return result;
120
120
  }
121
+ function findAndMap(array, predicate) {
122
+ for (const item of array) {
123
+ const value = predicate(item);
124
+ if (value !== false) return value;
125
+ }
126
+ return void 0;
127
+ }
121
128
  function arrayOps(array) {
122
129
  return {
123
130
  filterAndMap: (mapFilter) => filterAndMap(array, mapFilter),
124
131
  sortBy: (sortByValue, props) => sortBy(array, sortByValue, props),
125
- rejectDuplicates: (getKey) => rejectDuplicates(array, getKey)
132
+ rejectDuplicates: (getKey) => rejectDuplicates(array, getKey),
133
+ findAndMap: (predicate) => findAndMap(array, predicate)
126
134
  };
127
135
  }
128
136
 
@@ -139,5 +147,6 @@ export {
139
147
  hasDuplicates,
140
148
  rejectDuplicates,
141
149
  truncateArray,
150
+ findAndMap,
142
151
  arrayOps
143
152
  };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  sortBy
3
- } from "./chunk-4DVTWCXL.js";
3
+ } from "./chunk-27AL66CH.js";
4
4
  import {
5
5
  isPlainObject
6
6
  } from "./chunk-JF2MDHOJ.js";
@@ -0,0 +1,16 @@
1
+ import {
2
+ deepEqual
3
+ } from "./chunk-JQFUKJU5.js";
4
+
5
+ // src/keepPrevIfUnchanged.ts
6
+ function keepPrevIfUnchanged({
7
+ prev,
8
+ newValue,
9
+ equalityFn = deepEqual
10
+ }) {
11
+ return equalityFn(prev, newValue) ? prev : newValue;
12
+ }
13
+
14
+ export {
15
+ keepPrevIfUnchanged
16
+ };
@@ -9,7 +9,7 @@ import {
9
9
  } from "./chunk-VAAMRG4K.js";
10
10
  import {
11
11
  truncateArray
12
- } from "./chunk-4DVTWCXL.js";
12
+ } from "./chunk-27AL66CH.js";
13
13
  import {
14
14
  invariant
15
15
  } from "./chunk-C2SVCIWE.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  filterObjectOrArrayKeys
3
- } from "./chunk-XPOGWCUC.js";
4
- import "./chunk-4DVTWCXL.js";
3
+ } from "./chunk-6CG6JZKB.js";
4
+ import "./chunk-27AL66CH.js";
5
5
  import "./chunk-C2SVCIWE.js";
6
6
  import "./chunk-JF2MDHOJ.js";
7
7
  export {
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/keepPrevIfUnchanged.ts
21
+ var keepPrevIfUnchanged_exports = {};
22
+ __export(keepPrevIfUnchanged_exports, {
23
+ keepPrevIfUnchanged: () => keepPrevIfUnchanged
24
+ });
25
+ module.exports = __toCommonJS(keepPrevIfUnchanged_exports);
26
+
27
+ // src/deepEqual.ts
28
+ var has = Object.prototype.hasOwnProperty;
29
+ function find(iter, tar, maxDepth) {
30
+ for (const key of iter.keys()) {
31
+ if (deepEqual(key, tar, maxDepth)) return key;
32
+ }
33
+ }
34
+ function deepEqual(foo, bar, maxDepth = 20) {
35
+ let ctor, len, tmp;
36
+ if (foo === bar) return true;
37
+ if (maxDepth && maxDepth <= 0) return false;
38
+ if (foo && bar && (ctor = foo.constructor) === bar.constructor) {
39
+ if (ctor === Date)
40
+ return deepEqual(foo.getTime(), bar.getTime(), maxDepth - 1);
41
+ if (ctor === RegExp) return foo.toString() === bar.toString();
42
+ if (ctor === Array) {
43
+ if ((len = foo.length) === bar.length) {
44
+ while (len-- && deepEqual(foo[len], bar[len], maxDepth - 1)) ;
45
+ }
46
+ return len === -1;
47
+ }
48
+ if (ctor === Set) {
49
+ if (foo.size !== bar.size) {
50
+ return false;
51
+ }
52
+ for (len of foo) {
53
+ tmp = len;
54
+ if (tmp && typeof tmp === "object") {
55
+ tmp = find(bar, tmp, maxDepth - 1);
56
+ if (!tmp) return false;
57
+ }
58
+ if (!bar.has(tmp)) return false;
59
+ }
60
+ return true;
61
+ }
62
+ if (ctor === Map) {
63
+ if (foo.size !== bar.size) {
64
+ return false;
65
+ }
66
+ for (len of foo) {
67
+ tmp = len[0];
68
+ if (tmp && typeof tmp === "object") {
69
+ tmp = find(bar, tmp, maxDepth - 1);
70
+ if (!tmp) return false;
71
+ }
72
+ if (!deepEqual(len[1], bar.get(tmp), maxDepth - 1)) {
73
+ return false;
74
+ }
75
+ }
76
+ return true;
77
+ }
78
+ if (!ctor || typeof foo === "object") {
79
+ len = 0;
80
+ for (ctor in foo) {
81
+ if (has.call(foo, ctor) && ++len && !has.call(bar, ctor)) return false;
82
+ if (!(ctor in bar) || !deepEqual(foo[ctor], bar[ctor], maxDepth - 1))
83
+ return false;
84
+ }
85
+ return Object.keys(bar).length === len;
86
+ }
87
+ }
88
+ return foo !== foo && bar !== bar;
89
+ }
90
+
91
+ // src/keepPrevIfUnchanged.ts
92
+ function keepPrevIfUnchanged({
93
+ prev,
94
+ newValue,
95
+ equalityFn = deepEqual
96
+ }) {
97
+ return equalityFn(prev, newValue) ? prev : newValue;
98
+ }
99
+ // Annotate the CommonJS export names for ESM import in node:
100
+ 0 && (module.exports = {
101
+ keepPrevIfUnchanged
102
+ });
@@ -0,0 +1,7 @@
1
+ declare function keepPrevIfUnchanged<T>({ prev, newValue, equalityFn, }: {
2
+ prev: T;
3
+ newValue: T;
4
+ equalityFn?: (foo: any, bar: any) => boolean;
5
+ }): T;
6
+
7
+ export { keepPrevIfUnchanged };
@@ -0,0 +1,7 @@
1
+ declare function keepPrevIfUnchanged<T>({ prev, newValue, equalityFn, }: {
2
+ prev: T;
3
+ newValue: T;
4
+ equalityFn?: (foo: any, bar: any) => boolean;
5
+ }): T;
6
+
7
+ export { keepPrevIfUnchanged };
@@ -0,0 +1,7 @@
1
+ import {
2
+ keepPrevIfUnchanged
3
+ } from "./chunk-QQS7I7ZL.js";
4
+ import "./chunk-JQFUKJU5.js";
5
+ export {
6
+ keepPrevIfUnchanged
7
+ };
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/mutationUtils.ts
21
+ var mutationUtils_exports = {};
22
+ __export(mutationUtils_exports, {
23
+ updateObject: () => updateObject
24
+ });
25
+ module.exports = __toCommonJS(mutationUtils_exports);
26
+
27
+ // src/deepEqual.ts
28
+ var has = Object.prototype.hasOwnProperty;
29
+ function find(iter, tar, maxDepth) {
30
+ for (const key of iter.keys()) {
31
+ if (deepEqual(key, tar, maxDepth)) return key;
32
+ }
33
+ }
34
+ function deepEqual(foo, bar, maxDepth = 20) {
35
+ let ctor, len, tmp;
36
+ if (foo === bar) return true;
37
+ if (maxDepth && maxDepth <= 0) return false;
38
+ if (foo && bar && (ctor = foo.constructor) === bar.constructor) {
39
+ if (ctor === Date)
40
+ return deepEqual(foo.getTime(), bar.getTime(), maxDepth - 1);
41
+ if (ctor === RegExp) return foo.toString() === bar.toString();
42
+ if (ctor === Array) {
43
+ if ((len = foo.length) === bar.length) {
44
+ while (len-- && deepEqual(foo[len], bar[len], maxDepth - 1)) ;
45
+ }
46
+ return len === -1;
47
+ }
48
+ if (ctor === Set) {
49
+ if (foo.size !== bar.size) {
50
+ return false;
51
+ }
52
+ for (len of foo) {
53
+ tmp = len;
54
+ if (tmp && typeof tmp === "object") {
55
+ tmp = find(bar, tmp, maxDepth - 1);
56
+ if (!tmp) return false;
57
+ }
58
+ if (!bar.has(tmp)) return false;
59
+ }
60
+ return true;
61
+ }
62
+ if (ctor === Map) {
63
+ if (foo.size !== bar.size) {
64
+ return false;
65
+ }
66
+ for (len of foo) {
67
+ tmp = len[0];
68
+ if (tmp && typeof tmp === "object") {
69
+ tmp = find(bar, tmp, maxDepth - 1);
70
+ if (!tmp) return false;
71
+ }
72
+ if (!deepEqual(len[1], bar.get(tmp), maxDepth - 1)) {
73
+ return false;
74
+ }
75
+ }
76
+ return true;
77
+ }
78
+ if (!ctor || typeof foo === "object") {
79
+ len = 0;
80
+ for (ctor in foo) {
81
+ if (has.call(foo, ctor) && ++len && !has.call(bar, ctor)) return false;
82
+ if (!(ctor in bar) || !deepEqual(foo[ctor], bar[ctor], maxDepth - 1))
83
+ return false;
84
+ }
85
+ return Object.keys(bar).length === len;
86
+ }
87
+ }
88
+ return foo !== foo && bar !== bar;
89
+ }
90
+
91
+ // src/keepPrevIfUnchanged.ts
92
+ function keepPrevIfUnchanged({
93
+ prev,
94
+ newValue,
95
+ equalityFn = deepEqual
96
+ }) {
97
+ return equalityFn(prev, newValue) ? prev : newValue;
98
+ }
99
+
100
+ // src/mutationUtils.ts
101
+ function updateObject(object, updates) {
102
+ if (!object || typeof object !== "object") {
103
+ return;
104
+ }
105
+ for (const key of Object.keys(updates)) {
106
+ const value = updates[key];
107
+ if (value !== void 0) {
108
+ object[key] = keepPrevIfUnchanged({
109
+ prev: object[key],
110
+ newValue: value
111
+ });
112
+ }
113
+ }
114
+ }
115
+ // Annotate the CommonJS export names for ESM import in node:
116
+ 0 && (module.exports = {
117
+ updateObject
118
+ });
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Updates an object with a new set of values. undefined values are ignored in the updates object
3
+ * and deep equal values are not updated.
4
+ *
5
+ * @param object - The object to update.
6
+ * @param updates - The new values to update the object with.
7
+ */
8
+ declare function updateObject<T extends Record<string, unknown>>(object: T | undefined | null, updates: Partial<T>): void;
9
+
10
+ export { updateObject };
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Updates an object with a new set of values. undefined values are ignored in the updates object
3
+ * and deep equal values are not updated.
4
+ *
5
+ * @param object - The object to update.
6
+ * @param updates - The new values to update the object with.
7
+ */
8
+ declare function updateObject<T extends Record<string, unknown>>(object: T | undefined | null, updates: Partial<T>): void;
9
+
10
+ export { updateObject };
@@ -0,0 +1,23 @@
1
+ import {
2
+ keepPrevIfUnchanged
3
+ } from "./chunk-QQS7I7ZL.js";
4
+ import "./chunk-JQFUKJU5.js";
5
+
6
+ // src/mutationUtils.ts
7
+ function updateObject(object, updates) {
8
+ if (!object || typeof object !== "object") {
9
+ return;
10
+ }
11
+ for (const key of Object.keys(updates)) {
12
+ const value = updates[key];
13
+ if (value !== void 0) {
14
+ object[key] = keepPrevIfUnchanged({
15
+ prev: object[key],
16
+ newValue: value
17
+ });
18
+ }
19
+ }
20
+ }
21
+ export {
22
+ updateObject
23
+ };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  filterAndMap
3
- } from "./chunk-4DVTWCXL.js";
3
+ } from "./chunk-27AL66CH.js";
4
4
  import "./chunk-C2SVCIWE.js";
5
5
  import {
6
6
  isTruthy
package/dist/testUtils.js CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  } from "./chunk-JQFUKJU5.js";
12
12
  import {
13
13
  filterObjectOrArrayKeys
14
- } from "./chunk-XPOGWCUC.js";
14
+ } from "./chunk-6CG6JZKB.js";
15
15
  import {
16
16
  defer
17
17
  } from "./chunk-DFXNVEH6.js";
@@ -22,7 +22,7 @@ import "./chunk-KW55OTUG.js";
22
22
  import {
23
23
  arrayWithPrevAndIndex,
24
24
  filterAndMap
25
- } from "./chunk-4DVTWCXL.js";
25
+ } from "./chunk-27AL66CH.js";
26
26
  import {
27
27
  isObject
28
28
  } from "./chunk-C2SVCIWE.js";
@@ -27,9 +27,11 @@
27
27
  - [getValueStableKey](getValueStableKey.md)
28
28
  - [hash](hash.md)
29
29
  - [interpolate](interpolate/README.md)
30
+ - [keepPrevIfUnchanged](keepPrevIfUnchanged.md)
30
31
  - [levenshtein](levenshtein.md)
31
32
  - [main](main.md)
32
33
  - [mathUtils](mathUtils.md)
34
+ - [mutationUtils](mutationUtils.md)
33
35
  - [objUtils](objUtils.md)
34
36
  - [parallelAsyncCalls](parallelAsyncCalls/README.md)
35
37
  - [promiseUtils](promiseUtils/README.md)
@@ -63,6 +63,30 @@ const enhancedItems = arrayOps(items);
63
63
  enhancedItems.filterAndMap((item) => item === 2 ? false : item);
64
64
  ```
65
65
 
66
+ ##### findAndMap()
67
+
68
+ ```ts
69
+ findAndMap: <R>(predicate) => R | undefined;
70
+ ```
71
+
72
+ Defined in: [packages/utils/src/arrayUtils.ts:275](https://github.com/lucasols/utils/blob/main/packages/utils/src/arrayUtils.ts#L275)
73
+
74
+ ###### Type Parameters
75
+
76
+ ###### R
77
+
78
+ `R`
79
+
80
+ ###### Parameters
81
+
82
+ ###### predicate
83
+
84
+ (`value`) => `R` \| `false`
85
+
86
+ ###### Returns
87
+
88
+ `R` \| `undefined`
89
+
66
90
  ##### rejectDuplicates()
67
91
 
68
92
  ```ts
@@ -34,7 +34,7 @@ Defined in: [packages/utils/src/arrayUtils.ts:42](https://github.com/lucasols/ut
34
34
  function arrayOps<T>(array): ArrayOps<T>;
35
35
  ```
36
36
 
37
- Defined in: [packages/utils/src/arrayUtils.ts:289](https://github.com/lucasols/utils/blob/main/packages/utils/src/arrayUtils.ts#L289)
37
+ Defined in: [packages/utils/src/arrayUtils.ts:318](https://github.com/lucasols/utils/blob/main/packages/utils/src/arrayUtils.ts#L318)
38
38
 
39
39
  Enhance an array with extra methods
40
40
 
@@ -209,6 +209,62 @@ Defined in: [packages/utils/src/arrayUtils.ts:165](https://github.com/lucasols/u
209
209
 
210
210
  ***
211
211
 
212
+ ### findAndMap()
213
+
214
+ ```ts
215
+ function findAndMap<T, R>(array, predicate): undefined | R;
216
+ ```
217
+
218
+ Defined in: [packages/utils/src/arrayUtils.ts:295](https://github.com/lucasols/utils/blob/main/packages/utils/src/arrayUtils.ts#L295)
219
+
220
+ Finds the first item in an array where the predicate returns a non-false value and returns that mapped value.
221
+
222
+ Combines find and map operations - applies the predicate to each item until one returns
223
+ a value that is not `false`, then returns that mapped value. If no item matches, returns `undefined`.
224
+
225
+ #### Type Parameters
226
+
227
+ ##### T
228
+
229
+ `T`
230
+
231
+ ##### R
232
+
233
+ `R`
234
+
235
+ #### Parameters
236
+
237
+ ##### array
238
+
239
+ `T`[]
240
+
241
+ The array to search through
242
+
243
+ ##### predicate
244
+
245
+ (`value`) => `false` \| `R`
246
+
247
+ Function that returns a mapped value or `false` to skip the item
248
+
249
+ #### Returns
250
+
251
+ `undefined` \| `R`
252
+
253
+ The first mapped value that is not `false`, or `undefined` if no item matches
254
+
255
+ #### Example
256
+
257
+ ```ts
258
+ const users = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }];
259
+
260
+ const foundName = findAndMap(users, (user) =>
261
+ user.id === 2 ? user.name.toUpperCase() : false
262
+ );
263
+ // foundName is 'BOB'
264
+ ```
265
+
266
+ ***
267
+
212
268
  ### findBeforeIndex()
213
269
 
214
270
  ```ts
@@ -0,0 +1,43 @@
1
+ [**@ls-stack/utils**](README.md)
2
+
3
+ ***
4
+
5
+ [@ls-stack/utils](modules.md) / keepPrevIfUnchanged
6
+
7
+ # keepPrevIfUnchanged
8
+
9
+ ## Functions
10
+
11
+ ### keepPrevIfUnchanged()
12
+
13
+ ```ts
14
+ function keepPrevIfUnchanged<T>(__namedParameters): T;
15
+ ```
16
+
17
+ Defined in: [packages/utils/src/keepPrevIfUnchanged.ts:3](https://github.com/lucasols/utils/blob/main/packages/utils/src/keepPrevIfUnchanged.ts#L3)
18
+
19
+ #### Type Parameters
20
+
21
+ ##### T
22
+
23
+ `T`
24
+
25
+ #### Parameters
26
+
27
+ ##### \_\_namedParameters
28
+
29
+ ###### equalityFn?
30
+
31
+ (`foo`, `bar`) => `boolean` = `deepEqual`
32
+
33
+ ###### newValue
34
+
35
+ `T`
36
+
37
+ ###### prev
38
+
39
+ `T`
40
+
41
+ #### Returns
42
+
43
+ `T`
package/docs/modules.md CHANGED
@@ -27,9 +27,11 @@
27
27
  - [getValueStableKey](getValueStableKey.md)
28
28
  - [hash](hash.md)
29
29
  - [interpolate](interpolate/README.md)
30
+ - [keepPrevIfUnchanged](keepPrevIfUnchanged.md)
30
31
  - [levenshtein](levenshtein.md)
31
32
  - [main](main.md)
32
33
  - [mathUtils](mathUtils.md)
34
+ - [mutationUtils](mutationUtils.md)
33
35
  - [objUtils](objUtils.md)
34
36
  - [parallelAsyncCalls](parallelAsyncCalls/README.md)
35
37
  - [promiseUtils](promiseUtils/README.md)
@@ -0,0 +1,44 @@
1
+ [**@ls-stack/utils**](README.md)
2
+
3
+ ***
4
+
5
+ [@ls-stack/utils](modules.md) / mutationUtils
6
+
7
+ # mutationUtils
8
+
9
+ ## Functions
10
+
11
+ ### updateObject()
12
+
13
+ ```ts
14
+ function updateObject<T>(object, updates): void;
15
+ ```
16
+
17
+ Defined in: [packages/utils/src/mutationUtils.ts:10](https://github.com/lucasols/utils/blob/main/packages/utils/src/mutationUtils.ts#L10)
18
+
19
+ Updates an object with a new set of values. undefined values are ignored in the updates object
20
+ and deep equal values are not updated.
21
+
22
+ #### Type Parameters
23
+
24
+ ##### T
25
+
26
+ `T` *extends* `Record`\<`string`, `unknown`\>
27
+
28
+ #### Parameters
29
+
30
+ ##### object
31
+
32
+ The object to update.
33
+
34
+ `undefined` | `null` | `T`
35
+
36
+ ##### updates
37
+
38
+ `Partial`\<`T`\>
39
+
40
+ The new values to update the object with.
41
+
42
+ #### Returns
43
+
44
+ `void`
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ls-stack/utils",
3
3
  "description": "Universal TypeScript utilities for browser and Node.js",
4
- "version": "3.34.1",
4
+ "version": "3.36.0",
5
5
  "license": "MIT",
6
6
  "files": [
7
7
  "dist",
@@ -108,6 +108,10 @@
108
108
  "import": "./dist/interpolate.js",
109
109
  "require": "./dist/interpolate.cjs"
110
110
  },
111
+ "./keepPrevIfUnchanged": {
112
+ "import": "./dist/keepPrevIfUnchanged.js",
113
+ "require": "./dist/keepPrevIfUnchanged.cjs"
114
+ },
111
115
  "./levenshtein": {
112
116
  "import": "./dist/levenshtein.js",
113
117
  "require": "./dist/levenshtein.cjs"
@@ -116,6 +120,10 @@
116
120
  "import": "./dist/mathUtils.js",
117
121
  "require": "./dist/mathUtils.cjs"
118
122
  },
123
+ "./mutationUtils": {
124
+ "import": "./dist/mutationUtils.js",
125
+ "require": "./dist/mutationUtils.cjs"
126
+ },
119
127
  "./objUtils": {
120
128
  "import": "./dist/objUtils.js",
121
129
  "require": "./dist/objUtils.cjs"