@cometloop/safe 0.0.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.cjs +692 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +378 -0
- package/dist/index.d.ts +378 -0
- package/dist/index.js +658 -0
- package/dist/index.js.map +1 -0
- package/package.json +69 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
type Falsy = false | 0 | '' | null | undefined | 0n | void;
|
|
2
|
+
/**
|
|
3
|
+
* Strips falsy members from E via distributive conditional.
|
|
4
|
+
* When E is purely falsy (e.g. null, false, 0), the result is `never`,
|
|
5
|
+
* making the parseError return type unsatisfiable — a compile error.
|
|
6
|
+
*
|
|
7
|
+
* For union types like `string | null`, the falsy member (`null`) is
|
|
8
|
+
* stripped, so `parseError` must return `string` — which means
|
|
9
|
+
* `(e: unknown) => e?.message ?? null` correctly fails to compile.
|
|
10
|
+
*/
|
|
11
|
+
type NonFalsy<E> = E extends Falsy ? never : E;
|
|
12
|
+
type SafeOk<T> = readonly [T, null] & {
|
|
13
|
+
readonly ok: true;
|
|
14
|
+
readonly value: T;
|
|
15
|
+
readonly error: null;
|
|
16
|
+
};
|
|
17
|
+
type SafeErr<E> = readonly [null, E] & {
|
|
18
|
+
readonly ok: false;
|
|
19
|
+
readonly value: null;
|
|
20
|
+
readonly error: E;
|
|
21
|
+
};
|
|
22
|
+
type SafeResult<T, E = Error> = SafeOk<T> | SafeErr<E>;
|
|
23
|
+
type SafeOkObj<T> = {
|
|
24
|
+
readonly ok: true;
|
|
25
|
+
readonly data: T;
|
|
26
|
+
readonly error: null;
|
|
27
|
+
};
|
|
28
|
+
type SafeErrObj<E> = {
|
|
29
|
+
readonly ok: false;
|
|
30
|
+
readonly data: null;
|
|
31
|
+
readonly error: E;
|
|
32
|
+
};
|
|
33
|
+
type SafeResultObj<T, E = Error> = SafeOkObj<T> | SafeErrObj<E>;
|
|
34
|
+
declare function ok<T>(value: T): SafeOk<T>;
|
|
35
|
+
declare function err<E>(error: E): SafeErr<E>;
|
|
36
|
+
declare function okObj<T>(data: T): SafeOkObj<T>;
|
|
37
|
+
declare function errObj<E>(error: E): SafeErrObj<E>;
|
|
38
|
+
declare class TimeoutError extends Error {
|
|
39
|
+
constructor(ms: number);
|
|
40
|
+
}
|
|
41
|
+
type RetryConfig = {
|
|
42
|
+
times: number;
|
|
43
|
+
waitBefore?: (attempt: number) => number;
|
|
44
|
+
};
|
|
45
|
+
type SafeHooks<T, E, TContext extends unknown[] = [], TOut = T> = {
|
|
46
|
+
parseResult?: (response: T) => TOut;
|
|
47
|
+
onSuccess?: (result: TOut, context: TContext) => void;
|
|
48
|
+
onError?: (error: E, context: TContext) => void;
|
|
49
|
+
onSettled?: (result: TOut | null, error: E | null, context: TContext) => void;
|
|
50
|
+
onHookError?: (error: unknown, hookName: string) => void;
|
|
51
|
+
/** Fallback error value returned when `parseError` throws. */
|
|
52
|
+
defaultError?: E;
|
|
53
|
+
};
|
|
54
|
+
type SafeAsyncHooks<T, E, TContext extends unknown[] = [], TOut = T> = SafeHooks<T, E, TContext, TOut> & {
|
|
55
|
+
onRetry?: (error: E, attempt: number, context: TContext) => void;
|
|
56
|
+
retry?: RetryConfig;
|
|
57
|
+
abortAfter?: number;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Configuration for creating a pre-configured safe instance
|
|
61
|
+
* @typeParam E - The error type that parseError returns
|
|
62
|
+
* @typeParam TResult - The return type of parseResult (inferred from parseResult)
|
|
63
|
+
*/
|
|
64
|
+
type CreateSafeConfig<E, TResult = never> = {
|
|
65
|
+
/**
|
|
66
|
+
* Error mapping function applied to all caught errors.
|
|
67
|
+
*
|
|
68
|
+
* If `parseError` throws, the exception is caught and reported via `onHookError`
|
|
69
|
+
* (hookName `'parseError'`). The `defaultError` value is returned as the error
|
|
70
|
+
* result; if `defaultError` is not provided, the raw caught error is normalized
|
|
71
|
+
* to an `Error` instance via `new Error(String(e))`.
|
|
72
|
+
*/
|
|
73
|
+
parseError: (e: unknown) => NonFalsy<E>;
|
|
74
|
+
/**
|
|
75
|
+
* Fallback error value returned when `parseError` throws.
|
|
76
|
+
* Must be provided alongside `parseError` in `createSafe`.
|
|
77
|
+
*/
|
|
78
|
+
defaultError: E;
|
|
79
|
+
/** Optional response transform applied to all successful results. Per-call parseResult overrides this. */
|
|
80
|
+
parseResult?: (response: unknown) => TResult;
|
|
81
|
+
/** Optional default success hook (result is unknown since T varies per call) */
|
|
82
|
+
onSuccess?: (result: unknown) => void;
|
|
83
|
+
/** Optional default error hook (receives the mapped error type E) */
|
|
84
|
+
onError?: (error: E) => void;
|
|
85
|
+
/** Optional default settled hook — fires after success or error */
|
|
86
|
+
onSettled?: (result: unknown, error: E | null) => void;
|
|
87
|
+
/** Optional default retry hook for async operations */
|
|
88
|
+
onRetry?: (error: E, attempt: number) => void;
|
|
89
|
+
/** Optional default retry configuration for async operations */
|
|
90
|
+
retry?: RetryConfig;
|
|
91
|
+
/** Optional default timeout for all async operations in milliseconds */
|
|
92
|
+
abortAfter?: number;
|
|
93
|
+
/** Optional callback invoked when any hook throws. Receives the thrown error and the hook name. */
|
|
94
|
+
onHookError?: (error: unknown, hookName: string) => void;
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* A pre-configured safe instance with a fixed error type
|
|
98
|
+
* Methods do not accept parseError parameter (already configured)
|
|
99
|
+
* @typeParam E - The error type used by all methods
|
|
100
|
+
* @typeParam TResult - The factory parseResult return type (never = no factory parseResult)
|
|
101
|
+
*/
|
|
102
|
+
type SafeInstance<E, TResult = never> = {
|
|
103
|
+
sync: <T, TOut = [TResult] extends [never] ? T : TResult>(fn: () => T, hooks?: SafeHooks<T, E, [], TOut>) => SafeResult<TOut, E>;
|
|
104
|
+
async: <T, TOut = [TResult] extends [never] ? T : TResult>(fn: (signal?: AbortSignal) => Promise<T>, hooks?: SafeAsyncHooks<T, E, [], TOut>) => Promise<SafeResult<TOut, E>>;
|
|
105
|
+
wrap: <TArgs extends unknown[], T, TOut = [TResult] extends [never] ? T : TResult>(fn: (...args: TArgs) => T, hooks?: SafeHooks<T, E, TArgs, TOut>) => (...args: TArgs) => SafeResult<TOut, E>;
|
|
106
|
+
wrapAsync: <TArgs extends unknown[], T, TOut = [TResult] extends [never] ? T : TResult>(fn: (...args: TArgs) => Promise<T>, hooks?: SafeAsyncHooks<T, E, TArgs, TOut>) => (...args: TArgs) => Promise<SafeResult<TOut, E>>;
|
|
107
|
+
all: <T extends Record<string, (signal?: AbortSignal) => Promise<any>>>(fns: T) => Promise<SafeResult<{
|
|
108
|
+
[K in keyof T]: [TResult] extends [never] ? T[K] extends (signal?: AbortSignal) => Promise<infer V> ? V : never : TResult;
|
|
109
|
+
}, E>>;
|
|
110
|
+
allSettled: <T extends Record<string, (signal?: AbortSignal) => Promise<any>>>(fns: T) => Promise<{
|
|
111
|
+
[K in keyof T]: SafeResult<[
|
|
112
|
+
TResult
|
|
113
|
+
] extends [never] ? T[K] extends (signal?: AbortSignal) => Promise<infer V> ? V : never : TResult, E>;
|
|
114
|
+
}>;
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* Object-style variant of SafeInstance where all methods return SafeResultObj instead of SafeResult tuples.
|
|
118
|
+
* Created by wrapping a SafeInstance with withObjects().
|
|
119
|
+
*/
|
|
120
|
+
type SafeObjectInstance<E, TResult = never> = {
|
|
121
|
+
sync: <T, TOut = [TResult] extends [never] ? T : TResult>(fn: () => T, hooks?: SafeHooks<T, E, [], TOut>) => SafeResultObj<TOut, E>;
|
|
122
|
+
async: <T, TOut = [TResult] extends [never] ? T : TResult>(fn: (signal?: AbortSignal) => Promise<T>, hooks?: SafeAsyncHooks<T, E, [], TOut>) => Promise<SafeResultObj<TOut, E>>;
|
|
123
|
+
wrap: <TArgs extends unknown[], T, TOut = [TResult] extends [never] ? T : TResult>(fn: (...args: TArgs) => T, hooks?: SafeHooks<T, E, TArgs, TOut>) => (...args: TArgs) => SafeResultObj<TOut, E>;
|
|
124
|
+
wrapAsync: <TArgs extends unknown[], T, TOut = [TResult] extends [never] ? T : TResult>(fn: (...args: TArgs) => Promise<T>, hooks?: SafeAsyncHooks<T, E, TArgs, TOut>) => (...args: TArgs) => Promise<SafeResultObj<TOut, E>>;
|
|
125
|
+
all: <T extends Record<string, (signal?: AbortSignal) => Promise<any>>>(fns: T) => Promise<SafeResultObj<{
|
|
126
|
+
[K in keyof T]: [TResult] extends [never] ? T[K] extends (signal?: AbortSignal) => Promise<infer V> ? V : never : TResult;
|
|
127
|
+
}, E>>;
|
|
128
|
+
allSettled: <T extends Record<string, (signal?: AbortSignal) => Promise<any>>>(fns: T) => Promise<{
|
|
129
|
+
[K in keyof T]: SafeResultObj<[
|
|
130
|
+
TResult
|
|
131
|
+
] extends [never] ? T[K] extends (signal?: AbortSignal) => Promise<infer V> ? V : never : TResult, E>;
|
|
132
|
+
}>;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Execute a synchronous function and return a result tuple instead of throwing.
|
|
137
|
+
*
|
|
138
|
+
* Catches any error thrown by `fn` and returns `[null, error]`.
|
|
139
|
+
* On success, returns `[result, null]`.
|
|
140
|
+
*
|
|
141
|
+
* @param fn - The synchronous function to execute.
|
|
142
|
+
* @param parseError - Optional function to transform the caught error into a custom type `E`.
|
|
143
|
+
* If `parseError` throws, the exception is caught and reported via `onHookError`
|
|
144
|
+
* (hookName `'parseError'`). The `defaultError` value is returned if provided;
|
|
145
|
+
* otherwise the raw caught error is normalized to an `Error` instance.
|
|
146
|
+
* @param hooks - Optional hooks for side effects (`parseResult`, `onSuccess`, `onError`, `onSettled`).
|
|
147
|
+
* @returns A `SafeResult<T, E>` tuple: `[value, null]` on success or `[null, error]` on failure.
|
|
148
|
+
*
|
|
149
|
+
* @example
|
|
150
|
+
* ```typescript
|
|
151
|
+
* const [user, error] = safe.sync(() => JSON.parse(rawJson))
|
|
152
|
+
*
|
|
153
|
+
* // With custom error parsing and hooks
|
|
154
|
+
* const [value, err] = safe.sync(
|
|
155
|
+
* () => riskyOperation(),
|
|
156
|
+
* (e) => ({ code: 'PARSE_ERROR', message: String(e) }),
|
|
157
|
+
* { onError: (error) => console.error(error.code) }
|
|
158
|
+
* )
|
|
159
|
+
* ```
|
|
160
|
+
*/
|
|
161
|
+
declare function safeSync<T>(fn: () => T): SafeResult<T, Error>;
|
|
162
|
+
declare function safeSync<T, TOut = T>(fn: () => T, hooks: SafeHooks<T, Error, [], TOut>): SafeResult<TOut, Error>;
|
|
163
|
+
declare function safeSync<T, E>(fn: () => T, parseError: (e: unknown) => NonFalsy<E>): SafeResult<T, E>;
|
|
164
|
+
declare function safeSync<T, E, TOut = T>(fn: () => T, parseError: (e: unknown) => NonFalsy<E>, hooks: SafeHooks<T, E, [], TOut> & {
|
|
165
|
+
defaultError: E;
|
|
166
|
+
}): SafeResult<TOut, E>;
|
|
167
|
+
/**
|
|
168
|
+
* Execute an asynchronous function and return a result tuple instead of throwing.
|
|
169
|
+
*
|
|
170
|
+
* Catches any error thrown or rejected by `fn` and returns `[null, error]`.
|
|
171
|
+
* On success, returns `[result, null]`. Supports retry and timeout via hooks.
|
|
172
|
+
*
|
|
173
|
+
* @param fn - The async function to execute. Receives an optional `AbortSignal` when `abortAfter` is configured.
|
|
174
|
+
* @param parseError - Optional function to transform the caught error into a custom type `E`.
|
|
175
|
+
* If `parseError` throws, the exception is caught and reported via `onHookError`
|
|
176
|
+
* (hookName `'parseError'`). The `defaultError` value is returned if provided;
|
|
177
|
+
* otherwise the raw caught error is normalized to an `Error` instance.
|
|
178
|
+
* @param hooks - Optional hooks including `retry`, `abortAfter`, `onRetry`, `parseResult`, `onSuccess`, `onError`, `onSettled`.
|
|
179
|
+
* @returns A `Promise<SafeResult<T, E>>` tuple: `[value, null]` on success or `[null, error]` on failure.
|
|
180
|
+
*
|
|
181
|
+
* @example
|
|
182
|
+
* ```typescript
|
|
183
|
+
* const [data, error] = await safe.async(() => fetch('/api/users').then(r => r.json()))
|
|
184
|
+
*
|
|
185
|
+
* // With retry and timeout
|
|
186
|
+
* const [data, error] = await safe.async(
|
|
187
|
+
* (signal) => fetch('/api/users', { signal }).then(r => r.json()),
|
|
188
|
+
* { retry: { times: 3 }, abortAfter: 5000 }
|
|
189
|
+
* )
|
|
190
|
+
* ```
|
|
191
|
+
*/
|
|
192
|
+
declare function safeAsync<T>(fn: (signal?: AbortSignal) => Promise<T>): Promise<SafeResult<T, Error>>;
|
|
193
|
+
declare function safeAsync<T, TOut = T>(fn: (signal?: AbortSignal) => Promise<T>, hooks: SafeAsyncHooks<T, Error, [], TOut>): Promise<SafeResult<TOut, Error>>;
|
|
194
|
+
declare function safeAsync<T, E>(fn: (signal?: AbortSignal) => Promise<T>, parseError: (e: unknown) => NonFalsy<E>): Promise<SafeResult<T, E>>;
|
|
195
|
+
declare function safeAsync<T, E, TOut = T>(fn: (signal?: AbortSignal) => Promise<T>, parseError: (e: unknown) => NonFalsy<E>, hooks: SafeAsyncHooks<T, E, [], TOut> & {
|
|
196
|
+
defaultError: E;
|
|
197
|
+
}): Promise<SafeResult<TOut, E>>;
|
|
198
|
+
/**
|
|
199
|
+
* Wrap a synchronous function so it returns a result tuple instead of throwing.
|
|
200
|
+
*
|
|
201
|
+
* Returns a new function with the same parameter signature that catches
|
|
202
|
+
* errors and returns `[null, error]` instead of throwing. The original
|
|
203
|
+
* arguments are passed through to hooks as context.
|
|
204
|
+
*
|
|
205
|
+
* @param fn - The synchronous function to wrap.
|
|
206
|
+
* @param parseError - Optional function to transform the caught error into a custom type `E`.
|
|
207
|
+
* If `parseError` throws, the exception is caught and reported via `onHookError`
|
|
208
|
+
* (hookName `'parseError'`). The `defaultError` value is returned if provided;
|
|
209
|
+
* otherwise the raw caught error is normalized to an `Error` instance.
|
|
210
|
+
* @param hooks - Optional hooks for side effects (`parseResult`, `onSuccess`, `onError`, `onSettled`). Hooks receive the original call arguments as context.
|
|
211
|
+
* @returns A wrapped function `(...args) => SafeResult<T, E>`.
|
|
212
|
+
*
|
|
213
|
+
* @example
|
|
214
|
+
* ```typescript
|
|
215
|
+
* const safeJsonParse = safe.wrap(JSON.parse)
|
|
216
|
+
* const [data, error] = safeJsonParse('{"valid": true}')
|
|
217
|
+
*
|
|
218
|
+
* // With hooks that receive the original arguments
|
|
219
|
+
* const safeDivide = safe.wrap(
|
|
220
|
+
* (a: number, b: number) => { if (b === 0) throw new Error('Division by zero'); return a / b },
|
|
221
|
+
* { onError: (error, [a, b]) => console.error(`Failed to divide ${a} by ${b}`) }
|
|
222
|
+
* )
|
|
223
|
+
* ```
|
|
224
|
+
*/
|
|
225
|
+
declare function wrap<TArgs extends unknown[], T>(fn: (...args: TArgs) => T): (...args: TArgs) => SafeResult<T, Error>;
|
|
226
|
+
declare function wrap<TArgs extends unknown[], T, TOut = T>(fn: (...args: TArgs) => T, hooks: SafeHooks<T, Error, TArgs, TOut>): (...args: TArgs) => SafeResult<TOut, Error>;
|
|
227
|
+
declare function wrap<TArgs extends unknown[], T, E>(fn: (...args: TArgs) => T, parseError: (e: unknown) => NonFalsy<E>): (...args: TArgs) => SafeResult<T, E>;
|
|
228
|
+
declare function wrap<TArgs extends unknown[], T, E, TOut = T>(fn: (...args: TArgs) => T, parseError: (e: unknown) => NonFalsy<E>, hooks: SafeHooks<T, E, TArgs, TOut> & {
|
|
229
|
+
defaultError: E;
|
|
230
|
+
}): (...args: TArgs) => SafeResult<TOut, E>;
|
|
231
|
+
/**
|
|
232
|
+
* Wrap an asynchronous function so it returns a result tuple instead of throwing.
|
|
233
|
+
*
|
|
234
|
+
* Returns a new function with the same parameter signature that catches
|
|
235
|
+
* errors and returns `[null, error]` instead of throwing. Supports retry
|
|
236
|
+
* and timeout via hooks.
|
|
237
|
+
*
|
|
238
|
+
* **Note on `abortAfter`:** When configured, `abortAfter` acts as an external
|
|
239
|
+
* deadline — the promise is rejected with a `TimeoutError` after the specified
|
|
240
|
+
* duration, but the wrapped function does **not** receive an `AbortSignal`.
|
|
241
|
+
* This means the underlying operation will continue running in the background
|
|
242
|
+
* even after the timeout fires. If you need cooperative cancellation (e.g.
|
|
243
|
+
* passing a signal to `fetch`), use {@link safeAsync | safe.async} instead,
|
|
244
|
+
* which passes the signal directly to the function:
|
|
245
|
+
*
|
|
246
|
+
* ```typescript
|
|
247
|
+
* // Cooperative cancellation with safe.async
|
|
248
|
+
* const [data, error] = await safe.async(
|
|
249
|
+
* (signal) => fetch('/api/data', { signal }),
|
|
250
|
+
* { abortAfter: 5000 }
|
|
251
|
+
* )
|
|
252
|
+
* ```
|
|
253
|
+
*
|
|
254
|
+
* @param fn - The async function to wrap.
|
|
255
|
+
* @param parseError - Optional function to transform the caught error into a custom type `E`.
|
|
256
|
+
* If `parseError` throws, the exception is caught and reported via `onHookError`
|
|
257
|
+
* (hookName `'parseError'`). The `defaultError` value is returned if provided;
|
|
258
|
+
* otherwise the raw caught error is normalized to an `Error` instance.
|
|
259
|
+
* @param hooks - Optional hooks including `retry`, `abortAfter`, `onRetry`, `parseResult`, `onSuccess`, `onError`, `onSettled`. Hooks receive the original call arguments as context.
|
|
260
|
+
* @returns A wrapped function `(...args) => Promise<SafeResult<T, E>>`.
|
|
261
|
+
*
|
|
262
|
+
* @example
|
|
263
|
+
* ```typescript
|
|
264
|
+
* const safeFetchUser = safe.wrapAsync(
|
|
265
|
+
* (id: string) => fetch(`/api/users/${id}`).then(r => r.json())
|
|
266
|
+
* )
|
|
267
|
+
* const [user, error] = await safeFetchUser('123')
|
|
268
|
+
*
|
|
269
|
+
* // With retry
|
|
270
|
+
* const safeFetch = safe.wrapAsync(
|
|
271
|
+
* (url: string) => fetch(url).then(r => r.json()),
|
|
272
|
+
* { retry: { times: 3, waitBefore: (attempt) => attempt * 1000 } }
|
|
273
|
+
* )
|
|
274
|
+
* ```
|
|
275
|
+
*/
|
|
276
|
+
declare function wrapAsync<TArgs extends unknown[], T>(fn: (...args: TArgs) => Promise<T>): (...args: TArgs) => Promise<SafeResult<T, Error>>;
|
|
277
|
+
declare function wrapAsync<TArgs extends unknown[], T, TOut = T>(fn: (...args: TArgs) => Promise<T>, hooks: SafeAsyncHooks<T, Error, TArgs, TOut>): (...args: TArgs) => Promise<SafeResult<TOut, Error>>;
|
|
278
|
+
declare function wrapAsync<TArgs extends unknown[], T, E>(fn: (...args: TArgs) => Promise<T>, parseError: (e: unknown) => NonFalsy<E>): (...args: TArgs) => Promise<SafeResult<T, E>>;
|
|
279
|
+
declare function wrapAsync<TArgs extends unknown[], T, E, TOut = T>(fn: (...args: TArgs) => Promise<T>, parseError: (e: unknown) => NonFalsy<E>, hooks: SafeAsyncHooks<T, E, TArgs, TOut> & {
|
|
280
|
+
defaultError: E;
|
|
281
|
+
}): (...args: TArgs) => Promise<SafeResult<TOut, E>>;
|
|
282
|
+
/**
|
|
283
|
+
* Run multiple safe-wrapped async operations in parallel and return all values or the first error.
|
|
284
|
+
*
|
|
285
|
+
* Short-circuits: returns immediately when any operation fails, without waiting
|
|
286
|
+
* for remaining operations to settle. If all succeed, returns
|
|
287
|
+
* `ok({ key: value, ... })` with unwrapped values. If any fail, returns `err(firstError)`.
|
|
288
|
+
*
|
|
289
|
+
* @param promises - An object map of `Promise<SafeResult<T, E>>` entries.
|
|
290
|
+
* @returns A `Promise<SafeResult<{ [K]: V }, E>>` — all values on success, first error on failure.
|
|
291
|
+
*
|
|
292
|
+
* @example
|
|
293
|
+
* ```typescript
|
|
294
|
+
* const [data, error] = await safe.all({
|
|
295
|
+
* user: safe.async(() => fetchUser()),
|
|
296
|
+
* posts: safe.async(() => fetchPosts()),
|
|
297
|
+
* })
|
|
298
|
+
* if (error) return handleError(error)
|
|
299
|
+
* data.user // User
|
|
300
|
+
* data.posts // Post[]
|
|
301
|
+
* ```
|
|
302
|
+
*/
|
|
303
|
+
declare function safeAll<T extends Record<string, Promise<SafeResult<any, any>>>>(promises: T): Promise<SafeResult<{
|
|
304
|
+
[K in keyof T]: T[K] extends Promise<SafeResult<infer V, any>> ? V : never;
|
|
305
|
+
}, T[keyof T] extends Promise<SafeResult<any, infer E>> ? E : never>>;
|
|
306
|
+
/**
|
|
307
|
+
* Run multiple safe-wrapped async operations in parallel and return all individual results.
|
|
308
|
+
*
|
|
309
|
+
* Accepts an object map of `Promise<SafeResult>` entries. Always returns all results
|
|
310
|
+
* as named SafeResult entries — never fails at the group level.
|
|
311
|
+
*
|
|
312
|
+
* @param promises - An object map of `Promise<SafeResult<T, E>>` entries.
|
|
313
|
+
* @returns A `Promise<{ [K]: SafeResult<V, E> }>` — each key maps to its individual result.
|
|
314
|
+
*
|
|
315
|
+
* @example
|
|
316
|
+
* ```typescript
|
|
317
|
+
* const results = await safe.allSettled({
|
|
318
|
+
* user: safe.async(() => fetchUser()),
|
|
319
|
+
* posts: safe.async(() => fetchPosts()),
|
|
320
|
+
* })
|
|
321
|
+
* if (results.user.ok) {
|
|
322
|
+
* results.user.value // User
|
|
323
|
+
* }
|
|
324
|
+
* if (!results.posts.ok) {
|
|
325
|
+
* results.posts.error // Error
|
|
326
|
+
* }
|
|
327
|
+
* ```
|
|
328
|
+
*/
|
|
329
|
+
declare function safeAllSettled<T extends Record<string, Promise<SafeResult<any, any>>>>(promises: T): Promise<{
|
|
330
|
+
[K in keyof T]: Awaited<T[K]>;
|
|
331
|
+
}>;
|
|
332
|
+
declare const safe: {
|
|
333
|
+
readonly sync: typeof safeSync;
|
|
334
|
+
readonly async: typeof safeAsync;
|
|
335
|
+
readonly wrap: typeof wrap;
|
|
336
|
+
readonly wrapAsync: typeof wrapAsync;
|
|
337
|
+
readonly all: typeof safeAll;
|
|
338
|
+
readonly allSettled: typeof safeAllSettled;
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Create a pre-configured safe instance with a fixed error mapping function
|
|
343
|
+
*
|
|
344
|
+
* Returns a new safe object where all methods use the configured parseError.
|
|
345
|
+
* The error type E is automatically inferred from the parseError return type.
|
|
346
|
+
* If parseResult is provided, TResult is inferred from its return type
|
|
347
|
+
* and becomes the default result type for all methods.
|
|
348
|
+
*
|
|
349
|
+
* @example
|
|
350
|
+
* ```typescript
|
|
351
|
+
* const appSafe = createSafe({
|
|
352
|
+
* parseError: (e) => ({
|
|
353
|
+
* code: 'UNKNOWN_ERROR',
|
|
354
|
+
* message: e instanceof Error ? e.message : 'Unknown error',
|
|
355
|
+
* }),
|
|
356
|
+
* onError: (error) => logger.error(error.code),
|
|
357
|
+
* })
|
|
358
|
+
*
|
|
359
|
+
* const [result, error] = appSafe.sync(() => JSON.parse(data))
|
|
360
|
+
* // error is typed as { code: string; message: string }
|
|
361
|
+
*
|
|
362
|
+
* // With parseResult for runtime validation:
|
|
363
|
+
* const validatedSafe = createSafe({
|
|
364
|
+
* parseError: (e) => toAppError(e),
|
|
365
|
+
* parseResult: (response) => schema.parse(response),
|
|
366
|
+
* })
|
|
367
|
+
* // All methods return SafeResult<z.infer<typeof schema>, AppError>
|
|
368
|
+
* ```
|
|
369
|
+
*/
|
|
370
|
+
declare function createSafe<E, TResult = never>(config: CreateSafeConfig<E, TResult>): SafeInstance<E, TResult>;
|
|
371
|
+
|
|
372
|
+
declare function withObjects<T, E>(result: SafeResult<T, E>): SafeResultObj<T, E>;
|
|
373
|
+
declare function withObjects<T, E>(result: Promise<SafeResult<T, E>>): Promise<SafeResultObj<T, E>>;
|
|
374
|
+
declare function withObjects<A extends unknown[], T, E>(fn: (...args: A) => SafeResult<T, E>): (...args: A) => SafeResultObj<T, E>;
|
|
375
|
+
declare function withObjects<A extends unknown[], T, E>(fn: (...args: A) => Promise<SafeResult<T, E>>): (...args: A) => Promise<SafeResultObj<T, E>>;
|
|
376
|
+
declare function withObjects<E, TResult>(instance: SafeInstance<E, TResult>): SafeObjectInstance<E, TResult>;
|
|
377
|
+
|
|
378
|
+
export { type CreateSafeConfig, type NonFalsy, type RetryConfig, type SafeAsyncHooks, type SafeErr, type SafeErrObj, type SafeHooks, type SafeInstance, type SafeObjectInstance, type SafeOk, type SafeOkObj, type SafeResult, type SafeResultObj, TimeoutError, createSafe, err, errObj, ok, okObj, safe, withObjects };
|