@ooneex/utils 0.1.0 → 0.2.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/README.md +284 -448
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +4 -4
- package/package.json +14 -4
package/README.md
CHANGED
|
@@ -1,90 +1,90 @@
|
|
|
1
1
|
# @ooneex/utils
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
General-purpose utility functions including unique ID generation with nanoid, type guards, and common helper methods.
|
|
4
4
|
|
|
5
5
|

|
|
6
6
|

|
|
7
|
-

|
|
8
|
-

|
|
9
7
|

|
|
10
8
|

|
|
11
9
|
|
|
12
10
|
## Features
|
|
13
11
|
|
|
14
|
-
✅ **
|
|
12
|
+
✅ **ID Generation** - Generate unique IDs using nanoid with configurable length
|
|
15
13
|
|
|
16
|
-
✅ **
|
|
14
|
+
✅ **String Case Conversion** - Convert between camelCase, kebab-case, snake_case, and PascalCase
|
|
17
15
|
|
|
18
|
-
✅ **
|
|
16
|
+
✅ **String Utilities** - `trim`, `splitToWords`, `capitalizeWord` for common string operations
|
|
19
17
|
|
|
20
|
-
✅ **
|
|
18
|
+
✅ **Value Parsing** - `parseString` to convert string values to boolean, number, or string types
|
|
21
19
|
|
|
22
|
-
✅ **
|
|
20
|
+
✅ **Time Formatting** - `secondsToHMS`, `secondsToMS`, and `millisecondsToHMS` for duration display
|
|
23
21
|
|
|
24
|
-
✅ **
|
|
22
|
+
✅ **Number Formatting** - `formatRelativeNumber` for human-readable numbers with K, M, B suffixes
|
|
25
23
|
|
|
26
|
-
✅ **
|
|
24
|
+
✅ **Data Conversion** - `dataURLtoFile` to convert data URLs to File objects
|
|
27
25
|
|
|
28
|
-
✅ **
|
|
26
|
+
✅ **Environment Variables** - `parseEnvVars` to parse .env file content into key-value pairs
|
|
29
27
|
|
|
30
|
-
✅ **
|
|
28
|
+
✅ **Async Utilities** - `sleep` function for async/await workflows
|
|
31
29
|
|
|
32
|
-
✅ **
|
|
33
|
-
|
|
34
|
-
✅ **Zero Dependencies** - Only one small dependency (nanoid) for random generation
|
|
30
|
+
✅ **Zero Config** - Simple, pure functions with no configuration needed
|
|
35
31
|
|
|
36
32
|
## Installation
|
|
37
33
|
|
|
38
|
-
### Bun
|
|
39
34
|
```bash
|
|
40
35
|
bun add @ooneex/utils
|
|
41
36
|
```
|
|
42
37
|
|
|
43
|
-
|
|
44
|
-
```bash
|
|
45
|
-
pnpm add @ooneex/utils
|
|
46
|
-
```
|
|
38
|
+
## Usage
|
|
47
39
|
|
|
48
|
-
###
|
|
49
|
-
```bash
|
|
50
|
-
yarn add @ooneex/utils
|
|
51
|
-
```
|
|
40
|
+
### Unique ID Generation
|
|
52
41
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
npm install @ooneex/utils
|
|
56
|
-
```
|
|
42
|
+
```typescript
|
|
43
|
+
import { random } from '@ooneex/utils';
|
|
57
44
|
|
|
58
|
-
|
|
45
|
+
// Generate a unique ID (default length: 21)
|
|
46
|
+
const id = random();
|
|
47
|
+
console.log(id); // "V1StGXR8_Z5jdHi6B-myT"
|
|
48
|
+
|
|
49
|
+
// Generate with custom length
|
|
50
|
+
const shortId = random(10);
|
|
51
|
+
console.log(shortId); // "V1StGXR8_Z"
|
|
52
|
+
```
|
|
59
53
|
|
|
60
|
-
### String
|
|
54
|
+
### String Case Conversion
|
|
61
55
|
|
|
62
56
|
```typescript
|
|
63
57
|
import {
|
|
64
|
-
capitalizeWord,
|
|
65
58
|
toCamelCase,
|
|
66
|
-
toPascalCase,
|
|
67
59
|
toKebabCase,
|
|
68
|
-
|
|
69
|
-
|
|
60
|
+
toSnakeCase,
|
|
61
|
+
toPascalCase,
|
|
62
|
+
capitalizeWord
|
|
70
63
|
} from '@ooneex/utils';
|
|
71
64
|
|
|
72
|
-
//
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
//
|
|
86
|
-
|
|
87
|
-
|
|
65
|
+
// Convert to camelCase
|
|
66
|
+
toCamelCase('hello world'); // "helloWorld"
|
|
67
|
+
toCamelCase('hello-world'); // "helloWorld"
|
|
68
|
+
toCamelCase('hello_world'); // "helloWorld"
|
|
69
|
+
|
|
70
|
+
// Convert to kebab-case
|
|
71
|
+
toKebabCase('helloWorld'); // "hello-world"
|
|
72
|
+
toKebabCase('HelloWorld'); // "hello-world"
|
|
73
|
+
toKebabCase('hello_world'); // "hello-world"
|
|
74
|
+
|
|
75
|
+
// Convert to snake_case
|
|
76
|
+
toSnakeCase('helloWorld'); // "hello_world"
|
|
77
|
+
toSnakeCase('HelloWorld'); // "hello_world"
|
|
78
|
+
toSnakeCase('hello-world'); // "hello_world"
|
|
79
|
+
|
|
80
|
+
// Convert to PascalCase
|
|
81
|
+
toPascalCase('hello world'); // "HelloWorld"
|
|
82
|
+
toPascalCase('hello-world'); // "HelloWorld"
|
|
83
|
+
toPascalCase('hello_world'); // "HelloWorld"
|
|
84
|
+
|
|
85
|
+
// Capitalize first letter
|
|
86
|
+
capitalizeWord('hello'); // "Hello"
|
|
87
|
+
capitalizeWord('hello world'); // "Hello world"
|
|
88
88
|
```
|
|
89
89
|
|
|
90
90
|
### Time Formatting
|
|
@@ -93,555 +93,391 @@ console.log(trim('[test]', '\\[|\\]')); // 'test'
|
|
|
93
93
|
import {
|
|
94
94
|
secondsToHMS,
|
|
95
95
|
secondsToMS,
|
|
96
|
-
millisecondsToHMS
|
|
97
|
-
sleep
|
|
96
|
+
millisecondsToHMS
|
|
98
97
|
} from '@ooneex/utils';
|
|
99
98
|
|
|
100
|
-
//
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
99
|
+
// Seconds to Hours:Minutes:Seconds
|
|
100
|
+
secondsToHMS(3661); // "1:01:01"
|
|
101
|
+
secondsToHMS(125); // "0:02:05"
|
|
102
|
+
|
|
103
|
+
// Seconds to Minutes:Seconds
|
|
104
|
+
secondsToMS(125); // "2:05"
|
|
105
|
+
secondsToMS(65); // "1:05"
|
|
106
|
+
|
|
107
|
+
// Milliseconds to Hours:Minutes:Seconds
|
|
108
|
+
millisecondsToHMS(3661000); // "1:01:01"
|
|
109
|
+
millisecondsToHMS(125000); // "0:02:05"
|
|
110
|
+
```
|
|
104
111
|
|
|
105
|
-
|
|
106
|
-
console.log(secondsToMS(45)); // '0:45'
|
|
112
|
+
### Number Formatting
|
|
107
113
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
console.log(millisecondsToHMS(125000)); // '2:05'
|
|
114
|
+
```typescript
|
|
115
|
+
import { formatRelativeNumber } from '@ooneex/utils';
|
|
111
116
|
|
|
112
|
-
//
|
|
113
|
-
|
|
117
|
+
// Format large numbers with suffixes
|
|
118
|
+
formatRelativeNumber(1000); // "1K"
|
|
119
|
+
formatRelativeNumber(1500); // "1.5K"
|
|
120
|
+
formatRelativeNumber(1000000); // "1M"
|
|
121
|
+
formatRelativeNumber(1500000); // "1.5M"
|
|
122
|
+
formatRelativeNumber(1000000000); // "1B"
|
|
123
|
+
formatRelativeNumber(999); // "999"
|
|
114
124
|
```
|
|
115
125
|
|
|
116
|
-
###
|
|
126
|
+
### Async Sleep
|
|
117
127
|
|
|
118
128
|
```typescript
|
|
119
|
-
import {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
console.log(
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
console.log(
|
|
128
|
-
|
|
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'] }
|
|
129
|
+
import { sleep } from '@ooneex/utils';
|
|
130
|
+
|
|
131
|
+
async function example() {
|
|
132
|
+
console.log('Starting...');
|
|
133
|
+
|
|
134
|
+
// Wait for 2 seconds
|
|
135
|
+
await sleep(2000);
|
|
136
|
+
|
|
137
|
+
console.log('2 seconds later...');
|
|
138
|
+
}
|
|
141
139
|
```
|
|
142
140
|
|
|
143
|
-
###
|
|
141
|
+
### String Utilities
|
|
144
142
|
|
|
145
143
|
```typescript
|
|
146
|
-
import {
|
|
144
|
+
import { trim, splitToWords, parseString } from '@ooneex/utils';
|
|
147
145
|
|
|
148
|
-
//
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
//
|
|
160
|
-
|
|
161
|
-
console.log(formatRelativeNumber(1500000, { lang: 'de-DE' })); // '1,5 Mio.'
|
|
162
|
-
console.log(formatRelativeNumber(1500, { lang: 'fr-FR' })); // '1,5 k'
|
|
146
|
+
// Trim whitespace and normalize
|
|
147
|
+
trim(' hello world '); // "hello world"
|
|
148
|
+
|
|
149
|
+
// Split string into words
|
|
150
|
+
splitToWords('helloWorld'); // ["hello", "World"]
|
|
151
|
+
splitToWords('hello-world'); // ["hello", "world"]
|
|
152
|
+
splitToWords('hello_world'); // ["hello", "world"]
|
|
153
|
+
|
|
154
|
+
// Parse string values
|
|
155
|
+
parseString('true'); // true (boolean)
|
|
156
|
+
parseString('false'); // false (boolean)
|
|
157
|
+
parseString('123'); // 123 (number)
|
|
158
|
+
parseString('hello'); // "hello" (string)
|
|
163
159
|
```
|
|
164
160
|
|
|
165
|
-
###
|
|
161
|
+
### Data URL Conversion
|
|
166
162
|
|
|
167
163
|
```typescript
|
|
168
164
|
import { dataURLtoFile } from '@ooneex/utils';
|
|
169
165
|
|
|
170
|
-
// Convert data URL to File object
|
|
171
|
-
const dataUrl = 'data:
|
|
172
|
-
const file = dataURLtoFile(dataUrl, '
|
|
166
|
+
// Convert a data URL to a File object
|
|
167
|
+
const dataUrl = 'data:image/png;base64,iVBORw0KGgo...';
|
|
168
|
+
const file = dataURLtoFile(dataUrl, 'image.png');
|
|
173
169
|
|
|
174
|
-
console.log(file.name); //
|
|
175
|
-
console.log(file.type); //
|
|
176
|
-
console.log(file.size); // 11
|
|
170
|
+
console.log(file.name); // "image.png"
|
|
171
|
+
console.log(file.type); // "image/png"
|
|
177
172
|
```
|
|
178
173
|
|
|
179
|
-
###
|
|
174
|
+
### Environment Variable Parsing
|
|
180
175
|
|
|
181
176
|
```typescript
|
|
182
|
-
import {
|
|
183
|
-
|
|
184
|
-
// Generate random hex strings
|
|
185
|
-
console.log(random.nanoid()); // 'a1b2c3d4e5' (10 chars default)
|
|
186
|
-
console.log(random.nanoid(8)); // 'f6e5d4c3' (8 chars)
|
|
177
|
+
import { parseEnvVars } from '@ooneex/utils';
|
|
187
178
|
|
|
188
|
-
//
|
|
189
|
-
|
|
190
|
-
|
|
179
|
+
// Parse environment variable content
|
|
180
|
+
const envContent = `
|
|
181
|
+
DATABASE_URL=postgresql://localhost:5432/mydb
|
|
182
|
+
API_KEY=secret-key-123
|
|
183
|
+
DEBUG=true
|
|
184
|
+
PORT=3000
|
|
185
|
+
`;
|
|
191
186
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
187
|
+
const vars = parseEnvVars(envContent);
|
|
188
|
+
// {
|
|
189
|
+
// DATABASE_URL: 'postgresql://localhost:5432/mydb',
|
|
190
|
+
// API_KEY: 'secret-key-123',
|
|
191
|
+
// DEBUG: 'true',
|
|
192
|
+
// PORT: '3000'
|
|
193
|
+
// }
|
|
196
194
|
```
|
|
197
195
|
|
|
198
196
|
## API Reference
|
|
199
197
|
|
|
200
|
-
###
|
|
198
|
+
### Functions
|
|
201
199
|
|
|
202
|
-
#### `
|
|
203
|
-
|
|
200
|
+
#### `random(size?: number): string`
|
|
201
|
+
|
|
202
|
+
Generates a unique ID using nanoid.
|
|
204
203
|
|
|
205
204
|
**Parameters:**
|
|
206
|
-
- `
|
|
205
|
+
- `size` - Optional length of the ID (default: 21)
|
|
207
206
|
|
|
208
|
-
**Returns:**
|
|
207
|
+
**Returns:** A unique string ID
|
|
209
208
|
|
|
210
209
|
**Example:**
|
|
211
210
|
```typescript
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
capitalizeWord(''); // ''
|
|
211
|
+
const id = random(); // "V1StGXR8_Z5jdHi6B-myT"
|
|
212
|
+
const short = random(8); // "V1StGXR8"
|
|
215
213
|
```
|
|
216
214
|
|
|
217
|
-
|
|
218
|
-
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
#### `toCamelCase(str: string): string`
|
|
218
|
+
|
|
219
|
+
Converts a string to camelCase.
|
|
219
220
|
|
|
220
221
|
**Parameters:**
|
|
221
|
-
- `
|
|
222
|
+
- `str` - The input string
|
|
222
223
|
|
|
223
|
-
**Returns:** camelCase string
|
|
224
|
+
**Returns:** camelCase formatted string
|
|
224
225
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
toCamelCase('Hello-World_Example'); // 'helloWorldExample'
|
|
229
|
-
toCamelCase('API_KEY'); // 'apiKey'
|
|
230
|
-
```
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
#### `toKebabCase(str: string): string`
|
|
231
229
|
|
|
232
|
-
|
|
233
|
-
Converts string to PascalCase.
|
|
230
|
+
Converts a string to kebab-case.
|
|
234
231
|
|
|
235
232
|
**Parameters:**
|
|
236
|
-
- `
|
|
233
|
+
- `str` - The input string
|
|
237
234
|
|
|
238
|
-
**Returns:**
|
|
235
|
+
**Returns:** kebab-case formatted string
|
|
239
236
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
toPascalCase('api-key'); // 'ApiKey'
|
|
244
|
-
toPascalCase('user_name'); // 'UserName'
|
|
245
|
-
```
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
#### `toSnakeCase(str: string): string`
|
|
246
240
|
|
|
247
|
-
|
|
248
|
-
Converts string to kebab-case.
|
|
241
|
+
Converts a string to snake_case.
|
|
249
242
|
|
|
250
243
|
**Parameters:**
|
|
251
|
-
- `
|
|
244
|
+
- `str` - The input string
|
|
252
245
|
|
|
253
|
-
**Returns:**
|
|
246
|
+
**Returns:** snake_case formatted string
|
|
254
247
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
toKebabCase('camelCaseString'); // 'camel-case-string'
|
|
259
|
-
toKebabCase('PascalCaseString'); // 'pascal-case-string'
|
|
260
|
-
```
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
#### `toPascalCase(str: string): string`
|
|
261
251
|
|
|
262
|
-
|
|
263
|
-
Splits a string into individual words, handling various naming conventions.
|
|
252
|
+
Converts a string to PascalCase.
|
|
264
253
|
|
|
265
254
|
**Parameters:**
|
|
266
|
-
- `
|
|
255
|
+
- `str` - The input string
|
|
267
256
|
|
|
268
|
-
**Returns:**
|
|
257
|
+
**Returns:** PascalCase formatted string
|
|
269
258
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
splitToWords('hello-world_example'); // ['hello', 'world', 'example']
|
|
274
|
-
splitToWords('XMLHttpRequest'); // ['XML', 'Http', 'Request']
|
|
275
|
-
splitToWords('user123Name'); // ['user', '123', 'Name']
|
|
276
|
-
```
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
#### `capitalizeWord(str: string): string`
|
|
277
262
|
|
|
278
|
-
|
|
279
|
-
Trims specified characters from the beginning and end of a string.
|
|
263
|
+
Capitalizes the first letter of a string.
|
|
280
264
|
|
|
281
265
|
**Parameters:**
|
|
282
|
-
- `
|
|
283
|
-
- `char` - Characters to trim (default: space). Supports regex patterns.
|
|
266
|
+
- `str` - The input string
|
|
284
267
|
|
|
285
|
-
**Returns:**
|
|
268
|
+
**Returns:** String with first letter capitalized
|
|
286
269
|
|
|
287
|
-
|
|
288
|
-
```typescript
|
|
289
|
-
trim(' hello '); // 'hello'
|
|
290
|
-
trim('...hello...', '\\.'); // 'hello'
|
|
291
|
-
trim('[test]', '\\[|\\]'); // 'test'
|
|
292
|
-
trim('!!hello!!', '!'); // 'hello'
|
|
293
|
-
```
|
|
270
|
+
---
|
|
294
271
|
|
|
295
|
-
|
|
272
|
+
#### `splitToWords(str: string): string[]`
|
|
296
273
|
|
|
297
|
-
|
|
298
|
-
Converts seconds to HH:MM:SS or MM:SS or SS format.
|
|
274
|
+
Splits a string into an array of words.
|
|
299
275
|
|
|
300
276
|
**Parameters:**
|
|
301
|
-
- `
|
|
277
|
+
- `str` - The input string (camelCase, kebab-case, snake_case, or space-separated)
|
|
302
278
|
|
|
303
|
-
**Returns:**
|
|
279
|
+
**Returns:** Array of words
|
|
304
280
|
|
|
305
|
-
|
|
306
|
-
```typescript
|
|
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'
|
|
311
|
-
```
|
|
281
|
+
---
|
|
312
282
|
|
|
313
|
-
#### `
|
|
314
|
-
|
|
283
|
+
#### `trim(str: string): string`
|
|
284
|
+
|
|
285
|
+
Trims whitespace and normalizes internal spacing.
|
|
315
286
|
|
|
316
287
|
**Parameters:**
|
|
317
|
-
- `
|
|
288
|
+
- `str` - The input string
|
|
318
289
|
|
|
319
|
-
**Returns:**
|
|
290
|
+
**Returns:** Trimmed and normalized string
|
|
320
291
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
secondsToMS(45); // '0:45'
|
|
325
|
-
secondsToMS(3661); // '61:01'
|
|
326
|
-
```
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
#### `secondsToHMS(seconds: number): string`
|
|
327
295
|
|
|
328
|
-
|
|
329
|
-
Converts milliseconds to HH:MM:SS or MM:SS or SS format.
|
|
296
|
+
Converts seconds to H:MM:SS format.
|
|
330
297
|
|
|
331
298
|
**Parameters:**
|
|
332
|
-
- `
|
|
299
|
+
- `seconds` - Number of seconds
|
|
333
300
|
|
|
334
301
|
**Returns:** Formatted time string
|
|
335
302
|
|
|
336
|
-
|
|
337
|
-
```typescript
|
|
338
|
-
millisecondsToHMS(3661000); // '1:01:01'
|
|
339
|
-
millisecondsToHMS(125000); // '2:05'
|
|
340
|
-
millisecondsToHMS(45000); // '45'
|
|
341
|
-
millisecondsToHMS(500); // '0'
|
|
342
|
-
```
|
|
303
|
+
---
|
|
343
304
|
|
|
344
|
-
#### `
|
|
345
|
-
Creates a promise that resolves after the specified number of milliseconds.
|
|
305
|
+
#### `secondsToMS(seconds: number): string`
|
|
346
306
|
|
|
347
|
-
|
|
348
|
-
- `ms` - Number of milliseconds to wait
|
|
307
|
+
Converts seconds to M:SS format.
|
|
349
308
|
|
|
350
|
-
**
|
|
309
|
+
**Parameters:**
|
|
310
|
+
- `seconds` - Number of seconds
|
|
351
311
|
|
|
352
|
-
**
|
|
353
|
-
```typescript
|
|
354
|
-
await sleep(1000); // Wait 1 second
|
|
355
|
-
await sleep(500); // Wait 0.5 seconds
|
|
312
|
+
**Returns:** Formatted time string
|
|
356
313
|
|
|
357
|
-
|
|
358
|
-
async function delayedLog() {
|
|
359
|
-
console.log('First');
|
|
360
|
-
await sleep(2000);
|
|
361
|
-
console.log('Second (2 seconds later)');
|
|
362
|
-
}
|
|
363
|
-
```
|
|
314
|
+
---
|
|
364
315
|
|
|
365
|
-
|
|
316
|
+
#### `millisecondsToHMS(milliseconds: number): string`
|
|
366
317
|
|
|
367
|
-
|
|
368
|
-
Intelligently parses a string and returns the appropriate type.
|
|
318
|
+
Converts milliseconds to H:MM:SS format.
|
|
369
319
|
|
|
370
320
|
**Parameters:**
|
|
371
|
-
- `
|
|
321
|
+
- `milliseconds` - Number of milliseconds
|
|
372
322
|
|
|
373
|
-
**Returns:**
|
|
323
|
+
**Returns:** Formatted time string
|
|
374
324
|
|
|
375
|
-
|
|
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"`
|
|
325
|
+
---
|
|
384
326
|
|
|
385
|
-
|
|
386
|
-
```typescript
|
|
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[]
|
|
399
|
-
```
|
|
327
|
+
#### `formatRelativeNumber(num: number): string`
|
|
400
328
|
|
|
401
|
-
|
|
402
|
-
Parses environment variables, converting keys to camelCase and values using `parseString`.
|
|
329
|
+
Formats a number with K, M, or B suffix.
|
|
403
330
|
|
|
404
331
|
**Parameters:**
|
|
405
|
-
- `
|
|
332
|
+
- `num` - The number to format
|
|
406
333
|
|
|
407
|
-
**Returns:**
|
|
334
|
+
**Returns:** Formatted number string with suffix
|
|
408
335
|
|
|
409
|
-
|
|
410
|
-
```typescript
|
|
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);
|
|
436
|
-
```
|
|
336
|
+
---
|
|
437
337
|
|
|
438
|
-
|
|
338
|
+
#### `sleep(ms: number): Promise<void>`
|
|
439
339
|
|
|
440
|
-
|
|
441
|
-
Formats numbers using compact notation with locale support.
|
|
340
|
+
Pauses execution for the specified duration.
|
|
442
341
|
|
|
443
342
|
**Parameters:**
|
|
444
|
-
- `
|
|
445
|
-
- `config.precision` - Maximum decimal places (default: 1)
|
|
446
|
-
- `config.lang` - Locale code (default: 'en-GB')
|
|
343
|
+
- `ms` - Duration in milliseconds
|
|
447
344
|
|
|
448
|
-
**Returns:**
|
|
345
|
+
**Returns:** Promise that resolves after the duration
|
|
449
346
|
|
|
450
|
-
|
|
451
|
-
```typescript
|
|
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
|
-
```
|
|
347
|
+
---
|
|
467
348
|
|
|
468
|
-
|
|
349
|
+
#### `dataURLtoFile(dataUrl: string, filename: string): File`
|
|
469
350
|
|
|
470
|
-
#### `dataURLtoFile(dataurl: string, filename: string): File`
|
|
471
351
|
Converts a data URL to a File object.
|
|
472
352
|
|
|
473
353
|
**Parameters:**
|
|
474
|
-
- `
|
|
475
|
-
- `filename` -
|
|
354
|
+
- `dataUrl` - The data URL string
|
|
355
|
+
- `filename` - Name for the resulting file
|
|
476
356
|
|
|
477
357
|
**Returns:** File object
|
|
478
358
|
|
|
479
|
-
|
|
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);
|
|
497
|
-
```
|
|
359
|
+
---
|
|
498
360
|
|
|
499
|
-
|
|
361
|
+
#### `parseString(value: string): string | number | boolean`
|
|
500
362
|
|
|
501
|
-
|
|
502
|
-
Generates a random hexadecimal string.
|
|
363
|
+
Parses a string value to its appropriate type.
|
|
503
364
|
|
|
504
365
|
**Parameters:**
|
|
505
|
-
- `
|
|
506
|
-
|
|
507
|
-
**Returns:** Random hex string
|
|
508
|
-
|
|
509
|
-
**Example:**
|
|
510
|
-
```typescript
|
|
511
|
-
random.nanoid(); // 'a1b2c3d4e5' (10 characters)
|
|
512
|
-
random.nanoid(8); // 'f6e5d4c3' (8 characters)
|
|
513
|
-
random.nanoid(16); // '1a2b3c4d5e6f7890' (16 characters)
|
|
514
|
-
```
|
|
366
|
+
- `value` - The string to parse
|
|
515
367
|
|
|
516
|
-
|
|
517
|
-
Generates a random numeric string.
|
|
368
|
+
**Returns:** Parsed value (boolean, number, or string)
|
|
518
369
|
|
|
519
|
-
|
|
520
|
-
- `size` - Length of the generated string (default: 10)
|
|
521
|
-
|
|
522
|
-
**Returns:** Random numeric string
|
|
370
|
+
---
|
|
523
371
|
|
|
524
|
-
|
|
525
|
-
```typescript
|
|
526
|
-
random.stringInt(); // '1234567890' (10 digits)
|
|
527
|
-
random.stringInt(6); // '123456' (6 digits)
|
|
528
|
-
random.stringInt(4); // '9876' (4 digits)
|
|
529
|
-
```
|
|
372
|
+
#### `parseEnvVars(content: string): Record<string, string>`
|
|
530
373
|
|
|
531
|
-
|
|
532
|
-
Creates a factory function for generating random hex strings.
|
|
374
|
+
Parses environment variable content.
|
|
533
375
|
|
|
534
376
|
**Parameters:**
|
|
535
|
-
- `
|
|
377
|
+
- `content` - Raw environment variable content
|
|
536
378
|
|
|
537
|
-
**Returns:**
|
|
538
|
-
|
|
539
|
-
**Example:**
|
|
540
|
-
```typescript
|
|
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
|
|
545
|
-
|
|
546
|
-
const generateShortId = random.nanoidFactory(6);
|
|
547
|
-
generateShortId(); // 6-character hex string
|
|
548
|
-
```
|
|
379
|
+
**Returns:** Object with key-value pairs
|
|
549
380
|
|
|
550
381
|
## Advanced Usage
|
|
551
382
|
|
|
552
|
-
###
|
|
383
|
+
### Building File Names
|
|
553
384
|
|
|
554
385
|
```typescript
|
|
555
|
-
import {
|
|
386
|
+
import { toKebabCase, random } from '@ooneex/utils';
|
|
556
387
|
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
debug: boolean;
|
|
562
|
-
features: string[];
|
|
563
|
-
dbConfig: {
|
|
564
|
-
host: string;
|
|
565
|
-
port: number;
|
|
566
|
-
};
|
|
388
|
+
function generateFileName(title: string, extension: string): string {
|
|
389
|
+
const slug = toKebabCase(title);
|
|
390
|
+
const uniqueId = random(8);
|
|
391
|
+
return `${slug}-${uniqueId}.${extension}`;
|
|
567
392
|
}
|
|
568
393
|
|
|
569
|
-
|
|
570
|
-
|
|
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
|
-
};
|
|
394
|
+
const fileName = generateFileName('My Awesome Photo', 'jpg');
|
|
395
|
+
// "my-awesome-photo-V1StGXR8.jpg"
|
|
581
396
|
```
|
|
582
397
|
|
|
583
|
-
###
|
|
398
|
+
### Formatting Display Values
|
|
584
399
|
|
|
585
400
|
```typescript
|
|
586
|
-
import {
|
|
401
|
+
import { formatRelativeNumber, capitalizeWord } from '@ooneex/utils';
|
|
587
402
|
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
} {
|
|
594
|
-
const words = splitToWords(input);
|
|
403
|
+
interface SocialStats {
|
|
404
|
+
followers: number;
|
|
405
|
+
likes: number;
|
|
406
|
+
views: number;
|
|
407
|
+
}
|
|
595
408
|
|
|
409
|
+
function formatStats(stats: SocialStats): Record<string, string> {
|
|
596
410
|
return {
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
kebabCase: toKebabCase(input)
|
|
411
|
+
followers: formatRelativeNumber(stats.followers),
|
|
412
|
+
likes: formatRelativeNumber(stats.likes),
|
|
413
|
+
views: formatRelativeNumber(stats.views)
|
|
601
414
|
};
|
|
602
415
|
}
|
|
603
416
|
|
|
604
|
-
const
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
//
|
|
610
|
-
// }
|
|
417
|
+
const stats = formatStats({
|
|
418
|
+
followers: 15600,
|
|
419
|
+
likes: 1200000,
|
|
420
|
+
views: 45000
|
|
421
|
+
});
|
|
422
|
+
// { followers: "15.6K", likes: "1.2M", views: "45K" }
|
|
611
423
|
```
|
|
612
424
|
|
|
613
|
-
###
|
|
425
|
+
### Video Duration Display
|
|
614
426
|
|
|
615
427
|
```typescript
|
|
616
|
-
import {
|
|
428
|
+
import { secondsToHMS, secondsToMS } from '@ooneex/utils';
|
|
617
429
|
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
430
|
+
function formatDuration(seconds: number): string {
|
|
431
|
+
// Use H:MM:SS for videos over an hour, otherwise M:SS
|
|
432
|
+
return seconds >= 3600
|
|
433
|
+
? secondsToHMS(seconds)
|
|
434
|
+
: secondsToMS(seconds);
|
|
435
|
+
}
|
|
622
436
|
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
437
|
+
console.log(formatDuration(90)); // "1:30"
|
|
438
|
+
console.log(formatDuration(3700)); // "1:01:40"
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
### Retry with Delay
|
|
627
442
|
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
443
|
+
```typescript
|
|
444
|
+
import { sleep } from '@ooneex/utils';
|
|
445
|
+
|
|
446
|
+
async function retryWithBackoff<T>(
|
|
447
|
+
fn: () => Promise<T>,
|
|
448
|
+
maxRetries: number = 3,
|
|
449
|
+
baseDelay: number = 1000
|
|
450
|
+
): Promise<T> {
|
|
451
|
+
let lastError: Error;
|
|
452
|
+
|
|
453
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
454
|
+
try {
|
|
455
|
+
return await fn();
|
|
456
|
+
} catch (error) {
|
|
457
|
+
lastError = error as Error;
|
|
458
|
+
const delay = baseDelay * Math.pow(2, attempt);
|
|
459
|
+
console.log(`Attempt ${attempt + 1} failed, retrying in ${delay}ms...`);
|
|
460
|
+
await sleep(delay);
|
|
461
|
+
}
|
|
639
462
|
}
|
|
463
|
+
|
|
464
|
+
throw lastError!;
|
|
465
|
+
}
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
### API Route Slug Generation
|
|
469
|
+
|
|
470
|
+
```typescript
|
|
471
|
+
import { toKebabCase } from '@ooneex/utils';
|
|
472
|
+
|
|
473
|
+
function generateApiSlug(resourceName: string, action: string): string {
|
|
474
|
+
const resource = toKebabCase(resourceName);
|
|
475
|
+
const actionSlug = toKebabCase(action);
|
|
476
|
+
return `/api/${resource}/${actionSlug}`;
|
|
640
477
|
}
|
|
641
478
|
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
// "Processed: 15K/100K | Elapsed: 2:30 | ETA: 14:10"
|
|
479
|
+
generateApiSlug('UserProfile', 'getById'); // "/api/user-profile/get-by-id"
|
|
480
|
+
generateApiSlug('BlogPost', 'create'); // "/api/blog-post/create"
|
|
645
481
|
```
|
|
646
482
|
|
|
647
483
|
## License
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
declare const capitalizeWord: (word: string) => string;
|
|
2
|
-
declare const dataURLtoFile: (
|
|
2
|
+
declare const dataURLtoFile: (dataUrl: string, filename: string) => File;
|
|
3
3
|
declare const formatRelativeNumber: (num: number, config?: {
|
|
4
4
|
precision?: number;
|
|
5
5
|
lang?: string;
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var i=(r)=>r?r[0]?.toUpperCase()+r.slice(1).toLowerCase():r;var u=(r,t)=>{let o=r.split(","),
|
|
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]||"",g=atob(o[1]),a=g.length,f=new Uint8Array(a);while(a--)f[a]=g.charCodeAt(a);return new File([f],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 T=/\p{Lu}\p{Ll}+\p{N}+/u,b=/\p{Lu}\p{Ll}+/u,x=/\p{Lu}+\p{N}+/u,$=/\p{Lu}+(?=(\p{Lu}\p{Ll})|\P{L}|\b)/u,C=/\p{Ll}+\p{N}+/u,M=/(\p{Ll}+)/u,h=/\p{L}+/u,N=/\p{N}+/u,w=new RegExp(`${T.source}|${b.source}|${x.source}|${$.source}|${C.source}|${M.source}|${h.source}|${N.source}`,"gu"),n=(r)=>r.match(w)??[];var c=(r)=>{r=r.trim();let[t="",...o]=n(r);return[t.toLowerCase(),...o.map(i)].join("")};var F=(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 v={nanoid(r){return l("1234567890abcdef",r??10)()},stringInt(r){return l("1234567890",r??10)()},nanoidFactory(r){return l("1234567890abcdef",r??10)}};var I=(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 W=(r)=>{let t=Math.floor(r/60),o=r%60;return`${t}:${o.toString().padStart(2,"0")}`};var k=(r)=>new Promise((t)=>setTimeout(t,r));var y=(r)=>{return r=r.trim(),n(r).join("-").toLowerCase()};var R=(r)=>{return r=r.trim(),n(r).map(i).join("")};var z=(r)=>{return r=r.trim(),n(r).map((o)=>o.toLowerCase()).join("_")};export{p as trim,z as toSnakeCase,R as toPascalCase,y as toKebabCase,c as toCamelCase,n as splitToWords,k as sleep,W as secondsToMS,I as secondsToHMS,v as random,m as parseString,F as parseEnvVars,S as millisecondsToHMS,d as formatRelativeNumber,u as dataURLtoFile,i as capitalizeWord};
|
|
2
2
|
|
|
3
|
-
//# debugId=
|
|
3
|
+
//# debugId=5E119ED4001884A964756E2164756E21
|
package/dist/index.js.map
CHANGED
|
@@ -3,12 +3,12 @@
|
|
|
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", "src/toSnakeCase.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"export const capitalizeWord = (word: string): string =>\n word ? word[0]?.toUpperCase() + word.slice(1).toLowerCase() : word;\n",
|
|
6
|
-
"export const dataURLtoFile = (
|
|
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
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
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
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
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",
|
|
11
|
+
"const CAPITALIZED_WORD_WITH_DIGITS_REGEXP = /\\p{Lu}\\p{Ll}+\\p{N}+/u; // e.g. Apple123\nconst CAPITALIZED_WORD_REGEXP = /\\p{Lu}\\p{Ll}+/u; // e.g. Apple\nconst ACRONYM_WITH_DIGITS_REGEXP = /\\p{Lu}+\\p{N}+/u; // e.g. ID1, URL2\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_WITH_DIGITS_REGEXP = /\\p{Ll}+\\p{N}+/u; // e.g. v1, abc123\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_WITH_DIGITS_REGEXP.source}|${CAPITALIZED_WORD_REGEXP.source}|${ACRONYM_WITH_DIGITS_REGEXP.source}|${ACRONYM_REGEXP.source}|${LOWERCASED_WORD_WITH_DIGITS_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
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
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
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",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
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
20
|
"import { splitToWords } from \"./splitToWords\";\n\nexport const toSnakeCase = (input: string): string => {\n input = input.trim();\n const words = splitToWords(input);\n return words.map((word) => word.toLowerCase()).join(\"_\");\n};\n"
|
|
21
21
|
],
|
|
22
|
-
"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,
|
|
23
|
-
"debugId": "
|
|
22
|
+
"mappings": "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",
|
|
23
|
+
"debugId": "5E119ED4001884A964756E2164756E21",
|
|
24
24
|
"names": []
|
|
25
25
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ooneex/utils",
|
|
3
|
-
"description": "
|
|
4
|
-
"version": "0.1
|
|
3
|
+
"description": "General-purpose utility functions including unique ID generation with nanoid, type guards, and common helper methods",
|
|
4
|
+
"version": "0.2.1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
7
7
|
"dist",
|
|
@@ -25,10 +25,20 @@
|
|
|
25
25
|
"test": "bun test tests",
|
|
26
26
|
"build": "bunup",
|
|
27
27
|
"lint": "tsgo --noEmit && bunx biome lint",
|
|
28
|
-
"publish": "bun publish --tolerate-republish --access public"
|
|
28
|
+
"npm:publish": "bun publish --tolerate-republish --force --production --access public"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"nanoid": "^5.1.6"
|
|
32
32
|
},
|
|
33
|
-
"devDependencies": {}
|
|
33
|
+
"devDependencies": {},
|
|
34
|
+
"keywords": [
|
|
35
|
+
"bun",
|
|
36
|
+
"helpers",
|
|
37
|
+
"nanoid",
|
|
38
|
+
"ooneex",
|
|
39
|
+
"tools",
|
|
40
|
+
"typescript",
|
|
41
|
+
"utilities",
|
|
42
|
+
"utils"
|
|
43
|
+
]
|
|
34
44
|
}
|