@ooneex/utils 0.0.5 → 0.0.8
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 +539 -203
- package/dist/index.d.ts +23 -69
- package/dist/index.js +3 -1
- package/dist/index.js.map +24 -0
- package/dist/ooneex-utils-0.0.8.tgz +0 -0
- package/package.json +25 -12
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Ooneex
|
|
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
CHANGED
|
@@ -1,335 +1,671 @@
|
|
|
1
1
|
# @ooneex/utils
|
|
2
2
|
|
|
3
|
-
A comprehensive
|
|
3
|
+
A comprehensive TypeScript/JavaScript utility library providing essential helper functions for string manipulation, time formatting, data parsing, and more. This package offers a collection of lightweight, type-safe utilities designed to streamline common development tasks across web applications.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+

|
|
8
|
+

|
|
9
|
+

|
|
10
|
+

|
|
11
|
+
|
|
12
|
+
## Features
|
|
13
|
+
|
|
14
|
+
✅ **String Manipulation** - Case conversion utilities (camelCase, PascalCase, kebab-case)
|
|
15
|
+
|
|
16
|
+
✅ **Time Formatting** - Convert seconds/milliseconds to human-readable formats
|
|
17
|
+
|
|
18
|
+
✅ **Data Parsing** - Intelligent string parsing with type inference
|
|
19
|
+
|
|
20
|
+
✅ **Type-Safe** - Full TypeScript support with proper type definitions
|
|
21
|
+
|
|
22
|
+
✅ **Lightweight** - Minimal dependencies and optimized bundle size
|
|
23
|
+
|
|
24
|
+
✅ **Cross-Platform** - Works in Browser, Node.js, Bun, and Deno
|
|
25
|
+
|
|
26
|
+
✅ **Environment Variables** - Parse and transform environment variables
|
|
27
|
+
|
|
28
|
+
✅ **File Utilities** - Convert data URLs to File objects
|
|
29
|
+
|
|
30
|
+
✅ **Random Generation** - Generate random IDs and strings
|
|
31
|
+
|
|
32
|
+
✅ **Number Formatting** - Format numbers with locale-aware compact notation
|
|
33
|
+
|
|
34
|
+
✅ **Zero Dependencies** - Only one small dependency (nanoid) for random generation
|
|
4
35
|
|
|
5
36
|
## Installation
|
|
6
37
|
|
|
38
|
+
### Bun
|
|
7
39
|
```bash
|
|
8
|
-
npm install @ooneex/utils
|
|
9
|
-
# or
|
|
10
40
|
bun add @ooneex/utils
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### pnpm
|
|
44
|
+
```bash
|
|
14
45
|
pnpm add @ooneex/utils
|
|
15
46
|
```
|
|
16
47
|
|
|
48
|
+
### Yarn
|
|
49
|
+
```bash
|
|
50
|
+
yarn add @ooneex/utils
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### npm
|
|
54
|
+
```bash
|
|
55
|
+
npm install @ooneex/utils
|
|
56
|
+
```
|
|
57
|
+
|
|
17
58
|
## Usage
|
|
18
59
|
|
|
60
|
+
### String Manipulation
|
|
61
|
+
|
|
19
62
|
```typescript
|
|
20
|
-
import {
|
|
63
|
+
import {
|
|
64
|
+
capitalizeWord,
|
|
65
|
+
toCamelCase,
|
|
66
|
+
toPascalCase,
|
|
67
|
+
toKebabCase,
|
|
68
|
+
splitToWords,
|
|
69
|
+
trim
|
|
70
|
+
} from '@ooneex/utils';
|
|
71
|
+
|
|
72
|
+
// Capitalize words
|
|
73
|
+
console.log(capitalizeWord('hello')); // 'Hello'
|
|
74
|
+
console.log(capitalizeWord('WORLD')); // 'World'
|
|
75
|
+
|
|
76
|
+
// Case conversions
|
|
77
|
+
console.log(toCamelCase('hello world')); // 'helloWorld'
|
|
78
|
+
console.log(toPascalCase('hello world')); // 'HelloWorld'
|
|
79
|
+
console.log(toKebabCase('Hello World')); // 'hello-world'
|
|
80
|
+
|
|
81
|
+
// Split strings to words
|
|
82
|
+
console.log(splitToWords('HelloWorldExample')); // ['Hello', 'World', 'Example']
|
|
83
|
+
console.log(splitToWords('hello-world_example')); // ['hello', 'world', 'example']
|
|
84
|
+
|
|
85
|
+
// Advanced trimming
|
|
86
|
+
console.log(trim('...hello...', '\\.')); // 'hello'
|
|
87
|
+
console.log(trim('[test]', '\\[|\\]')); // 'test'
|
|
21
88
|
```
|
|
22
89
|
|
|
23
|
-
|
|
90
|
+
### Time Formatting
|
|
24
91
|
|
|
25
|
-
|
|
92
|
+
```typescript
|
|
93
|
+
import {
|
|
94
|
+
secondsToHMS,
|
|
95
|
+
secondsToMS,
|
|
96
|
+
millisecondsToHMS,
|
|
97
|
+
sleep
|
|
98
|
+
} from '@ooneex/utils';
|
|
99
|
+
|
|
100
|
+
// Convert seconds to time formats
|
|
101
|
+
console.log(secondsToHMS(3661)); // '1:01:01'
|
|
102
|
+
console.log(secondsToHMS(125)); // '2:05'
|
|
103
|
+
console.log(secondsToHMS(45)); // '45'
|
|
104
|
+
|
|
105
|
+
console.log(secondsToMS(125)); // '2:05'
|
|
106
|
+
console.log(secondsToMS(45)); // '0:45'
|
|
107
|
+
|
|
108
|
+
// Convert milliseconds to time format
|
|
109
|
+
console.log(millisecondsToHMS(3661000)); // '1:01:01'
|
|
110
|
+
console.log(millisecondsToHMS(125000)); // '2:05'
|
|
111
|
+
|
|
112
|
+
// Async sleep utility
|
|
113
|
+
await sleep(1000); // Wait 1 second
|
|
114
|
+
```
|
|
26
115
|
|
|
27
|
-
|
|
116
|
+
### Data Parsing
|
|
28
117
|
|
|
29
|
-
|
|
118
|
+
```typescript
|
|
119
|
+
import { parseString, parseEnvVars } from '@ooneex/utils';
|
|
120
|
+
|
|
121
|
+
// Intelligent string parsing with type inference
|
|
122
|
+
console.log(parseString('123')); // 123 (number)
|
|
123
|
+
console.log(parseString('12.34')); // 12.34 (number)
|
|
124
|
+
console.log(parseString('true')); // true (boolean)
|
|
125
|
+
console.log(parseString('false')); // false (boolean)
|
|
126
|
+
console.log(parseString('null')); // null
|
|
127
|
+
console.log(parseString('[1,2,3]')); // [1, 2, 3] (array)
|
|
128
|
+
console.log(parseString('{"name":"John"}')); // {name: "John"} (object)
|
|
129
|
+
console.log(parseString('1e5')); // 100000 (scientific notation)
|
|
130
|
+
console.log(parseString('hello')); // 'hello' (string fallback)
|
|
131
|
+
|
|
132
|
+
// Parse environment variables
|
|
133
|
+
const envs = {
|
|
134
|
+
'API_PORT': '3000',
|
|
135
|
+
'DEBUG_MODE': 'true',
|
|
136
|
+
'ALLOWED_HOSTS': '["localhost", "127.0.0.1"]'
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const parsed = parseEnvVars(envs);
|
|
140
|
+
// Result: { apiPort: 3000, debugMode: true, allowedHosts: ['localhost', '127.0.0.1'] }
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Number Formatting
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
import { formatRelativeNumber } from '@ooneex/utils';
|
|
147
|
+
|
|
148
|
+
// Format numbers with compact notation
|
|
149
|
+
console.log(formatRelativeNumber(1000)); // '1K'
|
|
150
|
+
console.log(formatRelativeNumber(1500)); // '1.5K'
|
|
151
|
+
console.log(formatRelativeNumber(1000000)); // '1M'
|
|
152
|
+
console.log(formatRelativeNumber(2500000)); // '2.5M'
|
|
153
|
+
console.log(formatRelativeNumber(1000000000)); // '1B'
|
|
154
|
+
|
|
155
|
+
// Custom precision
|
|
156
|
+
console.log(formatRelativeNumber(1234, { precision: 2 })); // '1.23K'
|
|
157
|
+
console.log(formatRelativeNumber(1234, { precision: 0 })); // '1K'
|
|
158
|
+
|
|
159
|
+
// Different locales
|
|
160
|
+
console.log(formatRelativeNumber(1500, { lang: 'de-DE' })); // '1500'
|
|
161
|
+
console.log(formatRelativeNumber(1500000, { lang: 'de-DE' })); // '1,5 Mio.'
|
|
162
|
+
console.log(formatRelativeNumber(1500, { lang: 'fr-FR' })); // '1,5 k'
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### File Utilities
|
|
30
166
|
|
|
31
|
-
**Examples:**
|
|
32
167
|
```typescript
|
|
33
168
|
import { dataURLtoFile } from '@ooneex/utils';
|
|
34
169
|
|
|
35
|
-
// Convert
|
|
170
|
+
// Convert data URL to File object
|
|
36
171
|
const dataUrl = 'data:text/plain;base64,SGVsbG8gV29ybGQ=';
|
|
37
172
|
const file = dataURLtoFile(dataUrl, 'hello.txt');
|
|
38
173
|
|
|
39
|
-
//
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
// The resulting File object can be used in FormData or uploaded
|
|
44
|
-
const formData = new FormData();
|
|
45
|
-
formData.append('file', file);
|
|
174
|
+
console.log(file.name); // 'hello.txt'
|
|
175
|
+
console.log(file.type); // 'text/plain'
|
|
176
|
+
console.log(file.size); // 11
|
|
46
177
|
```
|
|
47
178
|
|
|
48
|
-
###
|
|
179
|
+
### Random Generation
|
|
49
180
|
|
|
50
|
-
|
|
181
|
+
```typescript
|
|
182
|
+
import { random } from '@ooneex/utils';
|
|
51
183
|
|
|
52
|
-
|
|
184
|
+
// Generate random hex strings
|
|
185
|
+
console.log(random.nanoid()); // 'a1b2c3d4e5' (10 chars default)
|
|
186
|
+
console.log(random.nanoid(8)); // 'f6e5d4c3' (8 chars)
|
|
53
187
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
188
|
+
// Generate numeric strings
|
|
189
|
+
console.log(random.stringInt()); // '1234567890' (10 digits default)
|
|
190
|
+
console.log(random.stringInt(6)); // '123456' (6 digits)
|
|
57
191
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
192
|
+
// Create a factory function
|
|
193
|
+
const generateId = random.nanoidFactory(12);
|
|
194
|
+
console.log(generateId()); // 12-character hex string
|
|
195
|
+
console.log(generateId(8)); // 8-character hex string (overrides factory size)
|
|
62
196
|
```
|
|
63
197
|
|
|
64
|
-
|
|
198
|
+
## API Reference
|
|
199
|
+
|
|
200
|
+
### String Utilities
|
|
201
|
+
|
|
202
|
+
#### `capitalizeWord(word: string): string`
|
|
203
|
+
Capitalizes the first letter and lowercases the rest.
|
|
65
204
|
|
|
66
|
-
|
|
205
|
+
**Parameters:**
|
|
206
|
+
- `word` - The word to capitalize
|
|
67
207
|
|
|
68
|
-
**
|
|
208
|
+
**Returns:** Capitalized word
|
|
209
|
+
|
|
210
|
+
**Example:**
|
|
69
211
|
```typescript
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
splitToWords('PascalCaseString'); // ['Pascal', 'Case', 'String']
|
|
74
|
-
splitToWords('kebab-case-string'); // ['kebab', 'case', 'string']
|
|
75
|
-
splitToWords('snake_case_string'); // ['snake', 'case', 'string']
|
|
76
|
-
splitToWords('HTMLElement123'); // ['HTML', 'Element', '123']
|
|
77
|
-
splitToWords('URLParser'); // ['URL', 'Parser']
|
|
212
|
+
capitalizeWord('hello'); // 'Hello'
|
|
213
|
+
capitalizeWord('WORLD'); // 'World'
|
|
214
|
+
capitalizeWord(''); // ''
|
|
78
215
|
```
|
|
79
216
|
|
|
80
217
|
#### `toCamelCase(input: string): string`
|
|
218
|
+
Converts string to camelCase.
|
|
81
219
|
|
|
82
|
-
|
|
220
|
+
**Parameters:**
|
|
221
|
+
- `input` - The string to convert
|
|
83
222
|
|
|
84
|
-
**
|
|
85
|
-
```typescript
|
|
86
|
-
import { toCamelCase } from '@ooneex/utils';
|
|
223
|
+
**Returns:** camelCase string
|
|
87
224
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
toCamelCase('
|
|
91
|
-
toCamelCase('
|
|
92
|
-
toCamelCase('
|
|
225
|
+
**Example:**
|
|
226
|
+
```typescript
|
|
227
|
+
toCamelCase('hello world'); // 'helloWorld'
|
|
228
|
+
toCamelCase('Hello-World_Example'); // 'helloWorldExample'
|
|
229
|
+
toCamelCase('API_KEY'); // 'apiKey'
|
|
93
230
|
```
|
|
94
231
|
|
|
95
232
|
#### `toPascalCase(input: string): string`
|
|
233
|
+
Converts string to PascalCase.
|
|
96
234
|
|
|
97
|
-
|
|
235
|
+
**Parameters:**
|
|
236
|
+
- `input` - The string to convert
|
|
98
237
|
|
|
99
|
-
**
|
|
100
|
-
```typescript
|
|
101
|
-
import { toPascalCase } from '@ooneex/utils';
|
|
238
|
+
**Returns:** PascalCase string
|
|
102
239
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
toPascalCase('
|
|
106
|
-
toPascalCase('
|
|
107
|
-
toPascalCase('
|
|
240
|
+
**Example:**
|
|
241
|
+
```typescript
|
|
242
|
+
toPascalCase('hello world'); // 'HelloWorld'
|
|
243
|
+
toPascalCase('api-key'); // 'ApiKey'
|
|
244
|
+
toPascalCase('user_name'); // 'UserName'
|
|
108
245
|
```
|
|
109
246
|
|
|
110
247
|
#### `toKebabCase(input: string): string`
|
|
248
|
+
Converts string to kebab-case.
|
|
111
249
|
|
|
112
|
-
|
|
250
|
+
**Parameters:**
|
|
251
|
+
- `input` - The string to convert
|
|
113
252
|
|
|
114
|
-
**
|
|
253
|
+
**Returns:** kebab-case string
|
|
254
|
+
|
|
255
|
+
**Example:**
|
|
115
256
|
```typescript
|
|
116
|
-
|
|
257
|
+
toKebabCase('Hello World'); // 'hello-world'
|
|
258
|
+
toKebabCase('camelCaseString'); // 'camel-case-string'
|
|
259
|
+
toKebabCase('PascalCaseString'); // 'pascal-case-string'
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
#### `splitToWords(input: string): string[]`
|
|
263
|
+
Splits a string into individual words, handling various naming conventions.
|
|
264
|
+
|
|
265
|
+
**Parameters:**
|
|
266
|
+
- `input` - The string to split
|
|
117
267
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
268
|
+
**Returns:** Array of words
|
|
269
|
+
|
|
270
|
+
**Example:**
|
|
271
|
+
```typescript
|
|
272
|
+
splitToWords('HelloWorld'); // ['Hello', 'World']
|
|
273
|
+
splitToWords('hello-world_example'); // ['hello', 'world', 'example']
|
|
274
|
+
splitToWords('XMLHttpRequest'); // ['XML', 'Http', 'Request']
|
|
275
|
+
splitToWords('user123Name'); // ['user', '123', 'Name']
|
|
123
276
|
```
|
|
124
277
|
|
|
125
278
|
#### `trim(text: string, char?: string): string`
|
|
279
|
+
Trims specified characters from the beginning and end of a string.
|
|
126
280
|
|
|
127
|
-
|
|
281
|
+
**Parameters:**
|
|
282
|
+
- `text` - The string to trim
|
|
283
|
+
- `char` - Characters to trim (default: space). Supports regex patterns.
|
|
128
284
|
|
|
129
|
-
**
|
|
130
|
-
```typescript
|
|
131
|
-
import { trim } from '@ooneex/utils';
|
|
285
|
+
**Returns:** Trimmed string
|
|
132
286
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
trim('
|
|
136
|
-
trim('
|
|
137
|
-
trim('
|
|
287
|
+
**Example:**
|
|
288
|
+
```typescript
|
|
289
|
+
trim(' hello '); // 'hello'
|
|
290
|
+
trim('...hello...', '\\.'); // 'hello'
|
|
291
|
+
trim('[test]', '\\[|\\]'); // 'test'
|
|
292
|
+
trim('!!hello!!', '!'); // 'hello'
|
|
138
293
|
```
|
|
139
294
|
|
|
140
|
-
###
|
|
295
|
+
### Time Utilities
|
|
141
296
|
|
|
142
|
-
#### `
|
|
297
|
+
#### `secondsToHMS(seconds: number): string`
|
|
298
|
+
Converts seconds to HH:MM:SS or MM:SS or SS format.
|
|
143
299
|
|
|
144
|
-
|
|
300
|
+
**Parameters:**
|
|
301
|
+
- `seconds` - Number of seconds
|
|
145
302
|
|
|
146
|
-
**
|
|
303
|
+
**Returns:** Formatted time string
|
|
304
|
+
|
|
305
|
+
**Example:**
|
|
147
306
|
```typescript
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
parseString('true'); // true (boolean)
|
|
153
|
-
parseString('false'); // false (boolean)
|
|
154
|
-
parseString('null'); // null
|
|
155
|
-
parseString('[1, 2, 3]'); // [1, 2, 3] (array)
|
|
156
|
-
parseString('{"key": "value"}'); // { key: "value" } (object)
|
|
157
|
-
parseString('hello'); // 'hello' (string)
|
|
158
|
-
parseString('[apple, banana, 123]'); // ['apple', 'banana', 123]
|
|
307
|
+
secondsToHMS(3661); // '1:01:01' (1 hour, 1 minute, 1 second)
|
|
308
|
+
secondsToHMS(125); // '2:05' (2 minutes, 5 seconds)
|
|
309
|
+
secondsToHMS(45); // '45' (45 seconds)
|
|
310
|
+
secondsToHMS(0); // '0'
|
|
159
311
|
```
|
|
160
312
|
|
|
161
|
-
#### `
|
|
313
|
+
#### `secondsToMS(seconds: number): string`
|
|
314
|
+
Converts seconds to MM:SS format.
|
|
315
|
+
|
|
316
|
+
**Parameters:**
|
|
317
|
+
- `seconds` - Number of seconds
|
|
162
318
|
|
|
163
|
-
|
|
319
|
+
**Returns:** MM:SS formatted string
|
|
164
320
|
|
|
165
|
-
**
|
|
321
|
+
**Example:**
|
|
166
322
|
```typescript
|
|
167
|
-
|
|
323
|
+
secondsToMS(125); // '2:05'
|
|
324
|
+
secondsToMS(45); // '0:45'
|
|
325
|
+
secondsToMS(3661); // '61:01'
|
|
326
|
+
```
|
|
168
327
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
'PORT': '3000',
|
|
172
|
-
'ENABLE_LOGGING': 'true',
|
|
173
|
-
'MAX_CONNECTIONS': '100'
|
|
174
|
-
};
|
|
328
|
+
#### `millisecondsToHMS(ms: number): string`
|
|
329
|
+
Converts milliseconds to HH:MM:SS or MM:SS or SS format.
|
|
175
330
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
331
|
+
**Parameters:**
|
|
332
|
+
- `ms` - Number of milliseconds
|
|
333
|
+
|
|
334
|
+
**Returns:** Formatted time string
|
|
335
|
+
|
|
336
|
+
**Example:**
|
|
337
|
+
```typescript
|
|
338
|
+
millisecondsToHMS(3661000); // '1:01:01'
|
|
339
|
+
millisecondsToHMS(125000); // '2:05'
|
|
340
|
+
millisecondsToHMS(45000); // '45'
|
|
341
|
+
millisecondsToHMS(500); // '0'
|
|
183
342
|
```
|
|
184
343
|
|
|
185
|
-
|
|
344
|
+
#### `sleep(ms: number): Promise<void>`
|
|
345
|
+
Creates a promise that resolves after the specified number of milliseconds.
|
|
186
346
|
|
|
187
|
-
|
|
347
|
+
**Parameters:**
|
|
348
|
+
- `ms` - Number of milliseconds to wait
|
|
188
349
|
|
|
189
|
-
|
|
350
|
+
**Returns:** Promise that resolves after the delay
|
|
190
351
|
|
|
191
|
-
**
|
|
352
|
+
**Example:**
|
|
192
353
|
```typescript
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
354
|
+
await sleep(1000); // Wait 1 second
|
|
355
|
+
await sleep(500); // Wait 0.5 seconds
|
|
356
|
+
|
|
357
|
+
// Usage in async function
|
|
358
|
+
async function delayedLog() {
|
|
359
|
+
console.log('First');
|
|
360
|
+
await sleep(2000);
|
|
361
|
+
console.log('Second (2 seconds later)');
|
|
362
|
+
}
|
|
202
363
|
```
|
|
203
364
|
|
|
204
|
-
###
|
|
365
|
+
### Data Parsing
|
|
205
366
|
|
|
206
|
-
#### `
|
|
367
|
+
#### `parseString<T>(text: string): T`
|
|
368
|
+
Intelligently parses a string and returns the appropriate type.
|
|
369
|
+
|
|
370
|
+
**Parameters:**
|
|
371
|
+
- `text` - The string to parse
|
|
207
372
|
|
|
208
|
-
|
|
373
|
+
**Returns:** Parsed value with inferred type
|
|
209
374
|
|
|
210
|
-
**
|
|
375
|
+
**Supported Formats:**
|
|
376
|
+
- Integers: `"123"` → `123`
|
|
377
|
+
- Floats: `"12.34"` → `12.34`
|
|
378
|
+
- Scientific notation: `"1e5"` → `100000`
|
|
379
|
+
- Booleans: `"true"`, `"false"` (case insensitive)
|
|
380
|
+
- Null: `"null"` (case insensitive)
|
|
381
|
+
- Arrays: `"[1,2,3]"` → `[1, 2, 3]`
|
|
382
|
+
- Objects: `'{"key":"value"}'` → `{key: "value"}`
|
|
383
|
+
- JSON strings: `'"hello"'` → `"hello"`
|
|
384
|
+
|
|
385
|
+
**Example:**
|
|
211
386
|
```typescript
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
387
|
+
parseString('123'); // 123 (number)
|
|
388
|
+
parseString('12.34'); // 12.34 (number)
|
|
389
|
+
parseString('1e3'); // 1000 (number)
|
|
390
|
+
parseString('true'); // true (boolean)
|
|
391
|
+
parseString('null'); // null
|
|
392
|
+
parseString('[1,2,3]'); // [1, 2, 3] (array)
|
|
393
|
+
parseString('{"name":"John"}'); // {name: "John"} (object)
|
|
394
|
+
parseString('hello'); // 'hello' (string fallback)
|
|
395
|
+
|
|
396
|
+
// With type annotation
|
|
397
|
+
const num = parseString<number>('123'); // TypeScript knows it's a number
|
|
398
|
+
const arr = parseString<number[]>('[1,2,3]'); // TypeScript knows it's number[]
|
|
220
399
|
```
|
|
221
400
|
|
|
222
|
-
#### `
|
|
401
|
+
#### `parseEnvVars<T>(envs: Record<string, string>): T`
|
|
402
|
+
Parses environment variables, converting keys to camelCase and values using `parseString`.
|
|
223
403
|
|
|
224
|
-
|
|
404
|
+
**Parameters:**
|
|
405
|
+
- `envs` - Object with environment variable key-value pairs
|
|
225
406
|
|
|
226
|
-
**
|
|
407
|
+
**Returns:** Object with camelCase keys and parsed values
|
|
408
|
+
|
|
409
|
+
**Example:**
|
|
227
410
|
```typescript
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
411
|
+
const envVars = {
|
|
412
|
+
'API_PORT': '3000',
|
|
413
|
+
'DEBUG_MODE': 'true',
|
|
414
|
+
'ALLOWED_HOSTS': '["localhost", "127.0.0.1"]',
|
|
415
|
+
'MAX_CONNECTIONS': '100',
|
|
416
|
+
'ENABLE_SSL': 'false'
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
const config = parseEnvVars(envVars);
|
|
420
|
+
// Result:
|
|
421
|
+
// {
|
|
422
|
+
// apiPort: 3000,
|
|
423
|
+
// debugMode: true,
|
|
424
|
+
// allowedHosts: ['localhost', '127.0.0.1'],
|
|
425
|
+
// maxConnections: 100,
|
|
426
|
+
// enableSsl: false
|
|
427
|
+
// }
|
|
428
|
+
|
|
429
|
+
// With type annotation
|
|
430
|
+
interface Config {
|
|
431
|
+
apiPort: number;
|
|
432
|
+
debugMode: boolean;
|
|
433
|
+
allowedHosts: string[];
|
|
434
|
+
}
|
|
435
|
+
const typedConfig = parseEnvVars<Config>(envVars);
|
|
236
436
|
```
|
|
237
437
|
|
|
238
|
-
|
|
438
|
+
### Number Utilities
|
|
239
439
|
|
|
240
|
-
|
|
440
|
+
#### `formatRelativeNumber(num: number, config?: { precision?: number; lang?: string }): string`
|
|
441
|
+
Formats numbers using compact notation with locale support.
|
|
442
|
+
|
|
443
|
+
**Parameters:**
|
|
444
|
+
- `num` - The number to format
|
|
445
|
+
- `config.precision` - Maximum decimal places (default: 1)
|
|
446
|
+
- `config.lang` - Locale code (default: 'en-GB')
|
|
447
|
+
|
|
448
|
+
**Returns:** Formatted number string
|
|
241
449
|
|
|
242
|
-
**
|
|
450
|
+
**Example:**
|
|
243
451
|
```typescript
|
|
244
|
-
|
|
452
|
+
formatRelativeNumber(1000); // '1K'
|
|
453
|
+
formatRelativeNumber(1500); // '1.5K'
|
|
454
|
+
formatRelativeNumber(1000000); // '1M'
|
|
455
|
+
formatRelativeNumber(1000000000); // '1B'
|
|
456
|
+
|
|
457
|
+
// Custom precision
|
|
458
|
+
formatRelativeNumber(1234, { precision: 2 }); // '1.23K'
|
|
459
|
+
formatRelativeNumber(1234, { precision: 0 }); // '1K'
|
|
460
|
+
|
|
461
|
+
// Different locales
|
|
462
|
+
formatRelativeNumber(1500, { lang: 'de-DE' }); // '1500'
|
|
463
|
+
formatRelativeNumber(1500000, { lang: 'de-DE' }); // '1,5 Mio.'
|
|
464
|
+
formatRelativeNumber(1500, { lang: 'fr-FR' }); // '1,5 k'
|
|
465
|
+
formatRelativeNumber(1500, { lang: 'es-ES' }); // '1,5 mil'
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
### File Utilities
|
|
469
|
+
|
|
470
|
+
#### `dataURLtoFile(dataurl: string, filename: string): File`
|
|
471
|
+
Converts a data URL to a File object.
|
|
472
|
+
|
|
473
|
+
**Parameters:**
|
|
474
|
+
- `dataurl` - The data URL string
|
|
475
|
+
- `filename` - The desired filename for the File object
|
|
245
476
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
477
|
+
**Returns:** File object
|
|
478
|
+
|
|
479
|
+
**Example:**
|
|
480
|
+
```typescript
|
|
481
|
+
// Text file
|
|
482
|
+
const textDataUrl = 'data:text/plain;base64,SGVsbG8gV29ybGQ=';
|
|
483
|
+
const textFile = dataURLtoFile(textDataUrl, 'hello.txt');
|
|
484
|
+
console.log(textFile.name); // 'hello.txt'
|
|
485
|
+
console.log(textFile.type); // 'text/plain'
|
|
486
|
+
console.log(textFile.size); // 11
|
|
487
|
+
|
|
488
|
+
// Image file
|
|
489
|
+
const imgDataUrl = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==';
|
|
490
|
+
const imgFile = dataURLtoFile(imgDataUrl, 'pixel.png');
|
|
491
|
+
console.log(imgFile.type); // 'image/png'
|
|
492
|
+
|
|
493
|
+
// Usage with FileReader
|
|
494
|
+
const reader = new FileReader();
|
|
495
|
+
reader.onload = (e) => console.log(e.target?.result);
|
|
496
|
+
reader.readAsText(textFile);
|
|
250
497
|
```
|
|
251
498
|
|
|
252
499
|
### Random Generation
|
|
253
500
|
|
|
254
|
-
#### `random`
|
|
501
|
+
#### `random.nanoid(size?: number): string`
|
|
502
|
+
Generates a random hexadecimal string.
|
|
503
|
+
|
|
504
|
+
**Parameters:**
|
|
505
|
+
- `size` - Length of the generated string (default: 10)
|
|
255
506
|
|
|
256
|
-
|
|
507
|
+
**Returns:** Random hex string
|
|
257
508
|
|
|
258
|
-
**
|
|
509
|
+
**Example:**
|
|
259
510
|
```typescript
|
|
260
|
-
|
|
511
|
+
random.nanoid(); // 'a1b2c3d4e5' (10 characters)
|
|
512
|
+
random.nanoid(8); // 'f6e5d4c3' (8 characters)
|
|
513
|
+
random.nanoid(16); // '1a2b3c4d5e6f7890' (16 characters)
|
|
514
|
+
```
|
|
261
515
|
|
|
262
|
-
|
|
263
|
-
random.
|
|
264
|
-
random.nanoid(5); // '1a2b3'
|
|
265
|
-
random.nanoid(16); // '1234567890abcdef'
|
|
516
|
+
#### `random.stringInt(size?: number): string`
|
|
517
|
+
Generates a random numeric string.
|
|
266
518
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
random.stringInt(5); // '12345'
|
|
519
|
+
**Parameters:**
|
|
520
|
+
- `size` - Length of the generated string (default: 10)
|
|
270
521
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
522
|
+
**Returns:** Random numeric string
|
|
523
|
+
|
|
524
|
+
**Example:**
|
|
525
|
+
```typescript
|
|
526
|
+
random.stringInt(); // '1234567890' (10 digits)
|
|
527
|
+
random.stringInt(6); // '123456' (6 digits)
|
|
528
|
+
random.stringInt(4); // '9876' (4 digits)
|
|
275
529
|
```
|
|
276
530
|
|
|
277
|
-
|
|
531
|
+
#### `random.nanoidFactory(size?: number): (size?: number) => string`
|
|
532
|
+
Creates a factory function for generating random hex strings.
|
|
278
533
|
|
|
279
|
-
|
|
534
|
+
**Parameters:**
|
|
535
|
+
- `size` - Default length for the factory (default: 10)
|
|
280
536
|
|
|
281
|
-
|
|
537
|
+
**Returns:** Factory function that accepts optional size parameter
|
|
282
538
|
|
|
283
|
-
**
|
|
539
|
+
**Example:**
|
|
284
540
|
```typescript
|
|
285
|
-
|
|
541
|
+
const generateId = random.nanoidFactory(12);
|
|
542
|
+
generateId(); // 12-character hex string
|
|
543
|
+
generateId(8); // 8-character hex string (overrides factory default)
|
|
544
|
+
generateId(16); // 16-character hex string
|
|
286
545
|
|
|
287
|
-
|
|
288
|
-
|
|
546
|
+
const generateShortId = random.nanoidFactory(6);
|
|
547
|
+
generateShortId(); // 6-character hex string
|
|
548
|
+
```
|
|
289
549
|
|
|
290
|
-
|
|
291
|
-
async function delayedOperation() {
|
|
292
|
-
console.log('Starting...');
|
|
293
|
-
await sleep(2000); // Wait 2 seconds
|
|
294
|
-
console.log('Done!');
|
|
295
|
-
}
|
|
550
|
+
## Advanced Usage
|
|
296
551
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
552
|
+
### Environment Configuration
|
|
553
|
+
|
|
554
|
+
```typescript
|
|
555
|
+
import { parseEnvVars } from '@ooneex/utils';
|
|
556
|
+
|
|
557
|
+
// Define your configuration interface
|
|
558
|
+
interface AppConfig {
|
|
559
|
+
port: number;
|
|
560
|
+
host: string;
|
|
561
|
+
debug: boolean;
|
|
562
|
+
features: string[];
|
|
563
|
+
dbConfig: {
|
|
564
|
+
host: string;
|
|
565
|
+
port: number;
|
|
566
|
+
};
|
|
307
567
|
}
|
|
568
|
+
|
|
569
|
+
// Parse environment variables
|
|
570
|
+
const envConfig = parseEnvVars<Partial<AppConfig>>(process.env);
|
|
571
|
+
|
|
572
|
+
// Merge with defaults
|
|
573
|
+
const config: AppConfig = {
|
|
574
|
+
port: 3000,
|
|
575
|
+
host: 'localhost',
|
|
576
|
+
debug: false,
|
|
577
|
+
features: [],
|
|
578
|
+
dbConfig: { host: 'localhost', port: 5432 },
|
|
579
|
+
...envConfig
|
|
580
|
+
};
|
|
308
581
|
```
|
|
309
582
|
|
|
310
|
-
|
|
583
|
+
### String Processing Pipeline
|
|
311
584
|
|
|
312
|
-
|
|
585
|
+
```typescript
|
|
586
|
+
import { splitToWords, toCamelCase, capitalizeWord } from '@ooneex/utils';
|
|
587
|
+
|
|
588
|
+
function processUserInput(input: string): {
|
|
589
|
+
words: string[];
|
|
590
|
+
camelCase: string;
|
|
591
|
+
title: string;
|
|
592
|
+
kebabCase: string;
|
|
593
|
+
} {
|
|
594
|
+
const words = splitToWords(input);
|
|
595
|
+
|
|
596
|
+
return {
|
|
597
|
+
words,
|
|
598
|
+
camelCase: toCamelCase(input),
|
|
599
|
+
title: words.map(capitalizeWord).join(' '),
|
|
600
|
+
kebabCase: toKebabCase(input)
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
const result = processUserInput('user-profile_settings');
|
|
605
|
+
// {
|
|
606
|
+
// words: ['user', 'profile', 'settings'],
|
|
607
|
+
// camelCase: 'userProfileSettings',
|
|
608
|
+
// title: 'User Profile Settings',
|
|
609
|
+
// kebabCase: 'user-profile-settings'
|
|
610
|
+
// }
|
|
611
|
+
```
|
|
612
|
+
|
|
613
|
+
### Time-based Progress Tracking
|
|
313
614
|
|
|
314
615
|
```typescript
|
|
315
|
-
|
|
316
|
-
const parsedNumber = parseString<number>('123'); // Type: number
|
|
317
|
-
const parsedArray = parseString<string[]>('[a,b,c]'); // Type: string[]
|
|
616
|
+
import { millisecondsToHMS, formatRelativeNumber } from '@ooneex/utils';
|
|
318
617
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
618
|
+
class ProgressTracker {
|
|
619
|
+
private startTime: number;
|
|
620
|
+
private itemsProcessed: number = 0;
|
|
621
|
+
private totalItems: number;
|
|
622
|
+
|
|
623
|
+
constructor(totalItems: number) {
|
|
624
|
+
this.startTime = Date.now();
|
|
625
|
+
this.totalItems = totalItems;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
update(processed: number): string {
|
|
629
|
+
this.itemsProcessed = processed;
|
|
630
|
+
const elapsed = Date.now() - this.startTime;
|
|
631
|
+
const rate = processed / (elapsed / 1000);
|
|
632
|
+
const remaining = (this.totalItems - processed) / rate * 1000;
|
|
633
|
+
|
|
634
|
+
return [
|
|
635
|
+
`Processed: ${formatRelativeNumber(processed)}/${formatRelativeNumber(this.totalItems)}`,
|
|
636
|
+
`Elapsed: ${millisecondsToHMS(elapsed)}`,
|
|
637
|
+
`ETA: ${millisecondsToHMS(remaining)}`
|
|
638
|
+
].join(' | ');
|
|
639
|
+
}
|
|
324
640
|
}
|
|
325
641
|
|
|
326
|
-
const
|
|
642
|
+
const tracker = new ProgressTracker(100000);
|
|
643
|
+
console.log(tracker.update(15000));
|
|
644
|
+
// "Processed: 15K/100K | Elapsed: 2:30 | ETA: 14:10"
|
|
327
645
|
```
|
|
328
646
|
|
|
329
647
|
## License
|
|
330
648
|
|
|
331
|
-
MIT
|
|
649
|
+
This project is licensed under the MIT License - see the [LICENSE](./LICENSE) file for details.
|
|
332
650
|
|
|
333
651
|
## Contributing
|
|
334
652
|
|
|
335
|
-
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
653
|
+
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
|
|
654
|
+
|
|
655
|
+
### Development Setup
|
|
656
|
+
|
|
657
|
+
1. Clone the repository
|
|
658
|
+
2. Install dependencies: `bun install`
|
|
659
|
+
3. Run tests: `bun run test`
|
|
660
|
+
4. Build the project: `bun run build`
|
|
661
|
+
|
|
662
|
+
### Guidelines
|
|
663
|
+
|
|
664
|
+
- Write tests for new features
|
|
665
|
+
- Follow the existing code style
|
|
666
|
+
- Update documentation for API changes
|
|
667
|
+
- Ensure all tests pass before submitting PR
|
|
668
|
+
|
|
669
|
+
---
|
|
670
|
+
|
|
671
|
+
Made with ❤️ by the Ooneex team
|
package/dist/index.d.ts
CHANGED
|
@@ -1,69 +1,23 @@
|
|
|
1
|
-
declare
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
}
|
|
7
|
-
declare
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
declare
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
declare
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
declare
|
|
23
|
-
|
|
24
|
-
}
|
|
25
|
-
declare module "toCamelCase" {
|
|
26
|
-
export const toCamelCase: (input: string) => string;
|
|
27
|
-
}
|
|
28
|
-
declare module "parseEnvVars" {
|
|
29
|
-
export const parseEnvVars: <T = Record<string, unknown>>(envs: Record<string, unknown>) => T;
|
|
30
|
-
}
|
|
31
|
-
declare module "random" {
|
|
32
|
-
export const random: {
|
|
33
|
-
nanoid(size?: number): string;
|
|
34
|
-
stringInt(size?: number): string;
|
|
35
|
-
nanoidFactory(size?: number): (size?: number) => string;
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
declare module "secondsToHMS" {
|
|
39
|
-
export const secondsToHMS: (seconds: number) => string;
|
|
40
|
-
}
|
|
41
|
-
declare module "secondsToMS" {
|
|
42
|
-
export const secondsToMS: (seconds: number) => string;
|
|
43
|
-
}
|
|
44
|
-
declare module "sleep" {
|
|
45
|
-
export const sleep: (ms: number) => Promise<void>;
|
|
46
|
-
}
|
|
47
|
-
declare module "toKebabCase" {
|
|
48
|
-
export const toKebabCase: (input: string) => string;
|
|
49
|
-
}
|
|
50
|
-
declare module "toPascalCase" {
|
|
51
|
-
export const toPascalCase: (input: string) => string;
|
|
52
|
-
}
|
|
53
|
-
declare module "index" {
|
|
54
|
-
export { capitalizeWord } from "capitalizeWord";
|
|
55
|
-
export { dataURLtoFile } from "dataURLtoFile";
|
|
56
|
-
export { formatRelativeNumber } from "formatRelativeNumber";
|
|
57
|
-
export { millisecondsToHMS } from "millisecondsToHMS";
|
|
58
|
-
export { parseEnvVars } from "parseEnvVars";
|
|
59
|
-
export { parseString } from "parseString";
|
|
60
|
-
export { random } from "random";
|
|
61
|
-
export { secondsToHMS } from "secondsToHMS";
|
|
62
|
-
export { secondsToMS } from "secondsToMS";
|
|
63
|
-
export { sleep } from "sleep";
|
|
64
|
-
export { splitToWords } from "splitToWords";
|
|
65
|
-
export { toCamelCase } from "toCamelCase";
|
|
66
|
-
export { toKebabCase } from "toKebabCase";
|
|
67
|
-
export { toPascalCase } from "toPascalCase";
|
|
68
|
-
export { trim } from "trim";
|
|
69
|
-
}
|
|
1
|
+
declare const capitalizeWord: (word: string) => string;
|
|
2
|
+
declare const dataURLtoFile: (dataurl: string, filename: string) => File;
|
|
3
|
+
declare const formatRelativeNumber: (num: number, config?: {
|
|
4
|
+
precision?: number;
|
|
5
|
+
lang?: string;
|
|
6
|
+
}) => string;
|
|
7
|
+
declare const millisecondsToHMS: (ms: number) => string;
|
|
8
|
+
declare const parseEnvVars: <T = Record<string, string>>(envs: Record<string, string>) => T;
|
|
9
|
+
declare const parseString: <T = unknown>(text: string) => T;
|
|
10
|
+
declare const random: {
|
|
11
|
+
nanoid(size?: number): string;
|
|
12
|
+
stringInt(size?: number): string;
|
|
13
|
+
nanoidFactory(size?: number): (size?: number) => string;
|
|
14
|
+
};
|
|
15
|
+
declare const secondsToHMS: (seconds: number) => string;
|
|
16
|
+
declare const secondsToMS: (seconds: number) => string;
|
|
17
|
+
declare const sleep: (ms: number) => Promise<void>;
|
|
18
|
+
declare const splitToWords: (input: string) => string[];
|
|
19
|
+
declare const toCamelCase: (input: string) => string;
|
|
20
|
+
declare const toKebabCase: (input: string) => string;
|
|
21
|
+
declare const toPascalCase: (input: string) => string;
|
|
22
|
+
declare const trim: (text: string, char?: string) => string;
|
|
23
|
+
export { trim, toPascalCase, toKebabCase, toCamelCase, splitToWords, sleep, secondsToMS, secondsToHMS, random, parseString, parseEnvVars, millisecondsToHMS, formatRelativeNumber, dataURLtoFile, capitalizeWord };
|
package/dist/index.js
CHANGED
|
@@ -1 +1,3 @@
|
|
|
1
|
-
var i=(r)=>
|
|
1
|
+
var i=(r)=>r?r[0]?.toUpperCase()+r.slice(1).toLowerCase():r;var u=(r,t)=>{let o=r.split(","),s=o[0]?.match(/:(.*?);/)?.[1]||"",f=atob(o[1]),a=f.length,g=new Uint8Array(a);while(a--)g[a]=f.charCodeAt(a);return new File([g],t,{type:s})};var d=(r,t)=>new Intl.NumberFormat(t?.lang??"en-GB",{notation:"compact",compactDisplay:"short",maximumFractionDigits:t?.precision??1}).format(r);var S=(r)=>{let t=Math.floor(r/1000),o=Math.floor(t/3600),e=Math.floor(t%3600/60),s=t%60;if(o>0)return`${o}:${e.toString().padStart(2,"0")}:${s.toString().padStart(2,"0")}`;if(e>0)return`${e}:${s.toString().padStart(2,"0")}`;return s.toString()};var p=(r,t=" ")=>{if([".","[","]","(",")","+","*","^","$","?","/","\\"].includes(t))t=`\\${t}`;let o=new RegExp(`^${t}+|${t}+$`,"g");return r.replace(o,"")};var m=(r)=>{if(/^[0-9]+$/.test(r))return Number.parseInt(r,10);if(/^[0-9]+[.][0-9]+$/.test(r))return Number.parseFloat(r);if(/^true$/i.test(r))return!0;if(/^false$/i.test(r))return!1;if(/^null$/i.test(r))return null;if(/^\[/.test(r)&&/]$/.test(r)){let o=p(r,"\\[|\\]").split(/, */);return o=o.map((e)=>m(e)),o}try{let t=JSON.parse(r);if(t===Number.POSITIVE_INFINITY||t===Number.NEGATIVE_INFINITY)return r;return t}catch{return r}};var b=/\p{Lu}\p{Ll}+/u,T=/\p{Lu}+(?=(\p{Lu}\p{Ll})|\P{L}|\b)/u,$=/(\p{Ll}+)/u,x=/\p{L}+/u,M=/\p{N}+/u,h=new RegExp(`${b.source}|${T.source}|${$.source}|${x.source}|${M.source}`,"gu"),n=(r)=>r.match(h)??[];var c=(r)=>{r=r.trim();let[t="",...o]=n(r);return[t.toLowerCase(),...o.map(i)].join("")};var C=(r)=>{let t={};for(let o in r){let e=c(o),s=m(r[o]);t[e]=s}return t};import{customAlphabet as l}from"nanoid";var F={nanoid(r){return l("1234567890abcdef",r??10)()},stringInt(r){return l("1234567890",r??10)()},nanoidFactory(r){return l("1234567890abcdef",r??10)}};var N=(r)=>{let t=Math.floor(r),o=Math.floor(t/3600),e=Math.floor(t%3600/60),s=t%60;if(o>0)return`${o}:${e.toString().padStart(2,"0")}:${s.toString().padStart(2,"0")}`;if(e>0)return`${e}:${s.toString().padStart(2,"0")}`;return s.toString()};var I=(r)=>{let t=Math.floor(r/60),o=r%60;return`${t}:${o.toString().padStart(2,"0")}`};var v=(r)=>new Promise((t)=>setTimeout(t,r));var w=(r)=>{return r=r.trim(),n(r).join("-").toLowerCase()};var y=(r)=>{return r=r.trim(),n(r).map(i).join("")};export{p as trim,y as toPascalCase,w as toKebabCase,c as toCamelCase,n as splitToWords,v as sleep,I as secondsToMS,N as secondsToHMS,F as random,m as parseString,C as parseEnvVars,S as millisecondsToHMS,d as formatRelativeNumber,u as dataURLtoFile,i as capitalizeWord};
|
|
2
|
+
|
|
3
|
+
//# debugId=D3540DB7AD21EC7364756E2164756E21
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["src/capitalizeWord.ts", "src/dataURLtoFile.ts", "src/formatRelativeNumber.ts", "src/millisecondsToHMS.ts", "src/trim.ts", "src/parseString.ts", "src/splitToWords.ts", "src/toCamelCase.ts", "src/parseEnvVars.ts", "src/random.ts", "src/secondsToHMS.ts", "src/secondsToMS.ts", "src/sleep.ts", "src/toKebabCase.ts", "src/toPascalCase.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"export const capitalizeWord = (word: string): string =>\n word ? word[0]?.toUpperCase() + word.slice(1).toLowerCase() : word;\n",
|
|
6
|
+
"export const dataURLtoFile = (dataurl: string, filename: string): File => {\n const arr = dataurl.split(\",\");\n const mimeMatch = arr[0]?.match(/:(.*?);/);\n const mime = mimeMatch?.[1] || \"\";\n const bstr = atob(arr[1] as string);\n let n = bstr.length;\n const u8arr = new Uint8Array(n);\n while (n--) {\n u8arr[n] = bstr.charCodeAt(n);\n }\n return new File([u8arr], filename, { type: mime });\n};\n",
|
|
7
|
+
"export const formatRelativeNumber = (num: number, config?: { precision?: number; lang?: string }): string =>\n new Intl.NumberFormat(config?.lang ?? \"en-GB\", {\n notation: \"compact\",\n compactDisplay: \"short\",\n maximumFractionDigits: config?.precision ?? 1,\n }).format(num);\n",
|
|
8
|
+
"export const millisecondsToHMS = (ms: number): string => {\n const totalSeconds = Math.floor(ms / 1000);\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n\n if (hours > 0) {\n return `${hours}:${minutes.toString().padStart(2, \"0\")}:${seconds.toString().padStart(2, \"0\")}`;\n }\n\n if (minutes > 0) {\n return `${minutes}:${seconds.toString().padStart(2, \"0\")}`;\n }\n\n return seconds.toString();\n};\n",
|
|
9
|
+
"export const trim = (text: string, char = \" \"): string => {\n if ([\".\", \"[\", \"]\", \"(\", \")\", \"+\", \"*\", \"^\", \"$\", \"?\", \"/\", \"\\\\\"].includes(char)) {\n char = `\\\\${char}`;\n }\n\n const reg = new RegExp(`^${char}+|${char}+$`, \"g\");\n return text.replace(reg, \"\");\n};\n",
|
|
10
|
+
"import { trim } from \"./trim\";\n\nexport const parseString = <T = unknown>(text: string): T => {\n if (/^[0-9]+$/.test(text)) {\n return Number.parseInt(text, 10) as T;\n }\n\n if (/^[0-9]+[.][0-9]+$/.test(text)) {\n return Number.parseFloat(text) as T;\n }\n\n if (/^true$/i.test(text)) {\n return true as T;\n }\n\n if (/^false$/i.test(text)) {\n return false as T;\n }\n\n if (/^null$/i.test(text)) {\n return null as T;\n }\n\n if (/^\\[/.test(text) && /]$/.test(text)) {\n const trimmedText = trim(text, \"\\\\[|\\\\]\");\n\n let values: unknown[] = trimmedText.split(/, */);\n\n values = values.map((value) => parseString(value as string));\n\n return values as T;\n }\n\n try {\n const result = JSON.parse(text);\n\n if (result === Number.POSITIVE_INFINITY || result === Number.NEGATIVE_INFINITY) {\n return text as T;\n }\n\n return result;\n } catch {\n return text as T;\n }\n};\n",
|
|
11
|
+
"const CAPITALIZED_WORD_REGEXP = /\\p{Lu}\\p{Ll}+/u; // e.g. Apple\nconst ACRONYM_REGEXP = /\\p{Lu}+(?=(\\p{Lu}\\p{Ll})|\\P{L}|\\b)/u; // e.g. ID, URL, handles an acronym followed by a capitalized word e.g. HTMLElement\nconst LOWERCASED_WORD_REGEXP = /(\\p{Ll}+)/u; // e.g. apple\nconst ANY_LETTERS = /\\p{L}+/u; // will match any sequence of letters, including in languages without a concept of upper/lower case\nconst DIGITS_REGEXP = /\\p{N}+/u; // e.g. 123\n\nconst WORD_OR_NUMBER_REGEXP = new RegExp(\n `${CAPITALIZED_WORD_REGEXP.source}|${ACRONYM_REGEXP.source}|${LOWERCASED_WORD_REGEXP.source}|${ANY_LETTERS.source}|${DIGITS_REGEXP.source}`,\n \"gu\",\n);\n\nexport const splitToWords = (input: string): string[] => input.match(WORD_OR_NUMBER_REGEXP) ?? [];\n",
|
|
12
|
+
"import { capitalizeWord } from \"./capitalizeWord\";\nimport { splitToWords } from \"./splitToWords\";\n\nexport const toCamelCase = (input: string): string => {\n input = input.trim();\n const [first = \"\", ...rest] = splitToWords(input);\n return [first.toLowerCase(), ...rest.map(capitalizeWord)].join(\"\");\n};\n",
|
|
13
|
+
"import { parseString } from \"./parseString\";\nimport { toCamelCase } from \"./toCamelCase\";\n\nexport const parseEnvVars = <T = Record<string, string>>(envs: Record<string, string>): T => {\n const vars: Record<string, string> = {};\n\n for (const key in envs) {\n const k = toCamelCase(key);\n const value = parseString(envs[key] as string) as string;\n vars[k] = value;\n }\n\n return vars as T;\n};\n",
|
|
14
|
+
"import { customAlphabet } from \"nanoid\";\n\nexport const random = {\n nanoid(size?: number): string {\n return customAlphabet(\"1234567890abcdef\", size ?? 10)();\n },\n stringInt(size?: number): string {\n return customAlphabet(\"1234567890\", size ?? 10)();\n },\n nanoidFactory(size?: number): (size?: number) => string {\n return customAlphabet(\"1234567890abcdef\", size ?? 10);\n },\n};\n",
|
|
15
|
+
"export const secondsToHMS = (seconds: number): string => {\n const totalSeconds = Math.floor(seconds);\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const remainingSeconds = totalSeconds % 60;\n\n if (hours > 0) {\n return `${hours}:${minutes.toString().padStart(2, \"0\")}:${remainingSeconds.toString().padStart(2, \"0\")}`;\n }\n\n if (minutes > 0) {\n return `${minutes}:${remainingSeconds.toString().padStart(2, \"0\")}`;\n }\n\n return remainingSeconds.toString();\n};\n",
|
|
16
|
+
"export const secondsToMS = (seconds: number): string => {\n const minutes = Math.floor(seconds / 60);\n const remainingSeconds = seconds % 60;\n return `${minutes}:${remainingSeconds.toString().padStart(2, \"0\")}`;\n};\n",
|
|
17
|
+
"export const sleep = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n",
|
|
18
|
+
"import { splitToWords } from \"./splitToWords\";\n\nexport const toKebabCase = (input: string): string => {\n input = input.trim();\n return splitToWords(input).join(\"-\").toLowerCase();\n};\n",
|
|
19
|
+
"import { capitalizeWord } from \"./capitalizeWord\";\nimport { splitToWords } from \"./splitToWords\";\n\nexport const toPascalCase = (input: string): string => {\n input = input.trim();\n return splitToWords(input).map(capitalizeWord).join(\"\");\n};\n"
|
|
20
|
+
],
|
|
21
|
+
"mappings": "AAAO,IAAM,EAAiB,CAAC,IAC7B,EAAO,EAAK,IAAI,YAAY,EAAI,EAAK,MAAM,CAAC,EAAE,YAAY,EAAI,ECDzD,IAAM,EAAgB,CAAC,EAAiB,IAA2B,CACxE,IAAM,EAAM,EAAQ,MAAM,GAAG,EAEvB,EADY,EAAI,IAAI,MAAM,SAAS,IAChB,IAAM,GACzB,EAAO,KAAK,EAAI,EAAY,EAC9B,EAAI,EAAK,OACP,EAAQ,IAAI,WAAW,CAAC,EAC9B,MAAO,IACL,EAAM,GAAK,EAAK,WAAW,CAAC,EAE9B,OAAO,IAAI,KAAK,CAAC,CAAK,EAAG,EAAU,CAAE,KAAM,CAAK,CAAC,GCV5C,IAAM,EAAuB,CAAC,EAAa,IAChD,IAAI,KAAK,aAAa,GAAQ,MAAQ,QAAS,CAC7C,SAAU,UACV,eAAgB,QAChB,sBAAuB,GAAQ,WAAa,CAC9C,CAAC,EAAE,OAAO,CAAG,ECLR,IAAM,EAAoB,CAAC,IAAuB,CACvD,IAAM,EAAe,KAAK,MAAM,EAAK,IAAI,EACnC,EAAQ,KAAK,MAAM,EAAe,IAAI,EACtC,EAAU,KAAK,MAAO,EAAe,KAAQ,EAAE,EAC/C,EAAU,EAAe,GAE/B,GAAI,EAAQ,EACV,MAAO,GAAG,KAAS,EAAQ,SAAS,EAAE,SAAS,EAAG,GAAG,KAAK,EAAQ,SAAS,EAAE,SAAS,EAAG,GAAG,IAG9F,GAAI,EAAU,EACZ,MAAO,GAAG,KAAW,EAAQ,SAAS,EAAE,SAAS,EAAG,GAAG,IAGzD,OAAO,EAAQ,SAAS,GCdnB,IAAM,EAAO,CAAC,EAAc,EAAO,MAAgB,CACxD,GAAI,CAAC,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAI,EAAE,SAAS,CAAI,EAC7E,EAAO,KAAK,IAGd,IAAM,EAAM,IAAI,OAAO,IAAI,MAAS,MAAU,GAAG,EACjD,OAAO,EAAK,QAAQ,EAAK,EAAE,GCJtB,IAAM,EAAc,CAAc,IAAoB,CAC3D,GAAI,WAAW,KAAK,CAAI,EACtB,OAAO,OAAO,SAAS,EAAM,EAAE,EAGjC,GAAI,oBAAoB,KAAK,CAAI,EAC/B,OAAO,OAAO,WAAW,CAAI,EAG/B,GAAI,UAAU,KAAK,CAAI,EACrB,MAAO,GAGT,GAAI,WAAW,KAAK,CAAI,EACtB,MAAO,GAGT,GAAI,UAAU,KAAK,CAAI,EACrB,OAAO,KAGT,GAAI,MAAM,KAAK,CAAI,GAAK,KAAK,KAAK,CAAI,EAAG,CAGvC,IAAI,EAFgB,EAAK,EAAM,SAAS,EAEJ,MAAM,KAAK,EAI/C,OAFA,EAAS,EAAO,IAAI,CAAC,IAAU,EAAY,CAAe,CAAC,EAEpD,EAGT,GAAI,CACF,IAAM,EAAS,KAAK,MAAM,CAAI,EAE9B,GAAI,IAAW,OAAO,mBAAqB,IAAW,OAAO,kBAC3D,OAAO,EAGT,OAAO,EACP,KAAM,CACN,OAAO,IC1CX,IAAM,EAA0B,iBAC1B,EAAiB,sCACjB,EAAyB,aACzB,EAAc,UACd,EAAgB,UAEhB,EAAwB,IAAI,OAChC,GAAG,EAAwB,UAAU,EAAe,UAAU,EAAuB,UAAU,EAAY,UAAU,EAAc,SACnI,IACF,EAEa,EAAe,CAAC,IAA4B,EAAM,MAAM,CAAqB,GAAK,CAAC,ECRzF,IAAM,EAAc,CAAC,IAA0B,CACpD,EAAQ,EAAM,KAAK,EACnB,IAAO,EAAQ,MAAO,GAAQ,EAAa,CAAK,EAChD,MAAO,CAAC,EAAM,YAAY,EAAG,GAAG,EAAK,IAAI,CAAc,CAAC,EAAE,KAAK,EAAE,GCH5D,IAAM,EAAe,CAA6B,IAAoC,CAC3F,IAAM,EAA+B,CAAC,EAEtC,QAAW,KAAO,EAAM,CACtB,IAAM,EAAI,EAAY,CAAG,EACnB,EAAQ,EAAY,EAAK,EAAc,EAC7C,EAAK,GAAK,EAGZ,OAAO,GCZT,yBAAS,eAEF,IAAM,EAAS,CACpB,MAAM,CAAC,EAAuB,CAC5B,OAAO,EAAe,mBAAoB,GAAQ,EAAE,EAAE,GAExD,SAAS,CAAC,EAAuB,CAC/B,OAAO,EAAe,aAAc,GAAQ,EAAE,EAAE,GAElD,aAAa,CAAC,EAA0C,CACtD,OAAO,EAAe,mBAAoB,GAAQ,EAAE,EAExD,ECZO,IAAM,EAAe,CAAC,IAA4B,CACvD,IAAM,EAAe,KAAK,MAAM,CAAO,EACjC,EAAQ,KAAK,MAAM,EAAe,IAAI,EACtC,EAAU,KAAK,MAAO,EAAe,KAAQ,EAAE,EAC/C,EAAmB,EAAe,GAExC,GAAI,EAAQ,EACV,MAAO,GAAG,KAAS,EAAQ,SAAS,EAAE,SAAS,EAAG,GAAG,KAAK,EAAiB,SAAS,EAAE,SAAS,EAAG,GAAG,IAGvG,GAAI,EAAU,EACZ,MAAO,GAAG,KAAW,EAAiB,SAAS,EAAE,SAAS,EAAG,GAAG,IAGlE,OAAO,EAAiB,SAAS,GCd5B,IAAM,EAAc,CAAC,IAA4B,CACtD,IAAM,EAAU,KAAK,MAAM,EAAU,EAAE,EACjC,EAAmB,EAAU,GACnC,MAAO,GAAG,KAAW,EAAiB,SAAS,EAAE,SAAS,EAAG,GAAG,KCH3D,IAAM,EAAQ,CAAC,IAA8B,IAAI,QAAQ,CAAC,IAAY,WAAW,EAAS,CAAE,CAAC,ECE7F,IAAM,EAAc,CAAC,IAA0B,CAEpD,OADA,EAAQ,EAAM,KAAK,EACZ,EAAa,CAAK,EAAE,KAAK,GAAG,EAAE,YAAY,GCD5C,IAAM,EAAe,CAAC,IAA0B,CAErD,OADA,EAAQ,EAAM,KAAK,EACZ,EAAa,CAAK,EAAE,IAAI,CAAc,EAAE,KAAK,EAAE",
|
|
22
|
+
"debugId": "D3540DB7AD21EC7364756E2164756E21",
|
|
23
|
+
"names": []
|
|
24
|
+
}
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,23 +1,36 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ooneex/utils",
|
|
3
|
-
"version": "0.0.5",
|
|
4
3
|
"description": "",
|
|
5
|
-
"
|
|
6
|
-
"types": "dist/index.d.ts",
|
|
4
|
+
"version": "0.0.8",
|
|
7
5
|
"type": "module",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist",
|
|
8
|
+
"LICENSE",
|
|
9
|
+
"README.md",
|
|
10
|
+
"package.json"
|
|
11
|
+
],
|
|
12
|
+
"module": "./dist/index.js",
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"import": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"default": "./dist/index.js"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"./package.json": "./package.json"
|
|
22
|
+
},
|
|
8
23
|
"license": "MIT",
|
|
9
24
|
"scripts": {
|
|
10
|
-
"
|
|
11
|
-
"build": "
|
|
12
|
-
"
|
|
25
|
+
"test": "bun test tests",
|
|
26
|
+
"build": "bunup",
|
|
27
|
+
"lint": "tsgo --noEmit && bunx biome lint",
|
|
28
|
+
"publish:prod": "bun publish --tolerate-republish --access public",
|
|
29
|
+
"publish:pack": "bun pm pack --destination ./dist",
|
|
30
|
+
"publish:dry": "bun publish --dry-run"
|
|
13
31
|
},
|
|
14
|
-
"devDependencies": {},
|
|
15
|
-
"peerDependencies": {},
|
|
16
32
|
"dependencies": {
|
|
17
33
|
"nanoid": "^5.1.6"
|
|
18
34
|
},
|
|
19
|
-
"
|
|
20
|
-
"dist/**/*.js",
|
|
21
|
-
"dist/**/*.d.ts"
|
|
22
|
-
]
|
|
35
|
+
"devDependencies": {}
|
|
23
36
|
}
|