@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 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
+ ```