go-go-try 7.3.0 → 7.4.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 +129 -22
- package/dist/index.cjs +63 -17
- package/dist/index.d.cts +96 -22
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +96 -22
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +63 -18
- package/package.json +3 -3
- package/src/goTryAll.ts +55 -11
- package/src/goTryRaw.ts +64 -27
- package/src/index.test.ts +320 -26
- package/src/index.ts +5 -0
- package/src/types.ts +24 -0
- package/src/unknown-error.ts +20 -0
package/dist/index.d.mts
CHANGED
|
@@ -28,6 +28,38 @@ interface GoTryAllOptions {
|
|
|
28
28
|
type ErrorConstructor<E> = new (message: string, options?: {
|
|
29
29
|
cause?: unknown;
|
|
30
30
|
}) => E;
|
|
31
|
+
/**
|
|
32
|
+
* Options for goTryRaw function.
|
|
33
|
+
* errorClass and systemErrorClass are mutually exclusive - you can only provide one.
|
|
34
|
+
*/
|
|
35
|
+
type GoTryRawOptions<E = Error> = {
|
|
36
|
+
errorClass: ErrorConstructor<E>;
|
|
37
|
+
systemErrorClass?: never;
|
|
38
|
+
} | {
|
|
39
|
+
errorClass?: never;
|
|
40
|
+
systemErrorClass: ErrorConstructor<E>;
|
|
41
|
+
} | {
|
|
42
|
+
errorClass?: never;
|
|
43
|
+
systemErrorClass?: never;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Options for goTryAllRaw function.
|
|
47
|
+
* Includes concurrency control and error class options.
|
|
48
|
+
* errorClass and systemErrorClass are mutually exclusive.
|
|
49
|
+
*/
|
|
50
|
+
type GoTryAllRawOptions<E = Error> = {
|
|
51
|
+
concurrency?: number;
|
|
52
|
+
errorClass: ErrorConstructor<E>;
|
|
53
|
+
systemErrorClass?: never;
|
|
54
|
+
} | {
|
|
55
|
+
concurrency?: number;
|
|
56
|
+
errorClass?: never;
|
|
57
|
+
systemErrorClass: ErrorConstructor<E>;
|
|
58
|
+
} | {
|
|
59
|
+
concurrency?: number;
|
|
60
|
+
errorClass?: never;
|
|
61
|
+
systemErrorClass?: never;
|
|
62
|
+
};
|
|
31
63
|
/**
|
|
32
64
|
* Creates a union type from multiple tagged error classes.
|
|
33
65
|
*
|
|
@@ -71,14 +103,44 @@ declare function goTry<T>(promise: Promise<T>): Promise<Result<string, T>>;
|
|
|
71
103
|
declare function goTry<T>(fn: () => T): Result<string, T>;
|
|
72
104
|
declare function goTry<T>(value: T): Result<string, T>;
|
|
73
105
|
|
|
106
|
+
/**
|
|
107
|
+
* Default system error class for errors that aren't already wrapped in a tagged error class.
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* // By default, goTryRaw wraps unknown errors in UnknownError
|
|
111
|
+
* const [err, result] = goTryRaw(() => mightThrow())
|
|
112
|
+
* if (err) {
|
|
113
|
+
* console.log(err._tag) // 'UnknownError'
|
|
114
|
+
* }
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* // Use a custom system error class
|
|
118
|
+
* const SystemError = taggedError('SystemError')
|
|
119
|
+
* const [err, result] = goTryRaw(() => mightThrow(), {
|
|
120
|
+
* systemErrorClass: SystemError
|
|
121
|
+
* })
|
|
122
|
+
*/
|
|
123
|
+
declare const UnknownError: {
|
|
124
|
+
new (message: string, options?: {
|
|
125
|
+
cause?: unknown;
|
|
126
|
+
} | undefined): {
|
|
127
|
+
readonly _tag: "UnknownError";
|
|
128
|
+
readonly cause?: unknown;
|
|
129
|
+
name: string;
|
|
130
|
+
message: string;
|
|
131
|
+
stack?: string;
|
|
132
|
+
};
|
|
133
|
+
isError(error: unknown): error is Error;
|
|
134
|
+
};
|
|
135
|
+
|
|
74
136
|
/**
|
|
75
137
|
* Executes a function, promise, or value and returns a Result type.
|
|
76
138
|
* If an error occurs, it returns a Failure with the raw error object.
|
|
77
139
|
*
|
|
78
140
|
* @template T The type of the successful result
|
|
79
|
-
* @template E The type of the error
|
|
141
|
+
* @template E The type of the error
|
|
80
142
|
* @param {T | Promise<T> | (() => T | Promise<T>)} value - The value, promise, or function to execute
|
|
81
|
-
* @param {
|
|
143
|
+
* @param {GoTryRawOptions<E>} [options] - Optional options object
|
|
82
144
|
* @returns {Result<E, T> | Promise<Result<E, T>>} A Result type or a Promise of a Result type
|
|
83
145
|
*
|
|
84
146
|
* @example
|
|
@@ -94,21 +156,26 @@ declare function goTry<T>(value: T): Result<string, T>;
|
|
|
94
156
|
* const [err, result] = await goTryRaw(fetch('https://api.example.com/data'));
|
|
95
157
|
*
|
|
96
158
|
* @example
|
|
97
|
-
* // With
|
|
159
|
+
* // With options object - wrap all errors
|
|
98
160
|
* const DatabaseError = taggedError('DatabaseError');
|
|
99
|
-
* const [err, result] = await goTryRaw(fetchData(), DatabaseError);
|
|
100
|
-
*
|
|
161
|
+
* const [err, result] = await goTryRaw(fetchData(), { errorClass: DatabaseError });
|
|
162
|
+
*
|
|
163
|
+
* @example
|
|
164
|
+
* // With options object - systemErrorClass only wraps non-tagged errors
|
|
165
|
+
* const [err, result] = await goTryRaw(fetchData(), { systemErrorClass: UnknownError });
|
|
166
|
+
* // Errors thrown as tagged errors pass through
|
|
167
|
+
* // Other errors are wrapped in UnknownError
|
|
101
168
|
*/
|
|
102
|
-
declare function goTryRaw<T
|
|
103
|
-
declare function goTryRaw<T, E =
|
|
104
|
-
declare function goTryRaw<T
|
|
105
|
-
declare function goTryRaw<T, E =
|
|
106
|
-
declare function goTryRaw<T
|
|
107
|
-
declare function goTryRaw<T, E =
|
|
108
|
-
declare function goTryRaw<T
|
|
109
|
-
declare function goTryRaw<T, E =
|
|
110
|
-
declare function goTryRaw<T
|
|
111
|
-
declare function goTryRaw<T, E =
|
|
169
|
+
declare function goTryRaw<T>(fn: () => never): Result<Error, never>;
|
|
170
|
+
declare function goTryRaw<T, E = InstanceType<typeof UnknownError>>(fn: () => never, options: GoTryRawOptions<E>): Result<E, never>;
|
|
171
|
+
declare function goTryRaw<T>(fn: () => Promise<T>): Promise<Result<Error, T>>;
|
|
172
|
+
declare function goTryRaw<T, E = InstanceType<typeof UnknownError>>(fn: () => Promise<T>, options: GoTryRawOptions<E>): Promise<Result<E, T>>;
|
|
173
|
+
declare function goTryRaw<T>(promise: Promise<T>): Promise<Result<Error, T>>;
|
|
174
|
+
declare function goTryRaw<T, E = InstanceType<typeof UnknownError>>(promise: Promise<T>, options: GoTryRawOptions<E>): Promise<Result<E, T>>;
|
|
175
|
+
declare function goTryRaw<T>(fn: () => T): Result<Error, T>;
|
|
176
|
+
declare function goTryRaw<T, E = InstanceType<typeof UnknownError>>(fn: () => T, options: GoTryRawOptions<E>): Result<E, T>;
|
|
177
|
+
declare function goTryRaw<T>(value: T): Result<Error, T>;
|
|
178
|
+
declare function goTryRaw<T, E = InstanceType<typeof UnknownError>>(value: T, options: GoTryRawOptions<E>): Result<E, T>;
|
|
112
179
|
|
|
113
180
|
/**
|
|
114
181
|
* Executes a function, promise, or value and returns a Result type with a fallback default.
|
|
@@ -178,18 +245,25 @@ declare function goTryAll<T extends readonly unknown[]>(items: {
|
|
|
178
245
|
}]>;
|
|
179
246
|
/**
|
|
180
247
|
* Like `goTryAll`, but returns raw Error objects instead of error messages.
|
|
248
|
+
* Non-tagged errors are wrapped in `UnknownError` by default (consistent with `goTryRaw`).
|
|
249
|
+
* Tagged errors pass through unchanged.
|
|
250
|
+
*
|
|
251
|
+
* Supports `errorClass` and `systemErrorClass` options (mutually exclusive):
|
|
252
|
+
* - `errorClass`: Wrap ALL errors in the specified class
|
|
253
|
+
* - `systemErrorClass`: Only wrap non-tagged errors (defaults to UnknownError)
|
|
181
254
|
*
|
|
182
255
|
* @template T The tuple type of all promise results
|
|
256
|
+
* @template E The type of the error
|
|
183
257
|
* @param {readonly [...{ [K in keyof T]: Promise<T[K]> | (() => Promise<T[K]>) }]} items - Array of promises or factories
|
|
184
|
-
* @param {
|
|
185
|
-
* @returns {Promise<[{ [K in keyof T]:
|
|
258
|
+
* @param {GoTryAllRawOptions<E>} options - Optional configuration
|
|
259
|
+
* @returns {Promise<[{ [K in keyof T]: E | undefined }, { [K in keyof T]: T[K] | undefined }]>}
|
|
186
260
|
* A tuple where the first element is a tuple of Error objects (or undefined) and
|
|
187
261
|
* the second element is a tuple of results (or undefined), preserving input order
|
|
188
262
|
*/
|
|
189
|
-
declare function goTryAllRaw<T extends readonly unknown[]
|
|
263
|
+
declare function goTryAllRaw<T extends readonly unknown[], E = InstanceType<typeof UnknownError>>(items: {
|
|
190
264
|
[K in keyof T]: Promise<T[K]> | (() => Promise<T[K]>);
|
|
191
|
-
}, options?:
|
|
192
|
-
[K in keyof T]:
|
|
265
|
+
}, options?: GoTryAllRawOptions<E>): Promise<[{
|
|
266
|
+
[K in keyof T]: E | undefined;
|
|
193
267
|
}, {
|
|
194
268
|
[K in keyof T]: T[K] | undefined;
|
|
195
269
|
}]>;
|
|
@@ -301,6 +375,6 @@ declare function failure<E>(error: E): Failure<E>;
|
|
|
301
375
|
*/
|
|
302
376
|
declare function assertNever(value: never): never;
|
|
303
377
|
|
|
304
|
-
export { assert, assertNever, failure, goTry, goTryAll, goTryAllRaw, goTryOr, goTryRaw, isFailure, isSuccess, success, taggedError };
|
|
305
|
-
export type { ErrorConstructor, Failure, GoTryAllOptions, MaybePromise, Result, ResultWithDefault, Success, TaggedError, TaggedUnion };
|
|
378
|
+
export { UnknownError, assert, assertNever, failure, goTry, goTryAll, goTryAllRaw, goTryOr, goTryRaw, isFailure, isSuccess, success, taggedError };
|
|
379
|
+
export type { ErrorConstructor, Failure, GoTryAllOptions, GoTryAllRawOptions, GoTryRawOptions, MaybePromise, Result, ResultWithDefault, Success, TaggedError, TaggedUnion };
|
|
306
380
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","sources":["../src/types.ts","../src/goTry.ts","../src/goTryRaw.ts","../src/goTryOr.ts","../src/goTryAll.ts","../src/tagged-error.ts","../src/assert.ts","../src/result-helpers.ts"],"mappings":"AAAA;;;AAIM,KAAM,OAAO;AACb,KAAM,OAAO;AACb,KAAM,MAAM,SAAS,OAAO,MAAM,OAAO;AAEzC,KAAM,iBAAiB;AAEvB,KAAM,YAAY,UAAU,OAAO;AAEzC;;;;AAIM,UAAW,WAAW;;;;;AAMtB,UAAW,eAAe;;;;;;;AAQhC;;;AAGM,KAAM,gBAAgB;;;
|
|
1
|
+
{"version":3,"file":"index.d.mts","sources":["../src/types.ts","../src/goTry.ts","../src/unknown-error.ts","../src/goTryRaw.ts","../src/goTryOr.ts","../src/goTryAll.ts","../src/tagged-error.ts","../src/assert.ts","../src/result-helpers.ts"],"mappings":"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","names":[]}
|
package/dist/index.mjs
CHANGED
|
@@ -48,16 +48,46 @@ function goTry(value) {
|
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
function
|
|
51
|
+
function taggedError(tag) {
|
|
52
|
+
return class TaggedErrorClass extends Error {
|
|
53
|
+
constructor(message, options) {
|
|
54
|
+
super(message);
|
|
55
|
+
this._tag = tag;
|
|
56
|
+
this.name = tag;
|
|
57
|
+
this.cause = options?.cause;
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const UnknownError = taggedError("UnknownError");
|
|
63
|
+
|
|
64
|
+
function isTaggedError$1(err) {
|
|
65
|
+
return isError(err) && "_tag" in err && typeof err._tag === "string";
|
|
66
|
+
}
|
|
67
|
+
function goTryRaw(value, options) {
|
|
68
|
+
const { errorClass, systemErrorClass } = options || {};
|
|
69
|
+
const actualSystemErrorClass = systemErrorClass ?? UnknownError;
|
|
52
70
|
const wrapError = (err) => {
|
|
53
|
-
if (
|
|
71
|
+
if (errorClass) {
|
|
72
|
+
if (err === void 0) {
|
|
73
|
+
return new errorClass("undefined");
|
|
74
|
+
}
|
|
75
|
+
if (isError(err)) {
|
|
76
|
+
return new errorClass(err.message, { cause: err });
|
|
77
|
+
}
|
|
78
|
+
return new errorClass(String(err));
|
|
79
|
+
}
|
|
80
|
+
if (actualSystemErrorClass) {
|
|
81
|
+
if (isTaggedError$1(err)) {
|
|
82
|
+
return err;
|
|
83
|
+
}
|
|
54
84
|
if (err === void 0) {
|
|
55
|
-
return new
|
|
85
|
+
return new actualSystemErrorClass("undefined");
|
|
56
86
|
}
|
|
57
87
|
if (isError(err)) {
|
|
58
|
-
return new
|
|
88
|
+
return new actualSystemErrorClass(err.message, { cause: err });
|
|
59
89
|
}
|
|
60
|
-
return new
|
|
90
|
+
return new actualSystemErrorClass(String(err));
|
|
61
91
|
}
|
|
62
92
|
if (err === void 0) {
|
|
63
93
|
return new Error("undefined");
|
|
@@ -87,6 +117,31 @@ function goTryOr(value, defaultValue) {
|
|
|
87
117
|
}
|
|
88
118
|
}
|
|
89
119
|
|
|
120
|
+
function isTaggedError(err) {
|
|
121
|
+
return isError(err) && "_tag" in err && typeof err._tag === "string";
|
|
122
|
+
}
|
|
123
|
+
function wrapError(err, errorClass, systemErrorClass) {
|
|
124
|
+
if (errorClass) {
|
|
125
|
+
if (err === void 0) {
|
|
126
|
+
return new errorClass("undefined");
|
|
127
|
+
}
|
|
128
|
+
if (isError(err)) {
|
|
129
|
+
return new errorClass(err.message, { cause: err });
|
|
130
|
+
}
|
|
131
|
+
return new errorClass(String(err));
|
|
132
|
+
}
|
|
133
|
+
const actualSystemErrorClass = systemErrorClass ?? UnknownError;
|
|
134
|
+
if (isTaggedError(err)) {
|
|
135
|
+
return err;
|
|
136
|
+
}
|
|
137
|
+
if (err === void 0) {
|
|
138
|
+
return new actualSystemErrorClass("undefined");
|
|
139
|
+
}
|
|
140
|
+
if (isError(err)) {
|
|
141
|
+
return new actualSystemErrorClass(err.message, { cause: err });
|
|
142
|
+
}
|
|
143
|
+
return new actualSystemErrorClass(String(err));
|
|
144
|
+
}
|
|
90
145
|
async function runWithConcurrency(items, concurrency) {
|
|
91
146
|
if (items.length === 0) {
|
|
92
147
|
return [];
|
|
@@ -134,6 +189,7 @@ async function goTryAll(items, options) {
|
|
|
134
189
|
return [errors, results];
|
|
135
190
|
}
|
|
136
191
|
async function goTryAllRaw(items, options) {
|
|
192
|
+
const { errorClass, systemErrorClass } = options || {};
|
|
137
193
|
const settled = await runWithConcurrency(items, options?.concurrency ?? 0);
|
|
138
194
|
const errors = [];
|
|
139
195
|
const results = [];
|
|
@@ -144,24 +200,13 @@ async function goTryAllRaw(items, options) {
|
|
|
144
200
|
results[i] = item.value;
|
|
145
201
|
} else {
|
|
146
202
|
const reason = item.reason;
|
|
147
|
-
errors[i] =
|
|
203
|
+
errors[i] = wrapError(reason, errorClass, systemErrorClass);
|
|
148
204
|
results[i] = void 0;
|
|
149
205
|
}
|
|
150
206
|
}
|
|
151
207
|
return [errors, results];
|
|
152
208
|
}
|
|
153
209
|
|
|
154
|
-
function taggedError(tag) {
|
|
155
|
-
return class TaggedErrorClass extends Error {
|
|
156
|
-
constructor(message, options) {
|
|
157
|
-
super(message);
|
|
158
|
-
this._tag = tag;
|
|
159
|
-
this.name = tag;
|
|
160
|
-
this.cause = options?.cause;
|
|
161
|
-
}
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
|
|
165
210
|
function assert(condition, errorOrClass, message) {
|
|
166
211
|
if (!condition) {
|
|
167
212
|
if (typeof errorOrClass === "string") {
|
|
@@ -174,4 +219,4 @@ function assert(condition, errorOrClass, message) {
|
|
|
174
219
|
}
|
|
175
220
|
}
|
|
176
221
|
|
|
177
|
-
export { assert, assertNever, failure, goTry, goTryAll, goTryAllRaw, goTryOr, goTryRaw, isFailure, isSuccess, success, taggedError };
|
|
222
|
+
export { UnknownError, assert, assertNever, failure, goTry, goTryAll, goTryAllRaw, goTryOr, goTryRaw, isFailure, isSuccess, success, taggedError };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "go-go-try",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.4.1",
|
|
4
4
|
"description": "Tries to execute a sync/async function, returns a result tuple",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "thelinuxlich/go-go-try",
|
|
@@ -48,11 +48,11 @@
|
|
|
48
48
|
],
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@ark/attest": "^0.56.0",
|
|
51
|
-
"@biomejs/biome": "^2.
|
|
51
|
+
"@biomejs/biome": "^2.4.2",
|
|
52
52
|
"@vitest/coverage-v8": "^4.0.18",
|
|
53
53
|
"husky": "^9.1.7",
|
|
54
54
|
"lint-staged": "^16.2.7",
|
|
55
|
-
"pkgroll": "^2.
|
|
55
|
+
"pkgroll": "^2.26.2",
|
|
56
56
|
"tsx": "^4.21.0",
|
|
57
57
|
"typescript": "^5.9.3",
|
|
58
58
|
"vitest": "^4.0.18"
|
package/src/goTryAll.ts
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
|
-
import type { GoTryAllOptions } from './types.js'
|
|
1
|
+
import type { GoTryAllOptions, GoTryAllRawOptions, ErrorConstructor } from './types.js'
|
|
2
2
|
import { isError, getErrorMessage, type PromiseFactory } from './internals.js'
|
|
3
|
+
import { UnknownError } from './unknown-error.js'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Checks if a value is a tagged error (has a _tag property).
|
|
7
|
+
*/
|
|
8
|
+
function isTaggedError(err: unknown): err is { _tag: string } {
|
|
9
|
+
return isError(err) && '_tag' in err && typeof (err as { _tag?: unknown })._tag === 'string'
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Wraps an error based on the provided options (errorClass/systemErrorClass).
|
|
14
|
+
* Consistent with goTryRaw behavior.
|
|
15
|
+
*/
|
|
16
|
+
function wrapError<E>(err: unknown, errorClass: ErrorConstructor<E> | undefined, systemErrorClass: ErrorConstructor<E> | undefined): E {
|
|
17
|
+
// If errorClass is specified, wrap all errors with it
|
|
18
|
+
if (errorClass) {
|
|
19
|
+
if (err === undefined) {
|
|
20
|
+
return new errorClass('undefined')
|
|
21
|
+
}
|
|
22
|
+
if (isError(err)) {
|
|
23
|
+
return new errorClass(err.message, { cause: err })
|
|
24
|
+
}
|
|
25
|
+
return new errorClass(String(err))
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// If systemErrorClass is specified (or defaulted to UnknownError), only wrap non-tagged errors
|
|
29
|
+
const actualSystemErrorClass = systemErrorClass ?? UnknownError
|
|
30
|
+
if (isTaggedError(err)) {
|
|
31
|
+
return err as unknown as E
|
|
32
|
+
}
|
|
33
|
+
if (err === undefined) {
|
|
34
|
+
return new actualSystemErrorClass('undefined') as unknown as E
|
|
35
|
+
}
|
|
36
|
+
if (isError(err)) {
|
|
37
|
+
return new actualSystemErrorClass(err.message, { cause: err }) as unknown as E
|
|
38
|
+
}
|
|
39
|
+
return new actualSystemErrorClass(String(err)) as unknown as E
|
|
40
|
+
}
|
|
3
41
|
|
|
4
42
|
async function runWithConcurrency<T extends readonly unknown[]>(
|
|
5
43
|
items: { [K in keyof T]: Promise<T[K]> | PromiseFactory<T[K]> },
|
|
@@ -106,33 +144,39 @@ export async function goTryAll<T extends readonly unknown[]>(
|
|
|
106
144
|
|
|
107
145
|
/**
|
|
108
146
|
* Like `goTryAll`, but returns raw Error objects instead of error messages.
|
|
147
|
+
* Non-tagged errors are wrapped in `UnknownError` by default (consistent with `goTryRaw`).
|
|
148
|
+
* Tagged errors pass through unchanged.
|
|
149
|
+
*
|
|
150
|
+
* Supports `errorClass` and `systemErrorClass` options (mutually exclusive):
|
|
151
|
+
* - `errorClass`: Wrap ALL errors in the specified class
|
|
152
|
+
* - `systemErrorClass`: Only wrap non-tagged errors (defaults to UnknownError)
|
|
109
153
|
*
|
|
110
154
|
* @template T The tuple type of all promise results
|
|
155
|
+
* @template E The type of the error
|
|
111
156
|
* @param {readonly [...{ [K in keyof T]: Promise<T[K]> | (() => Promise<T[K]>) }]} items - Array of promises or factories
|
|
112
|
-
* @param {
|
|
113
|
-
* @returns {Promise<[{ [K in keyof T]:
|
|
157
|
+
* @param {GoTryAllRawOptions<E>} options - Optional configuration
|
|
158
|
+
* @returns {Promise<[{ [K in keyof T]: E | undefined }, { [K in keyof T]: T[K] | undefined }]>}
|
|
114
159
|
* A tuple where the first element is a tuple of Error objects (or undefined) and
|
|
115
160
|
* the second element is a tuple of results (or undefined), preserving input order
|
|
116
161
|
*/
|
|
117
|
-
export async function goTryAllRaw<T extends readonly unknown[]
|
|
162
|
+
export async function goTryAllRaw<T extends readonly unknown[], E = InstanceType<typeof UnknownError>>(
|
|
118
163
|
items: { [K in keyof T]: Promise<T[K]> | (() => Promise<T[K]>) },
|
|
119
|
-
options?:
|
|
120
|
-
): Promise<[{ [K in keyof T]:
|
|
164
|
+
options?: GoTryAllRawOptions<E>,
|
|
165
|
+
): Promise<[{ [K in keyof T]: E | undefined }, { [K in keyof T]: T[K] | undefined }]> {
|
|
166
|
+
const { errorClass, systemErrorClass } = options || {}
|
|
121
167
|
const settled = await runWithConcurrency(items, options?.concurrency ?? 0)
|
|
122
168
|
|
|
123
|
-
const errors = [] as { [K in keyof T]:
|
|
169
|
+
const errors = [] as { [K in keyof T]: E | undefined }
|
|
124
170
|
const results = [] as { [K in keyof T]: T[K] | undefined }
|
|
125
171
|
|
|
126
172
|
for (let i = 0; i < settled.length; i++) {
|
|
127
173
|
const item = settled[i]!
|
|
128
174
|
if (item.status === 'fulfilled') {
|
|
129
|
-
;(errors as (
|
|
175
|
+
;(errors as (E | undefined)[])[i] = undefined
|
|
130
176
|
;(results as unknown[])[i] = (item as PromiseFulfilledResult<T[number]>).value
|
|
131
177
|
} else {
|
|
132
178
|
const reason = (item as PromiseRejectedResult).reason
|
|
133
|
-
;(errors as (
|
|
134
|
-
? reason
|
|
135
|
-
: new Error(String(reason))
|
|
179
|
+
;(errors as (E | undefined)[])[i] = wrapError(reason, errorClass, systemErrorClass)
|
|
136
180
|
;(results as unknown[])[i] = undefined
|
|
137
181
|
}
|
|
138
182
|
}
|
package/src/goTryRaw.ts
CHANGED
|
@@ -1,15 +1,23 @@
|
|
|
1
|
-
import type { Result,
|
|
1
|
+
import type { Result, GoTryRawOptions } from './types.js'
|
|
2
2
|
import { success, failure } from './result-helpers.js'
|
|
3
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
|
+
}
|
|
4
12
|
|
|
5
13
|
/**
|
|
6
14
|
* Executes a function, promise, or value and returns a Result type.
|
|
7
15
|
* If an error occurs, it returns a Failure with the raw error object.
|
|
8
16
|
*
|
|
9
17
|
* @template T The type of the successful result
|
|
10
|
-
* @template E The type of the error
|
|
18
|
+
* @template E The type of the error
|
|
11
19
|
* @param {T | Promise<T> | (() => T | Promise<T>)} value - The value, promise, or function to execute
|
|
12
|
-
* @param {
|
|
20
|
+
* @param {GoTryRawOptions<E>} [options] - Optional options object
|
|
13
21
|
* @returns {Result<E, T> | Promise<Result<E, T>>} A Result type or a Promise of a Result type
|
|
14
22
|
*
|
|
15
23
|
* @example
|
|
@@ -25,47 +33,76 @@ import { isPromise, isError } from './internals.js'
|
|
|
25
33
|
* const [err, result] = await goTryRaw(fetch('https://api.example.com/data'));
|
|
26
34
|
*
|
|
27
35
|
* @example
|
|
28
|
-
* // With
|
|
36
|
+
* // With options object - wrap all errors
|
|
29
37
|
* const DatabaseError = taggedError('DatabaseError');
|
|
30
|
-
* const [err, result] = await goTryRaw(fetchData(), DatabaseError);
|
|
31
|
-
*
|
|
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
|
|
32
45
|
*/
|
|
33
|
-
export function goTryRaw<T
|
|
34
|
-
export function goTryRaw<T, E =
|
|
35
|
-
export function goTryRaw<T
|
|
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>(
|
|
36
49
|
fn: () => Promise<T>,
|
|
37
|
-
): Promise<Result<
|
|
38
|
-
export function goTryRaw<T, E =
|
|
50
|
+
): Promise<Result<Error, T>>
|
|
51
|
+
export function goTryRaw<T, E = InstanceType<typeof UnknownError>>(
|
|
39
52
|
fn: () => Promise<T>,
|
|
40
|
-
|
|
53
|
+
options: GoTryRawOptions<E>,
|
|
41
54
|
): Promise<Result<E, T>>
|
|
42
|
-
export function goTryRaw<T
|
|
55
|
+
export function goTryRaw<T>(
|
|
43
56
|
promise: Promise<T>,
|
|
44
|
-
): Promise<Result<
|
|
45
|
-
export function goTryRaw<T, E =
|
|
57
|
+
): Promise<Result<Error, T>>
|
|
58
|
+
export function goTryRaw<T, E = InstanceType<typeof UnknownError>>(
|
|
46
59
|
promise: Promise<T>,
|
|
47
|
-
|
|
60
|
+
options: GoTryRawOptions<E>,
|
|
48
61
|
): Promise<Result<E, T>>
|
|
49
|
-
export function goTryRaw<T
|
|
50
|
-
export function goTryRaw<T, E =
|
|
51
|
-
export function goTryRaw<T
|
|
52
|
-
export function goTryRaw<T, E =
|
|
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>
|
|
53
66
|
export function goTryRaw<T, E = Error>(
|
|
54
67
|
value: T | Promise<T> | (() => T | Promise<T>),
|
|
55
|
-
|
|
68
|
+
options?: GoTryRawOptions<E>,
|
|
56
69
|
): Result<E, T> | Promise<Result<E, T>> {
|
|
57
|
-
|
|
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
|
|
58
77
|
const wrapError = (err: unknown): E => {
|
|
59
|
-
|
|
78
|
+
// If errorClass is specified, wrap all errors with it
|
|
79
|
+
if (errorClass) {
|
|
60
80
|
if (err === undefined) {
|
|
61
|
-
return new
|
|
81
|
+
return new errorClass('undefined')
|
|
62
82
|
}
|
|
63
83
|
if (isError(err)) {
|
|
64
|
-
return new
|
|
84
|
+
return new errorClass(err.message, { cause: err })
|
|
65
85
|
}
|
|
66
|
-
return new
|
|
86
|
+
return new errorClass(String(err))
|
|
67
87
|
}
|
|
68
|
-
|
|
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
|
|
69
106
|
if (err === undefined) {
|
|
70
107
|
return new Error('undefined') as unknown as E
|
|
71
108
|
}
|