@valkyriestudios/utils 7.5.0 → 8.1.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.
Files changed (124) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/README.md +10 -57
  3. package/array/dedupe.js +25 -12
  4. package/array/isNotEmpty.js +1 -4
  5. package/array/join.js +8 -10
  6. package/array/mapFn.js +7 -9
  7. package/array/mapKey.js +5 -6
  8. package/array/mapPrimitive.js +5 -7
  9. package/array/shuffle.js +1 -4
  10. package/array/sort.js +16 -16
  11. package/caching/memoize.js +1 -1
  12. package/date/addUTC.js +4 -6
  13. package/date/diff.js +3 -4
  14. package/date/endOfUTC.js +23 -16
  15. package/date/is.js +1 -1
  16. package/date/startOfUTC.js +23 -16
  17. package/date/toUTC.js +1 -3
  18. package/date/toUnix.js +1 -3
  19. package/deep/define.js +1 -1
  20. package/deep/freeze.js +8 -12
  21. package/deep/get.js +16 -18
  22. package/deep/seal.js +8 -12
  23. package/deep/set.js +6 -21
  24. package/equal.js +7 -17
  25. package/hash/fnv1A.js +35 -27
  26. package/is.js +32 -35
  27. package/number/is.js +1 -4
  28. package/number/isAbove.js +1 -5
  29. package/number/isAboveOrEqual.js +1 -5
  30. package/number/isBelow.js +1 -5
  31. package/number/isBelowOrEqual.js +1 -5
  32. package/number/isBetween.js +1 -4
  33. package/number/isInteger.js +0 -3
  34. package/number/isIntegerAbove.js +1 -6
  35. package/number/isIntegerAboveOrEqual.js +1 -6
  36. package/number/isIntegerBelow.js +1 -6
  37. package/number/isIntegerBelowOrEqual.js +1 -6
  38. package/number/isIntegerBetween.js +1 -5
  39. package/number/isNumericalNaN.js +2 -1
  40. package/number/randomBetween.js +1 -4
  41. package/number/randomIntBetween.js +1 -4
  42. package/number/round.js +2 -6
  43. package/number/toPercentage.js +2 -3
  44. package/object/define.js +3 -5
  45. package/object/is.js +3 -1
  46. package/object/isNotEmpty.js +2 -4
  47. package/object/merge.js +7 -10
  48. package/object/pick.js +16 -12
  49. package/package.json +11 -15
  50. package/regexp/is.js +3 -1
  51. package/regexp/sanitize.js +2 -2
  52. package/src/array/dedupe.mjs +24 -0
  53. package/src/array/is.mjs +5 -0
  54. package/src/array/isNotEmpty.mjs +5 -0
  55. package/src/array/join.mjs +31 -0
  56. package/src/array/mapFn.mjs +34 -0
  57. package/src/array/mapKey.mjs +29 -0
  58. package/src/array/mapPrimitive.mjs +29 -0
  59. package/src/array/shuffle.mjs +14 -0
  60. package/src/array/sort.mjs +100 -0
  61. package/src/boolean/is.mjs +5 -0
  62. package/src/caching/memoize.mjs +24 -0
  63. package/src/date/addUTC.mjs +67 -0
  64. package/src/date/diff.mjs +46 -0
  65. package/src/date/endOfUTC.mjs +130 -0
  66. package/src/date/is.mjs +5 -0
  67. package/src/date/nowUnix.mjs +5 -0
  68. package/src/date/nowUnixMs.mjs +5 -0
  69. package/src/date/startOfUTC.mjs +129 -0
  70. package/src/date/toUTC.mjs +17 -0
  71. package/src/date/toUnix.mjs +9 -0
  72. package/src/deep/define.mjs +7 -0
  73. package/src/deep/freeze.mjs +22 -0
  74. package/src/deep/get.mjs +47 -0
  75. package/src/deep/seal.mjs +22 -0
  76. package/src/deep/set.mjs +41 -0
  77. package/src/equal.mjs +67 -0
  78. package/src/function/is.mjs +6 -0
  79. package/src/function/noop.mjs +5 -0
  80. package/src/function/noopresolve.mjs +6 -0
  81. package/src/function/noopreturn.mjs +6 -0
  82. package/src/function/sleep.mjs +12 -0
  83. package/src/hash/fnv1A.mjs +58 -0
  84. package/src/hash/guid.mjs +38 -0
  85. package/src/is.mjs +86 -0
  86. package/src/number/is.mjs +5 -0
  87. package/src/number/isAbove.mjs +6 -0
  88. package/src/number/isAboveOrEqual.mjs +6 -0
  89. package/src/number/isBelow.mjs +6 -0
  90. package/src/number/isBelowOrEqual.mjs +6 -0
  91. package/src/number/isBetween.mjs +13 -0
  92. package/src/number/isInteger.mjs +5 -0
  93. package/src/number/isIntegerAbove.mjs +6 -0
  94. package/src/number/isIntegerAboveOrEqual.mjs +6 -0
  95. package/src/number/isIntegerBelow.mjs +6 -0
  96. package/src/number/isIntegerBelowOrEqual.mjs +6 -0
  97. package/src/number/isIntegerBetween.mjs +13 -0
  98. package/src/number/isNumericalNaN.mjs +5 -0
  99. package/src/number/randomBetween.mjs +11 -0
  100. package/src/number/randomIntBetween.mjs +11 -0
  101. package/src/number/round.mjs +10 -0
  102. package/src/number/toPercentage.mjs +14 -0
  103. package/src/object/define.mjs +12 -0
  104. package/src/object/is.mjs +7 -0
  105. package/src/object/isNotEmpty.mjs +7 -0
  106. package/src/object/merge.mjs +27 -0
  107. package/src/object/pick.mjs +33 -0
  108. package/src/regexp/is.mjs +7 -0
  109. package/src/regexp/sanitize.mjs +12 -0
  110. package/src/string/humanizeBytes.mjs +29 -0
  111. package/src/string/humanizeNumber.mjs +84 -0
  112. package/src/string/is.mjs +5 -0
  113. package/src/string/isBetween.mjs +18 -0
  114. package/src/string/isNotEmpty.mjs +6 -0
  115. package/src/string/shorten.mjs +21 -0
  116. package/string/humanizeBytes.js +9 -10
  117. package/string/humanizeNumber.js +21 -22
  118. package/string/isBetween.js +2 -3
  119. package/string/isNotEmpty.js +2 -4
  120. package/string/shorten.js +3 -4
  121. package/object/defineFrozen.js +0 -13
  122. package/object/defineSealed.js +0 -13
  123. package/object/forValues.js +0 -18
  124. package/object/zip.js +0 -19
