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/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, defaults to 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 {ErrorConstructor<E>} [ErrorClass] - Optional error constructor to wrap caught errors
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 tagged error for discriminated unions
159
+ * // With options object - wrap all errors
98
160
  * const DatabaseError = taggedError('DatabaseError');
99
- * const [err, result] = await goTryRaw(fetchData(), DatabaseError);
100
- * // err is InstanceType<typeof DatabaseError> | undefined
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, E = Error>(fn: () => never): Result<E, never>;
103
- declare function goTryRaw<T, E = Error>(fn: () => never, ErrorClass: ErrorConstructor<E>): Result<E, never>;
104
- declare function goTryRaw<T, E = Error>(fn: () => Promise<T>): Promise<Result<E, T>>;
105
- declare function goTryRaw<T, E = Error>(fn: () => Promise<T>, ErrorClass: ErrorConstructor<E>): Promise<Result<E, T>>;
106
- declare function goTryRaw<T, E = Error>(promise: Promise<T>): Promise<Result<E, T>>;
107
- declare function goTryRaw<T, E = Error>(promise: Promise<T>, ErrorClass: ErrorConstructor<E>): Promise<Result<E, T>>;
108
- declare function goTryRaw<T, E = Error>(fn: () => T): Result<E, T>;
109
- declare function goTryRaw<T, E = Error>(fn: () => T, ErrorClass: ErrorConstructor<E>): Result<E, T>;
110
- declare function goTryRaw<T, E = Error>(value: T): Result<E, T>;
111
- declare function goTryRaw<T, E = Error>(value: T, ErrorClass: ErrorConstructor<E>): Result<E, T>;
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 {GoTryAllOptions} options - Optional configuration
185
- * @returns {Promise<[{ [K in keyof T]: Error | undefined }, { [K in keyof T]: T[K] | undefined }]>}
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[]>(items: {
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?: GoTryAllOptions): Promise<[{
192
- [K in keyof T]: Error | undefined;
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
@@ -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;;;AAE5B;;;;;;;;;;;;;AAaM,KAAM,WAAW,oBAAoB,gBAAgB;iCAC1B,gBAAgB;;;AC7CjD;;;;;;;;;;;;;;;;;;;;AAoBA,iBAAgB,KAAK,sBAAsB,MAAM;AACjD,iBAAgB,KAAK,cAAc,OAAO,MAAM,OAAO,CAAC,MAAM;AAC9D,iBAAgB,KAAK,aAAa,OAAO,MAAM,OAAO,CAAC,MAAM;AAC7D,iBAAgB,KAAK,kBAAkB,MAAM;AAC7C,iBAAgB,KAAK,eAAe,MAAM;;ACxB1C;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,iBAAgB,QAAQ,QAAQ,KAAK,oBAAoB,MAAM;AAC/D,iBAAgB,QAAQ,QAAQ,KAAK,+BAA+B,gBAAgB,MAAM,MAAM;AAChG,iBAAgB,QAAQ,QAAQ,KAAK,YACzB,OAAO,MAChB,OAAO,CAAC,MAAM;AACjB,iBAAgB,QAAQ,QAAQ,KAAK,YACzB,OAAO,iBACL,gBAAgB,MAC3B,OAAO,CAAC,MAAM;AACjB,iBAAgB,QAAQ,QAAQ,KAAK,WAC1B,OAAO,MACf,OAAO,CAAC,MAAM;AACjB,iBAAgB,QAAQ,QAAQ,KAAK,WAC1B,OAAO,iBACJ,gBAAgB,MAC3B,OAAO,CAAC,MAAM;AACjB,iBAAgB,QAAQ,QAAQ,KAAK,gBAAgB,MAAM;AAC3D,iBAAgB,QAAQ,QAAQ,KAAK,2BAA2B,gBAAgB,MAAM,MAAM;AAC5F,iBAAgB,QAAQ,QAAQ,KAAK,aAAa,MAAM;AACxD,iBAAgB,QAAQ,QAAQ,KAAK,wBAAwB,gBAAgB,MAAM,MAAM;;AC/CzF;;;;;;;;;;;;;;;;;;;;;AAqBA,iBAAgB,OAAO,mDAAmD,iBAAiB;AAC3F,iBAAgB,OAAO,cACX,OAAO,mCAEhB,OAAO,CAAC,iBAAiB;AAC5B,iBAAgB,OAAO,aACZ,OAAO,mCAEf,OAAO,CAAC,iBAAiB;AAC5B,iBAAgB,OAAO,+CAA+C,iBAAiB;AACvF,iBAAgB,OAAO,4CAA4C,iBAAiB;;ACgBpF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,iBAAsB,QAAQ;oBACH,OAAO,gBAAgB,OAAO;aAC7C,eAAe,GACxB,OAAO;;;;;AAoBV;;;;;;;;;;AAUA,iBAAsB,WAAW;oBACN,OAAO,gBAAgB,OAAO;aAC7C,eAAe,GACxB,OAAO;oBAAoB,KAAK;;;;;ACrHnC;;;;;;;;;;;;;;;;;;;;;;;;AAwBA,iBAAgB,WAAW;;;;;;;;;;;;;AC1B3B;;;;;;;;;;;;;;;;;;;;;;AAsBA,iBAAgB,MAAM,4BAA4B,KAAK;AAEvD;;;;;;;;;;;;;;AAcA,iBAAgB,MAAM,WAAW,KAAK;;ACpCtC,iBAAgB,SAAS,eAAe,MAAM,mBAAmB,OAAO;AAIxE,iBAAgB,SAAS,eAAe,MAAM,mBAAmB,OAAO;AAIxE,iBAAgB,OAAO,eAAe,OAAO;AAI7C,iBAAgB,OAAO,eAAe,OAAO;AAI7C;;;;;;;;;;;;;;;;;;;;;;;;;AAyBA,iBAAgB,WAAW","names":[]}
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 goTryRaw(value, ErrorClass) {
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 (ErrorClass) {
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 ErrorClass("undefined");
85
+ return new actualSystemErrorClass("undefined");
56
86
  }
57
87
  if (isError(err)) {
58
- return new ErrorClass(err.message, { cause: err });
88
+ return new actualSystemErrorClass(err.message, { cause: err });
59
89
  }
60
- return new ErrorClass(String(err));
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] = isError(reason) ? reason : new Error(String(reason));
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.0",
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.3.14",
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.23.0",
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 {GoTryAllOptions} options - Optional configuration
113
- * @returns {Promise<[{ [K in keyof T]: Error | undefined }, { [K in keyof T]: T[K] | undefined }]>}
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?: GoTryAllOptions,
120
- ): Promise<[{ [K in keyof T]: Error | undefined }, { [K in keyof T]: T[K] | undefined }]> {
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]: Error | undefined }
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 (Error | undefined)[])[i] = undefined
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 (Error | undefined)[])[i] = isError(reason)
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, ErrorConstructor } from './types.js'
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, defaults to 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 {ErrorConstructor<E>} [ErrorClass] - Optional error constructor to wrap caught errors
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 tagged error for discriminated unions
36
+ * // With options object - wrap all errors
29
37
  * const DatabaseError = taggedError('DatabaseError');
