errore 0.0.1 → 0.1.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.d.mts +290 -2
- package/dist/index.d.ts +290 -2
- package/dist/index.js +217 -3
- package/dist/index.mjs +195 -3
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -1,3 +1,291 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* The core type: either an Error or a value T.
|
|
3
|
+
* Unlike Result<T, E>, this is just a union - no wrapper needed.
|
|
4
|
+
*/
|
|
5
|
+
type Errore<T, E extends Error = Error> = E | T;
|
|
6
|
+
/**
|
|
7
|
+
* Extract the error type from an Errore union.
|
|
8
|
+
* @example InferError<NetworkError | User> // NetworkError
|
|
9
|
+
*/
|
|
10
|
+
type InferError<T> = T extends Error ? T : never;
|
|
11
|
+
/**
|
|
12
|
+
* Extract the value type from an Errore union.
|
|
13
|
+
* @example InferValue<NetworkError | User> // User
|
|
14
|
+
*/
|
|
15
|
+
type InferValue<T> = T extends Error ? never : T;
|
|
16
|
+
/**
|
|
17
|
+
* Utility to ensure T is not an Error type.
|
|
18
|
+
* Used to prevent ambiguous unions like Error | Error.
|
|
19
|
+
*/
|
|
20
|
+
type EnsureNotError<T> = T extends Error ? 'Error: Value type T cannot extend Error - this would make the union ambiguous' : T;
|
|
2
21
|
|
|
3
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Any tagged error (for generic constraints)
|
|
24
|
+
*/
|
|
25
|
+
type AnyTaggedError = Error & {
|
|
26
|
+
readonly _tag: string;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Instance type produced by TaggedError factory
|
|
30
|
+
*/
|
|
31
|
+
type TaggedErrorInstance<Tag extends string, Props> = Error & {
|
|
32
|
+
readonly _tag: Tag;
|
|
33
|
+
toJSON(): object;
|
|
34
|
+
} & Readonly<Props>;
|
|
35
|
+
/**
|
|
36
|
+
* Class type produced by TaggedError factory
|
|
37
|
+
*/
|
|
38
|
+
type TaggedErrorClass<Tag extends string, Props> = {
|
|
39
|
+
new (...args: keyof Props extends never ? [args?: {}] : [args: Props]): TaggedErrorInstance<Tag, Props>;
|
|
40
|
+
/** Type guard for this error class */
|
|
41
|
+
is(value: unknown): value is TaggedErrorInstance<Tag, Props>;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Factory for tagged error classes with discriminated _tag property.
|
|
45
|
+
* Enables exhaustive pattern matching on error unions.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* class NotFoundError extends TaggedError("NotFoundError")<{
|
|
49
|
+
* id: string;
|
|
50
|
+
* message: string;
|
|
51
|
+
* }>() {}
|
|
52
|
+
*
|
|
53
|
+
* const err = new NotFoundError({ id: "123", message: "Not found" });
|
|
54
|
+
* err._tag // "NotFoundError"
|
|
55
|
+
* err.id // "123"
|
|
56
|
+
*
|
|
57
|
+
* // Type guard
|
|
58
|
+
* NotFoundError.is(err) // true
|
|
59
|
+
* TaggedError.is(err) // true (any tagged error)
|
|
60
|
+
*/
|
|
61
|
+
declare const TaggedError: {
|
|
62
|
+
<Tag extends string>(tag: Tag): <Props extends Record<string, unknown> = {}>() => TaggedErrorClass<Tag, Props>;
|
|
63
|
+
/** Type guard for any TaggedError instance */
|
|
64
|
+
is(value: unknown): value is AnyTaggedError;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Type guard for tagged error instances.
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* if (isTaggedError(value)) { value._tag }
|
|
71
|
+
*/
|
|
72
|
+
declare const isTaggedError: (value: unknown) => value is AnyTaggedError;
|
|
73
|
+
/**
|
|
74
|
+
* Handler map for exhaustive matching
|
|
75
|
+
*/
|
|
76
|
+
type MatchHandlers<E extends AnyTaggedError, R> = {
|
|
77
|
+
[K in E['_tag']]: (err: Extract<E, {
|
|
78
|
+
_tag: K;
|
|
79
|
+
}>) => R;
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* Exhaustive pattern match on tagged error union by _tag.
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* matchError(err, {
|
|
86
|
+
* NotFoundError: (e) => `Missing: ${e.id}`,
|
|
87
|
+
* ValidationError: (e) => `Invalid: ${e.field}`,
|
|
88
|
+
* });
|
|
89
|
+
*/
|
|
90
|
+
declare function matchError<E extends AnyTaggedError, R>(err: E, handlers: MatchHandlers<E, R>): R;
|
|
91
|
+
/**
|
|
92
|
+
* Partial pattern match with fallback for unhandled tags.
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* matchErrorPartial(err, {
|
|
96
|
+
* NotFoundError: (e) => `Missing: ${e.id}`,
|
|
97
|
+
* }, (e) => `Unknown: ${e.message}`);
|
|
98
|
+
*/
|
|
99
|
+
declare function matchErrorPartial<E extends AnyTaggedError, R>(err: E, handlers: Partial<MatchHandlers<E, R>>, fallback: (e: E) => R): R;
|
|
100
|
+
declare const UnhandledError_base: TaggedErrorClass<"UnhandledError", {
|
|
101
|
+
message: string;
|
|
102
|
+
cause: unknown;
|
|
103
|
+
}>;
|
|
104
|
+
/**
|
|
105
|
+
* Default error type when catching unknown exceptions.
|
|
106
|
+
*/
|
|
107
|
+
declare class UnhandledError extends UnhandledError_base {
|
|
108
|
+
constructor(args: {
|
|
109
|
+
cause: unknown;
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Type guard: checks if value is an Error.
|
|
115
|
+
* After this check, TypeScript narrows the type.
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* const result = await fetchUser(id)
|
|
119
|
+
* if (isError(result)) {
|
|
120
|
+
* // result is narrowed to the error type
|
|
121
|
+
* return result
|
|
122
|
+
* }
|
|
123
|
+
* // result is narrowed to User
|
|
124
|
+
* console.log(result.name)
|
|
125
|
+
*/
|
|
126
|
+
declare function isError<T, E extends Error>(value: E | T): value is E;
|
|
127
|
+
/**
|
|
128
|
+
* Type guard: checks if value is NOT an Error.
|
|
129
|
+
* Inverse of isError for convenience.
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* const result = await fetchUser(id)
|
|
133
|
+
* if (isOk(result)) {
|
|
134
|
+
* console.log(result.name) // result is User
|
|
135
|
+
* }
|
|
136
|
+
*/
|
|
137
|
+
declare function isOk<T, E extends Error>(value: E | T): value is T;
|
|
138
|
+
/**
|
|
139
|
+
* Execute a sync function and return either the value or an error.
|
|
140
|
+
*
|
|
141
|
+
* @overload Simple form - wraps exceptions in UnhandledError
|
|
142
|
+
* @example
|
|
143
|
+
* const result = tryFn(() => JSON.parse(input))
|
|
144
|
+
* // result: UnhandledError | unknown
|
|
145
|
+
*
|
|
146
|
+
* @overload With custom catch - you control the error type
|
|
147
|
+
* @example
|
|
148
|
+
* const result = tryFn({
|
|
149
|
+
* try: () => JSON.parse(input),
|
|
150
|
+
* catch: (e) => new ParseError({ cause: e })
|
|
151
|
+
* })
|
|
152
|
+
* // result: ParseError | unknown
|
|
153
|
+
*/
|
|
154
|
+
declare function tryFn<T>(fn: () => T): UnhandledError | T;
|
|
155
|
+
declare function tryFn<T, E extends Error>(opts: {
|
|
156
|
+
try: () => T;
|
|
157
|
+
catch: (e: unknown) => E;
|
|
158
|
+
}): E | T;
|
|
159
|
+
/**
|
|
160
|
+
* Execute an async function and return either the value or an error.
|
|
161
|
+
*
|
|
162
|
+
* @overload Simple form - wraps exceptions in UnhandledError
|
|
163
|
+
* @example
|
|
164
|
+
* const result = await tryAsync(() => fetch(url).then(r => r.json()))
|
|
165
|
+
* // result: UnhandledError | unknown
|
|
166
|
+
*
|
|
167
|
+
* @overload With custom catch - you control the error type
|
|
168
|
+
* @example
|
|
169
|
+
* const result = await tryAsync({
|
|
170
|
+
* try: () => fetch(url),
|
|
171
|
+
* catch: (e) => new NetworkError({ cause: e })
|
|
172
|
+
* })
|
|
173
|
+
* // result: NetworkError | Response
|
|
174
|
+
*/
|
|
175
|
+
declare function tryAsync<T>(fn: () => Promise<T>): Promise<UnhandledError | T>;
|
|
176
|
+
declare function tryAsync<T, E extends Error>(opts: {
|
|
177
|
+
try: () => Promise<T>;
|
|
178
|
+
catch: (e: unknown) => E | Promise<E>;
|
|
179
|
+
}): Promise<E | T>;
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Transform the value if not an error.
|
|
183
|
+
* If the value is an error, returns it unchanged.
|
|
184
|
+
*
|
|
185
|
+
* @example
|
|
186
|
+
* const result = map(user, u => u.name)
|
|
187
|
+
* // If user is User, result is string
|
|
188
|
+
* // If user is NotFoundError, result is NotFoundError
|
|
189
|
+
*/
|
|
190
|
+
declare function map<T, U, E extends Error>(value: E | T, fn: (v: T) => U): E | U;
|
|
191
|
+
/**
|
|
192
|
+
* Transform the error if it is an error.
|
|
193
|
+
* If the value is not an error, returns it unchanged.
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* const result = mapError(fetchResult, e => new AppError({ cause: e }))
|
|
197
|
+
* // Converts any error type to AppError
|
|
198
|
+
*/
|
|
199
|
+
declare function mapError<T, E extends Error, E2 extends Error>(value: E | T, fn: (e: E) => E2): E2 | T;
|
|
200
|
+
/**
|
|
201
|
+
* Chain another errore-returning function.
|
|
202
|
+
* If the value is an error, returns it unchanged.
|
|
203
|
+
* If successful, runs fn and returns its result.
|
|
204
|
+
*
|
|
205
|
+
* @example
|
|
206
|
+
* const result = andThen(userId, id => fetchUser(id))
|
|
207
|
+
* // If userId is ValidationError, result is ValidationError
|
|
208
|
+
* // If userId is string, result is whatever fetchUser returns
|
|
209
|
+
*/
|
|
210
|
+
declare function andThen<T, U, E extends Error, E2 extends Error>(value: E | T, fn: (v: T) => E2 | U): E | E2 | U;
|
|
211
|
+
/**
|
|
212
|
+
* Async version of andThen.
|
|
213
|
+
*
|
|
214
|
+
* @example
|
|
215
|
+
* const result = await andThenAsync(userId, async id => {
|
|
216
|
+
* const user = await fetchUser(id)
|
|
217
|
+
* return user
|
|
218
|
+
* })
|
|
219
|
+
*/
|
|
220
|
+
declare function andThenAsync<T, U, E extends Error, E2 extends Error>(value: E | T, fn: (v: T) => Promise<E2 | U>): Promise<E | E2 | U>;
|
|
221
|
+
/**
|
|
222
|
+
* Run a side effect if the value is not an error.
|
|
223
|
+
* Returns the original value unchanged.
|
|
224
|
+
*
|
|
225
|
+
* @example
|
|
226
|
+
* const result = tap(user, u => console.log('Got user:', u.name))
|
|
227
|
+
*/
|
|
228
|
+
declare function tap<T, E extends Error>(value: E | T, fn: (v: T) => void): E | T;
|
|
229
|
+
/**
|
|
230
|
+
* Async version of tap.
|
|
231
|
+
*
|
|
232
|
+
* @example
|
|
233
|
+
* const result = await tapAsync(user, async u => {
|
|
234
|
+
* await logToService(u)
|
|
235
|
+
* })
|
|
236
|
+
*/
|
|
237
|
+
declare function tapAsync<T, E extends Error>(value: E | T, fn: (v: T) => Promise<void>): Promise<E | T>;
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Extract the value or throw if it's an error.
|
|
241
|
+
*
|
|
242
|
+
* @example
|
|
243
|
+
* const user = unwrap(result) // throws if result is an error
|
|
244
|
+
* console.log(user.name)
|
|
245
|
+
*
|
|
246
|
+
* @example With custom message
|
|
247
|
+
* const user = unwrap(result, 'Failed to get user')
|
|
248
|
+
*/
|
|
249
|
+
declare function unwrap<T, E extends Error>(value: E | T, message?: string): T;
|
|
250
|
+
/**
|
|
251
|
+
* Extract the value or return a fallback if it's an error.
|
|
252
|
+
*
|
|
253
|
+
* @example
|
|
254
|
+
* const name = unwrapOr(result, 'Anonymous')
|
|
255
|
+
* // If result is User, returns user
|
|
256
|
+
* // If result is Error, returns 'Anonymous'
|
|
257
|
+
*/
|
|
258
|
+
declare function unwrapOr<T, U, E extends Error>(value: E | T, fallback: U): T | U;
|
|
259
|
+
/**
|
|
260
|
+
* Pattern match on an errore value.
|
|
261
|
+
* Handles both success and error cases.
|
|
262
|
+
*
|
|
263
|
+
* @example
|
|
264
|
+
* const message = match(result, {
|
|
265
|
+
* ok: user => `Hello, ${user.name}`,
|
|
266
|
+
* err: error => `Failed: ${error.message}`
|
|
267
|
+
* })
|
|
268
|
+
*/
|
|
269
|
+
declare function match<T, E extends Error, R>(value: E | T, handlers: {
|
|
270
|
+
ok: (v: T) => R;
|
|
271
|
+
err: (e: E) => R;
|
|
272
|
+
}): R;
|
|
273
|
+
/**
|
|
274
|
+
* Partition an array of errore values into [successes, errors].
|
|
275
|
+
*
|
|
276
|
+
* @example
|
|
277
|
+
* const results = await Promise.all(ids.map(fetchUser))
|
|
278
|
+
* const [users, errors] = partition(results)
|
|
279
|
+
*/
|
|
280
|
+
declare function partition<T, E extends Error>(values: (E | T)[]): [T[], E[]];
|
|
281
|
+
/**
|
|
282
|
+
* Flatten a nested errore: (E1 | (E2 | T)) becomes (E1 | E2 | T).
|
|
283
|
+
* Useful when chaining operations that can fail.
|
|
284
|
+
*
|
|
285
|
+
* @example
|
|
286
|
+
* const nested: NetworkError | (ParseError | User) = await fetchAndParse()
|
|
287
|
+
* const flat: NetworkError | ParseError | User = flatten(nested)
|
|
288
|
+
*/
|
|
289
|
+
declare function flatten<T, E1 extends Error, E2 extends Error>(value: E1 | (E2 | T)): E1 | E2 | T;
|
|
290
|
+
|
|
291
|
+
export { type EnsureNotError, type Errore, type InferError, type InferValue, TaggedError, type TaggedErrorClass, type TaggedErrorInstance, UnhandledError, andThen, andThenAsync, flatten, isError, isOk, isTaggedError, map, mapError, match, matchError, matchErrorPartial, partition, tap, tapAsync, tryAsync, tryFn, unwrap, unwrapOr };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,291 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* The core type: either an Error or a value T.
|
|
3
|
+
* Unlike Result<T, E>, this is just a union - no wrapper needed.
|
|
4
|
+
*/
|
|
5
|
+
type Errore<T, E extends Error = Error> = E | T;
|
|
6
|
+
/**
|
|
7
|
+
* Extract the error type from an Errore union.
|
|
8
|
+
* @example InferError<NetworkError | User> // NetworkError
|
|
9
|
+
*/
|
|
10
|
+
type InferError<T> = T extends Error ? T : never;
|
|
11
|
+
/**
|
|
12
|
+
* Extract the value type from an Errore union.
|
|
13
|
+
* @example InferValue<NetworkError | User> // User
|
|
14
|
+
*/
|
|
15
|
+
type InferValue<T> = T extends Error ? never : T;
|
|
16
|
+
/**
|
|
17
|
+
* Utility to ensure T is not an Error type.
|
|
18
|
+
* Used to prevent ambiguous unions like Error | Error.
|
|
19
|
+
*/
|
|
20
|
+
type EnsureNotError<T> = T extends Error ? 'Error: Value type T cannot extend Error - this would make the union ambiguous' : T;
|
|
2
21
|
|
|
3
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Any tagged error (for generic constraints)
|
|
24
|
+
*/
|
|
25
|
+
type AnyTaggedError = Error & {
|
|
26
|
+
readonly _tag: string;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Instance type produced by TaggedError factory
|
|
30
|
+
*/
|
|
31
|
+
type TaggedErrorInstance<Tag extends string, Props> = Error & {
|
|
32
|
+
readonly _tag: Tag;
|
|
33
|
+
toJSON(): object;
|
|
34
|
+
} & Readonly<Props>;
|
|
35
|
+
/**
|
|
36
|
+
* Class type produced by TaggedError factory
|
|
37
|
+
*/
|
|
38
|
+
type TaggedErrorClass<Tag extends string, Props> = {
|
|
39
|
+
new (...args: keyof Props extends never ? [args?: {}] : [args: Props]): TaggedErrorInstance<Tag, Props>;
|
|
40
|
+
/** Type guard for this error class */
|
|
41
|
+
is(value: unknown): value is TaggedErrorInstance<Tag, Props>;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Factory for tagged error classes with discriminated _tag property.
|
|
45
|
+
* Enables exhaustive pattern matching on error unions.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* class NotFoundError extends TaggedError("NotFoundError")<{
|
|
49
|
+
* id: string;
|
|
50
|
+
* message: string;
|
|
51
|
+
* }>() {}
|
|
52
|
+
*
|
|
53
|
+
* const err = new NotFoundError({ id: "123", message: "Not found" });
|
|
54
|
+
* err._tag // "NotFoundError"
|
|
55
|
+
* err.id // "123"
|
|
56
|
+
*
|
|
57
|
+
* // Type guard
|
|
58
|
+
* NotFoundError.is(err) // true
|
|
59
|
+
* TaggedError.is(err) // true (any tagged error)
|
|
60
|
+
*/
|
|
61
|
+
declare const TaggedError: {
|
|
62
|
+
<Tag extends string>(tag: Tag): <Props extends Record<string, unknown> = {}>() => TaggedErrorClass<Tag, Props>;
|
|
63
|
+
/** Type guard for any TaggedError instance */
|
|
64
|
+
is(value: unknown): value is AnyTaggedError;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Type guard for tagged error instances.
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* if (isTaggedError(value)) { value._tag }
|
|
71
|
+
*/
|
|
72
|
+
declare const isTaggedError: (value: unknown) => value is AnyTaggedError;
|
|
73
|
+
/**
|
|
74
|
+
* Handler map for exhaustive matching
|
|
75
|
+
*/
|
|
76
|
+
type MatchHandlers<E extends AnyTaggedError, R> = {
|
|
77
|
+
[K in E['_tag']]: (err: Extract<E, {
|
|
78
|
+
_tag: K;
|
|
79
|
+
}>) => R;
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* Exhaustive pattern match on tagged error union by _tag.
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* matchError(err, {
|
|
86
|
+
* NotFoundError: (e) => `Missing: ${e.id}`,
|
|
87
|
+
* ValidationError: (e) => `Invalid: ${e.field}`,
|
|
88
|
+
* });
|
|
89
|
+
*/
|
|
90
|
+
declare function matchError<E extends AnyTaggedError, R>(err: E, handlers: MatchHandlers<E, R>): R;
|
|
91
|
+
/**
|
|
92
|
+
* Partial pattern match with fallback for unhandled tags.
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* matchErrorPartial(err, {
|
|
96
|
+
* NotFoundError: (e) => `Missing: ${e.id}`,
|
|
97
|
+
* }, (e) => `Unknown: ${e.message}`);
|
|
98
|
+
*/
|
|
99
|
+
declare function matchErrorPartial<E extends AnyTaggedError, R>(err: E, handlers: Partial<MatchHandlers<E, R>>, fallback: (e: E) => R): R;
|
|
100
|
+
declare const UnhandledError_base: TaggedErrorClass<"UnhandledError", {
|
|
101
|
+
message: string;
|
|
102
|
+
cause: unknown;
|
|
103
|
+
}>;
|
|
104
|
+
/**
|
|
105
|
+
* Default error type when catching unknown exceptions.
|
|
106
|
+
*/
|
|
107
|
+
declare class UnhandledError extends UnhandledError_base {
|
|
108
|
+
constructor(args: {
|
|
109
|
+
cause: unknown;
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Type guard: checks if value is an Error.
|
|
115
|
+
* After this check, TypeScript narrows the type.
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* const result = await fetchUser(id)
|
|
119
|
+
* if (isError(result)) {
|
|
120
|
+
* // result is narrowed to the error type
|
|
121
|
+
* return result
|
|
122
|
+
* }
|
|
123
|
+
* // result is narrowed to User
|
|
124
|
+
* console.log(result.name)
|
|
125
|
+
*/
|
|
126
|
+
declare function isError<T, E extends Error>(value: E | T): value is E;
|
|
127
|
+
/**
|
|
128
|
+
* Type guard: checks if value is NOT an Error.
|
|
129
|
+
* Inverse of isError for convenience.
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* const result = await fetchUser(id)
|
|
133
|
+
* if (isOk(result)) {
|
|
134
|
+
* console.log(result.name) // result is User
|
|
135
|
+
* }
|
|
136
|
+
*/
|
|
137
|
+
declare function isOk<T, E extends Error>(value: E | T): value is T;
|
|
138
|
+
/**
|
|
139
|
+
* Execute a sync function and return either the value or an error.
|
|
140
|
+
*
|
|
141
|
+
* @overload Simple form - wraps exceptions in UnhandledError
|
|
142
|
+
* @example
|
|
143
|
+
* const result = tryFn(() => JSON.parse(input))
|
|
144
|
+
* // result: UnhandledError | unknown
|
|
145
|
+
*
|
|
146
|
+
* @overload With custom catch - you control the error type
|
|
147
|
+
* @example
|
|
148
|
+
* const result = tryFn({
|
|
149
|
+
* try: () => JSON.parse(input),
|
|
150
|
+
* catch: (e) => new ParseError({ cause: e })
|
|
151
|
+
* })
|
|
152
|
+
* // result: ParseError | unknown
|
|
153
|
+
*/
|
|
154
|
+
declare function tryFn<T>(fn: () => T): UnhandledError | T;
|
|
155
|
+
declare function tryFn<T, E extends Error>(opts: {
|
|
156
|
+
try: () => T;
|
|
157
|
+
catch: (e: unknown) => E;
|
|
158
|
+
}): E | T;
|
|
159
|
+
/**
|
|
160
|
+
* Execute an async function and return either the value or an error.
|
|
161
|
+
*
|
|
162
|
+
* @overload Simple form - wraps exceptions in UnhandledError
|
|
163
|
+
* @example
|
|
164
|
+
* const result = await tryAsync(() => fetch(url).then(r => r.json()))
|
|
165
|
+
* // result: UnhandledError | unknown
|
|
166
|
+
*
|
|
167
|
+
* @overload With custom catch - you control the error type
|
|
168
|
+
* @example
|
|
169
|
+
* const result = await tryAsync({
|
|
170
|
+
* try: () => fetch(url),
|
|
171
|
+
* catch: (e) => new NetworkError({ cause: e })
|
|
172
|
+
* })
|
|
173
|
+
* // result: NetworkError | Response
|
|
174
|
+
*/
|
|
175
|
+
declare function tryAsync<T>(fn: () => Promise<T>): Promise<UnhandledError | T>;
|
|
176
|
+
declare function tryAsync<T, E extends Error>(opts: {
|
|
177
|
+
try: () => Promise<T>;
|
|
178
|
+
catch: (e: unknown) => E | Promise<E>;
|
|
179
|
+
}): Promise<E | T>;
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Transform the value if not an error.
|
|
183
|
+
* If the value is an error, returns it unchanged.
|
|
184
|
+
*
|
|
185
|
+
* @example
|
|
186
|
+
* const result = map(user, u => u.name)
|
|
187
|
+
* // If user is User, result is string
|
|
188
|
+
* // If user is NotFoundError, result is NotFoundError
|
|
189
|
+
*/
|
|
190
|
+
declare function map<T, U, E extends Error>(value: E | T, fn: (v: T) => U): E | U;
|
|
191
|
+
/**
|
|
192
|
+
* Transform the error if it is an error.
|
|
193
|
+
* If the value is not an error, returns it unchanged.
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* const result = mapError(fetchResult, e => new AppError({ cause: e }))
|
|
197
|
+
* // Converts any error type to AppError
|
|
198
|
+
*/
|
|
199
|
+
declare function mapError<T, E extends Error, E2 extends Error>(value: E | T, fn: (e: E) => E2): E2 | T;
|
|
200
|
+
/**
|
|
201
|
+
* Chain another errore-returning function.
|
|
202
|
+
* If the value is an error, returns it unchanged.
|
|
203
|
+
* If successful, runs fn and returns its result.
|
|
204
|
+
*
|
|
205
|
+
* @example
|
|
206
|
+
* const result = andThen(userId, id => fetchUser(id))
|
|
207
|
+
* // If userId is ValidationError, result is ValidationError
|
|
208
|
+
* // If userId is string, result is whatever fetchUser returns
|
|
209
|
+
*/
|
|
210
|
+
declare function andThen<T, U, E extends Error, E2 extends Error>(value: E | T, fn: (v: T) => E2 | U): E | E2 | U;
|
|
211
|
+
/**
|
|
212
|
+
* Async version of andThen.
|
|
213
|
+
*
|
|
214
|
+
* @example
|
|
215
|
+
* const result = await andThenAsync(userId, async id => {
|
|
216
|
+
* const user = await fetchUser(id)
|
|
217
|
+
* return user
|
|
218
|
+
* })
|
|
219
|
+
*/
|
|
220
|
+
declare function andThenAsync<T, U, E extends Error, E2 extends Error>(value: E | T, fn: (v: T) => Promise<E2 | U>): Promise<E | E2 | U>;
|
|
221
|
+
/**
|
|
222
|
+
* Run a side effect if the value is not an error.
|
|
223
|
+
* Returns the original value unchanged.
|
|
224
|
+
*
|
|
225
|
+
* @example
|
|
226
|
+
* const result = tap(user, u => console.log('Got user:', u.name))
|
|
227
|
+
*/
|
|
228
|
+
declare function tap<T, E extends Error>(value: E | T, fn: (v: T) => void): E | T;
|
|
229
|
+
/**
|
|
230
|
+
* Async version of tap.
|
|
231
|
+
*
|
|
232
|
+
* @example
|
|
233
|
+
* const result = await tapAsync(user, async u => {
|
|
234
|
+
* await logToService(u)
|
|
235
|
+
* })
|
|
236
|
+
*/
|
|
237
|
+
declare function tapAsync<T, E extends Error>(value: E | T, fn: (v: T) => Promise<void>): Promise<E | T>;
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Extract the value or throw if it's an error.
|
|
241
|
+
*
|
|
242
|
+
* @example
|
|
243
|
+
* const user = unwrap(result) // throws if result is an error
|
|
244
|
+
* console.log(user.name)
|
|
245
|
+
*
|
|
246
|
+
* @example With custom message
|
|
247
|
+
* const user = unwrap(result, 'Failed to get user')
|
|
248
|
+
*/
|
|
249
|
+
declare function unwrap<T, E extends Error>(value: E | T, message?: string): T;
|
|
250
|
+
/**
|
|
251
|
+
* Extract the value or return a fallback if it's an error.
|
|
252
|
+
*
|
|
253
|
+
* @example
|
|
254
|
+
* const name = unwrapOr(result, 'Anonymous')
|
|
255
|
+
* // If result is User, returns user
|
|
256
|
+
* // If result is Error, returns 'Anonymous'
|
|
257
|
+
*/
|
|
258
|
+
declare function unwrapOr<T, U, E extends Error>(value: E | T, fallback: U): T | U;
|
|
259
|
+
/**
|
|
260
|
+
* Pattern match on an errore value.
|
|
261
|
+
* Handles both success and error cases.
|
|
262
|
+
*
|
|
263
|
+
* @example
|
|
264
|
+
* const message = match(result, {
|
|
265
|
+
* ok: user => `Hello, ${user.name}`,
|
|
266
|
+
* err: error => `Failed: ${error.message}`
|
|
267
|
+
* })
|
|
268
|
+
*/
|
|
269
|
+
declare function match<T, E extends Error, R>(value: E | T, handlers: {
|
|
270
|
+
ok: (v: T) => R;
|
|
271
|
+
err: (e: E) => R;
|
|
272
|
+
}): R;
|
|
273
|
+
/**
|
|
274
|
+
* Partition an array of errore values into [successes, errors].
|
|
275
|
+
*
|
|
276
|
+
* @example
|
|
277
|
+
* const results = await Promise.all(ids.map(fetchUser))
|
|
278
|
+
* const [users, errors] = partition(results)
|
|
279
|
+
*/
|
|
280
|
+
declare function partition<T, E extends Error>(values: (E | T)[]): [T[], E[]];
|
|
281
|
+
/**
|
|
282
|
+
* Flatten a nested errore: (E1 | (E2 | T)) becomes (E1 | E2 | T).
|
|
283
|
+
* Useful when chaining operations that can fail.
|
|
284
|
+
*
|
|
285
|
+
* @example
|
|
286
|
+
* const nested: NetworkError | (ParseError | User) = await fetchAndParse()
|
|
287
|
+
* const flat: NetworkError | ParseError | User = flatten(nested)
|
|
288
|
+
*/
|
|
289
|
+
declare function flatten<T, E1 extends Error, E2 extends Error>(value: E1 | (E2 | T)): E1 | E2 | T;
|
|
290
|
+
|
|
291
|
+
export { type EnsureNotError, type Errore, type InferError, type InferValue, TaggedError, type TaggedErrorClass, type TaggedErrorInstance, UnhandledError, andThen, andThenAsync, flatten, isError, isOk, isTaggedError, map, mapError, match, matchError, matchErrorPartial, partition, tap, tapAsync, tryAsync, tryFn, unwrap, unwrapOr };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
var __defProp = Object.defineProperty;
|
|
2
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -19,11 +20,224 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
19
20
|
// src/index.ts
|
|
20
21
|
var index_exports = {};
|
|
21
22
|
__export(index_exports, {
|
|
22
|
-
|
|
23
|
+
TaggedError: () => TaggedError,
|
|
24
|
+
UnhandledError: () => UnhandledError,
|
|
25
|
+
andThen: () => andThen,
|
|
26
|
+
andThenAsync: () => andThenAsync,
|
|
27
|
+
flatten: () => flatten,
|
|
28
|
+
isError: () => isError,
|
|
29
|
+
isOk: () => isOk,
|
|
30
|
+
isTaggedError: () => isTaggedError,
|
|
31
|
+
map: () => map,
|
|
32
|
+
mapError: () => mapError,
|
|
33
|
+
match: () => match,
|
|
34
|
+
matchError: () => matchError,
|
|
35
|
+
matchErrorPartial: () => matchErrorPartial,
|
|
36
|
+
partition: () => partition,
|
|
37
|
+
tap: () => tap,
|
|
38
|
+
tapAsync: () => tapAsync,
|
|
39
|
+
tryAsync: () => tryAsync,
|
|
40
|
+
tryFn: () => tryFn,
|
|
41
|
+
unwrap: () => unwrap,
|
|
42
|
+
unwrapOr: () => unwrapOr
|
|
23
43
|
});
|
|
24
44
|
module.exports = __toCommonJS(index_exports);
|
|
25
|
-
|
|
45
|
+
|
|
46
|
+
// src/error.ts
|
|
47
|
+
var serializeCause = (cause) => {
|
|
48
|
+
if (cause instanceof Error) {
|
|
49
|
+
return { name: cause.name, message: cause.message, stack: cause.stack };
|
|
50
|
+
}
|
|
51
|
+
return cause;
|
|
52
|
+
};
|
|
53
|
+
var isAnyTaggedError = (value) => {
|
|
54
|
+
return value instanceof Error && "_tag" in value && typeof value._tag === "string";
|
|
55
|
+
};
|
|
56
|
+
var TaggedError = Object.assign(
|
|
57
|
+
(tag) => () => {
|
|
58
|
+
class Base extends Error {
|
|
59
|
+
_tag = tag;
|
|
60
|
+
/** Type guard for this error class */
|
|
61
|
+
static is(value) {
|
|
62
|
+
return value instanceof Base;
|
|
63
|
+
}
|
|
64
|
+
constructor(args) {
|
|
65
|
+
const message = args && "message" in args && typeof args.message === "string" ? args.message : void 0;
|
|
66
|
+
const cause = args && "cause" in args ? args.cause : void 0;
|
|
67
|
+
super(message, cause !== void 0 ? { cause } : void 0);
|
|
68
|
+
if (args) {
|
|
69
|
+
Object.assign(this, args);
|
|
70
|
+
}
|
|
71
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
72
|
+
this.name = tag;
|
|
73
|
+
if (cause instanceof Error && cause.stack) {
|
|
74
|
+
const indented = cause.stack.replace(/\n/g, "\n ");
|
|
75
|
+
this.stack = `${this.stack}
|
|
76
|
+
Caused by: ${indented}`;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
toJSON() {
|
|
80
|
+
return {
|
|
81
|
+
...this,
|
|
82
|
+
_tag: this._tag,
|
|
83
|
+
name: this.name,
|
|
84
|
+
message: this.message,
|
|
85
|
+
cause: serializeCause(this.cause),
|
|
86
|
+
stack: this.stack
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return Base;
|
|
91
|
+
},
|
|
92
|
+
{ is: isAnyTaggedError }
|
|
93
|
+
);
|
|
94
|
+
var isTaggedError = isAnyTaggedError;
|
|
95
|
+
function matchError(err, handlers) {
|
|
96
|
+
const handler = handlers[err._tag];
|
|
97
|
+
return handler(err);
|
|
98
|
+
}
|
|
99
|
+
function matchErrorPartial(err, handlers, fallback) {
|
|
100
|
+
const handler = handlers[err._tag];
|
|
101
|
+
if (handler) {
|
|
102
|
+
return handler(err);
|
|
103
|
+
}
|
|
104
|
+
return fallback(err);
|
|
105
|
+
}
|
|
106
|
+
var UnhandledError = class extends TaggedError("UnhandledError")() {
|
|
107
|
+
constructor(args) {
|
|
108
|
+
const message = args.cause instanceof Error ? `Unhandled exception: ${args.cause.message}` : `Unhandled exception: ${String(args.cause)}`;
|
|
109
|
+
super({ message, cause: args.cause });
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
// src/core.ts
|
|
114
|
+
function isError(value) {
|
|
115
|
+
return value instanceof Error;
|
|
116
|
+
}
|
|
117
|
+
function isOk(value) {
|
|
118
|
+
return !(value instanceof Error);
|
|
119
|
+
}
|
|
120
|
+
function tryFn(fnOrOpts) {
|
|
121
|
+
if (typeof fnOrOpts === "function") {
|
|
122
|
+
try {
|
|
123
|
+
return fnOrOpts();
|
|
124
|
+
} catch (cause) {
|
|
125
|
+
return new UnhandledError({ cause });
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
try {
|
|
129
|
+
return fnOrOpts.try();
|
|
130
|
+
} catch (cause) {
|
|
131
|
+
return fnOrOpts.catch(cause);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
async function tryAsync(fnOrOpts) {
|
|
135
|
+
if (typeof fnOrOpts === "function") {
|
|
136
|
+
try {
|
|
137
|
+
return await fnOrOpts();
|
|
138
|
+
} catch (cause) {
|
|
139
|
+
return new UnhandledError({ cause });
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
try {
|
|
143
|
+
return await fnOrOpts.try();
|
|
144
|
+
} catch (cause) {
|
|
145
|
+
return await fnOrOpts.catch(cause);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// src/transform.ts
|
|
150
|
+
function map(value, fn) {
|
|
151
|
+
if (value instanceof Error) {
|
|
152
|
+
return value;
|
|
153
|
+
}
|
|
154
|
+
return fn(value);
|
|
155
|
+
}
|
|
156
|
+
function mapError(value, fn) {
|
|
157
|
+
if (value instanceof Error) {
|
|
158
|
+
return fn(value);
|
|
159
|
+
}
|
|
160
|
+
return value;
|
|
161
|
+
}
|
|
162
|
+
function andThen(value, fn) {
|
|
163
|
+
if (value instanceof Error) {
|
|
164
|
+
return value;
|
|
165
|
+
}
|
|
166
|
+
return fn(value);
|
|
167
|
+
}
|
|
168
|
+
async function andThenAsync(value, fn) {
|
|
169
|
+
if (value instanceof Error) {
|
|
170
|
+
return value;
|
|
171
|
+
}
|
|
172
|
+
return fn(value);
|
|
173
|
+
}
|
|
174
|
+
function tap(value, fn) {
|
|
175
|
+
if (!(value instanceof Error)) {
|
|
176
|
+
fn(value);
|
|
177
|
+
}
|
|
178
|
+
return value;
|
|
179
|
+
}
|
|
180
|
+
async function tapAsync(value, fn) {
|
|
181
|
+
if (!(value instanceof Error)) {
|
|
182
|
+
await fn(value);
|
|
183
|
+
}
|
|
184
|
+
return value;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// src/extract.ts
|
|
188
|
+
function unwrap(value, message) {
|
|
189
|
+
if (value instanceof Error) {
|
|
190
|
+
throw new Error(message ?? `Unwrap called on error: ${value.message}`, { cause: value });
|
|
191
|
+
}
|
|
192
|
+
return value;
|
|
193
|
+
}
|
|
194
|
+
function unwrapOr(value, fallback) {
|
|
195
|
+
if (value instanceof Error) {
|
|
196
|
+
return fallback;
|
|
197
|
+
}
|
|
198
|
+
return value;
|
|
199
|
+
}
|
|
200
|
+
function match(value, handlers) {
|
|
201
|
+
if (value instanceof Error) {
|
|
202
|
+
return handlers.err(value);
|
|
203
|
+
}
|
|
204
|
+
return handlers.ok(value);
|
|
205
|
+
}
|
|
206
|
+
function partition(values) {
|
|
207
|
+
const oks = [];
|
|
208
|
+
const errs = [];
|
|
209
|
+
for (const v of values) {
|
|
210
|
+
if (v instanceof Error) {
|
|
211
|
+
errs.push(v);
|
|
212
|
+
} else {
|
|
213
|
+
oks.push(v);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return [oks, errs];
|
|
217
|
+
}
|
|
218
|
+
function flatten(value) {
|
|
219
|
+
return value;
|
|
220
|
+
}
|
|
26
221
|
// Annotate the CommonJS export names for ESM import in node:
|
|
27
222
|
0 && (module.exports = {
|
|
28
|
-
|
|
223
|
+
TaggedError,
|
|
224
|
+
UnhandledError,
|
|
225
|
+
andThen,
|
|
226
|
+
andThenAsync,
|
|
227
|
+
flatten,
|
|
228
|
+
isError,
|
|
229
|
+
isOk,
|
|
230
|
+
isTaggedError,
|
|
231
|
+
map,
|
|
232
|
+
mapError,
|
|
233
|
+
match,
|
|
234
|
+
matchError,
|
|
235
|
+
matchErrorPartial,
|
|
236
|
+
partition,
|
|
237
|
+
tap,
|
|
238
|
+
tapAsync,
|
|
239
|
+
tryAsync,
|
|
240
|
+
tryFn,
|
|
241
|
+
unwrap,
|
|
242
|
+
unwrapOr
|
|
29
243
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,197 @@
|
|
|
1
|
-
// src/
|
|
2
|
-
var
|
|
1
|
+
// src/error.ts
|
|
2
|
+
var serializeCause = (cause) => {
|
|
3
|
+
if (cause instanceof Error) {
|
|
4
|
+
return { name: cause.name, message: cause.message, stack: cause.stack };
|
|
5
|
+
}
|
|
6
|
+
return cause;
|
|
7
|
+
};
|
|
8
|
+
var isAnyTaggedError = (value) => {
|
|
9
|
+
return value instanceof Error && "_tag" in value && typeof value._tag === "string";
|
|
10
|
+
};
|
|
11
|
+
var TaggedError = Object.assign(
|
|
12
|
+
(tag) => () => {
|
|
13
|
+
class Base extends Error {
|
|
14
|
+
_tag = tag;
|
|
15
|
+
/** Type guard for this error class */
|
|
16
|
+
static is(value) {
|
|
17
|
+
return value instanceof Base;
|
|
18
|
+
}
|
|
19
|
+
constructor(args) {
|
|
20
|
+
const message = args && "message" in args && typeof args.message === "string" ? args.message : void 0;
|
|
21
|
+
const cause = args && "cause" in args ? args.cause : void 0;
|
|
22
|
+
super(message, cause !== void 0 ? { cause } : void 0);
|
|
23
|
+
if (args) {
|
|
24
|
+
Object.assign(this, args);
|
|
25
|
+
}
|
|
26
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
27
|
+
this.name = tag;
|
|
28
|
+
if (cause instanceof Error && cause.stack) {
|
|
29
|
+
const indented = cause.stack.replace(/\n/g, "\n ");
|
|
30
|
+
this.stack = `${this.stack}
|
|
31
|
+
Caused by: ${indented}`;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
toJSON() {
|
|
35
|
+
return {
|
|
36
|
+
...this,
|
|
37
|
+
_tag: this._tag,
|
|
38
|
+
name: this.name,
|
|
39
|
+
message: this.message,
|
|
40
|
+
cause: serializeCause(this.cause),
|
|
41
|
+
stack: this.stack
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return Base;
|
|
46
|
+
},
|
|
47
|
+
{ is: isAnyTaggedError }
|
|
48
|
+
);
|
|
49
|
+
var isTaggedError = isAnyTaggedError;
|
|
50
|
+
function matchError(err, handlers) {
|
|
51
|
+
const handler = handlers[err._tag];
|
|
52
|
+
return handler(err);
|
|
53
|
+
}
|
|
54
|
+
function matchErrorPartial(err, handlers, fallback) {
|
|
55
|
+
const handler = handlers[err._tag];
|
|
56
|
+
if (handler) {
|
|
57
|
+
return handler(err);
|
|
58
|
+
}
|
|
59
|
+
return fallback(err);
|
|
60
|
+
}
|
|
61
|
+
var UnhandledError = class extends TaggedError("UnhandledError")() {
|
|
62
|
+
constructor(args) {
|
|
63
|
+
const message = args.cause instanceof Error ? `Unhandled exception: ${args.cause.message}` : `Unhandled exception: ${String(args.cause)}`;
|
|
64
|
+
super({ message, cause: args.cause });
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// src/core.ts
|
|
69
|
+
function isError(value) {
|
|
70
|
+
return value instanceof Error;
|
|
71
|
+
}
|
|
72
|
+
function isOk(value) {
|
|
73
|
+
return !(value instanceof Error);
|
|
74
|
+
}
|
|
75
|
+
function tryFn(fnOrOpts) {
|
|
76
|
+
if (typeof fnOrOpts === "function") {
|
|
77
|
+
try {
|
|
78
|
+
return fnOrOpts();
|
|
79
|
+
} catch (cause) {
|
|
80
|
+
return new UnhandledError({ cause });
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
try {
|
|
84
|
+
return fnOrOpts.try();
|
|
85
|
+
} catch (cause) {
|
|
86
|
+
return fnOrOpts.catch(cause);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
async function tryAsync(fnOrOpts) {
|
|
90
|
+
if (typeof fnOrOpts === "function") {
|
|
91
|
+
try {
|
|
92
|
+
return await fnOrOpts();
|
|
93
|
+
} catch (cause) {
|
|
94
|
+
return new UnhandledError({ cause });
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
try {
|
|
98
|
+
return await fnOrOpts.try();
|
|
99
|
+
} catch (cause) {
|
|
100
|
+
return await fnOrOpts.catch(cause);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// src/transform.ts
|
|
105
|
+
function map(value, fn) {
|
|
106
|
+
if (value instanceof Error) {
|
|
107
|
+
return value;
|
|
108
|
+
}
|
|
109
|
+
return fn(value);
|
|
110
|
+
}
|
|
111
|
+
function mapError(value, fn) {
|
|
112
|
+
if (value instanceof Error) {
|
|
113
|
+
return fn(value);
|
|
114
|
+
}
|
|
115
|
+
return value;
|
|
116
|
+
}
|
|
117
|
+
function andThen(value, fn) {
|
|
118
|
+
if (value instanceof Error) {
|
|
119
|
+
return value;
|
|
120
|
+
}
|
|
121
|
+
return fn(value);
|
|
122
|
+
}
|
|
123
|
+
async function andThenAsync(value, fn) {
|
|
124
|
+
if (value instanceof Error) {
|
|
125
|
+
return value;
|
|
126
|
+
}
|
|
127
|
+
return fn(value);
|
|
128
|
+
}
|
|
129
|
+
function tap(value, fn) {
|
|
130
|
+
if (!(value instanceof Error)) {
|
|
131
|
+
fn(value);
|
|
132
|
+
}
|
|
133
|
+
return value;
|
|
134
|
+
}
|
|
135
|
+
async function tapAsync(value, fn) {
|
|
136
|
+
if (!(value instanceof Error)) {
|
|
137
|
+
await fn(value);
|
|
138
|
+
}
|
|
139
|
+
return value;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// src/extract.ts
|
|
143
|
+
function unwrap(value, message) {
|
|
144
|
+
if (value instanceof Error) {
|
|
145
|
+
throw new Error(message ?? `Unwrap called on error: ${value.message}`, { cause: value });
|
|
146
|
+
}
|
|
147
|
+
return value;
|
|
148
|
+
}
|
|
149
|
+
function unwrapOr(value, fallback) {
|
|
150
|
+
if (value instanceof Error) {
|
|
151
|
+
return fallback;
|
|
152
|
+
}
|
|
153
|
+
return value;
|
|
154
|
+
}
|
|
155
|
+
function match(value, handlers) {
|
|
156
|
+
if (value instanceof Error) {
|
|
157
|
+
return handlers.err(value);
|
|
158
|
+
}
|
|
159
|
+
return handlers.ok(value);
|
|
160
|
+
}
|
|
161
|
+
function partition(values) {
|
|
162
|
+
const oks = [];
|
|
163
|
+
const errs = [];
|
|
164
|
+
for (const v of values) {
|
|
165
|
+
if (v instanceof Error) {
|
|
166
|
+
errs.push(v);
|
|
167
|
+
} else {
|
|
168
|
+
oks.push(v);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return [oks, errs];
|
|
172
|
+
}
|
|
173
|
+
function flatten(value) {
|
|
174
|
+
return value;
|
|
175
|
+
}
|
|
3
176
|
export {
|
|
4
|
-
|
|
177
|
+
TaggedError,
|
|
178
|
+
UnhandledError,
|
|
179
|
+
andThen,
|
|
180
|
+
andThenAsync,
|
|
181
|
+
flatten,
|
|
182
|
+
isError,
|
|
183
|
+
isOk,
|
|
184
|
+
isTaggedError,
|
|
185
|
+
map,
|
|
186
|
+
mapError,
|
|
187
|
+
match,
|
|
188
|
+
matchError,
|
|
189
|
+
matchErrorPartial,
|
|
190
|
+
partition,
|
|
191
|
+
tap,
|
|
192
|
+
tapAsync,
|
|
193
|
+
tryAsync,
|
|
194
|
+
tryFn,
|
|
195
|
+
unwrap,
|
|
196
|
+
unwrapOr
|
|
5
197
|
};
|
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "errore",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "Type-safe errors as values for TypeScript. Like Go, but with full type inference.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
8
|
"exports": {
|
|
9
9
|
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
10
11
|
"import": "./dist/index.mjs",
|
|
11
|
-
"require": "./dist/index.js"
|
|
12
|
-
"types": "./dist/index.d.ts"
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
"files": [
|