@@ -0,0 +1,12 @@
1
+ 'use strict';
2
+
3
+ // Return a promise that only resolves after X milliseconds (interesting for async/await structures
4
+ // where we want to sleep for X milliseconds)
5
+ // example usage: await sleep(1000);
6
+ //
7
+ // (default sleep = 1000ms)
8
+ export default function sleep (milliseconds = 1000) {
9
+ return new Promise(resolve => {
10
+ setTimeout(() => resolve(), milliseconds);
11
+ });
12
+ }
@@ -0,0 +1,58 @@
1
+ 'use strict';
2
+
3
+ /* eslint-disable no-bitwise */
4
+
5
+ import isString from '../string/is.mjs';
6
+ import isNumericalNaN from '../number/isNumericalNaN.mjs';
7
+ import {PROTO_RGX} from '../regexp/is.mjs';
8
+ import {PROTO_OBJ} from '../object/is.mjs';
9
+
10
+ // https://tools.ietf.org/html/draft-eastlake-fnv-03
11
+
12
+ const FNV_32 = 2166136261;
13
+ const REPL_NAN = 'nan';
14
+ const REPL_TRUE = 'true';
15
+ const REPL_FALSE = 'false';
16
+ const REPL_UNDEF = 'undefined';
17
+ const REPL_NULL = 'null';
18
+
19
+ export default function fnv1A (data, offset = FNV_32) {
20
+ let hash = offset;
21
+ let sanitized;
22
+
23
+ // Convert data to a format that is hashable
24
+ if (isString(data)) {
25
+ sanitized = data;
26
+ } else if (Number.isFinite(data)) {
27
+ sanitized = `${data}`;
28
+ } else if (Array.isArray(data) || Object.prototype.toString.call(data) === PROTO_OBJ) {
29
+ sanitized = JSON.stringify(data);
30
+ } else if (Object.prototype.toString.call(data) === PROTO_RGX) {
31
+ sanitized = data.toString();
32
+ } else if (data instanceof Date) {
33
+ sanitized = `${data.getTime()}`;
34
+ } else if (isNumericalNaN(data)) {
35
+ sanitized = REPL_NAN;
36
+ } else if (data === false) {
37
+ sanitized = REPL_FALSE;
38
+ } else if (data === true) {
39
+ sanitized = REPL_TRUE;
40
+ } else if (data === null) {
41
+ sanitized = REPL_NULL;
42
+ } else if (data === undefined) {
43
+ sanitized = REPL_UNDEF;
44
+ } else {
45
+ throw new TypeError('An FNV1A Hash could not be calculated for this datatype');
46
+ }
47
+
48
+ // Calculate the hash of the sanitized data by looping over each char
49
+ for (let i = 0; i < sanitized.length; i++) {
50
+ hash ^= sanitized.charCodeAt(i);
51
+
52
+ // 32-bit FNV prime: 2**24 + 2**8 + 0x93 = 16777619
53
+ // Using bitshift for accuracy and performance. Numbers in JS suck.
54
+ hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
55
+ }
56
+
57
+ return hash >>> 0;
58
+ }
@@ -0,0 +1,38 @@
1
+ 'use strict';
2
+
3
+ /* eslint-disable no-bitwise, prefer-template */
4
+
5
+ // RFC4122 Compliant
6
+
7
+ // Generates a prebuilt hexmap from 0 to 255
8
+ const HEXMAP = [];
9
+ for (let i = 0; i < 256; i++) {
10
+ HEXMAP[i] = (i < 16 ? '0' : '') + i.toString(16);
11
+ }
12
+
13
+ export default function guid () {
14
+ const d0 = (Math.random()*0xffffffff) | 0;
15
+ const d1 = (Math.random()*0xffffffff) | 0;
16
+ const d2 = (Math.random()*0xffffffff) | 0;
17
+ const d3 = (Math.random()*0xffffffff) | 0;
18
+ return HEXMAP[d0 & 0xff] +
19
+ HEXMAP[(d0 >> 8) & 0xff] +
20
+ HEXMAP[(d0 >> 16) & 0xff] +
21
+ HEXMAP[(d0 >> 24) & 0xff] +
22
+ '-' +
23
+ HEXMAP[d1 & 0xff] +
24
+ HEXMAP[(d1 >> 8) & 0xff] +
25
+ '-' +
26
+ HEXMAP[((d1>>16) & 0x0f) | 0x40] +
27
+ HEXMAP[(d1>>24) & 0xff] +
28
+ '-' +
29
+ HEXMAP[(d2 & 0x3f) | 0x80] +
30
+ HEXMAP[(d2 >> 8) & 0xff] +
31
+ '-' +
32
+ HEXMAP[(d2 >> 16) & 0xff] +
33
+ HEXMAP[(d2 >> 24) & 0xff] +
34
+ HEXMAP[d3 & 0xff] +
35
+ HEXMAP[(d3 >> 8) & 0xff] +
36
+ HEXMAP[(d3 >> 16) & 0xff] +
37
+ HEXMAP[(d3 >> 24) & 0xff];
38
+ }
package/src/is.mjs ADDED
@@ -0,0 +1,86 @@
1
+ 'use strict';
2
+
3
+ import equal from './equal.mjs';
4
+ import isNotEmptyArray from './array/isNotEmpty.mjs';
5
+ import isBoolean from './boolean/is.mjs';
6
+ import isDate from './date/is.mjs';
7
+ import isFunction from './function/is.mjs';
8
+ import isNumberBetween from './number/isBetween.mjs';
9
+ import isNumberBelow from './number/isBelow.mjs';
10
+ import isNumberBelowOrEqual from './number/isBelowOrEqual.mjs';
11
+ import isNumberAbove from './number/isAbove.mjs';
12
+ import isNumberAboveOrEqual from './number/isAboveOrEqual.mjs';
13
+ import isIntegerBetween from './number/isIntegerBetween.mjs';
14
+ import isIntegerBelow from './number/isIntegerBelow.mjs';
15
+ import isIntegerBelowOrEqual from './number/isIntegerBelowOrEqual.mjs';
16
+ import isIntegerAbove from './number/isIntegerAbove.mjs';
17
+ import isIntegerAboveOrEqual from './number/isIntegerAboveOrEqual.mjs';
18
+ import isRegExp from './regexp/is.mjs';
19
+ import isObject from './object/is.mjs';
20
+ import isNotEmptyObject from './object/isNotEmpty.mjs';
21
+ import isString from './string/is.mjs';
22
+ import isStringBetween from './string/isBetween.mjs';
23
+ import isNotEmptyString from './string/isNotEmpty.mjs';
24
+
25
+ const Is = Object.freeze(Object.defineProperties(Object.create(null), {
26
+ // Array -----------------------------------------------------------------------------------------------
27
+ Array : {enumerable: true, writable: false, configurable: false, value: Array.isArray},
28
+ NeArray : {enumerable: true, writable: false, configurable: false, value: isNotEmptyArray},
29
+ NotEmptyArray : {enumerable: true, writable: false, configurable: false, value: isNotEmptyArray},
30
+ // Boolean ---------------------------------------------------------------------------------------------
31
+ Boolean : {enumerable: true, writable: false, configurable: false, value: isBoolean},
32
+ // Date ------------------------------------------------------------------------------------------------
33
+ Date : {enumerable: true, writable: false, configurable: false, value: isDate},
34
+ // Function --------------------------------------------------------------------------------------------
35
+ Function : {enumerable: true, writable: false, configurable: false, value: isFunction},
36
+ // Number ----------------------------------------------------------------------------------------------
37
+ Num : {enumerable: true, writable: false, configurable: false, value: Number.isFinite},
38
+ NumBetween : {enumerable: true, writable: false, configurable: false, value: isNumberBetween},
39
+ NumAbove : {enumerable: true, writable: false, configurable: false, value: isNumberAbove},
40
+ NumAboveOrEqual : {enumerable: true, writable: false, configurable: false, value: isNumberAboveOrEqual},
41
+ NumBelow : {enumerable: true, writable: false, configurable: false, value: isNumberBelow},
42
+ NumBelowOrEqual : {enumerable: true, writable: false, configurable: false, value: isNumberBelowOrEqual},
43
+ NumGt : {enumerable: true, writable: false, configurable: false, value: isNumberAbove},
44
+ NumGte : {enumerable: true, writable: false, configurable: false, value: isNumberAboveOrEqual},
45
+ NumLt : {enumerable: true, writable: false, configurable: false, value: isNumberBelow},
46
+ NumLte : {enumerable: true, writable: false, configurable: false, value: isNumberBelowOrEqual},
47
+ Number : {enumerable: true, writable: false, configurable: false, value: Number.isFinite},
48
+ NumberBetween : {enumerable: true, writable: false, configurable: false, value: isNumberBetween},
49
+ NumberAbove : {enumerable: true, writable: false, configurable: false, value: isNumberAbove},
50
+ NumberAboveOrEqual : {enumerable: true, writable: false, configurable: false, value: isNumberAboveOrEqual},
51
+ NumberBelow : {enumerable: true, writable: false, configurable: false, value: isNumberBelow},
52
+ NumberBelowOrEqual : {enumerable: true, writable: false, configurable: false, value: isNumberBelowOrEqual},
53
+ // Integer ---------------------------------------------------------------------------------------------
54
+ Int : {enumerable: true, writable: false, configurable: false, value: Number.isInteger},
55
+ IntBetween : {enumerable: true, writable: false, configurable: false, value: isIntegerBetween},
56
+ IntAbove : {enumerable: true, writable: false, configurable: false, value: isIntegerAbove},
57
+ IntAboveOrEqual : {enumerable: true, writable: false, configurable: false, value: isIntegerAboveOrEqual},
58
+ IntBelow : {enumerable: true, writable: false, configurable: false, value: isIntegerBelow},
59
+ IntBelowOrEqual : {enumerable: true, writable: false, configurable: false, value: isIntegerBelowOrEqual},
60
+ IntGt : {enumerable: true, writable: false, configurable: false, value: isIntegerAbove},
61
+ IntGte : {enumerable: true, writable: false, configurable: false, value: isIntegerAboveOrEqual},
62
+ IntLt : {enumerable: true, writable: false, configurable: false, value: isIntegerBelow},
63
+ IntLte : {enumerable: true, writable: false, configurable: false, value: isIntegerBelowOrEqual},
64
+ Integer : {enumerable: true, writable: false, configurable: false, value: Number.isInteger},
65
+ IntegerBetween : {enumerable: true, writable: false, configurable: false, value: isIntegerBetween},
66
+ IntegerBelow : {enumerable: true, writable: false, configurable: false, value: isIntegerBelow},
67
+ IntegerBelowOrEqual : {enumerable: true, writable: false, configurable: false, value: isIntegerBelowOrEqual},
68
+ IntegerAbove : {enumerable: true, writable: false, configurable: false, value: isIntegerAbove},
69
+ IntegerAboveOrEqual : {enumerable: true, writable: false, configurable: false, value: isIntegerAboveOrEqual},
70
+ // Regex -----------------------------------------------------------------------------------------------
71
+ RegExp : {enumerable: true, writable: false, configurable: false, value: isRegExp},
72
+ // Object ----------------------------------------------------------------------------------------------
73
+ Object : {enumerable: true, writable: false, configurable: false, value: isObject},
74
+ NeObject : {enumerable: true, writable: false, configurable: false, value: isNotEmptyObject},
75
+ NotEmptyObject : {enumerable: true, writable: false, configurable: false, value: isNotEmptyObject},
76
+ // String ----------------------------------------------------------------------------------------------
77
+ String : {enumerable: true, writable: false, configurable: false, value: isString},
78
+ StringBetween : {enumerable: true, writable: false, configurable: false, value: isStringBetween},
79
+ NeString : {enumerable: true, writable: false, configurable: false, value: isNotEmptyString},
80
+ NotEmptyString : {enumerable: true, writable: false, configurable: false, value: isNotEmptyString},
81
+ // Utils -----------------------------------------------------------------------------------------------
82
+ Equal : {enumerable: true, writable: false, configurable: false, value: equal},
83
+ Eq : {enumerable: true, writable: false, configurable: false, value: equal},
84
+ }));
85
+
86
+ export default Is;
@@ -0,0 +1,5 @@
1
+ 'use strict';
2
+
3
+ export default function isNumber (val) {
4
+ return Number.isFinite(val);
5
+ }
@@ -0,0 +1,6 @@
1
+ 'use strict';
2
+
3
+ // Check if a number is above a reference number
4
+ export default function isNumberAbove (val, ref) {
5
+ return !Number.isFinite(val) || !Number.isFinite(ref) ? false : val > ref;
6
+ }
@@ -0,0 +1,6 @@
1
+ 'use strict';
2
+
3
+ // Check if a number is above or equal to a reference number
4
+ export default function isNumberAboveOrEqual (val, ref) {
5
+ return !Number.isFinite(val) || !Number.isFinite(ref) ? false : val >= ref;
6
+ }
@@ -0,0 +1,6 @@
1
+ 'use strict';
2
+
3
+ // Check if a number is below a reference number
4
+ export default function isBelow (val, ref) {
5
+ return !Number.isFinite(val) || !Number.isFinite(ref) ? false : val < ref;
6
+ }
@@ -0,0 +1,6 @@
1
+ 'use strict';
2
+
3
+ // Check if a number is below or equal to a reference number
4
+ export default function isBelowOrEqual (val, ref) {
5
+ return !Number.isFinite(val) || !Number.isFinite(ref) ? false : val <= ref;
6
+ }
@@ -0,0 +1,13 @@
1
+ 'use strict';
2
+
3
+ // Check if a number is between a range
4
+ export default function isBetween (val, min, max) {
5
+ if (
6
+ !Number.isFinite(val) ||
7
+ !Number.isFinite(min) ||
8
+ !Number.isFinite(max) ||
9
+ min >= max
10
+ ) return false;
11
+
12
+ return val >= min && val <= max;
13
+ }
@@ -0,0 +1,5 @@
1
+ 'use strict';
2
+
3
+ export default function isInteger (val) {
4
+ return Number.isInteger(val);
5
+ }
@@ -0,0 +1,6 @@
1
+ 'use strict';
2
+
3
+ // Check if a number is an integer above a reference number
4
+ export default function isIntegerAbove (val, ref) {
5
+ return !Number.isInteger(val) || !Number.isFinite(ref) ? false : val > ref;
6
+ }
@@ -0,0 +1,6 @@
1
+ 'use strict';
2
+
3
+ // Check if a number is an integer above or equal to a reference number
4
+ export default function isIntegerAboveOrEqual (val, ref) {
5
+ return !Number.isInteger(val) || !Number.isFinite(ref) ? false : val >= ref;
6
+ }
@@ -0,0 +1,6 @@
1
+ 'use strict';
2
+
3
+ // Check if a number is an integer below a reference number
4
+ export default function isIntegerBelow (val, ref) {
5
+ return !Number.isInteger(val) || !Number.isFinite(ref) ? false : val < ref;
6
+ }
@@ -0,0 +1,6 @@
1
+ 'use strict';
2
+
3
+ // Check if a number is an integer below or equal to a reference number
4
+ export default function isIntegerBelowOrEqual (val, ref) {
5
+ return !Number.isInteger(val) || !Number.isFinite(ref) ? false : val <= ref;
6
+ }
@@ -0,0 +1,13 @@
1
+ 'use strict';
2
+
3
+ // Check if a number is an integer between a range
4
+ export default function isIntegerBetween (val, min, max) {
5
+ if (
6
+ !Number.isInteger(val) ||
7
+ !Number.isFinite(min) ||
8
+ !Number.isFinite(max) ||
9
+ min >= max
10
+ ) return false;
11
+
12
+ return val >= min && val <= max;
13
+ }
@@ -0,0 +1,5 @@
1
+ 'use strict';
2
+
3
+ export default function isNumericalNaN (val) {
4
+ return Number.isNaN(val) || val === Infinity;
5
+ }
@@ -0,0 +1,11 @@
1
+ 'use strict';
2
+
3
+ // Generate random between min and max
4
+ export default function randomBetween (min = 0, max = 10) {
5
+ if (
6
+ !Number.isFinite(min) ||
7
+ !Number.isFinite(max)
8
+ ) throw new TypeError('Min/Max should be numeric');
9
+
10
+ return (Math.random() * (max - min)) + min;
11
+ }
@@ -0,0 +1,11 @@
1
+ 'use strict';
2
+
3
+ // Generate random between min and max (max not inclusive)
4
+ export default function randomIntBetween (min = 0, max = 10) {
5
+ if (
6
+ !Number.isFinite(min) ||
7
+ !Number.isFinite(max)
8
+ ) throw new TypeError('Min/Max should be numeric');
9
+
10
+ return Math.floor((Math.random() * (max - min)) + min);
11
+ }
@@ -0,0 +1,10 @@
1
+ 'use strict';
2
+
3
+ // Round a numeric value to a certain precision
4
+ export default function round (val, precision = 0) {
5
+ if (!Number.isFinite(val)) throw new TypeError('Value should be numeric');
6
+
7
+ const exp = Math.pow(10, Number.isInteger(precision) && precision > 0 ? precision : 0);
8
+ const num = (val * exp) * (1 + Number.EPSILON);
9
+ return Math.round(num)/exp;
10
+ }
@@ -0,0 +1,14 @@
1
+ 'use strict';
2
+
3
+ import round from './round.mjs';
4
+
5
+ // Convert a float value to a percentage
6
+ export default function toPercentage (val, precision = 0, min = 0, max = 1) {
7
+ if (
8
+ !Number.isFinite(val) ||
9
+ !Number.isFinite(min) ||
10
+ !Number.isFinite(max)
11
+ ) throw new TypeError('value/min/max should be numeric');
12
+
13
+ return round(((val - min)/ (max - min)) * 100, precision);
14
+ }
@@ -0,0 +1,12 @@
1
+ 'use strict';
2
+
3
+ import {PROTO_OBJ} from './is.mjs';
4
+
5
+ export default function define (props, obj = {}) {
6
+ if (
7
+ Object.prototype.toString.call(props) !== PROTO_OBJ ||
8
+ Object.prototype.toString.call(obj) !== PROTO_OBJ
9
+ ) throw new TypeError('Please pass an object as the value for props and obj');
10
+
11
+ return Object.defineProperties(obj, props);
12
+ }
@@ -0,0 +1,7 @@
1
+ 'use strict';
2
+
3
+ export const PROTO_OBJ = '[object Object]';
4
+
5
+ export default function isObject (val) {
6
+ return Object.prototype.toString.call(val) === PROTO_OBJ;
7
+ }
@@ -0,0 +1,7 @@
1
+ 'use strict';
2
+
3
+ import {PROTO_OBJ} from './is.mjs';
4
+
5
+ export default function isNotEmptyObject (val) {
6
+ return Object.prototype.toString.call(val) === PROTO_OBJ && Object.keys(val).length > 0;
7
+ }
@@ -0,0 +1,27 @@
1
+ 'use strict';
2
+
3
+ import {PROTO_OBJ} from './is.mjs';
4
+
5
+ const merge = (target, source = {}) => {
6
+ if (
7
+ Object.prototype.toString.call(target) !== PROTO_OBJ ||
8
+ Object.prototype.toString.call(source) !== PROTO_OBJ
9
+ ) throw new TypeError('Please pass a target and object to merge');
10
+
11
+ return Object.keys(target).reduce((acc, key) => {
12
+ if (
13
+ Object.prototype.toString.call(target[key]) === PROTO_OBJ &&
14
+ !Array.isArray(target[key])
15
+ ) {
16
+ acc[key] = merge(target[key], source[key] || {});
17
+ } else {
18
+ acc[key] = source.hasOwnProperty(key)
19
+ ? source[key]
20
+ : target[key];
21
+ }
22
+ return acc;
23
+ }, {});
24
+ };
25
+
26
+
27
+ export default merge;
@@ -0,0 +1,33 @@
1
+ 'use strict';
2
+
3
+ import deepGet from '../deep/get.mjs';
4
+ import deepSet from '../deep/set.mjs';
5
+ import isNotEmptyString from '../string/isNotEmpty.mjs';
6
+ import {PROTO_OBJ} from './is.mjs';
7
+
8
+ export default function pick (obj, keys) {
9
+ if (
10
+ Object.prototype.toString.call(obj) !== PROTO_OBJ ||
11
+ !Array.isArray(keys) ||
12
+ keys.length === 0
13
+ ) throw new TypeError('Please pass an object to pick from and a keys array');
14
+
15
+ const map = {};
16
+ let key_deep = false;
17
+ let val;
18
+ for (const key of keys) {
19
+ if (!isNotEmptyString(key)) continue;
20
+ key_deep = key.match(/(\.|\[)/g);
21
+ val = key_deep
22
+ ? deepGet(obj, key.trim())
23
+ : obj[key.trim()];
24
+ if (val === undefined) continue;
25
+
26
+ if (key_deep) {
27
+ deepSet(map, key.trim(), val);
28
+ } else {
29
+ map[key.trim()] = val;
30
+ }
31
+ }
32
+ return map;
33
+ }
@@ -0,0 +1,7 @@
1
+ 'use strict';
2
+
3
+ export const PROTO_RGX = '[object RegExp]';
4
+
5
+ export default function isRegExp (val) {
6
+ return Object.prototype.toString.call(val) === PROTO_RGX;
7
+ }
@@ -0,0 +1,12 @@
1
+ 'use strict';
2
+
3
+ import isNotEmptyString from '../string/isNotEmpty.mjs';
4
+
5
+ // Escapes a value to be used inside of a regular expression (eg: new RegExp(...))
6
+ // For more info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#Escaping
7
+ //
8
+ // @param string val Value to escape
9
+ export default function sanitizeRegExp (val) {
10
+ if (!isNotEmptyString(val)) return false;
11
+ return val.trim().replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&');
12
+ }
@@ -0,0 +1,29 @@
1
+ 'use strict';
2
+
3
+ import isString from '../string/is.mjs';
4
+ import isNotEmptyString from '../string/isNotEmpty.mjs';
5
+ import {PROTO_OBJ} from '../object/is.mjs';
6
+ import humanizeNumber from './humanizeNumber.mjs';
7
+
8
+ // Humanize a numerical byte value into a readable file size
9
+ //
10
+ // @param int val Amount of bytes
11
+ export default function humanizeBytes (val, options = {}) {
12
+ const has_opts = Object.prototype.toString.call(options) === PROTO_OBJ;
13
+ return humanizeNumber(val, {
14
+ delim: has_opts && isString(options.delim)
15
+ ? options.delim
16
+ : ',',
17
+ separator: has_opts && isNotEmptyString(options.separator)
18
+ ? options.separator
19
+ : '.',
20
+ precision: has_opts && Number.isInteger(options.precision) && options.precision >= 0
21
+ ? options.precision
22
+ : 2,
23
+ units: has_opts && Array.isArray(options.units) && options.units.length > 0
24
+ ? options.units.filter(isNotEmptyString)
25
+ : [' bytes', ' KB', ' MB', ' GB', ' TB', ' PB', ' EB', ' ZB', ' YB'],
26
+ divider: 1024,
27
+ real: true,
28
+ });
29
+ }
@@ -0,0 +1,84 @@
1
+ 'use strict';
2
+
3
+ import isBoolean from '../boolean/is.mjs';
4
+ import isString from '../string/is.mjs';
5
+ import isNotEmptyString from '../string/isNotEmpty.mjs';
6
+ import round from '../number/round.mjs';
7
+ import {PROTO_OBJ} from '../object/is.mjs';
8
+
9
+ // Humanize a numerical value into a unit base
10
+ //
11
+ // @param int val Amount of bytes
12
+ export default function humanizeNumber (val, options = {}) {
13
+ const has_opts = Object.prototype.toString.call(options) === PROTO_OBJ;
14
+ const OPTS = {
15
+ delim: has_opts && isString(options.delim)
16
+ ? options.delim
17
+ : ',',
18
+ separator: has_opts && isNotEmptyString(options.separator)
19
+ ? options.separator
20
+ : '.',
21
+ precision: has_opts && Number.isInteger(options.precision) && options.precision >= 0
22
+ ? options.precision
23
+ : 2,
24
+ units: has_opts && ((Array.isArray(options.units) && options.units.length > 0) || options.units === false)
25
+ ? options.units ? options.units.filter(isString) : false
26
+ : ['', 'k', 'm', 'b', 't', 'q'],
27
+ // Have to have at least bigger than 1 to not end in infinite loop
28
+ divider: has_opts && Number.isInteger(options.divider) && options.divider > 1
29
+ ? options.divider
30
+ : 1000,
31
+ // Should we auto parse as integer (true) or not (false)
32
+ real: has_opts && isBoolean(options.real)
33
+ ? options.real
34
+ : false,
35
+ };
36
+
37
+ // If not a valid value, return
38
+ if (!(Number.isFinite(val) || isNotEmptyString(val))) {
39
+ return `0${OPTS.units.length > 0 ? OPTS.units[0] : ''}`;
40
+ }
41
+
42
+ // Ensure we are working with an integer
43
+ let normalized;
44
+ if (OPTS.real) {
45
+ normalized = parseInt(isString(val) ? val.trim() : val) || 0;
46
+ } else {
47
+ normalized = parseFloat(isString(val) ? val.trim() : val) || 0;
48
+ }
49
+ if (!Number.isFinite(normalized) || normalized === 0) {
50
+ return `0${OPTS.units.length > 0 ? OPTS.units[0] : ''}`;
51
+ }
52
+
53
+ // Determine sign
54
+ const sign = normalized < 0 ? '-' : '';
55
+
56
+ // Ensure val here is absolute
57
+ normalized = Math.abs(normalized);
58
+
59
+ // At each step, divide by divider, based on that we get the unit size
60
+ let postfix = '';
61
+ if (OPTS.units) {
62
+ let unit_ix = 0;
63
+ while (normalized >= OPTS.divider) {
64
+ unit_ix++;
65
+ normalized = normalized/OPTS.divider;
66
+ if (unit_ix === OPTS.units.length - 1) break;
67
+ }
68
+ postfix = OPTS.units[unit_ix];
69
+ }
70
+
71
+ // Round with precision
72
+ normalized = round(normalized, OPTS.precision);
73
+
74
+ // Humanize from eg: 10023 to 10,023
75
+ normalized = `${normalized}`.split('.');
76
+ normalized[0] = normalized[0].split('').reverse().map((char, ix, original) => {
77
+ if (ix > 0 && ix < original.length && ix % 3 === 0) return char + OPTS.delim;
78
+ return char;
79
+ }).reverse().join('');
80
+ normalized = normalized.join(OPTS.separator);
81
+
82
+ // Include a decimal point and a tenths-place digit if presenting less than then of KB or greater units
83
+ return `${sign}${normalized}${postfix}`;
84
+ }
@@ -0,0 +1,5 @@
1
+ 'use strict';
2
+
3
+ export default function isString (val) {
4
+ return typeof val === 'string' || val instanceof String;
5
+ }
@@ -0,0 +1,18 @@
1
+ 'use strict';
2
+
3
+ import isString from './is.mjs';
4
+
5
+ // Check if a string is between a range in length
6
+ export default function isStringBetween (val, min, max, trimmed = true) {
7
+ if (
8
+ !isString(val) ||
9
+ !Number.isFinite(min) ||
10
+ min < 0 ||
11
+ !Number.isFinite(max) ||
12
+ max < 0 ||
13
+ min >= max
14
+ ) return false;
15
+
16
+ const length = (trimmed === true ? val.trim() : val).length;
17
+ return length >= min && length <= max;
18
+ }
@@ -0,0 +1,6 @@
1
+ 'use strict';
2
+
3
+ export default function isNotEmptyString (val, trimmed = true) {
4
+ if (typeof val !== 'string' && !(val instanceof String)) return false;
5
+ return (trimmed === true ? val.trim() : val).length > 0;
6
+ }
@@ -0,0 +1,21 @@
1
+ 'use strict';
2
+
3
+ import isString from './is.mjs';
4
+ import isNumberAbove from '../number/isAbove.mjs';
5
+
6
+ // Shorten a string and add a postfix if it goes over a specific length, will autotrim value
7
+ //
8
+ // @param string val Value to shorten, returns false a string is not passed
9
+ // @param int length Length to shorten it at
10
+ // @param string postfix (default='...') Postfix to use when shortened
11
+ export default function shorten (val, length, postfix = '...') {
12
+ if (
13
+ !isString(val) ||
14
+ !isString(postfix) ||
15
+ !isNumberAbove(length, 0)
16
+ ) return false;
17
+
18
+ if (val.trim().length <= length) return val.trim();
19
+
20
+ return `${val.trim().substr(0, length)}${postfix}`;
21
+ }