go-go-try 7.4.1 → 8.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/dist/index.cjs +66 -4
- package/dist/index.d.cts +90 -15
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +90 -15
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +63 -5
- package/package.json +1 -1
- package/src/ensure.test.ts +116 -0
- package/src/ensure.ts +137 -0
- package/src/go.test.ts +107 -0
- package/src/go.ts +37 -0
- package/src/goElse.ts +74 -0
- package/src/index.ts +4 -0
package/dist/index.cjs
CHANGED
|
@@ -28,7 +28,7 @@ function getErrorMessage(error) {
|
|
|
28
28
|
return String(error);
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
|
-
function isPromise(value) {
|
|
31
|
+
function isPromise$1(value) {
|
|
32
32
|
return typeof value === "object" && value !== null && "then" in value && typeof value.then === "function";
|
|
33
33
|
}
|
|
34
34
|
function isError(value) {
|
|
@@ -41,7 +41,7 @@ function resolveDefault(defaultValue) {
|
|
|
41
41
|
function goTry(value) {
|
|
42
42
|
try {
|
|
43
43
|
const result = typeof value === "function" ? value() : value;
|
|
44
|
-
if (isPromise(result)) {
|
|
44
|
+
if (isPromise$1(result)) {
|
|
45
45
|
return result.then((resolvedValue) => success(resolvedValue)).catch((err) => failure(getErrorMessage(err)));
|
|
46
46
|
}
|
|
47
47
|
return success(result);
|
|
@@ -98,7 +98,7 @@ function goTryRaw(value, options) {
|
|
|
98
98
|
};
|
|
99
99
|
try {
|
|
100
100
|
const result = typeof value === "function" ? value() : value;
|
|
101
|
-
if (isPromise(result)) {
|
|
101
|
+
if (isPromise$1(result)) {
|
|
102
102
|
return result.then((resolvedValue) => success(resolvedValue)).catch((err) => failure(wrapError(err)));
|
|
103
103
|
}
|
|
104
104
|
return success(result);
|
|
@@ -110,7 +110,7 @@ function goTryRaw(value, options) {
|
|
|
110
110
|
function goTryOr(value, defaultValue) {
|
|
111
111
|
try {
|
|
112
112
|
const result = typeof value === "function" ? value() : value;
|
|
113
|
-
if (isPromise(result)) {
|
|
113
|
+
if (isPromise$1(result)) {
|
|
114
114
|
return result.then((resolvedValue) => success(resolvedValue)).catch((err) => [getErrorMessage(err), resolveDefault(defaultValue)]);
|
|
115
115
|
}
|
|
116
116
|
return success(result);
|
|
@@ -221,10 +221,72 @@ function assert(condition, errorOrClass, message) {
|
|
|
221
221
|
}
|
|
222
222
|
}
|
|
223
223
|
|
|
224
|
+
function isPromise(value) {
|
|
225
|
+
return value instanceof Promise;
|
|
226
|
+
}
|
|
227
|
+
function isErrorConstructor(error) {
|
|
228
|
+
return typeof error === "function" && error.prototype !== void 0 && error.prototype instanceof Error;
|
|
229
|
+
}
|
|
230
|
+
function throwError(value, error) {
|
|
231
|
+
if (isErrorConstructor(error)) {
|
|
232
|
+
throw new error(String(value), { cause: value });
|
|
233
|
+
}
|
|
234
|
+
throw error(value);
|
|
235
|
+
}
|
|
236
|
+
function ensure(value, predicate, error = UnknownError) {
|
|
237
|
+
if (typeof value === "function") {
|
|
238
|
+
const result = value();
|
|
239
|
+
if (isPromise(result)) {
|
|
240
|
+
return result.then((resolved) => {
|
|
241
|
+
if (!predicate(resolved)) {
|
|
242
|
+
throwError(resolved, error);
|
|
243
|
+
}
|
|
244
|
+
return resolved;
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
if (!predicate(result)) {
|
|
248
|
+
throwError(result, error);
|
|
249
|
+
}
|
|
250
|
+
return result;
|
|
251
|
+
}
|
|
252
|
+
if (isPromise(value)) {
|
|
253
|
+
return value.then((resolved) => {
|
|
254
|
+
if (!predicate(resolved)) {
|
|
255
|
+
throwError(resolved, error);
|
|
256
|
+
}
|
|
257
|
+
return resolved;
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
if (!predicate(value)) {
|
|
261
|
+
throwError(value, error);
|
|
262
|
+
}
|
|
263
|
+
return value;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
function goElse(value, defaultValue) {
|
|
267
|
+
try {
|
|
268
|
+
const result = typeof value === "function" ? value() : value;
|
|
269
|
+
if (isPromise$1(result)) {
|
|
270
|
+
return result.then((resolvedValue) => [void 0, resolvedValue]).catch((err) => {
|
|
271
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
272
|
+
return [error, resolveDefault(defaultValue)];
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
return [void 0, result];
|
|
276
|
+
} catch (err) {
|
|
277
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
278
|
+
return [error, resolveDefault(defaultValue)];
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
224
282
|
exports.UnknownError = UnknownError;
|
|
225
283
|
exports.assert = assert;
|
|
226
284
|
exports.assertNever = assertNever;
|
|
285
|
+
exports.ensure = ensure;
|
|
227
286
|
exports.failure = failure;
|
|
287
|
+
exports.go = goTryRaw;
|
|
288
|
+
exports.goAll = goTryAllRaw;
|
|
289
|
+
exports.goElse = goElse;
|
|
228
290
|
exports.goTry = goTry;
|
|
229
291
|
exports.goTryAll = goTryAll;
|
|
230
292
|
exports.goTryAllRaw = goTryAllRaw;
|
package/dist/index.d.cts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
type Success<T> = readonly [undefined, T];
|
|
5
5
|
type Failure<E> = readonly [E, undefined];
|
|
6
6
|
type Result<E, T> = Success<T> | Failure<E>;
|
|
7
|
-
type ResultWithDefault<E, T> = readonly [E | undefined, T];
|
|
7
|
+
type ResultWithDefault$1<E, T> = readonly [E | undefined, T];
|
|
8
8
|
type MaybePromise<T> = T | Promise<T>;
|
|
9
9
|
/**
|
|
10
10
|
* Base interface for tagged errors.
|
|
@@ -25,7 +25,7 @@ interface GoTryAllOptions {
|
|
|
25
25
|
/**
|
|
26
26
|
* Type for error constructors that can be used with goTryRaw.
|
|
27
27
|
*/
|
|
28
|
-
type ErrorConstructor<E> = new (message: string, options?: {
|
|
28
|
+
type ErrorConstructor$1<E> = new (message: string, options?: {
|
|
29
29
|
cause?: unknown;
|
|
30
30
|
}) => E;
|
|
31
31
|
/**
|
|
@@ -33,11 +33,11 @@ type ErrorConstructor<E> = new (message: string, options?: {
|
|
|
33
33
|
* errorClass and systemErrorClass are mutually exclusive - you can only provide one.
|
|
34
34
|
*/
|
|
35
35
|
type GoTryRawOptions<E = Error> = {
|
|
36
|
-
errorClass: ErrorConstructor<E>;
|
|
36
|
+
errorClass: ErrorConstructor$1<E>;
|
|
37
37
|
systemErrorClass?: never;
|
|
38
38
|
} | {
|
|
39
39
|
errorClass?: never;
|
|
40
|
-
systemErrorClass: ErrorConstructor<E>;
|
|
40
|
+
systemErrorClass: ErrorConstructor$1<E>;
|
|
41
41
|
} | {
|
|
42
42
|
errorClass?: never;
|
|
43
43
|
systemErrorClass?: never;
|
|
@@ -49,12 +49,12 @@ type GoTryRawOptions<E = Error> = {
|
|
|
49
49
|
*/
|
|
50
50
|
type GoTryAllRawOptions<E = Error> = {
|
|
51
51
|
concurrency?: number;
|
|
52
|
-
errorClass: ErrorConstructor<E>;
|
|
52
|
+
errorClass: ErrorConstructor$1<E>;
|
|
53
53
|
systemErrorClass?: never;
|
|
54
54
|
} | {
|
|
55
55
|
concurrency?: number;
|
|
56
56
|
errorClass?: never;
|
|
57
|
-
systemErrorClass: ErrorConstructor<E>;
|
|
57
|
+
systemErrorClass: ErrorConstructor$1<E>;
|
|
58
58
|
} | {
|
|
59
59
|
concurrency?: number;
|
|
60
60
|
errorClass?: never;
|
|
@@ -73,8 +73,8 @@ type GoTryAllRawOptions<E = Error> = {
|
|
|
73
73
|
* type AppError = TaggedUnion<[typeof DatabaseError, typeof NetworkError]>
|
|
74
74
|
* // Equivalent to: DatabaseError | NetworkError
|
|
75
75
|
*/
|
|
76
|
-
type TaggedUnion<T extends readonly ErrorConstructor<unknown>[]> = {
|
|
77
|
-
[K in keyof T]: T[K] extends ErrorConstructor<infer E> ? E : never;
|
|
76
|
+
type TaggedUnion<T extends readonly ErrorConstructor$1<unknown>[]> = {
|
|
77
|
+
[K in keyof T]: T[K] extends ErrorConstructor$1<infer E> ? E : never;
|
|
78
78
|
}[number];
|
|
79
79
|
|
|
80
80
|
/**
|
|
@@ -198,11 +198,11 @@ declare function goTryRaw<T, E = InstanceType<typeof UnknownError>>(value: T, op
|
|
|
198
198
|
* name: 'Guest'
|
|
199
199
|
* }))
|
|
200
200
|
*/
|
|
201
|
-
declare function goTryOr<T>(fn: () => never, defaultValue: T | (() => T)): ResultWithDefault<string, T>;
|
|
202
|
-
declare function goTryOr<T>(fn: () => Promise<T>, defaultValue: T | (() => T)): Promise<ResultWithDefault<string, T>>;
|
|
203
|
-
declare function goTryOr<T>(promise: Promise<T>, defaultValue: T | (() => T)): Promise<ResultWithDefault<string, T>>;
|
|
204
|
-
declare function goTryOr<T>(fn: () => T, defaultValue: T | (() => T)): ResultWithDefault<string, T>;
|
|
205
|
-
declare function goTryOr<T>(value: T, defaultValue: T | (() => T)): ResultWithDefault<string, T>;
|
|
201
|
+
declare function goTryOr<T>(fn: () => never, defaultValue: T | (() => T)): ResultWithDefault$1<string, T>;
|
|
202
|
+
declare function goTryOr<T>(fn: () => Promise<T>, defaultValue: T | (() => T)): Promise<ResultWithDefault$1<string, T>>;
|
|
203
|
+
declare function goTryOr<T>(promise: Promise<T>, defaultValue: T | (() => T)): Promise<ResultWithDefault$1<string, T>>;
|
|
204
|
+
declare function goTryOr<T>(fn: () => T, defaultValue: T | (() => T)): ResultWithDefault$1<string, T>;
|
|
205
|
+
declare function goTryOr<T>(value: T, defaultValue: T | (() => T)): ResultWithDefault$1<string, T>;
|
|
206
206
|
|
|
207
207
|
/**
|
|
208
208
|
* Executes multiple promises or factory functions in parallel (or with limited concurrency)
|
|
@@ -344,6 +344,47 @@ declare function assert(condition: unknown, error: Error | string): asserts cond
|
|
|
344
344
|
*/
|
|
345
345
|
declare function assert<T extends Error>(condition: unknown, ErrorClass: new (message: string) => T, message: string): asserts condition;
|
|
346
346
|
|
|
347
|
+
/**
|
|
348
|
+
* Error class constructor type.
|
|
349
|
+
*/
|
|
350
|
+
type ErrorConstructor<E extends Error = Error> = new (message: string, options?: {
|
|
351
|
+
cause?: unknown;
|
|
352
|
+
}) => E;
|
|
353
|
+
/**
|
|
354
|
+
* Ensures a value satisfies a predicate, throwing an error if not.
|
|
355
|
+
* Returns the value if the predicate passes.
|
|
356
|
+
*
|
|
357
|
+
* Accepts sync values, promises, or functions - just like `go`.
|
|
358
|
+
*
|
|
359
|
+
* The error can be either:
|
|
360
|
+
* - An Error class constructor (instantiated with the value as cause)
|
|
361
|
+
* - A function that creates and returns an Error
|
|
362
|
+
* - If omitted, defaults to UnknownError
|
|
363
|
+
*
|
|
364
|
+
* @example
|
|
365
|
+
* ```typescript
|
|
366
|
+
* // With sync value (uses UnknownError by default)
|
|
367
|
+
* ensure(42, n => n > 0)
|
|
368
|
+
*
|
|
369
|
+
* // With promise (awaited internally)
|
|
370
|
+
* const res = await ensure(fetch('/api'), r => r.ok, RequestFailedError)
|
|
371
|
+
*
|
|
372
|
+
* // With function
|
|
373
|
+
* const res = ensure(() => parseInt('42'), n => !isNaN(n), Error)
|
|
374
|
+
*
|
|
375
|
+
* // With error factory function
|
|
376
|
+
* const res = ensure(
|
|
377
|
+
* await fetch('/api'),
|
|
378
|
+
* r => r.ok,
|
|
379
|
+
* r => new Error(`HTTP ${r.status}`)
|
|
380
|
+
* )
|
|
381
|
+
* ```
|
|
382
|
+
*/
|
|
383
|
+
declare function ensure<T>(value: Promise<T>, predicate: (value: T) => boolean, error?: ErrorConstructor<Error> | ((value: T) => Error)): Promise<T>;
|
|
384
|
+
declare function ensure<T>(fn: () => Promise<T>, predicate: (value: T) => boolean, error?: ErrorConstructor<Error> | ((value: T) => Error)): Promise<T>;
|
|
385
|
+
declare function ensure<T>(fn: () => T, predicate: (value: T) => boolean, error?: ErrorConstructor<Error> | ((value: T) => Error)): T;
|
|
386
|
+
declare function ensure<T>(value: T, predicate: (value: T) => boolean, error?: ErrorConstructor<Error> | ((value: T) => Error)): T;
|
|
387
|
+
|
|
347
388
|
declare function isSuccess<E, T>(result: Result<E, T>): result is Success<T>;
|
|
348
389
|
declare function isFailure<E, T>(result: Result<E, T>): result is Failure<E>;
|
|
349
390
|
declare function success<T>(value: T): Success<T>;
|
|
@@ -375,6 +416,40 @@ declare function failure<E>(error: E): Failure<E>;
|
|
|
375
416
|
*/
|
|
376
417
|
declare function assertNever(value: never): never;
|
|
377
418
|
|
|
378
|
-
|
|
379
|
-
|
|
419
|
+
/**
|
|
420
|
+
* Result type with Error and a default value.
|
|
421
|
+
* On error, returns [Error, DefaultT]
|
|
422
|
+
* On success, returns [undefined, T]
|
|
423
|
+
*/
|
|
424
|
+
type ResultWithDefault<E, T, D = T> = readonly [E, D] | readonly [undefined, T];
|
|
425
|
+
/**
|
|
426
|
+
* Executes a function, promise, or value and returns a Result type with a fallback default.
|
|
427
|
+
* If an error occurs, it returns the actual Error object and the default value.
|
|
428
|
+
*
|
|
429
|
+
* @template T The type of the successful result
|
|
430
|
+
* @template D The type of the default value (defaults to T)
|
|
431
|
+
* @param {T | Promise<T> | (() => T | Promise<T>)} value - The value, promise, or function to execute
|
|
432
|
+
* @param {D | (() => D)} defaultValue - The default value or a function to compute it (only called on failure)
|
|
433
|
+
* @returns {ResultWithDefault<Error, T, D> | Promise<ResultWithDefault<Error, T, D>>} A tuple of [error, value] or Promise thereof
|
|
434
|
+
*
|
|
435
|
+
* @example
|
|
436
|
+
* // With a static default
|
|
437
|
+
* const [err, config] = goElse(() => JSON.parse('invalid'), { port: 3000 })
|
|
438
|
+
* // err is the Error object, config is { port: 3000 }
|
|
439
|
+
*
|
|
440
|
+
* @example
|
|
441
|
+
* // With a computed default (lazy evaluation)
|
|
442
|
+
* const [err, user] = await goElse(fetchUser(id), () => ({
|
|
443
|
+
* id: 'anonymous',
|
|
444
|
+
* name: 'Guest'
|
|
445
|
+
* }))
|
|
446
|
+
*/
|
|
447
|
+
declare function goElse<T, D = T>(fn: () => never, defaultValue: D | (() => D)): ResultWithDefault<Error, never, D>;
|
|
448
|
+
declare function goElse<T, D = T>(fn: () => Promise<T>, defaultValue: D | (() => D)): Promise<ResultWithDefault<Error, T, D>>;
|
|
449
|
+
declare function goElse<T, D = T>(promise: Promise<T>, defaultValue: D | (() => D)): Promise<ResultWithDefault<Error, T, D>>;
|
|
450
|
+
declare function goElse<T, D = T>(fn: () => T, defaultValue: D | (() => D)): ResultWithDefault<Error, T, D>;
|
|
451
|
+
declare function goElse<T, D = T>(value: T, defaultValue: D | (() => D)): ResultWithDefault<Error, T, D>;
|
|
452
|
+
|
|
453
|
+
export { UnknownError, assert, assertNever, ensure, failure, goTryRaw as go, goTryAllRaw as goAll, goElse, goTry, goTryAll, goTryAllRaw, goTryOr, goTryRaw, isFailure, isSuccess, success, taggedError };
|
|
454
|
+
export type { ErrorConstructor$1 as ErrorConstructor, Failure, GoTryAllOptions, GoTryAllRawOptions, GoTryRawOptions, MaybePromise, Result, ResultWithDefault$1 as ResultWithDefault, Success, TaggedError, TaggedUnion };
|
|
380
455
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","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":"AAAA;;;AAIM,KAAM,OAAO;AACb,KAAM,OAAO;AACb,KAAM,MAAM,SAAS,OAAO,MAAM,OAAO;AAEzC,
|
|
1
|
+
{"version":3,"file":"index.d.cts","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/ensure.ts","../src/result-helpers.ts","../src/goElse.ts"],"mappings":"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","names":["ResultWithDefault","ErrorConstructor"]}
|
package/dist/index.d.mts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
type Success<T> = readonly [undefined, T];
|
|
5
5
|
type Failure<E> = readonly [E, undefined];
|
|
6
6
|
type Result<E, T> = Success<T> | Failure<E>;
|
|
7
|
-
type ResultWithDefault<E, T> = readonly [E | undefined, T];
|
|
7
|
+
type ResultWithDefault$1<E, T> = readonly [E | undefined, T];
|
|
8
8
|
type MaybePromise<T> = T | Promise<T>;
|
|
9
9
|
/**
|
|
10
10
|
* Base interface for tagged errors.
|
|
@@ -25,7 +25,7 @@ interface GoTryAllOptions {
|
|
|
25
25
|
/**
|
|
26
26
|
* Type for error constructors that can be used with goTryRaw.
|
|
27
27
|
*/
|
|
28
|
-
type ErrorConstructor<E> = new (message: string, options?: {
|
|
28
|
+
type ErrorConstructor$1<E> = new (message: string, options?: {
|
|
29
29
|
cause?: unknown;
|
|
30
30
|
}) => E;
|
|
31
31
|
/**
|
|
@@ -33,11 +33,11 @@ type ErrorConstructor<E> = new (message: string, options?: {
|
|
|
33
33
|
* errorClass and systemErrorClass are mutually exclusive - you can only provide one.
|
|
34
34
|
*/
|
|
35
35
|
type GoTryRawOptions<E = Error> = {
|
|
36
|
-
errorClass: ErrorConstructor<E>;
|
|
36
|
+
errorClass: ErrorConstructor$1<E>;
|
|
37
37
|
systemErrorClass?: never;
|
|
38
38
|
} | {
|
|
39
39
|
errorClass?: never;
|
|
40
|
-
systemErrorClass: ErrorConstructor<E>;
|
|
40
|
+
systemErrorClass: ErrorConstructor$1<E>;
|
|
41
41
|
} | {
|
|
42
42
|
errorClass?: never;
|
|
43
43
|
systemErrorClass?: never;
|
|
@@ -49,12 +49,12 @@ type GoTryRawOptions<E = Error> = {
|
|
|
49
49
|
*/
|
|
50
50
|
type GoTryAllRawOptions<E = Error> = {
|
|
51
51
|
concurrency?: number;
|
|
52
|
-
errorClass: ErrorConstructor<E>;
|
|
52
|
+
errorClass: ErrorConstructor$1<E>;
|
|
53
53
|
systemErrorClass?: never;
|
|
54
54
|
} | {
|
|
55
55
|
concurrency?: number;
|
|
56
56
|
errorClass?: never;
|
|
57
|
-
systemErrorClass: ErrorConstructor<E>;
|
|
57
|
+
systemErrorClass: ErrorConstructor$1<E>;
|
|
58
58
|
} | {
|
|
59
59
|
concurrency?: number;
|
|
60
60
|
errorClass?: never;
|
|
@@ -73,8 +73,8 @@ type GoTryAllRawOptions<E = Error> = {
|
|
|
73
73
|
* type AppError = TaggedUnion<[typeof DatabaseError, typeof NetworkError]>
|
|
74
74
|
* // Equivalent to: DatabaseError | NetworkError
|
|
75
75
|
*/
|
|
76
|
-
type TaggedUnion<T extends readonly ErrorConstructor<unknown>[]> = {
|
|
77
|
-
[K in keyof T]: T[K] extends ErrorConstructor<infer E> ? E : never;
|
|
76
|
+
type TaggedUnion<T extends readonly ErrorConstructor$1<unknown>[]> = {
|
|
77
|
+
[K in keyof T]: T[K] extends ErrorConstructor$1<infer E> ? E : never;
|
|
78
78
|
}[number];
|
|
79
79
|
|
|
80
80
|
/**
|
|
@@ -198,11 +198,11 @@ declare function goTryRaw<T, E = InstanceType<typeof UnknownError>>(value: T, op
|
|
|
198
198
|
* name: 'Guest'
|
|
199
199
|
* }))
|
|
200
200
|
*/
|
|
201
|
-
declare function goTryOr<T>(fn: () => never, defaultValue: T | (() => T)): ResultWithDefault<string, T>;
|
|
202
|
-
declare function goTryOr<T>(fn: () => Promise<T>, defaultValue: T | (() => T)): Promise<ResultWithDefault<string, T>>;
|
|
203
|
-
declare function goTryOr<T>(promise: Promise<T>, defaultValue: T | (() => T)): Promise<ResultWithDefault<string, T>>;
|
|
204
|
-
declare function goTryOr<T>(fn: () => T, defaultValue: T | (() => T)): ResultWithDefault<string, T>;
|
|
205
|
-
declare function goTryOr<T>(value: T, defaultValue: T | (() => T)): ResultWithDefault<string, T>;
|
|
201
|
+
declare function goTryOr<T>(fn: () => never, defaultValue: T | (() => T)): ResultWithDefault$1<string, T>;
|
|
202
|
+
declare function goTryOr<T>(fn: () => Promise<T>, defaultValue: T | (() => T)): Promise<ResultWithDefault$1<string, T>>;
|
|
203
|
+
declare function goTryOr<T>(promise: Promise<T>, defaultValue: T | (() => T)): Promise<ResultWithDefault$1<string, T>>;
|
|
204
|
+
declare function goTryOr<T>(fn: () => T, defaultValue: T | (() => T)): ResultWithDefault$1<string, T>;
|
|
205
|
+
declare function goTryOr<T>(value: T, defaultValue: T | (() => T)): ResultWithDefault$1<string, T>;
|
|
206
206
|
|
|
207
207
|
/**
|
|
208
208
|
* Executes multiple promises or factory functions in parallel (or with limited concurrency)
|
|
@@ -344,6 +344,47 @@ declare function assert(condition: unknown, error: Error | string): asserts cond
|
|
|
344
344
|
*/
|
|
345
345
|
declare function assert<T extends Error>(condition: unknown, ErrorClass: new (message: string) => T, message: string): asserts condition;
|
|
346
346
|
|
|
347
|
+
/**
|
|
348
|
+
* Error class constructor type.
|
|
349
|
+
*/
|
|
350
|
+
type ErrorConstructor<E extends Error = Error> = new (message: string, options?: {
|
|
351
|
+
cause?: unknown;
|
|
352
|
+
}) => E;
|
|
353
|
+
/**
|
|
354
|
+
* Ensures a value satisfies a predicate, throwing an error if not.
|
|
355
|
+
* Returns the value if the predicate passes.
|
|
356
|
+
*
|
|
357
|
+
* Accepts sync values, promises, or functions - just like `go`.
|
|
358
|
+
*
|
|
359
|
+
* The error can be either:
|
|
360
|
+
* - An Error class constructor (instantiated with the value as cause)
|
|
361
|
+
* - A function that creates and returns an Error
|
|
362
|
+
* - If omitted, defaults to UnknownError
|
|
363
|
+
*
|
|
364
|
+
* @example
|
|
365
|
+
* ```typescript
|
|
366
|
+
* // With sync value (uses UnknownError by default)
|
|
367
|
+
* ensure(42, n => n > 0)
|
|
368
|
+
*
|
|
369
|
+
* // With promise (awaited internally)
|
|
370
|
+
* const res = await ensure(fetch('/api'), r => r.ok, RequestFailedError)
|
|
371
|
+
*
|
|
372
|
+
* // With function
|
|
373
|
+
* const res = ensure(() => parseInt('42'), n => !isNaN(n), Error)
|
|
374
|
+
*
|
|
375
|
+
* // With error factory function
|
|
376
|
+
* const res = ensure(
|
|
377
|
+
* await fetch('/api'),
|
|
378
|
+
* r => r.ok,
|
|
379
|
+
* r => new Error(`HTTP ${r.status}`)
|
|
380
|
+
* )
|
|
381
|
+
* ```
|
|
382
|
+
*/
|
|
383
|
+
declare function ensure<T>(value: Promise<T>, predicate: (value: T) => boolean, error?: ErrorConstructor<Error> | ((value: T) => Error)): Promise<T>;
|
|
384
|
+
declare function ensure<T>(fn: () => Promise<T>, predicate: (value: T) => boolean, error?: ErrorConstructor<Error> | ((value: T) => Error)): Promise<T>;
|
|
385
|
+
declare function ensure<T>(fn: () => T, predicate: (value: T) => boolean, error?: ErrorConstructor<Error> | ((value: T) => Error)): T;
|
|
386
|
+
declare function ensure<T>(value: T, predicate: (value: T) => boolean, error?: ErrorConstructor<Error> | ((value: T) => Error)): T;
|
|
387
|
+
|
|
347
388
|
declare function isSuccess<E, T>(result: Result<E, T>): result is Success<T>;
|
|
348
389
|
declare function isFailure<E, T>(result: Result<E, T>): result is Failure<E>;
|
|
349
390
|
declare function success<T>(value: T): Success<T>;
|
|
@@ -375,6 +416,40 @@ declare function failure<E>(error: E): Failure<E>;
|
|
|
375
416
|
*/
|
|
376
417
|
declare function assertNever(value: never): never;
|
|
377
418
|
|
|
378
|
-
|
|
379
|
-
|
|
419
|
+
/**
|
|
420
|
+
* Result type with Error and a default value.
|
|
421
|
+
* On error, returns [Error, DefaultT]
|
|
422
|
+
* On success, returns [undefined, T]
|
|
423
|
+
*/
|
|
424
|
+
type ResultWithDefault<E, T, D = T> = readonly [E, D] | readonly [undefined, T];
|
|
425
|
+
/**
|
|
426
|
+
* Executes a function, promise, or value and returns a Result type with a fallback default.
|
|
427
|
+
* If an error occurs, it returns the actual Error object and the default value.
|
|
428
|
+
*
|
|
429
|
+
* @template T The type of the successful result
|
|
430
|
+
* @template D The type of the default value (defaults to T)
|
|
431
|
+
* @param {T | Promise<T> | (() => T | Promise<T>)} value - The value, promise, or function to execute
|
|
432
|
+
* @param {D | (() => D)} defaultValue - The default value or a function to compute it (only called on failure)
|
|
433
|
+
* @returns {ResultWithDefault<Error, T, D> | Promise<ResultWithDefault<Error, T, D>>} A tuple of [error, value] or Promise thereof
|
|
434
|
+
*
|
|
435
|
+
* @example
|
|
436
|
+
* // With a static default
|
|
437
|
+
* const [err, config] = goElse(() => JSON.parse('invalid'), { port: 3000 })
|
|
438
|
+
* // err is the Error object, config is { port: 3000 }
|
|
439
|
+
*
|
|
440
|
+
* @example
|
|
441
|
+
* // With a computed default (lazy evaluation)
|
|
442
|
+
* const [err, user] = await goElse(fetchUser(id), () => ({
|
|
443
|
+
* id: 'anonymous',
|
|
444
|
+
* name: 'Guest'
|
|
445
|
+
* }))
|
|
446
|
+
*/
|
|
447
|
+
declare function goElse<T, D = T>(fn: () => never, defaultValue: D | (() => D)): ResultWithDefault<Error, never, D>;
|
|
448
|
+
declare function goElse<T, D = T>(fn: () => Promise<T>, defaultValue: D | (() => D)): Promise<ResultWithDefault<Error, T, D>>;
|
|
449
|
+
declare function goElse<T, D = T>(promise: Promise<T>, defaultValue: D | (() => D)): Promise<ResultWithDefault<Error, T, D>>;
|
|
450
|
+
declare function goElse<T, D = T>(fn: () => T, defaultValue: D | (() => D)): ResultWithDefault<Error, T, D>;
|
|
451
|
+
declare function goElse<T, D = T>(value: T, defaultValue: D | (() => D)): ResultWithDefault<Error, T, D>;
|
|
452
|
+
|
|
453
|
+
export { UnknownError, assert, assertNever, ensure, failure, goTryRaw as go, goTryAllRaw as goAll, goElse, goTry, goTryAll, goTryAllRaw, goTryOr, goTryRaw, isFailure, isSuccess, success, taggedError };
|
|
454
|
+
export type { ErrorConstructor$1 as ErrorConstructor, Failure, GoTryAllOptions, GoTryAllRawOptions, GoTryRawOptions, MaybePromise, Result, ResultWithDefault$1 as ResultWithDefault, Success, TaggedError, TaggedUnion };
|
|
380
455
|
//# 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/unknown-error.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,
|
|
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/ensure.ts","../src/result-helpers.ts","../src/goElse.ts"],"mappings":"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","names":["ResultWithDefault","ErrorConstructor"]}
|
package/dist/index.mjs
CHANGED
|
@@ -26,7 +26,7 @@ function getErrorMessage(error) {
|
|
|
26
26
|
return String(error);
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
-
function isPromise(value) {
|
|
29
|
+
function isPromise$1(value) {
|
|
30
30
|
return typeof value === "object" && value !== null && "then" in value && typeof value.then === "function";
|
|
31
31
|
}
|
|
32
32
|
function isError(value) {
|
|
@@ -39,7 +39,7 @@ function resolveDefault(defaultValue) {
|
|
|
39
39
|
function goTry(value) {
|
|
40
40
|
try {
|
|
41
41
|
const result = typeof value === "function" ? value() : value;
|
|
42
|
-
if (isPromise(result)) {
|
|
42
|
+
if (isPromise$1(result)) {
|
|
43
43
|
return result.then((resolvedValue) => success(resolvedValue)).catch((err) => failure(getErrorMessage(err)));
|
|
44
44
|
}
|
|
45
45
|
return success(result);
|
|
@@ -96,7 +96,7 @@ function goTryRaw(value, options) {
|
|
|
96
96
|
};
|
|
97
97
|
try {
|
|
98
98
|
const result = typeof value === "function" ? value() : value;
|
|
99
|
-
if (isPromise(result)) {
|
|
99
|
+
if (isPromise$1(result)) {
|
|
100
100
|
return result.then((resolvedValue) => success(resolvedValue)).catch((err) => failure(wrapError(err)));
|
|
101
101
|
}
|
|
102
102
|
return success(result);
|
|
@@ -108,7 +108,7 @@ function goTryRaw(value, options) {
|
|
|
108
108
|
function goTryOr(value, defaultValue) {
|
|
109
109
|
try {
|
|
110
110
|
const result = typeof value === "function" ? value() : value;
|
|
111
|
-
if (isPromise(result)) {
|
|
111
|
+
if (isPromise$1(result)) {
|
|
112
112
|
return result.then((resolvedValue) => success(resolvedValue)).catch((err) => [getErrorMessage(err), resolveDefault(defaultValue)]);
|
|
113
113
|
}
|
|
114
114
|
return success(result);
|
|
@@ -219,4 +219,62 @@ function assert(condition, errorOrClass, message) {
|
|
|
219
219
|
}
|
|
220
220
|
}
|
|
221
221
|
|
|
222
|
-
|
|
222
|
+
function isPromise(value) {
|
|
223
|
+
return value instanceof Promise;
|
|
224
|
+
}
|
|
225
|
+
function isErrorConstructor(error) {
|
|
226
|
+
return typeof error === "function" && error.prototype !== void 0 && error.prototype instanceof Error;
|
|
227
|
+
}
|
|
228
|
+
function throwError(value, error) {
|
|
229
|
+
if (isErrorConstructor(error)) {
|
|
230
|
+
throw new error(String(value), { cause: value });
|
|
231
|
+
}
|
|
232
|
+
throw error(value);
|
|
233
|
+
}
|
|
234
|
+
function ensure(value, predicate, error = UnknownError) {
|
|
235
|
+
if (typeof value === "function") {
|
|
236
|
+
const result = value();
|
|
237
|
+
if (isPromise(result)) {
|
|
238
|
+
return result.then((resolved) => {
|
|
239
|
+
if (!predicate(resolved)) {
|
|
240
|
+
throwError(resolved, error);
|
|
241
|
+
}
|
|
242
|
+
return resolved;
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
if (!predicate(result)) {
|
|
246
|
+
throwError(result, error);
|
|
247
|
+
}
|
|
248
|
+
return result;
|
|
249
|
+
}
|
|
250
|
+
if (isPromise(value)) {
|
|
251
|
+
return value.then((resolved) => {
|
|
252
|
+
if (!predicate(resolved)) {
|
|
253
|
+
throwError(resolved, error);
|
|
254
|
+
}
|
|
255
|
+
return resolved;
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
if (!predicate(value)) {
|
|
259
|
+
throwError(value, error);
|
|
260
|
+
}
|
|
261
|
+
return value;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function goElse(value, defaultValue) {
|
|
265
|
+
try {
|
|
266
|
+
const result = typeof value === "function" ? value() : value;
|
|
267
|
+
if (isPromise$1(result)) {
|
|
268
|
+
return result.then((resolvedValue) => [void 0, resolvedValue]).catch((err) => {
|
|
269
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
270
|
+
return [error, resolveDefault(defaultValue)];
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
return [void 0, result];
|
|
274
|
+
} catch (err) {
|
|
275
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
276
|
+
return [error, resolveDefault(defaultValue)];
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
export { UnknownError, assert, assertNever, ensure, failure, goTryRaw as go, goTryAllRaw as goAll, goElse, goTry, goTryAll, goTryAllRaw, goTryOr, goTryRaw, isFailure, isSuccess, success, taggedError };
|
package/package.json
CHANGED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { describe, test, expect } from 'vitest'
|
|
2
|
+
import { ensure } from './ensure.js'
|
|
3
|
+
import { taggedError } from './tagged-error.js'
|
|
4
|
+
import { UnknownError } from './unknown-error.js'
|
|
5
|
+
|
|
6
|
+
describe('ensure', () => {
|
|
7
|
+
test('returns value when predicate passes', () => {
|
|
8
|
+
const result = ensure(42, (n) => n > 0, () => new Error('negative'))
|
|
9
|
+
expect(result).toBe(42)
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
test('uses UnknownError when error parameter is omitted', () => {
|
|
13
|
+
expect(() => ensure(-1, (n) => n > 0)).toThrow(UnknownError)
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
test('uses UnknownError with async when error parameter is omitted', async () => {
|
|
17
|
+
await expect(ensure(Promise.resolve(-1), (n) => n > 0)).rejects.toThrow(UnknownError)
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
test('returns value when predicate passes with error class', () => {
|
|
21
|
+
const MyError = taggedError('MyError')
|
|
22
|
+
const result = ensure(42, (n) => n > 0, MyError)
|
|
23
|
+
expect(result).toBe(42)
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
test('returns value with complex predicate', () => {
|
|
27
|
+
const result = ensure([1, 2, 3], (arr) => arr.length > 0, () => new Error('empty'))
|
|
28
|
+
expect(result).toEqual([1, 2, 3])
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
test('throws error when predicate fails', () => {
|
|
32
|
+
expect(() => ensure(-1, (n) => n > 0, (n) => new Error(`${n} is negative`))).toThrow('-1 is negative')
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
test('throws with access to value in error factory', () => {
|
|
36
|
+
const obj = { status: 404 }
|
|
37
|
+
expect(() =>
|
|
38
|
+
ensure(
|
|
39
|
+
obj,
|
|
40
|
+
(o) => o.status === 200,
|
|
41
|
+
(o) => new Error(`HTTP ${o.status}`)
|
|
42
|
+
)
|
|
43
|
+
).toThrow('HTTP 404')
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
test('throws with error class constructor', () => {
|
|
47
|
+
const RequestFailed = taggedError('RequestFailed')
|
|
48
|
+
const obj = { status: 404 }
|
|
49
|
+
expect(() =>
|
|
50
|
+
ensure(
|
|
51
|
+
obj,
|
|
52
|
+
(o: { status: number }) => o.status === 200,
|
|
53
|
+
RequestFailed
|
|
54
|
+
)
|
|
55
|
+
).toThrow()
|
|
56
|
+
try {
|
|
57
|
+
ensure(obj, (o: { status: number }) => o.status === 200, RequestFailed)
|
|
58
|
+
} catch (e) {
|
|
59
|
+
expect(e).toBeInstanceOf(RequestFailed)
|
|
60
|
+
expect((e as Error & { cause?: unknown }).cause).toBe(obj)
|
|
61
|
+
}
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
test('narrows type when predicate is type guard', () => {
|
|
65
|
+
interface User {
|
|
66
|
+
name: string
|
|
67
|
+
}
|
|
68
|
+
const maybeUser: unknown = { name: 'Alice' }
|
|
69
|
+
|
|
70
|
+
const user = ensure(
|
|
71
|
+
maybeUser as unknown,
|
|
72
|
+
(u): u is User => typeof u === 'object' && u !== null && 'name' in u,
|
|
73
|
+
() => new Error('Not a user')
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
// TypeScript knows this is User, not unknown
|
|
77
|
+
expect((user as User).name).toBe('Alice')
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
test('works with async values (promise passed directly)', async () => {
|
|
81
|
+
const result = await ensure(Promise.resolve(42), (n) => n > 0, () => new Error('negative'))
|
|
82
|
+
expect(result).toBe(42)
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
test('throws with async values when predicate fails', async () => {
|
|
86
|
+
await expect(
|
|
87
|
+
ensure(Promise.resolve(-1), (n) => n > 0, (n) => new Error(`${n} is negative`))
|
|
88
|
+
).rejects.toThrow('-1 is negative')
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
test('works with sync functions', () => {
|
|
92
|
+
const result = ensure(() => 42, (n) => n > 0, () => new Error('negative'))
|
|
93
|
+
expect(result).toBe(42)
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
test('throws with sync functions when predicate fails', () => {
|
|
97
|
+
expect(() =>
|
|
98
|
+
ensure(() => -1, (n) => n > 0, (n) => new Error(`${n} is negative`))
|
|
99
|
+
).toThrow('-1 is negative')
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
test('works with async functions', async () => {
|
|
103
|
+
const result = await ensure(
|
|
104
|
+
() => Promise.resolve(42),
|
|
105
|
+
(n) => n > 0,
|
|
106
|
+
() => new Error('negative')
|
|
107
|
+
)
|
|
108
|
+
expect(result).toBe(42)
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
test('throws with async functions when predicate fails', async () => {
|
|
112
|
+
await expect(
|
|
113
|
+
ensure(() => Promise.resolve(-1), (n) => n > 0, (n) => new Error(`${n} is negative`))
|
|
114
|
+
).rejects.toThrow('-1 is negative')
|
|
115
|
+
})
|
|
116
|
+
})
|
package/src/ensure.ts
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { UnknownError } from './unknown-error.js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Error class constructor type.
|
|
5
|
+
*/
|
|
6
|
+
type ErrorConstructor<E extends Error = Error> = new (
|
|
7
|
+
message: string,
|
|
8
|
+
options?: { cause?: unknown },
|
|
9
|
+
) => E
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Helper to check if value is a Promise.
|
|
13
|
+
*/
|
|
14
|
+
function isPromise<T>(value: unknown): value is Promise<T> {
|
|
15
|
+
return value instanceof Promise
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Type guard to check if error is an Error class constructor.
|
|
20
|
+
*/
|
|
21
|
+
function isErrorConstructor<E extends Error>(
|
|
22
|
+
error: ErrorConstructor<E> | ((value: unknown) => E) | ((value: never) => E),
|
|
23
|
+
): error is ErrorConstructor<E> {
|
|
24
|
+
return (
|
|
25
|
+
typeof error === 'function' &&
|
|
26
|
+
error.prototype !== undefined &&
|
|
27
|
+
error.prototype instanceof Error
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Helper to throw error from class or factory.
|
|
33
|
+
*/
|
|
34
|
+
function throwError<T, E extends Error>(
|
|
35
|
+
value: T,
|
|
36
|
+
error: ErrorConstructor<E> | ((value: never) => E),
|
|
37
|
+
): never {
|
|
38
|
+
if (isErrorConstructor(error)) {
|
|
39
|
+
// It's an Error class constructor
|
|
40
|
+
throw new error(String(value), { cause: value })
|
|
41
|
+
}
|
|
42
|
+
// It's a factory function - cast to any to handle type variance
|
|
43
|
+
throw (error as (value: T) => E)(value)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Ensures a value satisfies a predicate, throwing an error if not.
|
|
48
|
+
* Returns the value if the predicate passes.
|
|
49
|
+
*
|
|
50
|
+
* Accepts sync values, promises, or functions - just like `go`.
|
|
51
|
+
*
|
|
52
|
+
* The error can be either:
|
|
53
|
+
* - An Error class constructor (instantiated with the value as cause)
|
|
54
|
+
* - A function that creates and returns an Error
|
|
55
|
+
* - If omitted, defaults to UnknownError
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```typescript
|
|
59
|
+
* // With sync value (uses UnknownError by default)
|
|
60
|
+
* ensure(42, n => n > 0)
|
|
61
|
+
*
|
|
62
|
+
* // With promise (awaited internally)
|
|
63
|
+
* const res = await ensure(fetch('/api'), r => r.ok, RequestFailedError)
|
|
64
|
+
*
|
|
65
|
+
* // With function
|
|
66
|
+
* const res = ensure(() => parseInt('42'), n => !isNaN(n), Error)
|
|
67
|
+
*
|
|
68
|
+
* // With error factory function
|
|
69
|
+
* const res = ensure(
|
|
70
|
+
* await fetch('/api'),
|
|
71
|
+
* r => r.ok,
|
|
72
|
+
* r => new Error(`HTTP ${r.status}`)
|
|
73
|
+
* )
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
// Promise overloads first (more specific)
|
|
77
|
+
export function ensure<T>(
|
|
78
|
+
value: Promise<T>,
|
|
79
|
+
predicate: (value: T) => boolean,
|
|
80
|
+
error?: ErrorConstructor<Error> | ((value: T) => Error),
|
|
81
|
+
): Promise<T>
|
|
82
|
+
// Function returning Promise
|
|
83
|
+
export function ensure<T>(
|
|
84
|
+
fn: () => Promise<T>,
|
|
85
|
+
predicate: (value: T) => boolean,
|
|
86
|
+
error?: ErrorConstructor<Error> | ((value: T) => Error),
|
|
87
|
+
): Promise<T>
|
|
88
|
+
// Sync function
|
|
89
|
+
export function ensure<T>(
|
|
90
|
+
fn: () => T,
|
|
91
|
+
predicate: (value: T) => boolean,
|
|
92
|
+
error?: ErrorConstructor<Error> | ((value: T) => Error),
|
|
93
|
+
): T
|
|
94
|
+
// Sync value (catch-all)
|
|
95
|
+
export function ensure<T>(
|
|
96
|
+
value: T,
|
|
97
|
+
predicate: (value: T) => boolean,
|
|
98
|
+
error?: ErrorConstructor<Error> | ((value: T) => Error),
|
|
99
|
+
): T
|
|
100
|
+
export function ensure<T>(
|
|
101
|
+
value: T | Promise<T> | (() => T | Promise<T>),
|
|
102
|
+
predicate: (value: T) => boolean,
|
|
103
|
+
error: ErrorConstructor<Error> | ((value: T) => Error) = UnknownError,
|
|
104
|
+
): T | Promise<T> {
|
|
105
|
+
// Handle function
|
|
106
|
+
if (typeof value === 'function') {
|
|
107
|
+
const result = (value as () => T | Promise<T>)()
|
|
108
|
+
if (isPromise<T>(result)) {
|
|
109
|
+
return result.then((resolved) => {
|
|
110
|
+
if (!predicate(resolved)) {
|
|
111
|
+
throwError(resolved, error)
|
|
112
|
+
}
|
|
113
|
+
return resolved
|
|
114
|
+
})
|
|
115
|
+
}
|
|
116
|
+
if (!predicate(result)) {
|
|
117
|
+
throwError(result, error)
|
|
118
|
+
}
|
|
119
|
+
return result
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Handle promise
|
|
123
|
+
if (isPromise<T>(value)) {
|
|
124
|
+
return value.then((resolved) => {
|
|
125
|
+
if (!predicate(resolved)) {
|
|
126
|
+
throwError(resolved, error)
|
|
127
|
+
}
|
|
128
|
+
return resolved
|
|
129
|
+
})
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Handle sync value
|
|
133
|
+
if (!predicate(value)) {
|
|
134
|
+
throwError(value, error)
|
|
135
|
+
}
|
|
136
|
+
return value
|
|
137
|
+
}
|
package/src/go.test.ts
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { describe, test, expect } from 'vitest'
|
|
2
|
+
import { go, goAll, goElse } from './index.js'
|
|
3
|
+
|
|
4
|
+
describe('go (alias for goTryRaw)', () => {
|
|
5
|
+
test('returns value on success', async () => {
|
|
6
|
+
const result = await go(Promise.resolve(42))
|
|
7
|
+
expect(result).toEqual([undefined, 42])
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
test('returns error on failure', async () => {
|
|
11
|
+
const error = new Error('oops')
|
|
12
|
+
const result = await go(Promise.reject(error))
|
|
13
|
+
// goTryRaw wraps errors in UnknownError by default
|
|
14
|
+
expect(result[0]).toBeInstanceOf(Error)
|
|
15
|
+
expect(result[0]?.message).toBe('oops')
|
|
16
|
+
expect(result[1]).toBeUndefined()
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
test('works with non-promise values', async () => {
|
|
20
|
+
const result = await go(42)
|
|
21
|
+
expect(result).toEqual([undefined, 42])
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
test('works with sync functions', async () => {
|
|
25
|
+
const result = await go(() => 'hello')
|
|
26
|
+
expect(result).toEqual([undefined, 'hello'])
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
test('catches sync errors', async () => {
|
|
30
|
+
const result = await go(() => {
|
|
31
|
+
throw new Error('sync error')
|
|
32
|
+
})
|
|
33
|
+
expect(result[0]?.message).toBe('sync error')
|
|
34
|
+
expect(result[1]).toBeUndefined()
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
test('is exported from index', () => {
|
|
38
|
+
// Verified by the import at the top of the file
|
|
39
|
+
expect(go).toBeDefined()
|
|
40
|
+
})
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
describe('goAll (alias for goTryAllRaw)', () => {
|
|
44
|
+
test('returns all results', async () => {
|
|
45
|
+
const [errors, results] = await goAll([
|
|
46
|
+
() => Promise.resolve(1),
|
|
47
|
+
() => Promise.resolve(2),
|
|
48
|
+
() => Promise.resolve(3),
|
|
49
|
+
])
|
|
50
|
+
expect(errors).toEqual([undefined, undefined, undefined])
|
|
51
|
+
expect(results).toEqual([1, 2, 3])
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
test('handles mixed success and failure', async () => {
|
|
55
|
+
const [errors, results] = await goAll([
|
|
56
|
+
() => Promise.resolve(1),
|
|
57
|
+
() => Promise.reject(new Error('failed')),
|
|
58
|
+
() => Promise.resolve(3),
|
|
59
|
+
])
|
|
60
|
+
expect(errors[0]).toBeUndefined()
|
|
61
|
+
expect(errors[1]).toBeInstanceOf(Error)
|
|
62
|
+
expect(errors[2]).toBeUndefined()
|
|
63
|
+
expect(results).toEqual([1, undefined, 3])
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
test('is exported from index', () => {
|
|
67
|
+
expect(goAll).toBeDefined()
|
|
68
|
+
})
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
describe('goElse', () => {
|
|
72
|
+
test('returns value on success', async () => {
|
|
73
|
+
const [err, value] = await goElse(Promise.resolve(42), 0)
|
|
74
|
+
expect(err).toBeUndefined()
|
|
75
|
+
expect(value).toBe(42)
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
test('returns default on failure with Error object', async () => {
|
|
79
|
+
const originalError = new Error('oops')
|
|
80
|
+
const [err, value] = await goElse(() => Promise.reject(originalError), 'default')
|
|
81
|
+
expect(err).toBeInstanceOf(Error)
|
|
82
|
+
expect(err?.message).toBe('oops')
|
|
83
|
+
expect(value).toBe('default')
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
test('returns default on sync error with Error object', async () => {
|
|
87
|
+
const [err, value] = await goElse(() => {
|
|
88
|
+
throw new Error('sync error')
|
|
89
|
+
}, 'fallback')
|
|
90
|
+
expect(err).toBeInstanceOf(Error)
|
|
91
|
+
expect(err?.message).toBe('sync error')
|
|
92
|
+
expect(value).toBe('fallback')
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
test('wraps non-Error throws in Error', async () => {
|
|
96
|
+
const [err, value] = await goElse(() => {
|
|
97
|
+
throw 'string error'
|
|
98
|
+
}, 'fallback')
|
|
99
|
+
expect(err).toBeInstanceOf(Error)
|
|
100
|
+
expect(err?.message).toBe('string error')
|
|
101
|
+
expect(value).toBe('fallback')
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
test('is exported from index', () => {
|
|
105
|
+
expect(goElse).toBeDefined()
|
|
106
|
+
})
|
|
107
|
+
})
|
package/src/go.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Alias for goTryRaw - the most common usage of go-go-try.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```typescript
|
|
6
|
+
* const [err, data] = await go(fetch('/api'))
|
|
7
|
+
* const [err2, result] = await go(() => computeSomething())
|
|
8
|
+
* ```
|
|
9
|
+
*/
|
|
10
|
+
export { goTryRaw as go } from './goTryRaw.js'
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Alias for goTryAllRaw - run multiple operations in parallel.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* const results = await goAll([
|
|
18
|
+
* fetch('/api/users'),
|
|
19
|
+
* fetch('/api/posts'),
|
|
20
|
+
* fetch('/api/comments')
|
|
21
|
+
* ])
|
|
22
|
+
* // results is [Result<Error, Response>, Result<Error, Response>, Result<Error, Response>]
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export { goTryAllRaw as goAll } from './goTryAll.js'
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Alias for goElse - returns a default value on error.
|
|
29
|
+
* Returns the actual Error object (not just message) on failure.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* const [err, data] = await goElse(fetch('/api'), { users: [] })
|
|
34
|
+
* // err is Error | undefined, data is the response or { users: [] }
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export { goElse } from './goElse.js'
|
package/src/goElse.ts
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { isPromise, resolveDefault } from './internals.js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Result type with Error and a default value.
|
|
5
|
+
* On error, returns [Error, DefaultT]
|
|
6
|
+
* On success, returns [undefined, T]
|
|
7
|
+
*/
|
|
8
|
+
export type ResultWithDefault<E, T, D = T> = readonly [E, D] | readonly [undefined, T]
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Executes a function, promise, or value and returns a Result type with a fallback default.
|
|
12
|
+
* If an error occurs, it returns the actual Error object and the default value.
|
|
13
|
+
*
|
|
14
|
+
* @template T The type of the successful result
|
|
15
|
+
* @template D The type of the default value (defaults to T)
|
|
16
|
+
* @param {T | Promise<T> | (() => T | Promise<T>)} value - The value, promise, or function to execute
|
|
17
|
+
* @param {D | (() => D)} defaultValue - The default value or a function to compute it (only called on failure)
|
|
18
|
+
* @returns {ResultWithDefault<Error, T, D> | Promise<ResultWithDefault<Error, T, D>>} A tuple of [error, value] or Promise thereof
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* // With a static default
|
|
22
|
+
* const [err, config] = goElse(() => JSON.parse('invalid'), { port: 3000 })
|
|
23
|
+
* // err is the Error object, config is { port: 3000 }
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* // With a computed default (lazy evaluation)
|
|
27
|
+
* const [err, user] = await goElse(fetchUser(id), () => ({
|
|
28
|
+
* id: 'anonymous',
|
|
29
|
+
* name: 'Guest'
|
|
30
|
+
* }))
|
|
31
|
+
*/
|
|
32
|
+
export function goElse<T, D = T>(
|
|
33
|
+
fn: () => never,
|
|
34
|
+
defaultValue: D | (() => D),
|
|
35
|
+
): ResultWithDefault<Error, never, D>
|
|
36
|
+
export function goElse<T, D = T>(
|
|
37
|
+
fn: () => Promise<T>,
|
|
38
|
+
defaultValue: D | (() => D),
|
|
39
|
+
): Promise<ResultWithDefault<Error, T, D>>
|
|
40
|
+
export function goElse<T, D = T>(
|
|
41
|
+
promise: Promise<T>,
|
|
42
|
+
defaultValue: D | (() => D),
|
|
43
|
+
): Promise<ResultWithDefault<Error, T, D>>
|
|
44
|
+
export function goElse<T, D = T>(
|
|
45
|
+
fn: () => T,
|
|
46
|
+
defaultValue: D | (() => D),
|
|
47
|
+
): ResultWithDefault<Error, T, D>
|
|
48
|
+
export function goElse<T, D = T>(
|
|
49
|
+
value: T,
|
|
50
|
+
defaultValue: D | (() => D),
|
|
51
|
+
): ResultWithDefault<Error, T, D>
|
|
52
|
+
export function goElse<T, D = T>(
|
|
53
|
+
value: T | Promise<T> | (() => T | Promise<T>),
|
|
54
|
+
defaultValue: D | (() => D),
|
|
55
|
+
): ResultWithDefault<Error, T, D> | Promise<ResultWithDefault<Error, T, D>> {
|
|
56
|
+
try {
|
|
57
|
+
const result =
|
|
58
|
+
typeof value === 'function' ? (value as () => T | Promise<T>)() : value
|
|
59
|
+
|
|
60
|
+
if (isPromise<T>(result)) {
|
|
61
|
+
return result
|
|
62
|
+
.then((resolvedValue): ResultWithDefault<Error, T, D> => [undefined, resolvedValue])
|
|
63
|
+
.catch((err): ResultWithDefault<Error, T, D> => {
|
|
64
|
+
const error = err instanceof Error ? err : new Error(String(err))
|
|
65
|
+
return [error, resolveDefault(defaultValue)]
|
|
66
|
+
})
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return [undefined, result]
|
|
70
|
+
} catch (err) {
|
|
71
|
+
const error = err instanceof Error ? err : new Error(String(err))
|
|
72
|
+
return [error, resolveDefault(defaultValue)]
|
|
73
|
+
}
|
|
74
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -22,7 +22,11 @@ export { goTryAll, goTryAllRaw } from './goTryAll.js'
|
|
|
22
22
|
// Export helper functions
|
|
23
23
|
export { taggedError } from './tagged-error.js'
|
|
24
24
|
export { assert } from './assert.js'
|
|
25
|
+
export { ensure } from './ensure.js'
|
|
25
26
|
export { isSuccess, isFailure, success, failure, assertNever } from './result-helpers.js'
|
|
26
27
|
|
|
27
28
|
// Export UnknownError tagged error
|
|
28
29
|
export { UnknownError } from './unknown-error.js'
|
|
30
|
+
|
|
31
|
+
// Export go aliases
|
|
32
|
+
export { go, goAll, goElse } from './go.js'
|