js-utils-core 1.0.1
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/arrayUtils.js +116 -0
- package/index.js +27 -0
- package/mathUtils.js +133 -0
- package/objectUtils.js +144 -0
- package/package.json +14 -0
- package/stringUtils.js +121 -0
- package/typeUtils.js +101 -0
package/arrayUtils.js
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Array utilities with clean, composable functions
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Get the first element or n elements from an array
|
|
7
|
+
*/
|
|
8
|
+
const head = (arr, n = 1) => {
|
|
9
|
+
if (n === 1) return arr[0];
|
|
10
|
+
return arr.slice(0, n);
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Get the last element or n elements from an array
|
|
15
|
+
*/
|
|
16
|
+
const tail = (arr, n = 1) => {
|
|
17
|
+
if (n === 1) return arr[arr.length - 1];
|
|
18
|
+
return arr.slice(-n);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Flatten array by one level or completely
|
|
23
|
+
*/
|
|
24
|
+
const flatten = (arr, depth = Infinity) => {
|
|
25
|
+
return arr.reduce((acc, val) => {
|
|
26
|
+
if (Array.isArray(val) && depth > 0) {
|
|
27
|
+
acc.push(...flatten(val, depth - 1));
|
|
28
|
+
} else {
|
|
29
|
+
acc.push(val);
|
|
30
|
+
}
|
|
31
|
+
return acc;
|
|
32
|
+
}, []);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Remove duplicate values, keeping first occurrence
|
|
37
|
+
*/
|
|
38
|
+
const unique = (arr, key = null) => {
|
|
39
|
+
if (!key) return [...new Set(arr)];
|
|
40
|
+
const seen = new Set();
|
|
41
|
+
return arr.filter((item) => {
|
|
42
|
+
const keyVal = key(item);
|
|
43
|
+
if (seen.has(keyVal)) return false;
|
|
44
|
+
seen.add(keyVal);
|
|
45
|
+
return true;
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Group array elements by a key function
|
|
51
|
+
*/
|
|
52
|
+
const groupBy = (arr, key) => {
|
|
53
|
+
return arr.reduce((acc, item) => {
|
|
54
|
+
const k = typeof key === "function" ? key(item) : item[key];
|
|
55
|
+
if (!acc[k]) acc[k] = [];
|
|
56
|
+
acc[k].push(item);
|
|
57
|
+
return acc;
|
|
58
|
+
}, {});
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Create chunks of specified size
|
|
63
|
+
*/
|
|
64
|
+
const chunk = (arr, size) => {
|
|
65
|
+
const chunks = [];
|
|
66
|
+
for (let i = 0; i < arr.length; i += size) {
|
|
67
|
+
chunks.push(arr.slice(i, i + size));
|
|
68
|
+
}
|
|
69
|
+
return chunks;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Find the minimum or maximum value
|
|
74
|
+
*/
|
|
75
|
+
const minBy = (arr, key) => {
|
|
76
|
+
return arr.reduce((min, item) => (key(item) < key(min) ? item : min));
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const maxBy = (arr, key) => {
|
|
80
|
+
return arr.reduce((max, item) => (key(item) > key(max) ? item : max));
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Sum array values
|
|
85
|
+
*/
|
|
86
|
+
const sum = (arr, key = null) => {
|
|
87
|
+
return arr.reduce((acc, item) => {
|
|
88
|
+
const val = key ? key(item) : item;
|
|
89
|
+
return acc + (typeof val === "number" ? val : 0);
|
|
90
|
+
}, 0);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Deep clone an object or array
|
|
95
|
+
*/
|
|
96
|
+
|
|
97
|
+
const deepClone = (obj) => {
|
|
98
|
+
if (obj === null || typeof obj !== "object") {
|
|
99
|
+
return obj;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return structuredClone(obj);
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
module.exports = {
|
|
106
|
+
head,
|
|
107
|
+
tail,
|
|
108
|
+
flatten,
|
|
109
|
+
unique,
|
|
110
|
+
groupBy,
|
|
111
|
+
chunk,
|
|
112
|
+
minBy,
|
|
113
|
+
maxBy,
|
|
114
|
+
sum,
|
|
115
|
+
deepClone,
|
|
116
|
+
};
|
package/index.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JS Utils - A clean utility library
|
|
3
|
+
* Inspired by lodash and radash with modern, functional approach
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const arrayUtils = require("./arrayUtils");
|
|
7
|
+
const objectUtils = require("./objectUtils");
|
|
8
|
+
const stringUtils = require("./stringUtils");
|
|
9
|
+
const typeUtils = require("./typeUtils");
|
|
10
|
+
const mathUtils = require("./mathUtils");
|
|
11
|
+
|
|
12
|
+
module.exports = {
|
|
13
|
+
// Array utilities
|
|
14
|
+
...arrayUtils,
|
|
15
|
+
|
|
16
|
+
// Object utilities
|
|
17
|
+
...objectUtils,
|
|
18
|
+
|
|
19
|
+
// String utilities
|
|
20
|
+
...stringUtils,
|
|
21
|
+
|
|
22
|
+
// Type utilities
|
|
23
|
+
...typeUtils,
|
|
24
|
+
|
|
25
|
+
// Math utilities
|
|
26
|
+
...mathUtils,
|
|
27
|
+
};
|
package/mathUtils.js
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Math utilities for common calculations
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Calculate average of numbers
|
|
7
|
+
*/
|
|
8
|
+
const average = (numbers) => {
|
|
9
|
+
if (numbers.length === 0) return 0;
|
|
10
|
+
return numbers.reduce((a, b) => a + b, 0) / numbers.length;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Calculate sum of numbers
|
|
15
|
+
*/
|
|
16
|
+
const sum = (numbers) => {
|
|
17
|
+
return numbers.reduce((a, b) => a + b, 0);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Find minimum value
|
|
22
|
+
*/
|
|
23
|
+
const min = (...numbers) => {
|
|
24
|
+
return Math.min(...numbers);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Find maximum value
|
|
29
|
+
*/
|
|
30
|
+
const max = (...numbers) => {
|
|
31
|
+
return Math.max(...numbers);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Clamp value between min and max
|
|
36
|
+
*/
|
|
37
|
+
const clamp = (value, min, max) => {
|
|
38
|
+
return Math.max(min, Math.min(value, max));
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Round to n decimal places
|
|
43
|
+
*/
|
|
44
|
+
const round = (num, decimals = 0) => {
|
|
45
|
+
return Math.round(num * Math.pow(10, decimals)) / Math.pow(10, decimals);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Calculate percentage
|
|
50
|
+
*/
|
|
51
|
+
const percentage = (value, total) => {
|
|
52
|
+
return (value / total) * 100;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Calculate percentage of value
|
|
57
|
+
*/
|
|
58
|
+
const percentageOf = (percent, total) => {
|
|
59
|
+
return (percent / 100) * total;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Check if number is even
|
|
64
|
+
*/
|
|
65
|
+
const isEven = (num) => {
|
|
66
|
+
return num % 2 === 0;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Check if number is odd
|
|
71
|
+
*/
|
|
72
|
+
const isOdd = (num) => {
|
|
73
|
+
return num % 2 !== 0;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Check if number is prime
|
|
78
|
+
*/
|
|
79
|
+
const isPrime = (num) => {
|
|
80
|
+
if (num <= 1) return false;
|
|
81
|
+
if (num <= 3) return true;
|
|
82
|
+
if (num % 2 === 0 || num % 3 === 0) return false;
|
|
83
|
+
for (let i = 5; i * i <= num; i += 6) {
|
|
84
|
+
if (num % i === 0 || num % (i + 2) === 0) return false;
|
|
85
|
+
}
|
|
86
|
+
return true;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Generate random number between min and max
|
|
91
|
+
*/
|
|
92
|
+
const random = (min = 0, max = 1) => {
|
|
93
|
+
return Math.random() * (max - min) + min;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Generate random integer between min and max (inclusive)
|
|
98
|
+
*/
|
|
99
|
+
const randomInt = (min, max) => {
|
|
100
|
+
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Calculate absolute difference
|
|
105
|
+
*/
|
|
106
|
+
const difference = (a, b) => {
|
|
107
|
+
return Math.abs(a - b);
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Check if two numbers are approximately equal
|
|
112
|
+
*/
|
|
113
|
+
const approximatelyEqual = (a, b, tolerance = 0.0001) => {
|
|
114
|
+
return Math.abs(a - b) < tolerance;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
module.exports = {
|
|
118
|
+
average,
|
|
119
|
+
sum,
|
|
120
|
+
min,
|
|
121
|
+
max,
|
|
122
|
+
clamp,
|
|
123
|
+
round,
|
|
124
|
+
percentage,
|
|
125
|
+
percentageOf,
|
|
126
|
+
isEven,
|
|
127
|
+
isOdd,
|
|
128
|
+
isPrime,
|
|
129
|
+
random,
|
|
130
|
+
randomInt,
|
|
131
|
+
difference,
|
|
132
|
+
approximatelyEqual,
|
|
133
|
+
};
|
package/objectUtils.js
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Object utilities with functional approach
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Deep clone using structuredClone or fallback
|
|
7
|
+
*/
|
|
8
|
+
const clone = (obj) => {
|
|
9
|
+
if (typeof structuredClone === "function") {
|
|
10
|
+
return structuredClone(obj);
|
|
11
|
+
}
|
|
12
|
+
// Fallback for older environments
|
|
13
|
+
return JSON.parse(JSON.stringify(obj));
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Pick specified keys from object
|
|
18
|
+
*/
|
|
19
|
+
const pick = (obj, keys) => {
|
|
20
|
+
return keys.reduce((acc, key) => {
|
|
21
|
+
if (key in obj) acc[key] = obj[key];
|
|
22
|
+
return acc;
|
|
23
|
+
}, {});
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Omit specified keys from object
|
|
28
|
+
*/
|
|
29
|
+
const omit = (obj, keys) => {
|
|
30
|
+
const keySet = new Set(keys);
|
|
31
|
+
return Object.entries(obj).reduce((acc, [key, val]) => {
|
|
32
|
+
if (!keySet.has(key)) acc[key] = val;
|
|
33
|
+
return acc;
|
|
34
|
+
}, {});
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Merge multiple objects (shallow)
|
|
39
|
+
*/
|
|
40
|
+
const merge = (...objects) => {
|
|
41
|
+
return Object.assign({}, ...objects);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Deep merge objects
|
|
46
|
+
*/
|
|
47
|
+
const deepMerge = (target, ...sources) => {
|
|
48
|
+
if (!sources.length) return target;
|
|
49
|
+
|
|
50
|
+
const result = clone(target);
|
|
51
|
+
|
|
52
|
+
for (const source of sources) {
|
|
53
|
+
for (const key in source) {
|
|
54
|
+
if (source.hasOwnProperty(key)) {
|
|
55
|
+
if (isPlainObject(source[key]) && isPlainObject(result[key])) {
|
|
56
|
+
result[key] = deepMerge(result[key], source[key]);
|
|
57
|
+
} else {
|
|
58
|
+
result[key] = source[key];
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return result;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Check if value is a plain object
|
|
69
|
+
*/
|
|
70
|
+
const isPlainObject = (val) => {
|
|
71
|
+
return val !== null && typeof val === "object" && val.constructor === Object;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Flatten nested object with dot notation
|
|
76
|
+
*/
|
|
77
|
+
const flatten = (obj, prefix = "") => {
|
|
78
|
+
const result = {};
|
|
79
|
+
|
|
80
|
+
const traverse = (current, key) => {
|
|
81
|
+
const newKey = prefix ? `${prefix}.${key}` : key;
|
|
82
|
+
|
|
83
|
+
if (isPlainObject(current[key]) && Object.keys(current[key]).length > 0) {
|
|
84
|
+
traverse(current[key], "");
|
|
85
|
+
for (const k in current[key]) {
|
|
86
|
+
traverse(current[key], k);
|
|
87
|
+
}
|
|
88
|
+
} else {
|
|
89
|
+
result[newKey] = current[key];
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
for (const key in obj) {
|
|
94
|
+
traverse(obj, key);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return result;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Get nested object value safely
|
|
102
|
+
*/
|
|
103
|
+
const get = (obj, path, defaultValue = undefined) => {
|
|
104
|
+
const keys = path.split(".");
|
|
105
|
+
let result = obj;
|
|
106
|
+
|
|
107
|
+
for (const key of keys) {
|
|
108
|
+
if (result == null) return defaultValue;
|
|
109
|
+
result = result[key];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return result !== undefined ? result : defaultValue;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Set nested object value
|
|
117
|
+
*/
|
|
118
|
+
const set = (obj, path, value) => {
|
|
119
|
+
const keys = path.split(".");
|
|
120
|
+
let current = obj;
|
|
121
|
+
|
|
122
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
123
|
+
const key = keys[i];
|
|
124
|
+
if (!(key in current) || typeof current[key] !== "object") {
|
|
125
|
+
current[key] = {};
|
|
126
|
+
}
|
|
127
|
+
current = current[key];
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
current[keys[keys.length - 1]] = value;
|
|
131
|
+
return obj;
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
module.exports = {
|
|
135
|
+
clone,
|
|
136
|
+
pick,
|
|
137
|
+
omit,
|
|
138
|
+
merge,
|
|
139
|
+
deepMerge,
|
|
140
|
+
isPlainObject,
|
|
141
|
+
flatten,
|
|
142
|
+
get,
|
|
143
|
+
set,
|
|
144
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "js-utils-core",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "A lightweight collection of reusable JavaScript utility functions designed to simplify everyday development tasks and promote clean, consistent code.",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
+
},
|
|
9
|
+
"author": "Manasa",
|
|
10
|
+
"license": "ISC",
|
|
11
|
+
"publishConfig": {
|
|
12
|
+
"access": "public"
|
|
13
|
+
}
|
|
14
|
+
}
|
package/stringUtils.js
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* String utilities with common transformations
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Convert string to camelCase
|
|
7
|
+
*/
|
|
8
|
+
const camelCase = (str) => {
|
|
9
|
+
return str
|
|
10
|
+
.replace(/[-_\s](.)/g, (_, char) => char.toUpperCase())
|
|
11
|
+
.replace(/^(.)/, (char) => char.toLowerCase());
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Convert string to snake_case
|
|
16
|
+
*/
|
|
17
|
+
const snakeCase = (str) => {
|
|
18
|
+
return str
|
|
19
|
+
.replace(/([A-Z])/g, "_$1")
|
|
20
|
+
.replace(/[-\s]/g, "_")
|
|
21
|
+
.toLowerCase()
|
|
22
|
+
.replace(/^_/, "");
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Convert string to PascalCase
|
|
27
|
+
*/
|
|
28
|
+
const pascalCase = (str) => {
|
|
29
|
+
return str
|
|
30
|
+
.split(/[-_\s]/)
|
|
31
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
|
32
|
+
.join("");
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Convert string to kebab-case
|
|
37
|
+
*/
|
|
38
|
+
const kebabCase = (str) => {
|
|
39
|
+
return str
|
|
40
|
+
.replace(/([A-Z])/g, "-$1")
|
|
41
|
+
.replace(/[-_\s]+/g, "-")
|
|
42
|
+
.toLowerCase()
|
|
43
|
+
.replace(/^-/, "");
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Capitalize first letter
|
|
48
|
+
*/
|
|
49
|
+
const capitalize = (str) => {
|
|
50
|
+
return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Repeat string n times
|
|
55
|
+
*/
|
|
56
|
+
const repeat = (str, n) => {
|
|
57
|
+
return str.repeat(Math.max(0, n));
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Pad string to desired length
|
|
62
|
+
*/
|
|
63
|
+
const padStart = (str, length, padString = " ") => {
|
|
64
|
+
return String(str).padStart(length, padString);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const padEnd = (str, length, padString = " ") => {
|
|
68
|
+
return String(str).padEnd(length, padString);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Truncate string with ellipsis
|
|
73
|
+
*/
|
|
74
|
+
const truncate = (str, length, suffix = "...") => {
|
|
75
|
+
if (str.length <= length) return str;
|
|
76
|
+
return str.slice(0, length - suffix.length) + suffix;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Check if string starts with prefix
|
|
81
|
+
*/
|
|
82
|
+
const startsWith = (str, prefix) => {
|
|
83
|
+
return String(str).startsWith(prefix);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Check if string ends with suffix
|
|
88
|
+
*/
|
|
89
|
+
const endsWith = (str, suffix) => {
|
|
90
|
+
return String(str).endsWith(suffix);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Remove whitespace from both ends
|
|
95
|
+
*/
|
|
96
|
+
const trim = (str) => {
|
|
97
|
+
return String(str).trim();
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Reverse a string
|
|
102
|
+
*/
|
|
103
|
+
const reverse = (str) => {
|
|
104
|
+
return String(str).split("").reverse().join("");
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
module.exports = {
|
|
108
|
+
camelCase,
|
|
109
|
+
snakeCase,
|
|
110
|
+
pascalCase,
|
|
111
|
+
kebabCase,
|
|
112
|
+
capitalize,
|
|
113
|
+
repeat,
|
|
114
|
+
padStart,
|
|
115
|
+
padEnd,
|
|
116
|
+
truncate,
|
|
117
|
+
startsWith,
|
|
118
|
+
endsWith,
|
|
119
|
+
trim,
|
|
120
|
+
reverse,
|
|
121
|
+
};
|
package/typeUtils.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type checking utilities
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Get exact type of value
|
|
7
|
+
*/
|
|
8
|
+
const typeOf = (val) => {
|
|
9
|
+
if (val === null) return "null";
|
|
10
|
+
if (val === undefined) return "undefined";
|
|
11
|
+
if (Array.isArray(val)) return "array";
|
|
12
|
+
if (val instanceof Date) return "date";
|
|
13
|
+
if (val instanceof RegExp) return "regexp";
|
|
14
|
+
if (val instanceof Map) return "map";
|
|
15
|
+
if (val instanceof Set) return "set";
|
|
16
|
+
return typeof val;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Check if value is null or undefined
|
|
21
|
+
*/
|
|
22
|
+
const isEmpty = (val) => {
|
|
23
|
+
if (val === null || val === undefined) return true;
|
|
24
|
+
if (typeof val === "string" || Array.isArray(val)) return val.length === 0;
|
|
25
|
+
if (val instanceof Map || val instanceof Set) return val.size === 0;
|
|
26
|
+
if (typeof val === "object") return Object.keys(val).length === 0;
|
|
27
|
+
return false;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Check if value is truthy (not empty, null, undefined, false, 0, NaN)
|
|
32
|
+
*/
|
|
33
|
+
const isTruthy = (val) => {
|
|
34
|
+
return !!val && !isEmpty(val);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Check various types
|
|
39
|
+
*/
|
|
40
|
+
const isNull = (val) => val === null;
|
|
41
|
+
const isUndefined = (val) => val === undefined;
|
|
42
|
+
const isBoolean = (val) => typeof val === "boolean";
|
|
43
|
+
const isNumber = (val) => typeof val === "number" && !isNaN(val);
|
|
44
|
+
const isString = (val) => typeof val === "string";
|
|
45
|
+
const isFunction = (val) => typeof val === "function";
|
|
46
|
+
const isObject = (val) => val !== null && typeof val === "object";
|
|
47
|
+
const isArray = (val) => Array.isArray(val);
|
|
48
|
+
const isDate = (val) => val instanceof Date && !isNaN(val.getTime());
|
|
49
|
+
const isRegExp = (val) => val instanceof RegExp;
|
|
50
|
+
const isMap = (val) => val instanceof Map;
|
|
51
|
+
const isSet = (val) => val instanceof Set;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Check if value is a plain object (not array, Date, etc.)
|
|
55
|
+
*/
|
|
56
|
+
const isPlainObject = (val) => {
|
|
57
|
+
return val !== null && typeof val === "object" && val.constructor === Object;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Check if value is numeric (including string numbers)
|
|
62
|
+
*/
|
|
63
|
+
const isNumeric = (val) => {
|
|
64
|
+
return !isNaN(val) && !isNaN(parseFloat(val));
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Check if value is integer
|
|
69
|
+
*/
|
|
70
|
+
const isInteger = (val) => {
|
|
71
|
+
return Number.isInteger(val);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Check if value is finite number
|
|
76
|
+
*/
|
|
77
|
+
const isFinite = (val) => {
|
|
78
|
+
return Number.isFinite(val);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
module.exports = {
|
|
82
|
+
typeOf,
|
|
83
|
+
isEmpty,
|
|
84
|
+
isTruthy,
|
|
85
|
+
isNull,
|
|
86
|
+
isUndefined,
|
|
87
|
+
isBoolean,
|
|
88
|
+
isNumber,
|
|
89
|
+
isString,
|
|
90
|
+
isFunction,
|
|
91
|
+
isObject,
|
|
92
|
+
isArray,
|
|
93
|
+
isDate,
|
|
94
|
+
isRegExp,
|
|
95
|
+
isMap,
|
|
96
|
+
isSet,
|
|
97
|
+
isPlainObject,
|
|
98
|
+
isNumeric,
|
|
99
|
+
isInteger,
|
|
100
|
+
isFinite,
|
|
101
|
+
};
|