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 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.all.clear()
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'); // "hello, world"
38
- * escapeCSVValue('contains "quotes"'); // "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'); // "hello, world"
38
- * escapeCSVValue('contains "quotes"'); // "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 ',' */
@@ -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
- all: EventHandlerMap<Events>;
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>>(all?: EventHandlerMap<Events>): Emitter<Events>;
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
- all: EventHandlerMap<Events>;
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>>(all?: EventHandlerMap<Events>): Emitter<Events>;
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(all) {
2
- all ||= /* @__PURE__ */ new Map();
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
- all,
7
+ events,
8
8
  /**
9
9
  * Register an event handler for the given type.
10
- * @param {string|symbol} type Type of event to listen for, or `'*'` for all events
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 = all.get(type);
14
+ const handlers = events.get(type);
16
15
  if (handlers) {
17
16
  handlers.push(handler);
18
17
  } else {
19
- all.set(type, [handler]);
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 = all.get(type);
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
- all.set(type, []);
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 = all.get(type);
53
- handlers?.slice().forEach((handler) => {
54
- handler(evt);
55
- });
56
- handlers = all.get("*");
57
- handlers?.slice().forEach((handler) => {
58
- handler(type, evt);
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 };
@@ -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 };
@@ -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": "1.2.0",
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.ts",
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 };
package/dist/lazy.mjs DELETED
@@ -1,11 +0,0 @@
1
- function lazy(getter) {
2
- return {
3
- get value() {
4
- const value = getter();
5
- Object.defineProperty(this, "value", { value });
6
- return value;
7
- }
8
- };
9
- }
10
-
11
- export { lazy };