@superutils/core 1.0.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/LICENSE +21 -0
- package/README.md +267 -0
- package/dist/index.d.ts +1320 -0
- package/dist/index.js +931 -0
- package/package.json +39 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Toufiqur Rahaman Chowdhury
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
# @superutils/core
|
|
2
|
+
|
|
3
|
+
A collection of lightweight, dependency-free utility functions and types.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Installation](#installation)
|
|
8
|
+
- [Usage](#usage)
|
|
9
|
+
- [`is`](#is): Type checkers
|
|
10
|
+
- [`deferred()`](#deferred): Debounce callbacks
|
|
11
|
+
- [`throttle()`](#throttle): Throttle callbacks
|
|
12
|
+
- [`fallbackIfFails()`](#fallbackIfFails): Gracefully invoke functions
|
|
13
|
+
- [`objCopy()`](#objCopy): Deep-copy objects
|
|
14
|
+
- [`search()`](#search): Search iterable collections
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @superutils/core
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
<div id="is"></div>
|
|
25
|
+
|
|
26
|
+
### `is`: type checkers
|
|
27
|
+
|
|
28
|
+
The `is` object provides a comprehensive set of type-checking functions.
|
|
29
|
+
|
|
30
|
+
```javascript
|
|
31
|
+
import { is } from '@superutils/core'
|
|
32
|
+
|
|
33
|
+
is.fn(() => {}) // true
|
|
34
|
+
is.asyncFn(async () => {}) // true
|
|
35
|
+
is.arr([]) // true
|
|
36
|
+
is.arrLike([]) // true
|
|
37
|
+
is.arrLike(new Map()) // true
|
|
38
|
+
is.arrLike(new Set()) // true
|
|
39
|
+
is.date(new Date()) // true
|
|
40
|
+
is.date(new Date(undefined)) // false
|
|
41
|
+
is.empty(' ') // true
|
|
42
|
+
is.empty([]) // true
|
|
43
|
+
is.empty(new Map()) // true
|
|
44
|
+
is.empty(null) // true
|
|
45
|
+
is.empty(undefined) // true
|
|
46
|
+
is.map(new Map()) // true
|
|
47
|
+
is.number(123) // true
|
|
48
|
+
is.number(NaN) // false
|
|
49
|
+
is.url('https://google.com') // true
|
|
50
|
+
...
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
All these functions can also be imported independantly.
|
|
55
|
+
Simply remove the dot (".") and uppercase the first letter of the function name.
|
|
56
|
+
|
|
57
|
+
```javascript
|
|
58
|
+
import {
|
|
59
|
+
isArr,
|
|
60
|
+
isFn,
|
|
61
|
+
isArrLike,
|
|
62
|
+
isDate,
|
|
63
|
+
isEmpty,
|
|
64
|
+
isMap,
|
|
65
|
+
isNumber,
|
|
66
|
+
isUrl,
|
|
67
|
+
} from '@superutils/core'
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
<div id="deferred"></div>
|
|
71
|
+
|
|
72
|
+
### `deferred(fn)`: debounce callbacks
|
|
73
|
+
|
|
74
|
+
`debounce()`, a sugar for `deferred()`, is also available.
|
|
75
|
+
|
|
76
|
+
```javascript
|
|
77
|
+
|
|
78
|
+
import { deferred } from '@superutils/core'
|
|
79
|
+
|
|
80
|
+
const handleChange = deferred(
|
|
81
|
+
event => console.log(event.target.value),
|
|
82
|
+
300 // debounce delay in milliseconds
|
|
83
|
+
)
|
|
84
|
+
handleChange({ target: { value 1 } }) // will be ignored
|
|
85
|
+
handleChange({ target: { value 2 } }) // will be ignored
|
|
86
|
+
handleChange({ target: { value 3 } }) // will be executed
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
<div id="throttle"></div>
|
|
90
|
+
|
|
91
|
+
### `throttle(fn)`: throttle callbacks
|
|
92
|
+
|
|
93
|
+
```javascript
|
|
94
|
+
import { throttle } from '@superutils/core'
|
|
95
|
+
|
|
96
|
+
const handleChange = throttle(
|
|
97
|
+
event => console.log(event.target.value),
|
|
98
|
+
300 // throttle duration in milliseconds
|
|
99
|
+
)
|
|
100
|
+
handleChange({ target: { value 1 } }) // will be executed
|
|
101
|
+
handleChange({ target: { value 2 } }) // will be ignored
|
|
102
|
+
handleChange({ target: { value 3 } }) // will be ignored
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
<div id="fallbackIfFails"></div>
|
|
106
|
+
|
|
107
|
+
### `fallbackIfFails(fn, args, fallback)`: gracefully invoke functions
|
|
108
|
+
|
|
109
|
+
Based on the function provided `fallbackIfFails` will either execute synchronously or asynchronously.
|
|
110
|
+
|
|
111
|
+
#### Sync operations:
|
|
112
|
+
|
|
113
|
+
```javascript
|
|
114
|
+
import { fallbackIfFails } from '@superutils/core'
|
|
115
|
+
|
|
116
|
+
const allProducts = []
|
|
117
|
+
// an example sync function that may fail
|
|
118
|
+
const getProducts = () => {
|
|
119
|
+
if (!allProducts?.length) throw new Error('No products available')
|
|
120
|
+
return allProducts
|
|
121
|
+
}
|
|
122
|
+
const result = fallbackIfFails(
|
|
123
|
+
getProducts, // function to invoke
|
|
124
|
+
[], // Parameters to be provided to the function. A function can also be used here that returns an array
|
|
125
|
+
[], // Fallback value to be returned when function throws an error.
|
|
126
|
+
)
|
|
127
|
+
console.log({ result })
|
|
128
|
+
// Result: []
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
#### Async operations:
|
|
132
|
+
|
|
133
|
+
```javascript
|
|
134
|
+
import { fallbackIfFails } from '@superutils/core'
|
|
135
|
+
|
|
136
|
+
const allProducts = []
|
|
137
|
+
// an example sync function that may fail
|
|
138
|
+
const getProducts = () =>
|
|
139
|
+
fetch('https://dummyjson.com/products').then(r => r.json())
|
|
140
|
+
fallbackIfFails(
|
|
141
|
+
getProducts, // function to invoke
|
|
142
|
+
[], // Parameters to be provided to the function. A function can also be used here that returns an array
|
|
143
|
+
{ products: [] }, // Fallback value to be returned when function throws an error.
|
|
144
|
+
).then(console.log)
|
|
145
|
+
// Prints the result when request is successful or fallback value when request fails
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
<div id="objCopy"></div>
|
|
149
|
+
|
|
150
|
+
### `objCopy(source, dest, ignoreKeys, override)`: deep-copy objects
|
|
151
|
+
|
|
152
|
+
```javascript
|
|
153
|
+
import { objCopy } from '@superutils/core'
|
|
154
|
+
|
|
155
|
+
const source = {
|
|
156
|
+
a: 1,
|
|
157
|
+
b: 2,
|
|
158
|
+
c: 3,
|
|
159
|
+
}
|
|
160
|
+
const dest = {
|
|
161
|
+
d: 4,
|
|
162
|
+
e: 5,
|
|
163
|
+
}
|
|
164
|
+
const copied = objCopy(
|
|
165
|
+
source,
|
|
166
|
+
dest,
|
|
167
|
+
['a'], // exclude source property
|
|
168
|
+
'empty', // only override if dest doesn't have the property or value is "empty" (check `is.emtpy()`)
|
|
169
|
+
)
|
|
170
|
+
// Result:
|
|
171
|
+
// {
|
|
172
|
+
// b: 2,
|
|
173
|
+
// c: 33,
|
|
174
|
+
// d: 4,
|
|
175
|
+
// e: 5,
|
|
176
|
+
// }
|
|
177
|
+
console.log(dest === copied) // true (dest is returned)
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
<div id="search"></div>
|
|
181
|
+
|
|
182
|
+
### `search(data, options)`: search iterable collections (Array/Map/Set)
|
|
183
|
+
|
|
184
|
+
```javascript
|
|
185
|
+
import { search } from '@superutils/core'
|
|
186
|
+
|
|
187
|
+
// sample colletion
|
|
188
|
+
const data = new Map([
|
|
189
|
+
[1, { age: 30, name: 'Alice' }],
|
|
190
|
+
[2, { age: 25, name: 'Bob' }],
|
|
191
|
+
[3, { age: 35, name: 'Charlie' }],
|
|
192
|
+
[4, { age: 28, name: 'Dave' }],
|
|
193
|
+
[5, { age: 22, name: 'Eve' }],
|
|
194
|
+
])
|
|
195
|
+
|
|
196
|
+
// Case-insensitive search by name
|
|
197
|
+
search(data, { query: { name: 've' } })
|
|
198
|
+
search(data, { query: { name: /ve/i } }) // Using regular expression
|
|
199
|
+
// Result:
|
|
200
|
+
// new Map([
|
|
201
|
+
// [4, { age: 28, name: 'Dave' }],
|
|
202
|
+
// [5, { age: 22, name: 'Eve' }],
|
|
203
|
+
// ])
|
|
204
|
+
|
|
205
|
+
// Return result as Array
|
|
206
|
+
search(data, { asMap: false, query: { name: 've' } })
|
|
207
|
+
// Result: [
|
|
208
|
+
// { age: 28, name: 'Dave' },
|
|
209
|
+
// { age: 22, name: 'Eve' }
|
|
210
|
+
// ]
|
|
211
|
+
|
|
212
|
+
// Search multiple properties
|
|
213
|
+
search(data, { query: { age: 28, name: 've' } })
|
|
214
|
+
// Result:
|
|
215
|
+
// new Map([
|
|
216
|
+
// [4, { age: 28, name: 'Dave' }],
|
|
217
|
+
// ])
|
|
218
|
+
|
|
219
|
+
// Fuzzy search accross all properties
|
|
220
|
+
search(data, { query: 'li' })
|
|
221
|
+
search(data, { query: /li/i }) // Using regular expression
|
|
222
|
+
// Result:
|
|
223
|
+
// new Map([
|
|
224
|
+
// [1, { age: 30, name: 'Alice' }],
|
|
225
|
+
// [3, { age: 35, name: 'Charlie' }],
|
|
226
|
+
// ])
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
#### Advanced Search Options:
|
|
230
|
+
|
|
231
|
+
```javascript
|
|
232
|
+
import { search } from '@superutils/core'
|
|
233
|
+
|
|
234
|
+
// Sample colletion
|
|
235
|
+
const data = new Map([
|
|
236
|
+
[1, { age: 30, name: 'Alice' }],
|
|
237
|
+
[2, { age: 25, name: 'Bob' }],
|
|
238
|
+
[3, { age: 35, name: 'Charlie' }],
|
|
239
|
+
[4, { age: 28, name: 'Dave' }],
|
|
240
|
+
[5, { age: 22, name: 'Eve' }],
|
|
241
|
+
])
|
|
242
|
+
search(data, {
|
|
243
|
+
asMap: false, // Result type: true => Map (default, keys preserved), false => Array
|
|
244
|
+
ignoreCase: false, // For text case-sensitivity
|
|
245
|
+
limit: 10, // Number of items returned. Default: no limit
|
|
246
|
+
matchExact: true, // true: full text search. false (default): partial matching
|
|
247
|
+
matchAll: true, // if true, item will be matched only when all of the query properties match
|
|
248
|
+
query: {
|
|
249
|
+
age: /(2[5-9])|(3[0-5])/, // match ages 25-35
|
|
250
|
+
name: /ali|ob|ve/i,
|
|
251
|
+
},
|
|
252
|
+
// transform the property values (or item itself when in fuzzy search mode)
|
|
253
|
+
transform: (item, value, property) => {
|
|
254
|
+
// exclude items by returning undefined or emptry string
|
|
255
|
+
if (item.age < 18) return ''
|
|
256
|
+
|
|
257
|
+
// return value as string to search continue search as per criteria
|
|
258
|
+
return `${value}`
|
|
259
|
+
},
|
|
260
|
+
})
|
|
261
|
+
// Result:
|
|
262
|
+
// [
|
|
263
|
+
// { age: 30, name: 'Alice' },
|
|
264
|
+
// { age: 25, name: 'Bob' },
|
|
265
|
+
// { age: 28, name: 'Dave' }
|
|
266
|
+
// ]
|
|
267
|
+
```
|