go-go-try 7.2.1 → 7.4.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/AGENTS.md +81 -23
- package/README.md +84 -18
- package/dist/index.cjs +104 -61
- package/dist/index.d.cts +217 -94
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +217 -94
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +102 -62
- package/package.json +3 -3
- package/src/assert.ts +59 -0
- package/src/goTry.ts +45 -0
- package/src/goTryAll.ts +141 -0
- package/src/goTryOr.ts +55 -0
- package/src/goTryRaw.ts +126 -0
- package/src/index.test.ts +411 -22
- package/src/index.ts +27 -459
- package/src/internals.ts +45 -0
- package/src/result-helpers.ts +46 -0
- package/src/tagged-error.ts +38 -0
- package/src/types.ts +64 -0
- package/src/unknown-error.ts +20 -0
package/src/assert.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Asserts that a condition is true, otherwise throws the provided error.
|
|
3
|
+
* Provides type narrowing when used with Result types.
|
|
4
|
+
*
|
|
5
|
+
* @param condition - The condition to assert
|
|
6
|
+
* @param error - An Error instance or string message to throw if condition is falsy
|
|
7
|
+
* @throws {Error} Throws the provided error if condition is falsy
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* // With Result type - narrows error to undefined after assertion
|
|
11
|
+
* const [err, user] = goTryRaw(fetchUser(), DatabaseError)
|
|
12
|
+
* assert(err === undefined, new DatabaseError('Failed to fetch user'))
|
|
13
|
+
* // TypeScript now knows: err is undefined, user is User
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* // With string message
|
|
17
|
+
* assert(response.ok, 'Response was not ok')
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* // With custom Error instance
|
|
21
|
+
* assert(value > 0, new ValidationError('Value must be positive'))
|
|
22
|
+
*/
|
|
23
|
+
export function assert(condition: unknown, error: Error | string): asserts condition
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Asserts that a condition is true, otherwise instantiates and throws the error class.
|
|
27
|
+
* Provides type narrowing when used with Result types.
|
|
28
|
+
*
|
|
29
|
+
* @param condition - The condition to assert
|
|
30
|
+
* @param ErrorClass - An Error class constructor (e.g., from taggedError)
|
|
31
|
+
* @param message - The error message to pass to the constructor
|
|
32
|
+
* @throws {Error} Throws a new instance of ErrorClass if condition is falsy
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* const ValidationError = taggedError('ValidationError')
|
|
36
|
+
* assert(value > 0, ValidationError, 'Value must be positive')
|
|
37
|
+
* // Equivalent to: if (!(value > 0)) throw new ValidationError('Value must be positive')
|
|
38
|
+
*/
|
|
39
|
+
export function assert<T extends Error>(
|
|
40
|
+
condition: unknown,
|
|
41
|
+
ErrorClass: new (message: string) => T,
|
|
42
|
+
message: string,
|
|
43
|
+
): asserts condition
|
|
44
|
+
|
|
45
|
+
export function assert(
|
|
46
|
+
condition: unknown,
|
|
47
|
+
errorOrClass: Error | string | (new (message: string) => Error),
|
|
48
|
+
message?: string,
|
|
49
|
+
): asserts condition {
|
|
50
|
+
if (!condition) {
|
|
51
|
+
if (typeof errorOrClass === 'string') {
|
|
52
|
+
throw new Error(errorOrClass)
|
|
53
|
+
}
|
|
54
|
+
if (typeof errorOrClass === 'function' && message !== undefined) {
|
|
55
|
+
throw new errorOrClass(message)
|
|
56
|
+
}
|
|
57
|
+
throw errorOrClass
|
|
58
|
+
}
|
|
59
|
+
}
|
package/src/goTry.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { Result } from './types.js'
|
|
2
|
+
import { success, failure } from './result-helpers.js'
|
|
3
|
+
import { isPromise, getErrorMessage } from './internals.js'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Executes a function, promise, or value and returns a Result type.
|
|
7
|
+
* If an error occurs, it returns a Failure with the error message as a string.
|
|
8
|
+
*
|
|
9
|
+
* @template T The type of the successful result
|
|
10
|
+
* @param {T | Promise<T> | (() => T | Promise<T>)} value - The value, promise, or function to execute
|
|
11
|
+
* @returns {Result<string, T> | Promise<Result<string, T>>} A Result type or a Promise of a Result type
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* // With a value
|
|
15
|
+
* const [err, result] = goTry(42);
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* // With a function
|
|
19
|
+
* const [err, result] = goTry(() => JSON.parse('{"key": "value"}'));
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* // With a promise
|
|
23
|
+
* const [err, result] = await goTry(fetch('https://api.example.com/data'));
|
|
24
|
+
*/
|
|
25
|
+
export function goTry<T>(fn: () => never): Result<string, never>
|
|
26
|
+
export function goTry<T>(fn: () => Promise<T>): Promise<Result<string, T>>
|
|
27
|
+
export function goTry<T>(promise: Promise<T>): Promise<Result<string, T>>
|
|
28
|
+
export function goTry<T>(fn: () => T): Result<string, T>
|
|
29
|
+
export function goTry<T>(value: T): Result<string, T>
|
|
30
|
+
export function goTry<T>(
|
|
31
|
+
value: T | Promise<T> | (() => T | Promise<T>),
|
|
32
|
+
): Result<string, T> | Promise<Result<string, T>> {
|
|
33
|
+
try {
|
|
34
|
+
const result =
|
|
35
|
+
typeof value === 'function' ? (value as () => T | Promise<T>)() : value
|
|
36
|
+
if (isPromise<T>(result)) {
|
|
37
|
+
return result
|
|
38
|
+
.then((resolvedValue) => success<T>(resolvedValue))
|
|
39
|
+
.catch((err) => failure<string>(getErrorMessage(err)))
|
|
40
|
+
}
|
|
41
|
+
return success<T>(result)
|
|
42
|
+
} catch (err) {
|
|
43
|
+
return failure<string>(getErrorMessage(err))
|
|
44
|
+
}
|
|
45
|
+
}
|
package/src/goTryAll.ts
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import type { GoTryAllOptions } from './types.js'
|
|
2
|
+
import { isError, getErrorMessage, type PromiseFactory } from './internals.js'
|
|
3
|
+
|
|
4
|
+
async function runWithConcurrency<T extends readonly unknown[]>(
|
|
5
|
+
items: { [K in keyof T]: Promise<T[K]> | PromiseFactory<T[K]> },
|
|
6
|
+
concurrency: number,
|
|
7
|
+
): Promise<PromiseSettledResult<T[number]>[]> {
|
|
8
|
+
if (items.length === 0) {
|
|
9
|
+
return []
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Auto-detect factory mode by checking if first item is a function
|
|
13
|
+
const isFactoryMode = typeof items[0] === 'function'
|
|
14
|
+
|
|
15
|
+
// concurrency of 0 means unlimited (run all in parallel)
|
|
16
|
+
if (!isFactoryMode && (concurrency <= 0)) {
|
|
17
|
+
return Promise.allSettled(items as Promise<T[number]>[])
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const results: PromiseSettledResult<T[number]>[] = new Array(items.length)
|
|
21
|
+
let index = 0
|
|
22
|
+
|
|
23
|
+
async function worker(): Promise<void> {
|
|
24
|
+
while (index < items.length) {
|
|
25
|
+
const currentIndex = index++
|
|
26
|
+
try {
|
|
27
|
+
const item = items[currentIndex]
|
|
28
|
+
// If factory mode, call the function; otherwise await the promise directly
|
|
29
|
+
const value = isFactoryMode
|
|
30
|
+
? await (item as PromiseFactory<T[number]>)()
|
|
31
|
+
: await (item as Promise<T[number]>)
|
|
32
|
+
results[currentIndex] = { status: 'fulfilled', value }
|
|
33
|
+
} catch (reason) {
|
|
34
|
+
results[currentIndex] = { status: 'rejected', reason }
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Determine number of workers
|
|
40
|
+
const workerCount = concurrency <= 0 ? items.length : Math.min(concurrency, items.length)
|
|
41
|
+
|
|
42
|
+
// Start workers
|
|
43
|
+
const workers: Promise<void>[] = []
|
|
44
|
+
for (let i = 0; i < workerCount; i++) {
|
|
45
|
+
workers.push(worker())
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
await Promise.all(workers)
|
|
49
|
+
return results
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Executes multiple promises or factory functions in parallel (or with limited concurrency)
|
|
54
|
+
* and returns a tuple of [errors, results]. Unlike Promise.all, this doesn't fail fast -
|
|
55
|
+
* it waits for all promises to settle.
|
|
56
|
+
*
|
|
57
|
+
* Accepts either:
|
|
58
|
+
* - An array of promises (for simple parallel execution)
|
|
59
|
+
* - An array of factory functions that return promises (for lazy execution with concurrency control)
|
|
60
|
+
*
|
|
61
|
+
* @template T The tuple type of all promise results
|
|
62
|
+
* @param {readonly [...{ [K in keyof T]: Promise<T[K]> | (() => Promise<T[K]>) }]} items - Array of promises or factories
|
|
63
|
+
* @param {GoTryAllOptions} options - Optional configuration
|
|
64
|
+
* @returns {Promise<[{ [K in keyof T]: string | undefined }, { [K in keyof T]: T[K] | undefined }]>}
|
|
65
|
+
* A tuple where the first element is a tuple of errors (or undefined) and
|
|
66
|
+
* the second element is a tuple of results (or undefined), preserving input order
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* // Run all in parallel (default) - with promises
|
|
70
|
+
* const [errors, results] = await goTryAll([
|
|
71
|
+
* fetchUser(1),
|
|
72
|
+
* fetchUser(2),
|
|
73
|
+
* fetchUser(3)
|
|
74
|
+
* ])
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* // Limit concurrency with factory functions (lazy execution)
|
|
78
|
+
* const [errors, results] = await goTryAll([
|
|
79
|
+
* () => fetchUser(1), // Only called when a slot is available
|
|
80
|
+
* () => fetchUser(2), // Only called when a slot is available
|
|
81
|
+
* () => fetchUser(3), // Only called when a slot is available
|
|
82
|
+
* ], { concurrency: 2 })
|
|
83
|
+
*/
|
|
84
|
+
export async function goTryAll<T extends readonly unknown[]>(
|
|
85
|
+
items: { [K in keyof T]: Promise<T[K]> | (() => Promise<T[K]>) },
|
|
86
|
+
options?: GoTryAllOptions,
|
|
87
|
+
): Promise<[{ [K in keyof T]: string | undefined }, { [K in keyof T]: T[K] | undefined }]> {
|
|
88
|
+
const settled = await runWithConcurrency(items, options?.concurrency ?? 0)
|
|
89
|
+
|
|
90
|
+
const errors = [] as { [K in keyof T]: string | undefined }
|
|
91
|
+
const results = [] as { [K in keyof T]: T[K] | undefined }
|
|
92
|
+
|
|
93
|
+
for (let i = 0; i < settled.length; i++) {
|
|
94
|
+
const item = settled[i]!
|
|
95
|
+
if (item.status === 'fulfilled') {
|
|
96
|
+
;(errors as (string | undefined)[])[i] = undefined
|
|
97
|
+
;(results as unknown[])[i] = (item as PromiseFulfilledResult<T[number]>).value
|
|
98
|
+
} else {
|
|
99
|
+
;(errors as (string | undefined)[])[i] = getErrorMessage((item as PromiseRejectedResult).reason)
|
|
100
|
+
;(results as unknown[])[i] = undefined
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return [errors, results]
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Like `goTryAll`, but returns raw Error objects instead of error messages.
|
|
109
|
+
*
|
|
110
|
+
* @template T The tuple type of all promise results
|
|
111
|
+
* @param {readonly [...{ [K in keyof T]: Promise<T[K]> | (() => Promise<T[K]>) }]} items - Array of promises or factories
|
|
112
|
+
* @param {GoTryAllOptions} options - Optional configuration
|
|
113
|
+
* @returns {Promise<[{ [K in keyof T]: Error | undefined }, { [K in keyof T]: T[K] | undefined }]>}
|
|
114
|
+
* A tuple where the first element is a tuple of Error objects (or undefined) and
|
|
115
|
+
* the second element is a tuple of results (or undefined), preserving input order
|
|
116
|
+
*/
|
|
117
|
+
export async function goTryAllRaw<T extends readonly unknown[]>(
|
|
118
|
+
items: { [K in keyof T]: Promise<T[K]> | (() => Promise<T[K]>) },
|
|
119
|
+
options?: GoTryAllOptions,
|
|
120
|
+
): Promise<[{ [K in keyof T]: Error | undefined }, { [K in keyof T]: T[K] | undefined }]> {
|
|
121
|
+
const settled = await runWithConcurrency(items, options?.concurrency ?? 0)
|
|
122
|
+
|
|
123
|
+
const errors = [] as { [K in keyof T]: Error | undefined }
|
|
124
|
+
const results = [] as { [K in keyof T]: T[K] | undefined }
|
|
125
|
+
|
|
126
|
+
for (let i = 0; i < settled.length; i++) {
|
|
127
|
+
const item = settled[i]!
|
|
128
|
+
if (item.status === 'fulfilled') {
|
|
129
|
+
;(errors as (Error | undefined)[])[i] = undefined
|
|
130
|
+
;(results as unknown[])[i] = (item as PromiseFulfilledResult<T[number]>).value
|
|
131
|
+
} else {
|
|
132
|
+
const reason = (item as PromiseRejectedResult).reason
|
|
133
|
+
;(errors as (Error | undefined)[])[i] = isError(reason)
|
|
134
|
+
? reason
|
|
135
|
+
: new Error(String(reason))
|
|
136
|
+
;(results as unknown[])[i] = undefined
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return [errors, results]
|
|
141
|
+
}
|
package/src/goTryOr.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { ResultWithDefault } from './types.js'
|
|
2
|
+
import { success } from './result-helpers.js'
|
|
3
|
+
import { isPromise, getErrorMessage, resolveDefault } from './internals.js'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Executes a function, promise, or value and returns a Result type with a fallback default.
|
|
7
|
+
* If an error occurs, it returns the error message and the default value.
|
|
8
|
+
*
|
|
9
|
+
* @template T The type of the successful result
|
|
10
|
+
* @param {T | Promise<T> | (() => T | Promise<T>)} value - The value, promise, or function to execute
|
|
11
|
+
* @param {T | (() => T)} defaultValue - The default value or a function to compute it (only called on failure)
|
|
12
|
+
* @returns {ResultWithDefault<string, T> | Promise<ResultWithDefault<string, T>>} A tuple of [error, value] or Promise thereof
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* // With a static default
|
|
16
|
+
* const [err, config] = goTryOr(() => JSON.parse('invalid'), { port: 3000 })
|
|
17
|
+
* // err is the error message, config is { port: 3000 }
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* // With a computed default (lazy evaluation)
|
|
21
|
+
* const [err, user] = await goTryOr(fetchUser(id), () => ({
|
|
22
|
+
* id: 'anonymous',
|
|
23
|
+
* name: 'Guest'
|
|
24
|
+
* }))
|
|
25
|
+
*/
|
|
26
|
+
export function goTryOr<T>(fn: () => never, defaultValue: T | (() => T)): ResultWithDefault<string, T>
|
|
27
|
+
export function goTryOr<T>(
|
|
28
|
+
fn: () => Promise<T>,
|
|
29
|
+
defaultValue: T | (() => T),
|
|
30
|
+
): Promise<ResultWithDefault<string, T>>
|
|
31
|
+
export function goTryOr<T>(
|
|
32
|
+
promise: Promise<T>,
|
|
33
|
+
defaultValue: T | (() => T),
|
|
34
|
+
): Promise<ResultWithDefault<string, T>>
|
|
35
|
+
export function goTryOr<T>(fn: () => T, defaultValue: T | (() => T)): ResultWithDefault<string, T>
|
|
36
|
+
export function goTryOr<T>(value: T, defaultValue: T | (() => T)): ResultWithDefault<string, T>
|
|
37
|
+
export function goTryOr<T>(
|
|
38
|
+
value: T | Promise<T> | (() => T | Promise<T>),
|
|
39
|
+
defaultValue: T | (() => T),
|
|
40
|
+
): ResultWithDefault<string, T> | Promise<ResultWithDefault<string, T>> {
|
|
41
|
+
try {
|
|
42
|
+
const result =
|
|
43
|
+
typeof value === 'function' ? (value as () => T | Promise<T>)() : value
|
|
44
|
+
|
|
45
|
+
if (isPromise<T>(result)) {
|
|
46
|
+
return result
|
|
47
|
+
.then((resolvedValue) => success<T>(resolvedValue))
|
|
48
|
+
.catch((err) => [getErrorMessage(err), resolveDefault(defaultValue)] as const)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return success<T>(result)
|
|
52
|
+
} catch (err) {
|
|
53
|
+
return [getErrorMessage(err), resolveDefault(defaultValue)] as const
|
|
54
|
+
}
|
|
55
|
+
}
|
package/src/goTryRaw.ts
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import type { Result, GoTryRawOptions } from './types.js'
|
|
2
|
+
import { success, failure } from './result-helpers.js'
|
|
3
|
+
import { isPromise, isError } from './internals.js'
|
|
4
|
+
import { UnknownError } from './unknown-error.js'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Checks if a value is a tagged error (has a _tag property).
|
|
8
|
+
*/
|
|
9
|
+
function isTaggedError(err: unknown): err is { _tag: string } {
|
|
10
|
+
return isError(err) && '_tag' in err && typeof (err as { _tag?: unknown })._tag === 'string'
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Executes a function, promise, or value and returns a Result type.
|
|
15
|
+
* If an error occurs, it returns a Failure with the raw error object.
|
|
16
|
+
*
|
|
17
|
+
* @template T The type of the successful result
|
|
18
|
+
* @template E The type of the error
|
|
19
|
+
* @param {T | Promise<T> | (() => T | Promise<T>)} value - The value, promise, or function to execute
|
|
20
|
+
* @param {GoTryRawOptions<E>} [options] - Optional options object
|
|
21
|
+
* @returns {Result<E, T> | Promise<Result<E, T>>} A Result type or a Promise of a Result type
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* // With a value
|
|
25
|
+
* const [err, result] = goTryRaw(42);
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* // With a function
|
|
29
|
+
* const [err, result] = goTryRaw(() => JSON.parse('{"key": "value"}'));
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* // With a promise
|
|
33
|
+
* const [err, result] = await goTryRaw(fetch('https://api.example.com/data'));
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* // With options object - wrap all errors
|
|
37
|
+
* const DatabaseError = taggedError('DatabaseError');
|
|
38
|
+
* const [err, result] = await goTryRaw(fetchData(), { errorClass: DatabaseError });
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* // With options object - systemErrorClass only wraps non-tagged errors
|
|
42
|
+
* const [err, result] = await goTryRaw(fetchData(), { systemErrorClass: UnknownError });
|
|
43
|
+
* // Errors thrown as tagged errors pass through
|
|
44
|
+
* // Other errors are wrapped in UnknownError
|
|
45
|
+
*/
|
|
46
|
+
export function goTryRaw<T>(fn: () => never): Result<Error, never>
|
|
47
|
+
export function goTryRaw<T, E = InstanceType<typeof UnknownError>>(fn: () => never, options: GoTryRawOptions<E>): Result<E, never>
|
|
48
|
+
export function goTryRaw<T>(
|
|
49
|
+
fn: () => Promise<T>,
|
|
50
|
+
): Promise<Result<Error, T>>
|
|
51
|
+
export function goTryRaw<T, E = InstanceType<typeof UnknownError>>(
|
|
52
|
+
fn: () => Promise<T>,
|
|
53
|
+
options: GoTryRawOptions<E>,
|
|
54
|
+
): Promise<Result<E, T>>
|
|
55
|
+
export function goTryRaw<T>(
|
|
56
|
+
promise: Promise<T>,
|
|
57
|
+
): Promise<Result<Error, T>>
|
|
58
|
+
export function goTryRaw<T, E = InstanceType<typeof UnknownError>>(
|
|
59
|
+
promise: Promise<T>,
|
|
60
|
+
options: GoTryRawOptions<E>,
|
|
61
|
+
): Promise<Result<E, T>>
|
|
62
|
+
export function goTryRaw<T>(fn: () => T): Result<Error, T>
|
|
63
|
+
export function goTryRaw<T, E = InstanceType<typeof UnknownError>>(fn: () => T, options: GoTryRawOptions<E>): Result<E, T>
|
|
64
|
+
export function goTryRaw<T>(value: T): Result<Error, T>
|
|
65
|
+
export function goTryRaw<T, E = InstanceType<typeof UnknownError>>(value: T, options: GoTryRawOptions<E>): Result<E, T>
|
|
66
|
+
export function goTryRaw<T, E = Error>(
|
|
67
|
+
value: T | Promise<T> | (() => T | Promise<T>),
|
|
68
|
+
options?: GoTryRawOptions<E>,
|
|
69
|
+
): Result<E, T> | Promise<Result<E, T>> {
|
|
70
|
+
const { errorClass, systemErrorClass } = options || {}
|
|
71
|
+
|
|
72
|
+
// Determine the actual system error class to use
|
|
73
|
+
// Default to UnknownError when systemErrorClass is not specified
|
|
74
|
+
const actualSystemErrorClass = systemErrorClass ?? UnknownError
|
|
75
|
+
|
|
76
|
+
// Helper to wrap error based on the options
|
|
77
|
+
const wrapError = (err: unknown): E => {
|
|
78
|
+
// If errorClass is specified, wrap all errors with it
|
|
79
|
+
if (errorClass) {
|
|
80
|
+
if (err === undefined) {
|
|
81
|
+
return new errorClass('undefined')
|
|
82
|
+
}
|
|
83
|
+
if (isError(err)) {
|
|
84
|
+
return new errorClass(err.message, { cause: err })
|
|
85
|
+
}
|
|
86
|
+
return new errorClass(String(err))
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// If actualSystemErrorClass is specified, only wrap non-tagged errors
|
|
90
|
+
if (actualSystemErrorClass) {
|
|
91
|
+
if (isTaggedError(err)) {
|
|
92
|
+
return err as unknown as E
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Wrap non-tagged errors with systemErrorClass
|
|
96
|
+
if (err === undefined) {
|
|
97
|
+
return new actualSystemErrorClass('undefined') as unknown as E
|
|
98
|
+
}
|
|
99
|
+
if (isError(err)) {
|
|
100
|
+
return new actualSystemErrorClass(err.message, { cause: err }) as unknown as E
|
|
101
|
+
}
|
|
102
|
+
return new actualSystemErrorClass(String(err)) as unknown as E
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// No options - original behavior: return raw error
|
|
106
|
+
if (err === undefined) {
|
|
107
|
+
return new Error('undefined') as unknown as E
|
|
108
|
+
}
|
|
109
|
+
return (
|
|
110
|
+
isError(err) ? err : new Error(String(err))
|
|
111
|
+
) as unknown as E
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
const result =
|
|
116
|
+
typeof value === 'function' ? (value as () => T | Promise<T>)() : value
|
|
117
|
+
if (isPromise<T>(result)) {
|
|
118
|
+
return result
|
|
119
|
+
.then((resolvedValue) => success<T>(resolvedValue))
|
|
120
|
+
.catch((err) => failure<E>(wrapError(err)))
|
|
121
|
+
}
|
|
122
|
+
return success<T>(result)
|
|
123
|
+
} catch (err) {
|
|
124
|
+
return failure<E>(wrapError(err))
|
|
125
|
+
}
|
|
126
|
+
}
|