moderndash 2.1.4 → 2.2.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/dist/index.d.ts CHANGED
@@ -7,12 +7,12 @@
7
7
  *
8
8
  * chunk(['a', 'b', 'c', 'd'], 3)
9
9
  * // => [['a', 'b', 'c'], ['d']]
10
- * @param size The length of each chunk
10
+ * @param chunkSize The length of each chunk
11
11
  * @param array The array to chunk.
12
12
  * @template TElem The type of the array elements.
13
13
  * @returns Returns the new array of chunks.
14
14
  */
15
- declare function chunk<TElem>(array: readonly TElem[], size: number): TElem[][];
15
+ declare function chunk<TElem>(array: readonly TElem[], chunkSize: number): TElem[][];
16
16
 
17
17
  /**
18
18
  * Creates an object with counts of occurrences of items in the array.
@@ -91,7 +91,7 @@ declare function difference<TElem>(arrayOrCompFn: (a: TElem, b: TElem) => boolea
91
91
  * { 'user': 'pebbles', 'active': true }
92
92
  * ]
93
93
  *
94
- * dropRightWhile(users, ({ active }) => active)
94
+ * dropRightWhile(users, user => user.active)
95
95
  * // => objects for ['barney']
96
96
  * @param predicate The function invoked per iteration.
97
97
  * @param array The array to query.
@@ -111,7 +111,7 @@ declare function dropRightWhile<TElem>(array: readonly TElem[], predicate: (valu
111
111
  * { 'user': 'pebbles', 'active': false }
112
112
  * ]
113
113
  *
114
- * dropWhile(users, ({ active }) => active)
114
+ * dropWhile(users, user => user.active)
115
115
  * // => objects for ['pebbles']
116
116
  * @param predicate The function invoked per iteration.
117
117
  * @param array The array to query.
@@ -236,7 +236,7 @@ declare function sort<TElem>(array: readonly TElem[], ...orders: {
236
236
  * { 'user': 'pebbles', 'active': true }
237
237
  * ]
238
238
  *
239
- * takeRightWhile(users, ({ active }) => active)
239
+ * takeRightWhile(users, user => user.active)
240
240
  * // => objects for ['fred', 'pebbles']
241
241
  * @param predicate The function invoked per iteration.
242
242
  * @param array The array to query.
@@ -256,7 +256,7 @@ declare function takeRightWhile<TElem>(array: readonly TElem[], predicate: (elem
256
256
  * { 'user': 'pebbles', 'active': false }
257
257
  * ]
258
258
  *
259
- * takeWhile(users, ({ active }) => active)
259
+ * takeWhile(users, user => user.active)
260
260
  * // => objects for ['barney', 'fred']
261
261
  * @param predicate The function invoked per iteration.
262
262
  * @param array The array to query.
@@ -478,16 +478,18 @@ declare function decMaxCalls(n: number): (target: unknown, key: string, descript
478
478
  type GenericFunction<TFunc extends (...args: any) => any> = (...args: Parameters<TFunc>) => ReturnType<TFunc>;
479
479
 
480
480
  /**
481
- * Creates a function that caches the result of `func`.
481
+ * Creates a function that memoizes the result of a given function.
482
482
  *
483
- * The cache key is either determined by the provided `resolver` or by the arguments used in the cached function.
484
- *
485
- * The `cache` property is exposed on the cached function. It is an instance of `Map` and can be used to clear or inspect the cache.
486
- * The cache property can be replaced by a custom cache as long as it implements the `Map` interface.
483
+ * The cache key is determined by the `resolver` or by the arguments from the function call.
487
484
  *
488
485
  * **Options:**
489
- * - `resolver` A function that determines the cache key for storing the result based on the arguments provided.
490
- * - `ttl` sets the time to live for the cache in milliseconds. After `ttl` milliseconds, the next call to the memoized function will result in a cache miss.
486
+ * - `resolver` A function that determines the cache key based on the arguments provided.
487
+ * - `ttl` the time to live for the cache entries in milliseconds.
488
+ *
489
+ * **Properties:**
490
+ * - `cache` The cache is an instance of `Map` and can be used to clear or inspect the cache.
491
+ * It can be replaced by a custom cache that matches the `Map` interface.
492
+ *
491
493
  *
492
494
  * This function can be used as a decorator with {@link decMemoize}.
493
495
  *
@@ -803,6 +805,20 @@ declare function sum(numbers: readonly number[]): number;
803
805
  */
