es-toolkit 1.15.1-dev.425 → 1.15.1-dev.427

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.
@@ -42,57 +42,32 @@ function fill(array, value, start = 0, end = array.length) {
42
42
  return initial.fill(array, value, start, end);
43
43
  }
44
44
 
45
- function flatten(value, depth = 1) {
46
- const result = [];
47
- const flooredDepth = Math.floor(depth);
48
- if (!Array.isArray(value)) {
49
- return result;
50
- }
51
- const recursive = (arr, currentDepth) => {
52
- for (const item of arr) {
53
- if (currentDepth < flooredDepth &&
54
- (Array.isArray(item) ||
55
- Boolean(item?.[Symbol.isConcatSpreadable]) ||
56
- (item !== null && typeof item === 'object' && Object.prototype.toString.call(item) === '[object Arguments]'))) {
57
- if (Array.isArray(item)) {
58
- recursive(item, currentDepth + 1);
59
- }
60
- else {
61
- recursive(Array.from(item), currentDepth + 1);
62
- }
63
- }
64
- else {
65
- result.push(item);
66
- }
45
+ const IS_PLAIN = /^\w*$/;
46
+ const IS_DEEP = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/;
47
+ function isDeepKey(key) {
48
+ switch (typeof key) {
49
+ case 'number':
50
+ case 'symbol': {
51
+ return false;
67
52
  }
68
- };
69
- recursive(value, 0);
70
- return result;
71
- }
72
-
73
- function flattenDeep(value) {
74
- return flatten(value, Infinity);
75
- }
76
-
77
- function flattenDepth(value, depth = 1) {
78
- return flatten(value, depth);
53
+ case 'string': {
54
+ return !IS_PLAIN.test(key) && IS_DEEP.test(key);
55
+ }
56
+ }
79
57
  }
80
58
 
81
59
  function isSymbol(value) {
82
60
  return typeof value === 'symbol' || (value != null && value instanceof Symbol);
83
61
  }
84
62
 
85
- const regexIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/;
86
- const regexIsPlainProp = /^\w*$/;
87
- function isKey(value, object) {
88
- if (Array.isArray(value)) {
89
- return false;
63
+ function toKey(value) {
64
+ if (typeof value === 'string' || isSymbol(value)) {
65
+ return value;
90
66
  }
91
- if (typeof value === 'number' || typeof value === 'boolean' || value == null || isSymbol(value)) {
92
- return true;
67
+ if (Object.is(value?.valueOf(), -0)) {
68
+ return '-0';
93
69
  }
94
- return ((typeof value === 'string' && (regexIsPlainProp.test(value) || !regexIsDeepProp.test(value))) ||
95
- (object != null && Object.hasOwn(object, value)));
70
+ return `${value}`;
96
71
  }
97
72
 
98
73
  function toPath(deepKey) {
@@ -130,10 +105,319 @@ function toPath(deepKey) {
130
105
  else {
131
106
  lastIndex = PROPERTY_REGEXP.lastIndex;
132
107
  }
133
- }
108
+ }
109
+ return result;
110
+ }
111
+
112
+ function get(object, path, defaultValue) {
113
+ let resolvedPath;
114
+ if (Array.isArray(path)) {
115
+ resolvedPath = path;
116
+ }
117
+ else if (typeof path === 'string' && isDeepKey(path) && object?.[path] == null) {
118
+ resolvedPath = toPath(path);
119
+ }
120
+ else {
121
+ resolvedPath = [path];
122
+ }
123
+ if (resolvedPath.length === 0) {
124
+ return defaultValue;
125
+ }
126
+ let current = object;
127
+ let index;
128
+ for (index = 0; index < resolvedPath.length && current != null; index++) {
129
+ const key = toKey(resolvedPath[index]);
130
+ current = current[key];
131
+ }
132
+ if (current === null && index === resolvedPath.length) {
133
+ return current;
134
+ }
135
+ return current ?? defaultValue;
136
+ }
137
+
138
+ function property(path) {
139
+ return function (object) {
140
+ return get(object, path);
141
+ };
142
+ }
143
+
144
+ function isArrayMatch(target, source) {
145
+ if (source.length === 0) {
146
+ return true;
147
+ }
148
+ if (!Array.isArray(target)) {
149
+ return false;
150
+ }
151
+ const countedIndex = new Set();
152
+ for (let i = 0; i < source.length; i++) {
153
+ const sourceItem = source[i];
154
+ const index = target.findIndex((targetItem, index) => {
155
+ return isMatch(targetItem, sourceItem) && !countedIndex.has(index);
156
+ });
157
+ if (index === -1) {
158
+ return false;
159
+ }
160
+ countedIndex.add(index);
161
+ }
162
+ return true;
163
+ }
164
+
165
+ function isMapMatch(target, source) {
166
+ if (source.size === 0) {
167
+ return true;
168
+ }
169
+ if (!(target instanceof Map)) {
170
+ return false;
171
+ }
172
+ for (const [key, value] of source.entries()) {
173
+ if (!isMatch(target.get(key), value)) {
174
+ return false;
175
+ }
176
+ }
177
+ return true;
178
+ }
179
+
180
+ function isSetMatch(target, source) {
181
+ if (source.size === 0) {
182
+ return true;
183
+ }
184
+ if (!(target instanceof Set)) {
185
+ return false;
186
+ }
187
+ return isArrayMatch([...target], [...source]);
188
+ }
189
+
190
+ function isMatch(target, source) {
191
+ if (source === target) {
192
+ return true;
193
+ }
194
+ switch (typeof source) {
195
+ case 'object': {
196
+ if (source == null) {
197
+ return true;
198
+ }
199
+ const keys = Object.keys(source);
200
+ if (target == null) {
201
+ if (keys.length === 0) {
202
+ return true;
203
+ }
204
+ return false;
205
+ }
206
+ if (Array.isArray(source)) {
207
+ return isArrayMatch(target, source);
208
+ }
209
+ if (source instanceof Map) {
210
+ return isMapMatch(target, source);
211
+ }
212
+ if (source instanceof Set) {
213
+ return isSetMatch(target, source);
214
+ }
215
+ for (let i = 0; i < keys.length; i++) {
216
+ const key = keys[i];
217
+ if (!isTypedArray$1.isPrimitive(target) && !(key in target)) {
218
+ return false;
219
+ }
220
+ if (source[key] === undefined && target[key] !== undefined) {
221
+ return false;
222
+ }
223
+ if (!isMatch(target[key], source[key])) {
224
+ return false;
225
+ }
226
+ }
227
+ return true;
228
+ }
229
+ case 'function': {
230
+ if (Object.keys(source).length > 0) {
231
+ return isMatch(target, { ...source });
232
+ }
233
+ return false;
234
+ }
235
+ default: {
236
+ return !source;
237
+ }
238
+ }
239
+ }
240
+
241
+ function matches(source) {
242
+ source = toMerged.cloneDeep(source);
243
+ return (target) => {
244
+ return isMatch(target, source);
245
+ };
246
+ }
247
+
248
+ function cloneDeep(obj) {
249
+ if (typeof obj !== 'object') {
250
+ return toMerged.cloneDeep(obj);
251
+ }
252
+ switch (Object.prototype.toString.call(obj)) {
253
+ case isFunction.numberTag:
254
+ case isFunction.stringTag:
255
+ case isFunction.booleanTag: {
256
+ const result = new obj.constructor(obj?.valueOf());
257
+ toMerged.copyProperties(result, obj);
258
+ return result;
259
+ }
260
+ case isFunction.argumentsTag: {
261
+ const result = {};
262
+ toMerged.copyProperties(result, obj);
263
+ result.length = obj.length;
264
+ result[Symbol.iterator] = obj[Symbol.iterator];
265
+ return result;
266
+ }
267
+ default: {
268
+ return toMerged.cloneDeep(obj);
269
+ }
270
+ }
271
+ }
272
+
273
+ const IS_UNSIGNED_INTEGER = /^(?:0|[1-9]\d*)$/;
274
+ function isIndex(value) {
275
+ switch (typeof value) {
276
+ case 'number': {
277
+ return Number.isInteger(value) && value >= 0 && value < Number.MAX_SAFE_INTEGER;
278
+ }
279
+ case 'symbol': {
280
+ return false;
281
+ }
282
+ case 'string': {
283
+ return IS_UNSIGNED_INTEGER.test(value);
284
+ }
285
+ }
286
+ }
287
+
288
+ function isArguments(value) {
289
+ return value !== null && typeof value === 'object' && isFunction.getTag(value) === '[object Arguments]';
290
+ }
291
+
292
+ function has(object, path) {
293
+ let resolvedPath;
294
+ if (Array.isArray(path)) {
295
+ resolvedPath = path;
296
+ }
297
+ else if (typeof path === 'string' && isDeepKey(path) && object?.[path] == null) {
298
+ resolvedPath = toPath(path);
299
+ }
300
+ else {
301
+ resolvedPath = [path];
302
+ }
303
+ if (resolvedPath.length === 0) {
304
+ return false;
305
+ }
306
+ let current = object;
307
+ for (let i = 0; i < resolvedPath.length; i++) {
308
+ const key = resolvedPath[i];
309
+ if (current == null || !Object.prototype.hasOwnProperty.call(current, key)) {
310
+ const isSparseIndex = (Array.isArray(current) || isArguments(current)) && isIndex(key) && key < current.length;
311
+ if (!isSparseIndex) {
312
+ return false;
313
+ }
314
+ }
315
+ current = current[key];
316
+ }
317
+ return true;
318
+ }
319
+
320
+ function matchesProperty(property, source) {
321
+ property = Array.isArray(property) ? property : toKey(property);
322
+ source = cloneDeep(source);
323
+ return function (target) {
324
+ const result = get(target, property);
325
+ if (result === undefined) {
326
+ return has(target, property);
327
+ }
328
+ if (source === undefined) {
329
+ return result === undefined;
330
+ }
331
+ return isMatch(result, source);
332
+ };
333
+ }
334
+
335
+ function find(source, doesMatch) {
336
+ let values = source;
337
+ if (!Array.isArray(source)) {
338
+ values = Object.values(source);
339
+ }
340
+ switch (typeof doesMatch) {
341
+ case 'function': {
342
+ if (!Array.isArray(source)) {
343
+ const entries = Object.entries(source);
344
+ for (let i = 0; i < entries.length; i++) {
345
+ const entry = entries[i];
346
+ const key = entry[0];
347
+ const value = entry[1];
348
+ if (doesMatch(value, key, source)) {
349
+ return value;
350
+ }
351
+ }
352
+ return undefined;
353
+ }
354
+ return values.find(doesMatch);
355
+ }
356
+ case 'object': {
357
+ if (Array.isArray(doesMatch) && doesMatch.length === 2) {
358
+ const key = doesMatch[0];
359
+ const value = doesMatch[1];
360
+ return values.find(matchesProperty(key, value));
361
+ }
362
+ else {
363
+ return values.find(matches(doesMatch));
364
+ }
365
+ }
366
+ case 'string': {
367
+ return values.find(property(doesMatch));
368
+ }
369
+ }
370
+ }
371
+
372
+ function flatten(value, depth = 1) {
373
+ const result = [];
374
+ const flooredDepth = Math.floor(depth);
375
+ if (!Array.isArray(value)) {
376
+ return result;
377
+ }
378
+ const recursive = (arr, currentDepth) => {
379
+ for (const item of arr) {
380
+ if (currentDepth < flooredDepth &&
381
+ (Array.isArray(item) ||
382
+ Boolean(item?.[Symbol.isConcatSpreadable]) ||
383
+ (item !== null && typeof item === 'object' && Object.prototype.toString.call(item) === '[object Arguments]'))) {
384
+ if (Array.isArray(item)) {
385
+ recursive(item, currentDepth + 1);
386
+ }
387
+ else {
388
+ recursive(Array.from(item), currentDepth + 1);
389
+ }
390
+ }
391
+ else {
392
+ result.push(item);
393
+ }
394
+ }
395
+ };
396
+ recursive(value, 0);
134
397
  return result;
135
398
  }
136
399
 
400
+ function flattenDeep(value) {
401
+ return flatten(value, Infinity);
402
+ }
403
+
404
+ function flattenDepth(value, depth = 1) {
405
+ return flatten(value, depth);
406
+ }
407
+
408
+ const regexIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/;
409
+ const regexIsPlainProp = /^\w*$/;
410
+ function isKey(value, object) {
411
+ if (Array.isArray(value)) {
412
+ return false;
413
+ }
414
+ if (typeof value === 'number' || typeof value === 'boolean' || value == null || isSymbol(value)) {
415
+ return true;
416
+ }
417
+ return ((typeof value === 'string' && (regexIsPlainProp.test(value) || !regexIsDeepProp.test(value))) ||
418
+ (object != null && Object.hasOwn(object, value)));
419
+ }
420
+
137
421
  function getPath(key, object) {
138
422
  if (Array.isArray(key)) {
139
423
  const path = [];
@@ -213,21 +497,6 @@ function size(target) {
213
497
  return Object.keys(target).length;
214
498
  }
215
499
 
216
- const IS_UNSIGNED_INTEGER = /^(?:0|[1-9]\d*)$/;
217
- function isIndex(value) {
218
- switch (typeof value) {
219
- case 'number': {
220
- return Number.isInteger(value) && value >= 0 && value < Number.MAX_SAFE_INTEGER;
221
- }
222
- case 'symbol': {
223
- return false;
224
- }
225
- case 'string': {
226
- return IS_UNSIGNED_INTEGER.test(value);
227
- }
228
- }
229
- }
230
-
231
500
  function set(obj, path, value) {
232
501
  const resolvedPath = Array.isArray(path) ? path : typeof path === 'string' ? toPath(path) : [path];
233
502
  let current = obj;
@@ -292,94 +561,6 @@ function bind(func, thisObj, ...partialArgs) {
292
561
  const bindPlaceholder = Symbol('bind.placeholder');
293
562
  bind.placeholder = bindPlaceholder;
294
563
 
295
- const IS_PLAIN = /^\w*$/;
296
- const IS_DEEP = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/;
297
- function isDeepKey(key) {
298
- switch (typeof key) {
299
- case 'number':
300
- case 'symbol': {
301
- return false;
302
- }
303
- case 'string': {
304
- return !IS_PLAIN.test(key) && IS_DEEP.test(key);
305
- }
306
- }
307
- }
308
-
309
- function toKey(value) {
310
- if (typeof value === 'string' || isSymbol(value)) {
311
- return value;
312
- }
313
- if (Object.is(value?.valueOf(), -0)) {
314
- return '-0';
315
- }
316
- return `${value}`;
317
- }
318
-
319
- function get(object, path, defaultValue) {
320
- let resolvedPath;
321
- if (Array.isArray(path)) {
322
- resolvedPath = path;
323
- }
324
- else if (typeof path === 'string' && isDeepKey(path) && object?.[path] == null) {
325
- resolvedPath = toPath(path);
326
- }
327
- else {
328
- resolvedPath = [path];
329
- }
330
- if (resolvedPath.length === 0) {
331
- return defaultValue;
332
- }
333
- let current = object;
334
- let index;
335
- for (index = 0; index < resolvedPath.length && current != null; index++) {
336
- const key = toKey(resolvedPath[index]);
337
- current = current[key];
338
- }
339
- if (current === null && index === resolvedPath.length) {
340
- return current;
341
- }
342
- return current ?? defaultValue;
343
- }
344
-
345
- function isArguments(value) {
346
- return value !== null && typeof value === 'object' && isFunction.getTag(value) === '[object Arguments]';
347
- }
348
-
349
- function has(object, path) {
350
- let resolvedPath;
351
- if (Array.isArray(path)) {
352
- resolvedPath = path;
353
- }
354
- else if (typeof path === 'string' && isDeepKey(path) && object?.[path] == null) {
355
- resolvedPath = toPath(path);
356
- }
357
- else {
358
- resolvedPath = [path];
359
- }
360
- if (resolvedPath.length === 0) {
361
- return false;
362
- }
363
- let current = object;
364
- for (let i = 0; i < resolvedPath.length; i++) {
365
- const key = resolvedPath[i];
366
- if (current == null || !Object.prototype.hasOwnProperty.call(current, key)) {
367
- const isSparseIndex = (Array.isArray(current) || isArguments(current)) && isIndex(key) && key < current.length;
368
- if (!isSparseIndex) {
369
- return false;
370
- }
371
- }
372
- current = current[key];
373
- }
374
- return true;
375
- }
376
-
377
- function property(path) {
378
- return function (object) {
379
- return get(object, path);
380
- };
381
- }
382
-
383
564
  function identity(x) {
384
565
  return x;
385
566
  }
@@ -446,31 +627,6 @@ function isTypedArray(x) {
446
627
  return isTypedArray$1.isTypedArray(x);
447
628
  }
448
629
 
449
- function cloneDeep(obj) {
450
- if (typeof obj !== 'object') {
451
- return toMerged.cloneDeep(obj);
452
- }
453
- switch (Object.prototype.toString.call(obj)) {
454
- case isFunction.numberTag:
455
- case isFunction.stringTag:
456
- case isFunction.booleanTag: {
457
- const result = new obj.constructor(obj?.valueOf());
458
- toMerged.copyProperties(result, obj);
459
- return result;
460
- }
461
- case isFunction.argumentsTag: {
462
- const result = {};
463
- toMerged.copyProperties(result, obj);
464
- result.length = obj.length;
465
- result[Symbol.iterator] = obj[Symbol.iterator];
466
- return result;
467
- }
468
- default: {
469
- return toMerged.cloneDeep(obj);
470
- }
471
- }
472
- }
473
-
474
630
  function mergeWith(object, ...otherArgs) {
475
631
  const sources = otherArgs.slice(0, -1);
476
632
  const merge = otherArgs[otherArgs.length - 1];
@@ -557,110 +713,6 @@ function isBoolean(x) {
557
713
  return false;
558
714
  }
559
715
 
560
- function isArrayMatch(target, source) {
561
- if (source.length === 0) {
562
- return true;
563
- }
564
- if (!Array.isArray(target)) {
565
- return false;
566
- }
567
- const countedIndex = new Set();
568
- for (let i = 0; i < source.length; i++) {
569
- const sourceItem = source[i];
570
- const index = target.findIndex((targetItem, index) => {
571
- return isMatch(targetItem, sourceItem) && !countedIndex.has(index);
572
- });
573
- if (index === -1) {
574
- return false;
575
- }
576
- countedIndex.add(index);
577
- }
578
- return true;
579
- }
580
-
581
- function isMapMatch(target, source) {
582
- if (source.size === 0) {
583
- return true;
584
- }
585
- if (!(target instanceof Map)) {
586
- return false;
587
- }
588
- for (const [key, value] of source.entries()) {
589
- if (!isMatch(target.get(key), value)) {
590
- return false;
591
- }
592
- }
593
- return true;
594
- }
595
-
596
- function isSetMatch(target, source) {
597
- if (source.size === 0) {
598
- return true;
599
- }
600
- if (!(target instanceof Set)) {
601
- return false;
602
- }
603
- return isArrayMatch([...target], [...source]);
604
- }
605
-
606
- function isMatch(target, source) {
607
- if (source === target) {
608
- return true;
609
- }
610
- switch (typeof source) {
611
- case 'object': {
612
- if (source == null) {
613
- return true;
614
- }
615
- const keys = Object.keys(source);
616
- if (target == null) {
617
- if (keys.length === 0) {
618
- return true;
619
- }
620
- return false;
621
- }
622
- if (Array.isArray(source)) {
623
- return isArrayMatch(target, source);
624
- }
625
- if (source instanceof Map) {
626
- return isMapMatch(target, source);
627
- }
628
- if (source instanceof Set) {
629
- return isSetMatch(target, source);
630
- }
631
- for (let i = 0; i < keys.length; i++) {
632
- const key = keys[i];
633
- if (!isTypedArray$1.isPrimitive(target) && !(key in target)) {
634
- return false;
635
- }
636
- if (source[key] === undefined && target[key] !== undefined) {
637
- return false;
638
- }
639
- if (!isMatch(target[key], source[key])) {
640
- return false;
641
- }
642
- }
643
- return true;
644
- }
645
- case 'function': {
646
- if (Object.keys(source).length > 0) {
647
- return isMatch(target, { ...source });
648
- }
649
- return false;
650
- }
651
- default: {
652
- return !source;
653
- }
654
- }
655
- }
656
-
657
- function matches(source) {
658
- source = toMerged.cloneDeep(source);
659
- return (target) => {
660
- return isMatch(target, source);
661
- };
662
- }
663
-
664
716
  const startsWith = (str, target, position = 0) => {
665
717
  return str.startsWith(target, position);
666
718
  };
@@ -800,6 +852,7 @@ exports.concat = concat;
800
852
  exports.difference = difference;
801
853
  exports.endsWith = endsWith;
802
854
  exports.fill = fill;
855
+ exports.find = find;
803
856
  exports.flatten = flatten;
804
857
  exports.flattenDeep = flattenDeep;
805
858
  exports.flattenDepth = flattenDepth;
@@ -816,6 +869,7 @@ exports.isTypedArray = isTypedArray;
816
869
  exports.mapKeys = mapKeys;
817
870
  exports.mapValues = mapValues;
818
871
  exports.matches = matches;
872
+ exports.matchesProperty = matchesProperty;
819
873
  exports.max = max;
820
874
  exports.merge = merge;
821
875
  exports.mergeWith = mergeWith;
@@ -97,6 +97,7 @@ export { chunk } from './array/chunk.mjs';
97
97
  export { concat } from './array/concat.mjs';
98
98
  export { difference } from './array/difference.mjs';
99
99
  export { fill } from './array/fill.mjs';
100
+ export { find } from './array/find.mjs';
100
101
  export { flatten } from './array/flatten.mjs';
101
102
  export { flattenDeep } from './array/flattenDeep.mjs';
102
103
  export { flattenDepth } from './array/flattenDepth.mjs';
@@ -122,6 +123,7 @@ export { isBoolean } from './predicate/isBoolean.mjs';
122
123
  export { isTypedArray } from './predicate/isTypedArray.mjs';
123
124
  export { isMatch } from './predicate/isMatch.mjs';
124
125
  export { matches } from './predicate/matches.mjs';
126
+ export { matchesProperty } from './predicate/matchesProperty.mjs';
125
127
  export { startsWith } from './string/startsWith.mjs';
126
128
  export { endsWith } from './string/endsWith.mjs';
127
129
  export { padStart } from './string/padStart.mjs';
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Creates a function that checks if a given target object matches a specific property value.
3
+ *
4
+ * The returned function takes a target object and determines if the property at the
5
+ * specified path within the target object is equal to the given value.
6
+ *
7
+ * @param {PropertyKey | PropertyKey[]} property - The property path to check within the target object.
8
+ * This can be a single property key or an array of property keys.
9
+ * @param {unknown} source - The value to compare against the property value in the target object.
10
+ *
11
+ * @returns {(target: unknown) => boolean} - A function that takes a target object and returns
12
+ * `true` if the property value at the given path in the target object matches the provided value,
13
+ * otherwise returns `false`.
14
+ *
15
+ * @example
16
+ * // Using a single property key
17
+ * const checkName = matchesProperty('name', 'Alice');
18
+ * console.log(checkName({ name: 'Alice' })); // true
19
+ * console.log(checkName({ name: 'Bob' })); // false
20
+ *
21
+ * // Using an array of property keys
22
+ * const checkNested = matchesProperty(['address', 'city'], 'New York');
23
+ * console.log(checkNested({ address: { city: 'New York' } })); // true
24
+ * console.log(checkNested({ address: { city: 'Los Angeles' } })); // false
25
+ */
26
+ declare function matchesProperty(property: PropertyKey | readonly PropertyKey[], source: unknown): (target?: unknown) => boolean;
27
+
28
+ export { matchesProperty };