@zokugun/xtry 0.4.0 → 0.5.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/README.md +78 -17
- package/lib/async.d.ts +7 -0
- package/lib/async.js +5 -0
- package/lib/defer.d.ts +16 -0
- package/lib/defer.js +45 -0
- package/lib/index.d.ts +7 -4
- package/lib/index.js +5 -4
- package/lib/partial.d.ts +12 -2
- package/lib/partial.js +15 -4
- package/lib/result.d.ts +5 -0
- package/lib/result.js +5 -1
- package/lib/sync.d.ts +7 -0
- package/lib/sync.js +5 -0
- package/lib/try.d.ts +8 -2
- package/lib/try.js +29 -1
- package/lib/utils/is-promise-like.d.ts +3 -0
- package/lib/utils/is-promise-like.js +3 -0
- package/lib/utils/types.d.ts +5 -0
- package/lib/utils/types.js +1 -0
- package/package.json +14 -15
package/README.md
CHANGED
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
|
|
10
10
|
Simple `try/catch` wrappers that always return a `Result` discriminated union, plus ready-made helpers (`ok`, `err`) for predictable control flow.
|
|
11
11
|
|
|
12
|
-
Why xtry
|
|
13
|
-
|
|
12
|
+
Why `@zokugun/xtry`?
|
|
13
|
+
--------------------
|
|
14
14
|
|
|
15
15
|
- Turn any sync or async function into an explicit `Result` object with zero dependencies.
|
|
16
16
|
- Strong TypeScript types guide your control flow (`fails` and tagged errors).
|
|
@@ -27,9 +27,9 @@ Quick Start
|
|
|
27
27
|
-----------
|
|
28
28
|
|
|
29
29
|
```typescript
|
|
30
|
-
import {
|
|
30
|
+
import { xtry } from '@zokugun/xtry'
|
|
31
31
|
|
|
32
|
-
const userResult = await
|
|
32
|
+
const userResult = await xtry(fetchUserFromApi());
|
|
33
33
|
|
|
34
34
|
if(userResult.fails) {
|
|
35
35
|
console.error(userResult.error);
|
|
@@ -43,18 +43,18 @@ Advanced Example
|
|
|
43
43
|
----------------
|
|
44
44
|
|
|
45
45
|
```typescript
|
|
46
|
-
import { err, type Result,
|
|
46
|
+
import { err, type Result, xtry } from '@zokugun/xtry'
|
|
47
47
|
|
|
48
48
|
export type FoobarError = { type: 'FOOBAR'; message: string };
|
|
49
49
|
|
|
50
50
|
async function foobar(): Result<number, FoobarError> {
|
|
51
|
-
const result = await
|
|
51
|
+
const result = await xtry(fetchUserFromApi());
|
|
52
52
|
|
|
53
53
|
if(fails) {
|
|
54
54
|
return err({ type: 'FOOBAR', message: 'The promise has failed...' });
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
return
|
|
57
|
+
return xtry(() => calculateAge(result.value));
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
async function main() {
|
|
@@ -113,6 +113,11 @@ function add(_x: string, _y: number): Result<number, MyError> {
|
|
|
113
113
|
}
|
|
114
114
|
```
|
|
115
115
|
|
|
116
|
+
Tips
|
|
117
|
+
----
|
|
118
|
+
|
|
119
|
+
- Narrow on `fails` first, then use other flags (`success`, custom `miscue` or `value`) for the happy-path branching.
|
|
120
|
+
|
|
116
121
|
API reference
|
|
117
122
|
-------------
|
|
118
123
|
|
|
@@ -123,20 +128,32 @@ type Success<T> = { fails: false; value: T; error: undefined };
|
|
|
123
128
|
type Failure<E> = { fails: true; value: undefined; error: E };
|
|
124
129
|
type Result<T, E> = Success<T> | Failure<E>;
|
|
125
130
|
|
|
126
|
-
function ok<T>(value
|
|
131
|
+
function ok<T>(value?: T): Success<T>;
|
|
127
132
|
function err<E>(error: E): Failure<E>;
|
|
128
133
|
```
|
|
129
134
|
|
|
135
|
+
#### Pre-built `ok` constants
|
|
136
|
+
|
|
137
|
+
To minimize allocations when returning the same `Success` shape, you can reuse the exported frozen helpers:
|
|
138
|
+
|
|
139
|
+
| Constant | Wrapped value | Type | Typical usage |
|
|
140
|
+
| ---------- | ------------- | ---------------- | --------------------------------------------------- |
|
|
141
|
+
| `OK` | `ok()` | `Success<void>` | Generic void success (e.g., cleanup, notifications) |
|
|
142
|
+
| `OK_NULL` | `ok(null)` | `Success<null>` | APIs that explicitly signal "nothing" with `null` |
|
|
143
|
+
| `OK_TRUE` | `ok(true)` | `Success<true>` | Flag-style functions (`enable()` / `disable()`) |
|
|
144
|
+
| `OK_FALSE` | `ok(false)` | `Success<false>` | Guard checks that succeed with `false` |
|
|
145
|
+
|
|
130
146
|
### Try helpers
|
|
131
147
|
|
|
132
|
-
```
|
|
133
|
-
function xtry<T, E>(func: () =>
|
|
134
|
-
function
|
|
148
|
+
```
|
|
149
|
+
function xtry<T, E>(func: (() => MaybePromise<T>) | Promise<T>, handler?: (error: unknown) => void | E): MaybePromise<Result<T, E>>;
|
|
150
|
+
function xtrySync<T, E>(func: () => Exclude<T, Promise<unknown>>, handler?: (error: unknown) => void | E): Result<T, E>;
|
|
151
|
+
function xtryAsync<T, E>(func: (() => Promise<T>) | Promise<T>, handler?: (error: unknown) => void | E): Promise<Result<T, E>>;
|
|
135
152
|
|
|
136
153
|
function stringifyError(error: unknown): string;
|
|
137
154
|
```
|
|
138
155
|
|
|
139
|
-
|
|
156
|
+
`xtry` inspects the supplied value: if it is or returns a promise you get a `Promise<Result<…>>`, otherwise you get a plain `Result`. Use `xtrySync`/`xtryAsync` when you need to force a specific flavor (tree shaking, stricter contracts, etc.). All helpers:
|
|
140
157
|
|
|
141
158
|
- execute the supplied function and capture thrown values;
|
|
142
159
|
- call the optional `handler` before turning that value into `err(error)`;
|
|
@@ -151,17 +168,61 @@ type YResult<T, E, M> = Failure<E> | YSuccess<T> | YFailure<M>;
|
|
|
151
168
|
|
|
152
169
|
function yok<T>(value: T): YSuccess<T>;
|
|
153
170
|
function yerr<M>(type: M): YFailure<M>;
|
|
154
|
-
function
|
|
155
|
-
function
|
|
171
|
+
function yres<T, E>(result: MaybePromise<Result<T, E>>): MaybePromise<Failure<E> | YSuccess<T>>;
|
|
172
|
+
function yresSync<T, E>(result: Result<T, E>): Failure<E> | YSuccess<T>;
|
|
173
|
+
function yresAsync<T, E>(promise: Promise<Result<T, E>>): Promise<Failure<E> | YSuccess<T>>;
|
|
156
174
|
function yep<T>(result: Success<T>): YSuccess<T>;
|
|
157
175
|
```
|
|
158
176
|
|
|
159
177
|
These helpers are useful when you need to separate soft rejections (`success: false`) from hard failures (`fails: true`).
|
|
160
178
|
|
|
161
|
-
|
|
162
|
-
|
|
179
|
+
### Defer helpers
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
type DeferSync<E> = (result?: Result<unknown, E>) => Result<unknown, E> | Success<void>;
|
|
183
|
+
type DeferAsync<E> = (result?: Result<unknown, E>) => Promise<Result<unknown, E> | Success<void>>;
|
|
184
|
+
|
|
185
|
+
function xdefer<E>(callback: () => Result<unknown, E> | Promise<Result<unknown, E>>): DeferSync<E> | DeferAsync<E>;
|
|
186
|
+
function xdeferSync<E>(callback: () => Result<unknown, E>): DeferSync<E>;
|
|
187
|
+
function xdeferAsync<E>(callback: (() => Promise<Result<unknown, E>>) | Promise<Result<unknown, E>>): DeferAsync<E>;
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Use these helpers to express "finally" logic that can also fail while preserving the original result when needed:
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
import { stringifyError, xdefer, xtry } from '@zokugun/xtry/async'
|
|
194
|
+
|
|
195
|
+
function test(): Result<void, string> {
|
|
196
|
+
const closeConnection = xdefer(xtry(connection.close()));
|
|
197
|
+
|
|
198
|
+
const queryResult = await xtry(connection.query('SELECT 1'));
|
|
199
|
+
|
|
200
|
+
if(queryResult.fails) {
|
|
201
|
+
return closeConnection(err(stringifyError(queryResult.error)))
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
...
|
|
205
|
+
|
|
206
|
+
return closeConnection();
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
- `xdefer` inspects the callback result: if it fails, it becomes the returned error unless the main result already failed.
|
|
211
|
+
- Passing a promise (or async factory) makes the defer helper async-aware; `xdeferSync`/`xdeferAsync` let you pin the behavior explicitly for bundlers.
|
|
212
|
+
- Calling the returned function with no arguments just runs the deferred work and yields `ok()`.
|
|
213
|
+
|
|
214
|
+
Module entry points
|
|
215
|
+
-------------------
|
|
216
|
+
|
|
217
|
+
Choose the entry point that matches your environment and naming preferences:
|
|
218
|
+
|
|
219
|
+
| Import path | Description | `xtry` name | `xdefer` name | Extra alias |
|
|
220
|
+
| --------------------- | --------------------------- | ------------------------------- | ------------------------------------- | ------------------------------- |
|
|
221
|
+
| `@zokugun/xtry` | Both sync, async and hybrid | `xtry`, `xtryAsync`, `xtrySync` | `xdefer`, `xdeferAsync`, `xdeferSync` | `yres`, `yresAsync`, `yresSync` |
|
|
222
|
+
| `@zokugun/xtry/async` | Async-only | `xtryAsync` as `xtry` | `xdeferAsync` as `xdefer` | `yresAsync` as `yres` |
|
|
223
|
+
| `@zokugun/xtry/sync` | Synchronous-only | `xtrySync` as `xtry` | `xdeferSync` as `xdefer` | `yresSync` as `yres` |
|
|
163
224
|
|
|
164
|
-
|
|
225
|
+
All modules share the same `Result`, `Partial`, and `stringifyError` exports, so you can swap entry points without refactoring types.
|
|
165
226
|
|
|
166
227
|
Donations
|
|
167
228
|
---------
|
package/lib/async.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { xdeferAsync as xdefer } from './defer.js';
|
|
2
|
+
export type { YResult, YSuccess, YFailure } from './partial.js';
|
|
3
|
+
export { yok, yerr, yresAsync as yres, yep, YOK, YOK_NULL, YOK_TRUE, YOK_FALSE } from './partial.js';
|
|
4
|
+
export type { Success, Failure, Result } from './result.js';
|
|
5
|
+
export { ok, err, OK, OK_NULL, OK_TRUE, OK_FALSE } from './result.js';
|
|
6
|
+
export { stringifyError } from './stringify-error.js';
|
|
7
|
+
export { xtryAsync as xtry } from './try.js';
|
package/lib/async.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { xdeferAsync as xdefer } from './defer.js';
|
|
2
|
+
export { yok, yerr, yresAsync as yres, yep, YOK, YOK_NULL, YOK_TRUE, YOK_FALSE } from './partial.js';
|
|
3
|
+
export { ok, err, OK, OK_NULL, OK_TRUE, OK_FALSE } from './result.js';
|
|
4
|
+
export { stringifyError } from './stringify-error.js';
|
|
5
|
+
export { xtryAsync as xtry } from './try.js';
|
package/lib/defer.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type Result, type Success } from './result.js';
|
|
2
|
+
import { type NonPromiseCallback, type PromiseCallback } from './utils/types.js';
|
|
3
|
+
type DeferAsync<E> = {
|
|
4
|
+
(): Promise<Success<void>>;
|
|
5
|
+
(result: UnknownResult<E>): Promise<UnknownResult<E>>;
|
|
6
|
+
};
|
|
7
|
+
type DeferSync<E> = {
|
|
8
|
+
(): Success<void>;
|
|
9
|
+
(result: UnknownResult<E>): UnknownResult<E>;
|
|
10
|
+
};
|
|
11
|
+
type UnknownResult<E> = Result<unknown, E>;
|
|
12
|
+
export declare function xdefer<E>(callback: NonPromiseCallback<UnknownResult<E>>): DeferSync<E>;
|
|
13
|
+
export declare function xdefer<E>(callback: PromiseCallback<UnknownResult<E>>): DeferAsync<E>;
|
|
14
|
+
export declare function xdeferAsync<E>(callback: PromiseCallback<UnknownResult<E>>): DeferAsync<E>;
|
|
15
|
+
export declare function xdeferSync<E>(callback: NonPromiseCallback<UnknownResult<E>>): DeferSync<E>;
|
|
16
|
+
export {};
|
package/lib/defer.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { ok } from './result.js';
|
|
2
|
+
import { isPromiseLike } from './utils/is-promise-like.js';
|
|
3
|
+
export function xdefer(callback) {
|
|
4
|
+
// eslint-disable-next-line @typescript-eslint/promise-function-async
|
|
5
|
+
return ((result) => {
|
|
6
|
+
const finalize = (deferResult) => {
|
|
7
|
+
if (deferResult.fails) {
|
|
8
|
+
if (result?.fails) {
|
|
9
|
+
return result;
|
|
10
|
+
}
|
|
11
|
+
return deferResult;
|
|
12
|
+
}
|
|
13
|
+
return result ?? ok();
|
|
14
|
+
};
|
|
15
|
+
const deferredValue = callback instanceof Function ? callback() : callback;
|
|
16
|
+
if (isPromiseLike(deferredValue)) {
|
|
17
|
+
return Promise.resolve(deferredValue).then(finalize);
|
|
18
|
+
}
|
|
19
|
+
return finalize(deferredValue);
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
export function xdeferAsync(callback) {
|
|
23
|
+
return (async (result) => {
|
|
24
|
+
const deferResult = await (callback instanceof Promise ? callback : callback());
|
|
25
|
+
if (deferResult.fails) {
|
|
26
|
+
if (result?.fails) {
|
|
27
|
+
return result;
|
|
28
|
+
}
|
|
29
|
+
return deferResult;
|
|
30
|
+
}
|
|
31
|
+
return result ?? ok();
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
export function xdeferSync(callback) {
|
|
35
|
+
return ((result) => {
|
|
36
|
+
const deferResult = callback();
|
|
37
|
+
if (deferResult.fails) {
|
|
38
|
+
if (result?.fails) {
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
return deferResult;
|
|
42
|
+
}
|
|
43
|
+
return result ?? ok();
|
|
44
|
+
});
|
|
45
|
+
}
|
package/lib/index.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
export
|
|
1
|
+
export { xdefer, xdeferAsync, xdeferSync } from './defer.js';
|
|
2
|
+
export type { YResult, YSuccess, YFailure } from './partial.js';
|
|
3
|
+
export { yok, yerr, yres, yresAsync, yresSync, yep, YOK, YOK_NULL, YOK_TRUE, YOK_FALSE } from './partial.js';
|
|
4
|
+
export type { Success, Failure, Result } from './result.js';
|
|
5
|
+
export { ok, err, OK, OK_NULL, OK_TRUE, OK_FALSE } from './result.js';
|
|
6
|
+
export { stringifyError } from './stringify-error.js';
|
|
7
|
+
export { xtry, xtryAsync, xtrySync } from './try.js';
|
package/lib/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
export
|
|
1
|
+
export { xdefer, xdeferAsync, xdeferSync } from './defer.js';
|
|
2
|
+
export { yok, yerr, yres, yresAsync, yresSync, yep, YOK, YOK_NULL, YOK_TRUE, YOK_FALSE } from './partial.js';
|
|
3
|
+
export { ok, err, OK, OK_NULL, OK_TRUE, OK_FALSE } from './result.js';
|
|
4
|
+
export { stringifyError } from './stringify-error.js';
|
|
5
|
+
export { xtry, xtryAsync, xtrySync } from './try.js';
|
package/lib/partial.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type Result, type Failure, type Success } from './result.js';
|
|
2
|
+
import { type NotPromise } from './utils/types.js';
|
|
2
3
|
export type YResult<T, E, M> = Failure<E> | YSuccess<T> | YFailure<M>;
|
|
3
4
|
export type YSuccess<T> = Success<T> & {
|
|
4
5
|
success: true;
|
|
@@ -10,8 +11,17 @@ export type YFailure<M> = {
|
|
|
10
11
|
value: undefined;
|
|
11
12
|
error: undefined;
|
|
12
13
|
};
|
|
14
|
+
export declare function yok(): YSuccess<void>;
|
|
13
15
|
export declare function yok<T>(value: T): YSuccess<T>;
|
|
14
16
|
export declare function yerr<M>(miscue: M): YFailure<M>;
|
|
15
|
-
|
|
16
|
-
export declare function
|
|
17
|
+
type YRResult<T, E> = Failure<E> | YSuccess<T>;
|
|
18
|
+
export declare function yres<T, E>(result: NotPromise<Result<T, E>>): YRResult<T, E>;
|
|
19
|
+
export declare function yres<T, E>(result: Promise<Result<T, E>>): Promise<YRResult<T, E>>;
|
|
20
|
+
export declare function yresSync<T, E>(result: NotPromise<Result<T, E>>): YRResult<T, E>;
|
|
21
|
+
export declare function yresAsync<T, E>(promise: Promise<Result<T, E>>): Promise<YRResult<T, E>>;
|
|
17
22
|
export declare function yep<T>(result: Success<T>): YSuccess<T>;
|
|
23
|
+
export declare const YOK: Readonly<YSuccess<void>>;
|
|
24
|
+
export declare const YOK_NULL: Readonly<YSuccess<null>>;
|
|
25
|
+
export declare const YOK_TRUE: Readonly<YSuccess<boolean>>;
|
|
26
|
+
export declare const YOK_FALSE: Readonly<YSuccess<boolean>>;
|
|
27
|
+
export {};
|
package/lib/partial.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { isPromiseLike } from './utils/is-promise-like.js';
|
|
1
2
|
export function yok(value) {
|
|
2
3
|
return {
|
|
3
4
|
fails: false,
|
|
4
5
|
success: true,
|
|
5
|
-
value,
|
|
6
|
+
value: value,
|
|
6
7
|
error: undefined,
|
|
7
8
|
};
|
|
8
9
|
}
|
|
@@ -15,14 +16,20 @@ export function yerr(miscue) {
|
|
|
15
16
|
error: undefined,
|
|
16
17
|
};
|
|
17
18
|
}
|
|
18
|
-
export function
|
|
19
|
+
export function yres(result) {
|
|
20
|
+
if (isPromiseLike(result)) {
|
|
21
|
+
return result.then(yresSync);
|
|
22
|
+
}
|
|
23
|
+
return yresSync(result);
|
|
24
|
+
}
|
|
25
|
+
export function yresSync(result) {
|
|
19
26
|
if (result.fails) {
|
|
20
27
|
return result;
|
|
21
28
|
}
|
|
22
29
|
return yep(result);
|
|
23
30
|
}
|
|
24
|
-
export async function
|
|
25
|
-
return promise.then(
|
|
31
|
+
export async function yresAsync(promise) {
|
|
32
|
+
return promise.then(yresSync);
|
|
26
33
|
}
|
|
27
34
|
export function yep(result) {
|
|
28
35
|
return {
|
|
@@ -30,3 +37,7 @@ export function yep(result) {
|
|
|
30
37
|
success: true,
|
|
31
38
|
};
|
|
32
39
|
}
|
|
40
|
+
export const YOK = Object.freeze(yok());
|
|
41
|
+
export const YOK_NULL = Object.freeze(yok(null));
|
|
42
|
+
export const YOK_TRUE = Object.freeze(yok(true));
|
|
43
|
+
export const YOK_FALSE = Object.freeze(yok(false));
|
package/lib/result.d.ts
CHANGED
|
@@ -9,5 +9,10 @@ export type Failure<E> = {
|
|
|
9
9
|
error: E;
|
|
10
10
|
};
|
|
11
11
|
export type Result<T, E> = Success<T> | Failure<E>;
|
|
12
|
+
export declare function ok(): Success<void>;
|
|
12
13
|
export declare function ok<T>(value: T): Success<T>;
|
|
13
14
|
export declare function err<E>(error: E): Failure<E>;
|
|
15
|
+
export declare const OK: Readonly<Success<void>>;
|
|
16
|
+
export declare const OK_NULL: Readonly<Success<null>>;
|
|
17
|
+
export declare const OK_TRUE: Readonly<Success<boolean>>;
|
|
18
|
+
export declare const OK_FALSE: Readonly<Success<boolean>>;
|
package/lib/result.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export function ok(value) {
|
|
2
2
|
return {
|
|
3
3
|
fails: false,
|
|
4
|
-
value,
|
|
4
|
+
value: value,
|
|
5
5
|
error: undefined,
|
|
6
6
|
};
|
|
7
7
|
}
|
|
@@ -12,3 +12,7 @@ export function err(error) {
|
|
|
12
12
|
error,
|
|
13
13
|
};
|
|
14
14
|
}
|
|
15
|
+
export const OK = Object.freeze(ok());
|
|
16
|
+
export const OK_NULL = Object.freeze(ok(null));
|
|
17
|
+
export const OK_TRUE = Object.freeze(ok(true));
|
|
18
|
+
export const OK_FALSE = Object.freeze(ok(false));
|
package/lib/sync.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { xdeferSync as xdefer } from './defer.js';
|
|
2
|
+
export type { YResult, YSuccess, YFailure } from './partial.js';
|
|
3
|
+
export { yok, yerr, yresSync as yres, yep, YOK, YOK_NULL, YOK_TRUE, YOK_FALSE } from './partial.js';
|
|
4
|
+
export type { Success, Failure, Result } from './result.js';
|
|
5
|
+
export { ok, err, OK, OK_NULL, OK_TRUE, OK_FALSE } from './result.js';
|
|
6
|
+
export { stringifyError } from './stringify-error.js';
|
|
7
|
+
export { xtrySync as xtry } from './try.js';
|
package/lib/sync.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { xdeferSync as xdefer } from './defer.js';
|
|
2
|
+
export { yok, yerr, yresSync as yres, yep, YOK, YOK_NULL, YOK_TRUE, YOK_FALSE } from './partial.js';
|
|
3
|
+
export { ok, err, OK, OK_NULL, OK_TRUE, OK_FALSE } from './result.js';
|
|
4
|
+
export { stringifyError } from './stringify-error.js';
|
|
5
|
+
export { xtrySync as xtry } from './try.js';
|
package/lib/try.d.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
1
|
import { type Result } from './result.js';
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
import { type NonPromiseCallback, type PromiseCallback } from './utils/types.js';
|
|
3
|
+
type ErrorHandler<T> = (error: unknown) => T | undefined;
|
|
4
|
+
type VoidableResult<T, E> = E extends void ? Result<T, unknown> : Result<T, E>;
|
|
5
|
+
export declare function xtry<T, E = unknown>(func: NonPromiseCallback<T>, handler?: ErrorHandler<E>): VoidableResult<T, E>;
|
|
6
|
+
export declare function xtry<T, E = unknown>(func: PromiseCallback<T>, handler?: ErrorHandler<E>): Promise<VoidableResult<T, E>>;
|
|
7
|
+
export declare function xtrySync<T, E = unknown>(func: NonPromiseCallback<T>, handler?: ErrorHandler<E>): VoidableResult<T, E>;
|
|
8
|
+
export declare function xtryAsync<T, E = unknown>(func: PromiseCallback<T>, handler?: ErrorHandler<E>): Promise<VoidableResult<T, E>>;
|
|
9
|
+
export {};
|
package/lib/try.js
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
import { err, ok } from './result.js';
|
|
2
|
+
import { isPromiseLike } from './utils/is-promise-like.js';
|
|
2
3
|
export function xtry(func, handler) {
|
|
4
|
+
// eslint-disable-next-line @typescript-eslint/promise-function-async
|
|
5
|
+
const run = func instanceof Function ? func : () => func;
|
|
6
|
+
const handleError = (error) => {
|
|
7
|
+
if (handler) {
|
|
8
|
+
const newError = handler(error);
|
|
9
|
+
if (newError !== undefined) {
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
11
|
+
return err(newError);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return err(error);
|
|
15
|
+
};
|
|
16
|
+
const handleSuccess = (value) => ok(value);
|
|
17
|
+
try {
|
|
18
|
+
const value = run();
|
|
19
|
+
if (isPromiseLike(value)) {
|
|
20
|
+
return Promise.resolve(value).then(handleSuccess, handleError);
|
|
21
|
+
}
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
23
|
+
return ok(value);
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
27
|
+
return handleError(error);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export function xtrySync(func, handler) {
|
|
3
31
|
try {
|
|
4
32
|
const value = func();
|
|
5
33
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
@@ -17,7 +45,7 @@ export function xtry(func, handler) {
|
|
|
17
45
|
return err(error);
|
|
18
46
|
}
|
|
19
47
|
}
|
|
20
|
-
export async function
|
|
48
|
+
export async function xtryAsync(func, handler) {
|
|
21
49
|
try {
|
|
22
50
|
const value = await (func instanceof Promise ? func : Promise.resolve().then(func));
|
|
23
51
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type NotPromise<T> = Exclude<T, Promise<unknown>>;
|
|
2
|
+
export type NonPromiseCallback<T> = () => NotPromise<T>;
|
|
3
|
+
export type PromiseCallback<T> = (() => Promise<T>) | Promise<T>;
|
|
4
|
+
export type Callback<T> = NonPromiseCallback<T> | PromiseCallback<T>;
|
|
5
|
+
export type MaybePromise<T> = T | Promise<T>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zokugun/xtry",
|
|
3
3
|
"description": "simple try/catch wrapper returning Result",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.5.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Baptiste Augrain",
|
|
7
7
|
"email": "daiyam@zokugun.org"
|
|
@@ -16,41 +16,40 @@
|
|
|
16
16
|
"url": "https://github.com/zokugun/node-xtry/issues"
|
|
17
17
|
},
|
|
18
18
|
"type": "module",
|
|
19
|
+
"exports": {
|
|
20
|
+
".": "./lib/index.js",
|
|
21
|
+
"./async": "./lib/async.js",
|
|
22
|
+
"./sync": "./lib/sync.js"
|
|
23
|
+
},
|
|
19
24
|
"main": "lib/index.js",
|
|
20
25
|
"scripts": {
|
|
21
26
|
"commit": "cz",
|
|
22
27
|
"compile": "tsc -p src",
|
|
23
28
|
"lint": "xo",
|
|
29
|
+
"lint:fix": "xo --fix",
|
|
24
30
|
"prepare": "husky; fixpack || true",
|
|
25
31
|
"prepublishOnly": "npm run compile",
|
|
26
32
|
"release": "release-it",
|
|
27
|
-
"test": "
|
|
28
|
-
"
|
|
29
|
-
"test
|
|
30
|
-
"watch:src": "tsc -watch -p src",
|
|
31
|
-
"watch:test": "tsc-watch -p test"
|
|
33
|
+
"test": "vitest run",
|
|
34
|
+
"watch:source": "tsc-watch -p src",
|
|
35
|
+
"watch:test": "vitest"
|
|
32
36
|
},
|
|
33
37
|
"dependencies": {},
|
|
34
38
|
"devDependencies": {
|
|
35
39
|
"@commitlint/cli": "^19.7.1",
|
|
36
40
|
"@commitlint/config-conventional": "^19.7.1",
|
|
37
|
-
"@types/chai": "^5.0.1",
|
|
38
41
|
"@types/fs-extra": "^11.0.4",
|
|
39
|
-
"@types/mocha": "^10.0.10",
|
|
40
42
|
"@types/node": "^20.14.8",
|
|
41
|
-
"chai": "^5.2.0",
|
|
42
43
|
"commitizen": "^4.3.1",
|
|
43
|
-
"eslint-plugin-chai-friendly": "^1.0.1",
|
|
44
44
|
"fixpack": "^4.0.0",
|
|
45
|
-
"fs-extra": "^11.3.
|
|
46
|
-
"globby": "^
|
|
45
|
+
"fs-extra": "^11.3.3",
|
|
46
|
+
"globby": "^16.1.0",
|
|
47
47
|
"husky": "^9.1.7",
|
|
48
|
-
"lint-staged": "^
|
|
49
|
-
"mocha": "^11.1.0",
|
|
48
|
+
"lint-staged": "^16.1.4",
|
|
50
49
|
"release-it": "^18.1.2",
|
|
51
|
-
"source-map-support": "^0.5.21",
|
|
52
50
|
"tsc-watch": "^6.3.0",
|
|
53
51
|
"typescript": "^5.7.3",
|
|
52
|
+
"vitest": "^4.0.16",
|
|
54
53
|
"xo": "0.60.0"
|
|
55
54
|
},
|
|
56
55
|
"keywords": [
|