804
806
  type PlainObject = Record<PropertyKey, unknown>;
805
807
 
808
+ /**
809
+ * Flattens an object into a single level object.
810
+ *
811
+ * @example
812
+ * const obj = { a: { b: 2, c: [{ d: 3 }, {d: 4 }] } };
813
+ * flatKeys(obj);
814
+ * // => { 'a.b': 2, 'a.c[0].d': 3, 'a.c[1].d': 4 }
815
+ *
816
+ * @param obj The object to flatten.
817
+ * @template TObj The type of the object to flatten.
818
+ * @returns A new object with flattened keys.
819
+ */
820
+ declare function flatKeys<TObj extends PlainObject>(obj: TObj): Record<string, unknown>;
821
+
806
822
  /**
807
823
  * This function combines two or more objects into a single new object. Arrays and other types are overwritten.
808
824
  *
@@ -876,13 +892,25 @@ declare function pick<TObj extends PlainObject, Key extends keyof TObj>(object:
876
892
  * set(obj, 'a.c', 1);
877
893
  * // => { a: { b: 2, c: 1 } }
878
894
  *
895
+ * // `[number]` can be used to access array elements
896
+ * set(obj, 'a.c[0]', 'hello');
897
+ * // => { a: { b: 2, c: ['hello'] } }
898
+ *
899
+ * // numbers with dots are treated as keys
900
+ * set(obj, 'a.c.0.d', 'world');
901
+ * // => { a: { b: 2, c: { 0: { d: 'world' } } }
902
+ *
903
+ * // supports numbers in keys
904
+ * set(obj, 'a.e0.a', 1);
905
+ * // => { a: { e0: { a: 1 } } }
906
+ *
879
907
  * @param obj The object to modify.
880
908
  * @param path The path of the property to set.
881
909
  * @param value The value to set.
882
910
  * @template TObj The type of the object.
883
911
  * @returns The modified object.
884
912
  */
885
- declare function set<TObj extends PlainObject>(obj: TObj, path: string, value: unknown): TObj;
913
+ declare function set(obj: PlainObject, path: string, value: unknown): PlainObject;
886
914
 
887
915
  /**
888
916
  * A class for managing a queue of async functions that runs a set number concurrently.
@@ -1287,4 +1315,4 @@ declare function isPlainObject(value: unknown): value is PlainObject;
1287
1315
  */
1288
1316
  declare function isUrl(str: string): boolean;
1289
1317
 
