utilful 1.2.0 → 2.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/README.md +151 -25
- package/dist/csv.d.mts +2 -2
- package/dist/csv.d.ts +2 -2
- package/dist/emitter.d.mts +2 -2
- package/dist/emitter.d.ts +2 -2
- package/dist/emitter.mjs +21 -22
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.mjs +2 -2
- package/dist/object.d.mts +18 -1
- package/dist/object.d.ts +18 -1
- package/dist/object.mjs +10 -1
- package/dist/result.d.mts +32 -0
- package/dist/result.d.ts +32 -0
- package/dist/result.mjs +43 -0
- package/package.json +6 -6
- package/dist/lazy.d.mts +0 -20
- package/dist/lazy.d.ts +0 -20
- package/dist/lazy.mjs +0 -11
package/README.md
CHANGED
|
@@ -10,10 +10,10 @@ A collection of TypeScript utilities that I use across my projects.
|
|
|
10
10
|
- [CSV](#csv)
|
|
11
11
|
- [Emitter](#emitter)
|
|
12
12
|
- [JSON](#json)
|
|
13
|
-
- [Lazy](#lazy)
|
|
14
13
|
- [Module](#module)
|
|
15
14
|
- [Object](#object)
|
|
16
15
|
- [Path](#path)
|
|
16
|
+
- [Result](#result)
|
|
17
17
|
- [String](#string)
|
|
18
18
|
|
|
19
19
|
## Installation
|
|
@@ -137,7 +137,7 @@ emitter.on('*', (type, e) => console.log(type, e))
|
|
|
137
137
|
emitter.emit('foo', { a: 'b' })
|
|
138
138
|
|
|
139
139
|
// Clearing all events
|
|
140
|
-
emitter.
|
|
140
|
+
emitter.events.clear()
|
|
141
141
|
|
|
142
142
|
// Working with handler references:
|
|
143
143
|
function onFoo() {}
|
|
@@ -168,29 +168,6 @@ Clones the given JSON value.
|
|
|
168
168
|
declare function cloneJSON<T>(value: T): T
|
|
169
169
|
```
|
|
170
170
|
|
|
171
|
-
### Lazy
|
|
172
|
-
|
|
173
|
-
A simple general purpose memoizer utility.
|
|
174
|
-
|
|
175
|
-
- Lazily computes a value when accessed
|
|
176
|
-
- Auto-caches the result by overwriting the getter
|
|
177
|
-
- Typesafe
|
|
178
|
-
|
|
179
|
-
Useful for deferring initialization or expensive operations. Unlike a simple getter, there is no runtime overhead after the first invokation, since the getter itself is overwritten with the memoized value.
|
|
180
|
-
|
|
181
|
-
```ts
|
|
182
|
-
declare function lazy<T>(getter: () => T): { value: T }
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
**Example:**
|
|
186
|
-
|
|
187
|
-
```ts
|
|
188
|
-
const myValue = lazy(() => 'Hello, World!')
|
|
189
|
-
console.log(myValue.value) // Computes value, overwrites getter
|
|
190
|
-
console.log(myValue.value) // Returns cached value
|
|
191
|
-
console.log(myValue.value) // Returns cached value
|
|
192
|
-
```
|
|
193
|
-
|
|
194
171
|
### Module
|
|
195
172
|
|
|
196
173
|
#### `interopDefault`
|
|
@@ -215,6 +192,28 @@ async function loadModule() {
|
|
|
215
192
|
|
|
216
193
|
### Object
|
|
217
194
|
|
|
195
|
+
#### `memoize`
|
|
196
|
+
|
|
197
|
+
A simple general purpose memoizer utility.
|
|
198
|
+
|
|
199
|
+
- Lazily computes a value when accessed
|
|
200
|
+
- Auto-caches the result by overwriting the getter
|
|
201
|
+
|
|
202
|
+
Useful for deferring initialization or expensive operations. Unlike a simple getter, there is no runtime overhead after the first invokation, since the getter itself is overwritten with the memoized value.
|
|
203
|
+
|
|
204
|
+
```ts
|
|
205
|
+
declare function memoize<T>(getter: () => T): { value: T }
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
**Example:**
|
|
209
|
+
|
|
210
|
+
```ts
|
|
211
|
+
const myValue = lazy(() => 'Hello, World!')
|
|
212
|
+
console.log(myValue.value) // Computes value, overwrites getter
|
|
213
|
+
console.log(myValue.value) // Returns cached value
|
|
214
|
+
console.log(myValue.value) // Returns cached value
|
|
215
|
+
```
|
|
216
|
+
|
|
218
217
|
#### `objectKeys`
|
|
219
218
|
|
|
220
219
|
Strictly typed `Object.keys`.
|
|
@@ -327,6 +326,133 @@ const url = withQuery('https://example.com', {
|
|
|
327
326
|
})
|
|
328
327
|
```
|
|
329
328
|
|
|
329
|
+
### Result
|
|
330
|
+
|
|
331
|
+
The `Result` type that represents either success (`Ok`) or failure (`Err`). It helps to handle errors in a more explicit and type-safe way, without relying on exceptions.
|
|
332
|
+
|
|
333
|
+
A common use case for `Result` is error handling in functions that might fail. Here's an example of a function that divides two numbers and returns a `Result`:
|
|
334
|
+
|
|
335
|
+
```ts
|
|
336
|
+
import { err, ok } from 'utilful'
|
|
337
|
+
|
|
338
|
+
function divide(a: number, b: number) {
|
|
339
|
+
if (b === 0) {
|
|
340
|
+
return err('Division by zero')
|
|
341
|
+
}
|
|
342
|
+
return ok(a / b)
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
const result = divide(10, 2)
|
|
346
|
+
if (result.ok)
|
|
347
|
+
console.log('Result:', result.value)
|
|
348
|
+
else
|
|
349
|
+
console.error('Error:', result.error)
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
#### `Result`
|
|
353
|
+
|
|
354
|
+
The `Result` type represents either success (`Ok`) or failure (`Err`).
|
|
355
|
+
|
|
356
|
+
**Type Definition:**
|
|
357
|
+
|
|
358
|
+
```ts
|
|
359
|
+
type Result<T, E> = Ok<T> | Err<E>
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
#### `Ok`
|
|
363
|
+
|
|
364
|
+
The `Ok` type wraps a successful value.
|
|
365
|
+
|
|
366
|
+
**Example:**
|
|
367
|
+
|
|
368
|
+
```ts
|
|
369
|
+
const result = new Ok(42)
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
#### `Err`
|
|
373
|
+
|
|
374
|
+
The `Err` type wraps an error value.
|
|
375
|
+
|
|
376
|
+
**Example:**
|
|
377
|
+
|
|
378
|
+
```ts
|
|
379
|
+
const result = new Err('Something went wrong')
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
#### `ok`
|
|
383
|
+
|
|
384
|
+
Shorthand function to create an `Ok` result. Use it to wrap a successful value.
|
|
385
|
+
|
|
386
|
+
**Type Definition:**
|
|
387
|
+
|
|
388
|
+
```ts
|
|
389
|
+
function ok<T>(value: T): Ok<T>
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
#### `err`
|
|
393
|
+
|
|
394
|
+
Shorthand function to create an `Err` result. Use it to wrap an error value.
|
|
395
|
+
|
|
396
|
+
**Type Definition:**
|
|
397
|
+
|
|
398
|
+
```ts
|
|
399
|
+
function err<E extends string = string>(err: E): Err<E>
|
|
400
|
+
function err<E = unknown>(err: E): Err<E>
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
#### `toResult`
|
|
404
|
+
|
|
405
|
+
Wraps a function that might throw an error and returns a `Result` with the result of the function.
|
|
406
|
+
|
|
407
|
+
**Type Definition:**
|
|
408
|
+
|
|
409
|
+
```ts
|
|
410
|
+
function toResult<T, E = unknown>(fn: () => T): Result<T, E>
|
|
411
|
+
function toResult<T, E = unknown>(promise: Promise<T>): Promise<Result<T, E>>
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
#### `unwrapResult`
|
|
415
|
+
|
|
416
|
+
Unwraps a `Result`, `Ok`, or `Err` value and returns the value or error in an object. If the result is an `Ok`, the object contains the value and an `undefined` error. If the result is an `Err`, the object contains an `undefined` value and the error.
|
|
417
|
+
|
|
418
|
+
**Example:**
|
|
419
|
+
|
|
420
|
+
```ts
|
|
421
|
+
const result = toResult(() => JSON.parse('{"foo":"bar"}'))
|
|
422
|
+
const { value, error } = unwrapResult(result)
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
**Type Definition:**
|
|
426
|
+
|
|
427
|
+
```ts
|
|
428
|
+
function unwrapResult<T>(result: Ok<T>): { value: T, error: undefined }
|
|
429
|
+
function unwrapResult<E>(result: Err<E>): { value: undefined, error: E }
|
|
430
|
+
function unwrapResult<T, E>(result: Result<T, E>): { value: T, error: undefined } | { value: undefined, error: E }
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
#### `tryCatch`
|
|
434
|
+
|
|
435
|
+
A simpler alternative to `toResult` + `unwrapResult`. It executes a function that might throw an error and directly returns the result in a `ResultData` format. Works with both synchronous functions and promises.
|
|
436
|
+
|
|
437
|
+
**Example:**
|
|
438
|
+
|
|
439
|
+
```ts
|
|
440
|
+
import { tryCatch } from 'utilful'
|
|
441
|
+
|
|
442
|
+
// Synchronous usage
|
|
443
|
+
const { value, error } = tryCatch(() => JSON.parse('{"foo":"bar"}'))
|
|
444
|
+
|
|
445
|
+
// Asynchronous usage
|
|
446
|
+
const { value, error } = await tryCatch(fetch('https://api.example.com/data').then(r => r.json()))
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
**Type Definition:**
|
|
450
|
+
|
|
451
|
+
```ts
|
|
452
|
+
function tryCatch<T, E = unknown>(fn: () => T): { value: T, error: undefined } | { value: undefined, error: E }
|
|
453
|
+
function tryCatch<T, E = unknown>(promise: Promise<T>): Promise<{ value: T, error: undefined } | { value: undefined, error: E }>
|
|
454
|
+
```
|
|
455
|
+
|
|
330
456
|
### String
|
|
331
457
|
|
|
332
458
|
#### `template`
|
package/dist/csv.d.mts
CHANGED
|
@@ -34,8 +34,8 @@ declare function createCSV<T extends Record<string, unknown>>(data: T[], columns
|
|
|
34
34
|
* Within quoted values, double quotes are escaped by doubling them.
|
|
35
35
|
*
|
|
36
36
|
* @example
|
|
37
|
-
* escapeCSVValue('hello, world')
|
|
38
|
-
* escapeCSVValue('contains "quotes"')
|
|
37
|
+
* escapeCSVValue('hello, world') // "hello, world"
|
|
38
|
+
* escapeCSVValue('contains "quotes"') // "contains ""quotes"""
|
|
39
39
|
*/
|
|
40
40
|
declare function escapeCSVValue(value: unknown, options?: {
|
|
41
41
|
/** @default ',' */
|
package/dist/csv.d.ts
CHANGED
|
@@ -34,8 +34,8 @@ declare function createCSV<T extends Record<string, unknown>>(data: T[], columns
|
|
|
34
34
|
* Within quoted values, double quotes are escaped by doubling them.
|
|
35
35
|
*
|
|
36
36
|
* @example
|
|
37
|
-
* escapeCSVValue('hello, world')
|
|
38
|
-
* escapeCSVValue('contains "quotes"')
|
|
37
|
+
* escapeCSVValue('hello, world') // "hello, world"
|
|
38
|
+
* escapeCSVValue('contains "quotes"') // "contains ""quotes"""
|
|
39
39
|
*/
|
|
40
40
|
declare function escapeCSVValue(value: unknown, options?: {
|
|
41
41
|
/** @default ',' */
|
package/dist/emitter.d.mts
CHANGED
|
@@ -5,7 +5,7 @@ type EventHandlerList<T = unknown> = Handler<T>[];
|
|
|
5
5
|
type WildCardEventHandlerList<T = Record<string, unknown>> = WildcardHandler<T>[];
|
|
6
6
|
type EventHandlerMap<Events extends Record<EventType, unknown>> = Map<keyof Events | '*', EventHandlerList<Events[keyof Events]> | WildCardEventHandlerList<Events>>;
|
|
7
7
|
interface Emitter<Events extends Record<EventType, unknown>> {
|
|
8
|
-
|
|
8
|
+
events: EventHandlerMap<Events>;
|
|
9
9
|
on<Key extends keyof Events>(type: Key, handler: Handler<Events[Key]>): void;
|
|
10
10
|
on(type: '*', handler: WildcardHandler<Events>): void;
|
|
11
11
|
off<Key extends keyof Events>(type: Key, handler?: Handler<Events[Key]>): void;
|
|
@@ -19,6 +19,6 @@ interface Emitter<Events extends Record<EventType, unknown>> {
|
|
|
19
19
|
* @remarks Ported from `mitt`.
|
|
20
20
|
* @see https://github.com/developit/mitt
|
|
21
21
|
*/
|
|
22
|
-
declare function createEmitter<Events extends Record<EventType, unknown>>(
|
|
22
|
+
declare function createEmitter<Events extends Record<EventType, unknown>>(events?: EventHandlerMap<Events>): Emitter<Events>;
|
|
23
23
|
|
|
24
24
|
export { type Emitter, type EventHandlerList, type EventHandlerMap, type EventType, type Handler, type WildCardEventHandlerList, type WildcardHandler, createEmitter };
|
package/dist/emitter.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ type EventHandlerList<T = unknown> = Handler<T>[];
|
|
|
5
5
|
type WildCardEventHandlerList<T = Record<string, unknown>> = WildcardHandler<T>[];
|
|
6
6
|
type EventHandlerMap<Events extends Record<EventType, unknown>> = Map<keyof Events | '*', EventHandlerList<Events[keyof Events]> | WildCardEventHandlerList<Events>>;
|
|
7
7
|
interface Emitter<Events extends Record<EventType, unknown>> {
|
|
8
|
-
|
|
8
|
+
events: EventHandlerMap<Events>;
|
|
9
9
|
on<Key extends keyof Events>(type: Key, handler: Handler<Events[Key]>): void;
|
|
10
10
|
on(type: '*', handler: WildcardHandler<Events>): void;
|
|
11
11
|
off<Key extends keyof Events>(type: Key, handler?: Handler<Events[Key]>): void;
|
|
@@ -19,6 +19,6 @@ interface Emitter<Events extends Record<EventType, unknown>> {
|
|
|
19
19
|
* @remarks Ported from `mitt`.
|
|
20
20
|
* @see https://github.com/developit/mitt
|
|
21
21
|
*/
|
|
22
|
-
declare function createEmitter<Events extends Record<EventType, unknown>>(
|
|
22
|
+
declare function createEmitter<Events extends Record<EventType, unknown>>(events?: EventHandlerMap<Events>): Emitter<Events>;
|
|
23
23
|
|
|
24
24
|
export { type Emitter, type EventHandlerList, type EventHandlerMap, type EventType, type Handler, type WildCardEventHandlerList, type WildcardHandler, createEmitter };
|
package/dist/emitter.mjs
CHANGED
|
@@ -1,62 +1,61 @@
|
|
|
1
|
-
function createEmitter(
|
|
2
|
-
|
|
1
|
+
function createEmitter(events) {
|
|
2
|
+
events ||= /* @__PURE__ */ new Map();
|
|
3
3
|
return {
|
|
4
4
|
/**
|
|
5
5
|
* A Map of event names to registered handler functions.
|
|
6
6
|
*/
|
|
7
|
-
|
|
7
|
+
events,
|
|
8
8
|
/**
|
|
9
9
|
* Register an event handler for the given type.
|
|
10
|
-
*
|
|
11
|
-
* @param {Function} handler Function to call in response to given event
|
|
10
|
+
*
|
|
12
11
|
* @memberOf createEmitter
|
|
13
12
|
*/
|
|
14
13
|
on(type, handler) {
|
|
15
|
-
const handlers =
|
|
14
|
+
const handlers = events.get(type);
|
|
16
15
|
if (handlers) {
|
|
17
16
|
handlers.push(handler);
|
|
18
17
|
} else {
|
|
19
|
-
|
|
18
|
+
events.set(type, [handler]);
|
|
20
19
|
}
|
|
21
20
|
},
|
|
22
21
|
/**
|
|
23
22
|
* Remove an event handler for the given type.
|
|
23
|
+
*
|
|
24
|
+
* @remarks
|
|
24
25
|
* If `handler` is omitted, all handlers of the given type are removed.
|
|
25
26
|
*
|
|
26
|
-
* @param {string|symbol} type Type of event to unregister `handler` from (`'*'` to remove a wildcard handler)
|
|
27
|
-
* @param {Function} [handler] Handler function to remove
|
|
28
27
|
* @memberOf createEmitter
|
|
29
28
|
*/
|
|
30
29
|
off(type, handler) {
|
|
31
|
-
const handlers =
|
|
30
|
+
const handlers = events.get(type);
|
|
32
31
|
if (handlers) {
|
|
33
32
|
if (handler) {
|
|
34
33
|
handlers.splice(handlers.indexOf(handler) >>> 0, 1);
|
|
35
34
|
} else {
|
|
36
|
-
|
|
35
|
+
events.set(type, []);
|
|
37
36
|
}
|
|
38
37
|
}
|
|
39
38
|
},
|
|
40
39
|
/**
|
|
41
40
|
* Invoke all handlers for the given type.
|
|
42
|
-
* If present, `'*'` handlers are invoked after type-matched handlers.
|
|
43
41
|
*
|
|
44
42
|
* @remarks
|
|
43
|
+
* If present, `'*'` handlers are invoked after type-matched handlers.
|
|
45
44
|
* Manually firing '*' handlers is not supported.
|
|
46
45
|
*
|
|
47
|
-
* @param {string|symbol} type The event type to invoke
|
|
48
|
-
* @param {Any} [evt] Any value (object is recommended and powerful), passed to each handler
|
|
49
46
|
* @memberOf createEmitter
|
|
50
47
|
*/
|
|
51
48
|
emit(type, evt) {
|
|
52
|
-
let handlers =
|
|
53
|
-
handlers
|
|
54
|
-
handler
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
handlers
|
|
58
|
-
|
|
59
|
-
|
|
49
|
+
let handlers = events.get(type);
|
|
50
|
+
if (handlers) {
|
|
51
|
+
for (const handler of [...handlers])
|
|
52
|
+
handler(evt);
|
|
53
|
+
}
|
|
54
|
+
handlers = events.get("*");
|
|
55
|
+
if (handlers) {
|
|
56
|
+
for (const handler of [...handlers])
|
|
57
|
+
handler(type, evt);
|
|
58
|
+
}
|
|
60
59
|
}
|
|
61
60
|
};
|
|
62
61
|
}
|
package/dist/index.d.mts
CHANGED
|
@@ -2,9 +2,9 @@ export { MaybeArray, toArray } from './array.mjs';
|
|
|
2
2
|
export { CSVRow, createCSV, escapeCSVValue, parseCSV } from './csv.mjs';
|
|
3
3
|
export { Emitter, EventHandlerList, EventHandlerMap, EventType, Handler, WildCardEventHandlerList, WildcardHandler, createEmitter } from './emitter.mjs';
|
|
4
4
|
export { cloneJSON, tryParseJSON } from './json.mjs';
|
|
5
|
-
export { lazy } from './lazy.mjs';
|
|
6
5
|
export { interopDefault } from './module.mjs';
|
|
7
|
-
export { deepApply, objectEntries, objectKeys } from './object.mjs';
|
|
6
|
+
export { deepApply, memoize, objectEntries, objectKeys } from './object.mjs';
|
|
8
7
|
export { QueryObject, QueryValue, getPathname, joinURL, withBase, withLeadingSlash, withQuery, withTrailingSlash, withoutBase, withoutLeadingSlash, withoutTrailingSlash } from './path.mjs';
|
|
8
|
+
export { Err, ErrData, Ok, OkData, Result, ResultData, err, ok, toResult, tryCatch, unwrapResult } from './result.mjs';
|
|
9
9
|
export { generateRandomId, template } from './string.mjs';
|
|
10
10
|
export { AutocompletableString, LooseAutocomplete, UnifyIntersection } from './types.mjs';
|
package/dist/index.d.ts
CHANGED
|
@@ -2,9 +2,9 @@ export { MaybeArray, toArray } from './array.js';
|
|
|
2
2
|
export { CSVRow, createCSV, escapeCSVValue, parseCSV } from './csv.js';
|
|
3
3
|
export { Emitter, EventHandlerList, EventHandlerMap, EventType, Handler, WildCardEventHandlerList, WildcardHandler, createEmitter } from './emitter.js';
|
|
4
4
|
export { cloneJSON, tryParseJSON } from './json.js';
|
|
5
|
-
export { lazy } from './lazy.js';
|
|
6
5
|
export { interopDefault } from './module.js';
|
|
7
|
-
export { deepApply, objectEntries, objectKeys } from './object.js';
|
|
6
|
+
export { deepApply, memoize, objectEntries, objectKeys } from './object.js';
|
|
8
7
|
export { QueryObject, QueryValue, getPathname, joinURL, withBase, withLeadingSlash, withQuery, withTrailingSlash, withoutBase, withoutLeadingSlash, withoutTrailingSlash } from './path.js';
|
|
8
|
+
export { Err, ErrData, Ok, OkData, Result, ResultData, err, ok, toResult, tryCatch, unwrapResult } from './result.js';
|
|
9
9
|
export { generateRandomId, template } from './string.js';
|
|
10
10
|
export { AutocompletableString, LooseAutocomplete, UnifyIntersection } from './types.js';
|
package/dist/index.mjs
CHANGED
|
@@ -2,8 +2,8 @@ export { toArray } from './array.mjs';
|
|
|
2
2
|
export { createCSV, escapeCSVValue, parseCSV } from './csv.mjs';
|
|
3
3
|
export { createEmitter } from './emitter.mjs';
|
|
4
4
|
export { cloneJSON, tryParseJSON } from './json.mjs';
|
|
5
|
-
export { lazy } from './lazy.mjs';
|
|
6
5
|
export { interopDefault } from './module.mjs';
|
|
7
|
-
export { deepApply, objectEntries, objectKeys } from './object.mjs';
|
|
6
|
+
export { deepApply, memoize, objectEntries, objectKeys } from './object.mjs';
|
|
8
7
|
export { getPathname, joinURL, withBase, withLeadingSlash, withQuery, withTrailingSlash, withoutBase, withoutLeadingSlash, withoutTrailingSlash } from './path.mjs';
|
|
8
|
+
export { Err, Ok, err, ok, toResult, tryCatch, unwrapResult } from './result.mjs';
|
|
9
9
|
export { generateRandomId, template } from './string.mjs';
|
package/dist/object.d.mts
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A simple general purpose memoizer utility.
|
|
3
|
+
* - Lazily computes a value when accessed
|
|
4
|
+
* - Auto-caches the result by overwriting the getter
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* Useful for deferring initialization or expensive operations. Unlike a simple getter, there is no runtime overhead after the first invokation, since the getter itself is overwritten with the memoized value.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* const myValue = lazy(() => 'Hello, World!')
|
|
11
|
+
* console.log(myValue.value) // Computes value, overwrites getter
|
|
12
|
+
* console.log(myValue.value) // Returns cached value
|
|
13
|
+
* console.log(myValue.value) // Returns cached value
|
|
14
|
+
*/
|
|
15
|
+
declare function memoize<T>(getter: () => T): {
|
|
16
|
+
value: T;
|
|
17
|
+
};
|
|
1
18
|
/**
|
|
2
19
|
* Strictly typed `Object.keys`.
|
|
3
20
|
*/
|
|
@@ -11,4 +28,4 @@ declare function objectEntries<T extends Record<any, any>>(obj: T): Array<[keyof
|
|
|
11
28
|
*/
|
|
12
29
|
declare function deepApply<T extends Record<any, any>>(data: T, callback: (item: T, key: keyof T, value: T[keyof T]) => void): void;
|
|
13
30
|
|
|
14
|
-
export { deepApply, objectEntries, objectKeys };
|
|
31
|
+
export { deepApply, memoize, objectEntries, objectKeys };
|
package/dist/object.d.ts
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A simple general purpose memoizer utility.
|
|
3
|
+
* - Lazily computes a value when accessed
|
|
4
|
+
* - Auto-caches the result by overwriting the getter
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* Useful for deferring initialization or expensive operations. Unlike a simple getter, there is no runtime overhead after the first invokation, since the getter itself is overwritten with the memoized value.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* const myValue = lazy(() => 'Hello, World!')
|
|
11
|
+
* console.log(myValue.value) // Computes value, overwrites getter
|
|
12
|
+
* console.log(myValue.value) // Returns cached value
|
|
13
|
+
* console.log(myValue.value) // Returns cached value
|
|
14
|
+
*/
|
|
15
|
+
declare function memoize<T>(getter: () => T): {
|
|
16
|
+
value: T;
|
|
17
|
+
};
|
|
1
18
|
/**
|
|
2
19
|
* Strictly typed `Object.keys`.
|
|
3
20
|
*/
|
|
@@ -11,4 +28,4 @@ declare function objectEntries<T extends Record<any, any>>(obj: T): Array<[keyof
|
|
|
11
28
|
*/
|
|
12
29
|
declare function deepApply<T extends Record<any, any>>(data: T, callback: (item: T, key: keyof T, value: T[keyof T]) => void): void;
|
|
13
30
|
|
|
14
|
-
export { deepApply, objectEntries, objectKeys };
|
|
31
|
+
export { deepApply, memoize, objectEntries, objectKeys };
|
package/dist/object.mjs
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
function memoize(getter) {
|
|
2
|
+
return {
|
|
3
|
+
get value() {
|
|
4
|
+
const value = getter();
|
|
5
|
+
Object.defineProperty(this, "value", { value });
|
|
6
|
+
return value;
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
}
|
|
1
10
|
function objectKeys(obj) {
|
|
2
11
|
return Object.keys(obj);
|
|
3
12
|
}
|
|
@@ -22,4 +31,4 @@ function isObject(value) {
|
|
|
22
31
|
return Object.prototype.toString.call(value) === "[object Object]";
|
|
23
32
|
}
|
|
24
33
|
|
|
25
|
-
export { deepApply, objectEntries, objectKeys };
|
|
34
|
+
export { deepApply, memoize, objectEntries, objectKeys };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
type Result<T, E> = Ok<T> | Err<E>;
|
|
2
|
+
interface OkData<T> {
|
|
3
|
+
value: T;
|
|
4
|
+
error: undefined;
|
|
5
|
+
}
|
|
6
|
+
interface ErrData<E> {
|
|
7
|
+
value: undefined;
|
|
8
|
+
error: E;
|
|
9
|
+
}
|
|
10
|
+
type ResultData<T, E> = OkData<T> | ErrData<E>;
|
|
11
|
+
declare class Ok<T> {
|
|
12
|
+
readonly value: T;
|
|
13
|
+
readonly ok = true;
|
|
14
|
+
constructor(value: T);
|
|
15
|
+
}
|
|
16
|
+
declare class Err<E> {
|
|
17
|
+
readonly error: E;
|
|
18
|
+
readonly ok = false;
|
|
19
|
+
constructor(error: E);
|
|
20
|
+
}
|
|
21
|
+
declare function ok<T>(value: T): Ok<T>;
|
|
22
|
+
declare function err<E extends string = string>(error: E): Err<E>;
|
|
23
|
+
declare function err<E = unknown>(error: E): Err<E>;
|
|
24
|
+
declare function toResult<T, E = unknown>(fn: () => T): Result<T, E>;
|
|
25
|
+
declare function toResult<T, E = unknown>(promise: Promise<T>): Promise<Result<T, E>>;
|
|
26
|
+
declare function unwrapResult<T>(result: Ok<T>): OkData<T>;
|
|
27
|
+
declare function unwrapResult<E>(result: Err<E>): ErrData<E>;
|
|
28
|
+
declare function unwrapResult<T, E>(result: Result<T, E>): ResultData<T, E>;
|
|
29
|
+
declare function tryCatch<T, E = unknown>(fn: () => T): ResultData<T, E>;
|
|
30
|
+
declare function tryCatch<T, E = unknown>(promise: Promise<T>): Promise<ResultData<T, E>>;
|
|
31
|
+
|
|
32
|
+
export { Err, type ErrData, Ok, type OkData, type Result, type ResultData, err, ok, toResult, tryCatch, unwrapResult };
|
package/dist/result.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
type Result<T, E> = Ok<T> | Err<E>;
|
|
2
|
+
interface OkData<T> {
|
|
3
|
+
value: T;
|
|
4
|
+
error: undefined;
|
|
5
|
+
}
|
|
6
|
+
interface ErrData<E> {
|
|
7
|
+
value: undefined;
|
|
8
|
+
error: E;
|
|
9
|
+
}
|
|
10
|
+
type ResultData<T, E> = OkData<T> | ErrData<E>;
|
|
11
|
+
declare class Ok<T> {
|
|
12
|
+
readonly value: T;
|
|
13
|
+
readonly ok = true;
|
|
14
|
+
constructor(value: T);
|
|
15
|
+
}
|
|
16
|
+
declare class Err<E> {
|
|
17
|
+
readonly error: E;
|
|
18
|
+
readonly ok = false;
|
|
19
|
+
constructor(error: E);
|
|
20
|
+
}
|
|
21
|
+
declare function ok<T>(value: T): Ok<T>;
|
|
22
|
+
declare function err<E extends string = string>(error: E): Err<E>;
|
|
23
|
+
declare function err<E = unknown>(error: E): Err<E>;
|
|
24
|
+
declare function toResult<T, E = unknown>(fn: () => T): Result<T, E>;
|
|
25
|
+
declare function toResult<T, E = unknown>(promise: Promise<T>): Promise<Result<T, E>>;
|
|
26
|
+
declare function unwrapResult<T>(result: Ok<T>): OkData<T>;
|
|
27
|
+
declare function unwrapResult<E>(result: Err<E>): ErrData<E>;
|
|
28
|
+
declare function unwrapResult<T, E>(result: Result<T, E>): ResultData<T, E>;
|
|
29
|
+
declare function tryCatch<T, E = unknown>(fn: () => T): ResultData<T, E>;
|
|
30
|
+
declare function tryCatch<T, E = unknown>(promise: Promise<T>): Promise<ResultData<T, E>>;
|
|
31
|
+
|
|
32
|
+
export { Err, type ErrData, Ok, type OkData, type Result, type ResultData, err, ok, toResult, tryCatch, unwrapResult };
|
package/dist/result.mjs
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
class Ok {
|
|
2
|
+
value;
|
|
3
|
+
ok = true;
|
|
4
|
+
constructor(value) {
|
|
5
|
+
this.value = value;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
class Err {
|
|
9
|
+
error;
|
|
10
|
+
ok = false;
|
|
11
|
+
constructor(error) {
|
|
12
|
+
this.error = error;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function ok(value) {
|
|
16
|
+
return new Ok(value);
|
|
17
|
+
}
|
|
18
|
+
function err(error) {
|
|
19
|
+
return new Err(error);
|
|
20
|
+
}
|
|
21
|
+
function toResult(fnOrPromise) {
|
|
22
|
+
if (fnOrPromise instanceof Promise) {
|
|
23
|
+
return fnOrPromise.then(ok).catch(err);
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
return ok(fnOrPromise());
|
|
27
|
+
} catch (error) {
|
|
28
|
+
return err(error);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function unwrapResult(result) {
|
|
32
|
+
return result.ok ? { value: result.value, error: void 0 } : { value: void 0, error: result.error };
|
|
33
|
+
}
|
|
34
|
+
function tryCatch(fnOrPromise) {
|
|
35
|
+
if (fnOrPromise instanceof Promise) {
|
|
36
|
+
return toResult(fnOrPromise).then(
|
|
37
|
+
(result) => unwrapResult(result)
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
return unwrapResult(toResult(fnOrPromise));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export { Err, Ok, err, ok, toResult, tryCatch, unwrapResult };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "utilful",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "2.0.0",
|
|
5
5
|
"packageManager": "pnpm@10.5.2",
|
|
6
6
|
"description": "A collection of TypeScript utilities",
|
|
7
7
|
"author": "Johann Schopplich <hello@johannschopplich.com>",
|
|
@@ -36,10 +36,6 @@
|
|
|
36
36
|
"types": "./dist/json.d.mts",
|
|
37
37
|
"default": "./dist/json.mjs"
|
|
38
38
|
},
|
|
39
|
-
"./lazy": {
|
|
40
|
-
"types": "./dist/lazy.d.mts",
|
|
41
|
-
"default": "./dist/lazy.mjs"
|
|
42
|
-
},
|
|
43
39
|
"./module": {
|
|
44
40
|
"types": "./dist/module.d.mts",
|
|
45
41
|
"default": "./dist/module.mjs"
|
|
@@ -52,6 +48,10 @@
|
|
|
52
48
|
"types": "./dist/path.d.mts",
|
|
53
49
|
"default": "./dist/path.mjs"
|
|
54
50
|
},
|
|
51
|
+
"./result": {
|
|
52
|
+
"types": "./dist/result.d.mts",
|
|
53
|
+
"default": "./dist/result.mjs"
|
|
54
|
+
},
|
|
55
55
|
"./string": {
|
|
56
56
|
"types": "./dist/string.d.mts",
|
|
57
57
|
"default": "./dist/string.mjs"
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"default": "./dist/types.mjs"
|
|
62
62
|
}
|
|
63
63
|
},
|
|
64
|
-
"types": "./dist/index.d.
|
|
64
|
+
"types": "./dist/index.d.mts",
|
|
65
65
|
"files": [
|
|
66
66
|
"dist"
|
|
67
67
|
],
|
package/dist/lazy.d.mts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A simple general purpose memoizer utility.
|
|
3
|
-
* - Lazily computes a value when accessed
|
|
4
|
-
* - Auto-caches the result by overwriting the getter
|
|
5
|
-
* - Typesafe
|
|
6
|
-
*
|
|
7
|
-
* @remarks
|
|
8
|
-
* Useful for deferring initialization or expensive operations. Unlike a simple getter, there is no runtime overhead after the first invokation, since the getter itself is overwritten with the memoized value.
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* const myValue = lazy(() => 'Hello, World!')
|
|
12
|
-
* console.log(myValue.value) // Computes value, overwrites getter
|
|
13
|
-
* console.log(myValue.value) // Returns cached value
|
|
14
|
-
* console.log(myValue.value) // Returns cached value
|
|
15
|
-
*/
|
|
16
|
-
declare function lazy<T>(getter: () => T): {
|
|
17
|
-
value: T;
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export { lazy };
|
package/dist/lazy.d.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A simple general purpose memoizer utility.
|
|
3
|
-
* - Lazily computes a value when accessed
|
|
4
|
-
* - Auto-caches the result by overwriting the getter
|
|
5
|
-
* - Typesafe
|
|
6
|
-
*
|
|
7
|
-
* @remarks
|
|
8
|
-
* Useful for deferring initialization or expensive operations. Unlike a simple getter, there is no runtime overhead after the first invokation, since the getter itself is overwritten with the memoized value.
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* const myValue = lazy(() => 'Hello, World!')
|
|
12
|
-
* console.log(myValue.value) // Computes value, overwrites getter
|
|
13
|
-
* console.log(myValue.value) // Returns cached value
|
|
14
|
-
* console.log(myValue.value) // Returns cached value
|
|
15
|
-
*/
|
|
16
|
-
declare function lazy<T>(getter: () => T): {
|
|
17
|
-
value: T;
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export { lazy };
|