30
- * const [err, result] = await goTryRaw(fetchData(), DatabaseError);
31
- * // err is InstanceType<typeof DatabaseError> | undefined
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, E = Error>(fn: () => never): Result<E, never>
34
- export function goTryRaw<T, E = Error>(fn: () => never, ErrorClass: ErrorConstructor<E>): Result<E, never>
35
- export function goTryRaw<T, E = Error>(
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<E, T>>
38
- export function goTryRaw<T, E = Error>(
50
+ ): Promise<Result<Error, T>>
51
+ export function goTryRaw<T, E = InstanceType<typeof UnknownError>>(
39
52
  fn: () => Promise<T>,
40
- ErrorClass: ErrorConstructor<E>,
53
+ options: GoTryRawOptions<E>,
41
54
  ): Promise<Result<E, T>>
42
- export function goTryRaw<T, E = Error>(
55
+ export function goTryRaw<T>(
43
56
  promise: Promise<T>,
44
- ): Promise<Result<E, T>>
45
- export function goTryRaw<T, E = Error>(
57
+ ): Promise<Result<Error, T>>
58
+ export function goTryRaw<T, E = InstanceType<typeof UnknownError>>(
46
59
  promise: Promise<T>,
47
- ErrorClass: ErrorConstructor<E>,
60
+ options: GoTryRawOptions<E>,
48
61
  ): Promise<Result<E, T>>
49
- export function goTryRaw<T, E = Error>(fn: () => T): Result<E, T>
50
- export function goTryRaw<T, E = Error>(fn: () => T, ErrorClass: ErrorConstructor<E>): Result<E, T>
51
- export function goTryRaw<T, E = Error>(value: T): Result<E, T>
52
- export function goTryRaw<T, E = Error>(value: T, ErrorClass: ErrorConstructor<E>): 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>
53
66
  export function goTryRaw<T, E = Error>(
54
67
  value: T | Promise<T> | (() => T | Promise<T>),
55
- ErrorClass?: ErrorConstructor<E>,
68
+ options?: GoTryRawOptions<E>,
56
69
  ): Result<E, T> | Promise<Result<E, T>> {
57
- // Helper to wrap error in the provided class or return as-is
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
- if (ErrorClass) {
78
+ // If errorClass is specified, wrap all errors with it
79
+ if (errorClass) {
60
80
  if (err === undefined) {
61
- return new ErrorClass('undefined')
81
+ return new errorClass('undefined')
62
82
  }
63
83
  if (isError(err)) {
64
- return new ErrorClass(err.message, { cause: err })
84
+ return new errorClass(err.message, { cause: err })
65
85
  }
66
- return new ErrorClass(String(err))
86
+ return new errorClass(String(err))
67
87
  }
68
- // Default behavior: return raw error
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
  }