1290
- export { ArrayMinLength, GenericFunction, Jsonifiable, PlainObject, Queue, average, camelCase, capitalize, chunk, count, debounce, deburr, decDebounce, decMaxCalls, decMemoize, decMinCalls, decThrottle, difference, dropRightWhile, dropWhile, escapeHtml, escapeRegExp, group, hash, intersection, isEmpty, isEqual, isPlainObject, isUrl, kebabCase, maxCalls, median, memoize, merge, minCalls, omit, pascalCase, pick, races, randomElem, randomFloat, randomInt, randomString, range, retry, round, set, shuffle, sleep, snakeCase, sort, splitWords, sum, takeRightWhile, takeWhile, throttle, timeout, times, titleCase, toDecorator, tryCatch, unescapeHtml, unique };
1318
+ export { ArrayMinLength, GenericFunction, Jsonifiable, PlainObject, Queue, average, camelCase, capitalize, chunk, count, debounce, deburr, decDebounce, decMaxCalls, decMemoize, decMinCalls, decThrottle, difference, dropRightWhile, dropWhile, escapeHtml, escapeRegExp, flatKeys, group, hash, intersection, isEmpty, isEqual, isPlainObject, isUrl, kebabCase, maxCalls, median, memoize, merge, minCalls, omit, pascalCase, pick, races, randomElem, randomFloat, randomInt, randomString, range, retry, round, set, shuffle, sleep, snakeCase, sort, splitWords, sum, takeRightWhile, takeWhile, throttle, timeout, times, titleCase, toDecorator, tryCatch, unescapeHtml, unique };
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // src/array/chunk.ts
2
- function chunk(array, size) {
3
- const intSize = Math.trunc(size);
2
+ function chunk(array, chunkSize) {
3
+ const intSize = Math.trunc(chunkSize);
4
4
  if (array.length === 0 || intSize < 1) {
5
5
  return [];
6
6
  }
@@ -402,6 +402,29 @@ function isPlainObject(value) {
402
402
  return value?.constructor === Object;
403
403
  }
404
404
 
405
+ // src/object/flatKeys.ts
406
+ function flatKeys(obj) {
407
+ const result = {};
408
+ function addToResult(prefix, value) {
409
+ if (isPlainObject(value)) {
410
+ const flatObj = flatKeys(value);
411
+ for (const [flatKey, flatValue] of Object.entries(flatObj)) {
412
+ result[`${prefix}.${flatKey}`] = flatValue;
413
+ }
414
+ } else if (Array.isArray(value)) {
415
+ for (const [index, element] of value.entries()) {
416
+ addToResult(`${prefix}[${index}]`, element);
417
+ }
418
+ } else {
419
+ result[prefix] = value;
420
+ }
421
+ }
422
+ for (const [key, value] of Object.entries(obj)) {
423
+ addToResult(key, value);
424
+ }
425
+ return result;
426
+ }
427
+
405
428
  // src/object/merge.ts
406
429
  function merge(target, ...sources) {
407
430
  const targetCopy = { ...target };
@@ -430,18 +453,28 @@ function omit(object, keysToOmit) {
430
453
  }
431
454
 
432
455
  // src/object/set.ts
456
+ var validPathRegex = /^(?:[^.[\]]+(?:\[\d+])*(?:\.|\[\d+]))+(?:[^.[\]]+(?:\[\d+])*)+$/;
457
+ var pathSplitRegex = /\.|(?=\[)/g;
458
+ var matchBracketsRegex = /[[\]]/g;
433
459
  function set(obj, path, value) {
434
- const pathParts = path.split(/[.[\]]/g).filter((x) => Boolean(x.trim()));
460
+ if (!validPathRegex.test(path))
461
+ throw new Error("Invalid path, look at the examples for the correct format.");
462
+ const pathParts = path.split(pathSplitRegex);
435
463
  let currentObj = obj;
436
464
  for (let index = 0; index < pathParts.length; index++) {
437
- const key = pathParts[index];
465
+ const key = pathParts[index].replace(matchBracketsRegex, "");
438
466
  if (index === pathParts.length - 1) {
439
467
  currentObj[key] = value;
440
468
  break;
441
469
  }
442
- const nextIsNumber = !Number.isNaN(Number.parseInt(pathParts[index + 1]));
443
- if (currentObj[key] === void 0)
444
- currentObj[key] = nextIsNumber ? [] : {};
470
+ const nextElemIn = pathParts[index + 1].startsWith("[") ? "array" : "object";
471
+ if (currentObj[key] === void 0) {
472
+ currentObj[key] = nextElemIn === "array" ? [] : {};
473
+ } else if (nextElemIn === "array" && !Array.isArray(currentObj[key])) {
474
+ currentObj[key] = [];
475
+ } else if (nextElemIn === "object" && !isPlainObject(currentObj[key])) {
476
+ currentObj[key] = {};
477
+ }
445
478
  currentObj = currentObj[key];
446
479
  }
447
480
  return obj;
@@ -598,17 +631,18 @@ async function tryCatch(promise) {
598
631
  }
599
632
 
600
633
  // src/string/splitWords.ts
634
+ var splitWordsRegex = new RegExp(
635
+ "[^\\dA-Za-z]|(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])"
636
+ // lookahead for an uppercase letter followed by a lowercase letter
637
+ );
601
638
  function splitWords(str) {
602
- const regex = new RegExp(
603
- "[^\\dA-Za-z]|(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])"
604
- // lookahead for an uppercase letter followed by a lowercase letter
605
- );
606
- return str.split(regex).filter(Boolean);
639
+ return str.split(splitWordsRegex).filter(Boolean);
607
640
  }
608
641
 
609
642
  // src/string/deburr.ts
643
+ var accentControlRegex = /[\u0300-\u036F]/g;
610
644
  function deburr(str) {
611
- return str.normalize("NFD").replace(/[\u0300-\u036F]/g, "");
645
+ return str.normalize("NFD").replace(accentControlRegex, "");
612
646
  }
613
647
 
614
648
  // src/string/camelCase.ts
@@ -630,20 +664,22 @@ function capitalize(str) {
630
664
  }
631
665
 
632
666
  // src/string/escapeHtml.ts
667
+ var charRegex = /["&'<>]/g;
668
+ var escapeChars = /* @__PURE__ */ new Map([
669
+ ["&", "&amp;"],
670
+ ["<", "&lt;"],
671
+ [">", "&gt;"],
672
+ ["'", "&#39;"],
673
+ ['"', "&quot;"]
674
+ ]);
633
675
  function escapeHtml(str) {
634
- const escapeChars = {
635
- "&": "&amp;",
636
- "<": "&lt;",
637
- ">": "&gt;",
638
- "'": "&#39;",
639
- '"': "&quot;"
640
- };
641
- return str.replace(/["&'<>]/g, (char) => escapeChars[char]);
676
+ return str.replace(charRegex, (char) => escapeChars.get(char));
642
677
  }
643
678
 
644
679
  // src/string/escapeRegExp.ts
680
+ var escapleCharsRegex = /[$()*+.?[\\\]^{|}]/g;
645
681
  function escapeRegExp(str) {
646
- return str.replace(/[$()*+.?[\\\]^{|}]/g, "\\$&");
682
+ return str.replace(escapleCharsRegex, "\\$&");
647
683
  }
648
684
 
649
685
  // src/string/kebabCase.ts
@@ -694,15 +730,16 @@ function titleCase(str) {
694
730
  }
695
731
 
696
732
  // src/string/unescapeHtml.ts
733
+ var htmlEntitiesRegex = /&(?:amp|lt|gt|quot|#39);/g;
734
+ var entityMap = /* @__PURE__ */ new Map([
735
+ ["&amp;", "&"],
736
+ ["&lt;", "<"],
737
+ ["&gt;", ">"],
738
+ ["&quot;", '"'],
739
+ ["&#39;", "'"]
740
+ ]);
697
741
  function unescapeHtml(str) {
698
- const entityMap = {
699
- "&amp;": "&",
700
- "&lt;": "<",
701
- "&gt;": ">",
702
- "&quot;": '"',
703
- "&#39;": "'"
704
- };
705
- return str.replace(/&(?:amp|lt|gt|quot|#(0+)?39);/g, (entity) => entityMap[entity]);
742
+ return str.replace(htmlEntitiesRegex, (entity) => entityMap.get(entity));
706
743
  }
707
744
 
708
745
  // src/validate/isEmpty.ts
@@ -791,6 +828,7 @@ export {
791
828
  dropWhile,
792
829
  escapeHtml,
793
830
  escapeRegExp,
831
+ flatKeys,
794
832
  group,
795
833
  hash,
796
834
  intersection,