trycatchless 1.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/README.md +118 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +37 -0
- package/package.json +35 -0
package/README.md
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# tryit
|
|
2
|
+
|
|
3
|
+
> A tiny, type-safe utility for linear async error handling in TypeScript and JavaScript.
|
|
4
|
+
|
|
5
|
+
`tryit` simplifies error handling by converting Promises into a standardized `[error, result]` tuple, inspired by Go. It helps you write cleaner, more readable code by eliminating nested `try/catch` blocks and variable scoping issues.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- ๐ฆ **Zero dependencies**: Lightweight and fast.
|
|
10
|
+
- ๐ก๏ธ **Type-safe**: Full TypeScript support with generics.
|
|
11
|
+
- ๐งน **Clean Syntax**: Linear control flow without nesting.
|
|
12
|
+
- ๐ง **Error Normalization**: Automatically converts non-Error throws (like strings or objects) into proper `Error` objects, preserving the original data.
|
|
13
|
+
- ๐ **Safe**: Validates inputs and handles edge cases gracefully.
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install tryit
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
### Basic Usage
|
|
24
|
+
|
|
25
|
+
**Before:** Standard `try/catch` often leads to nested logic and "let" variables defined outside blocks.
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
let data;
|
|
29
|
+
try {
|
|
30
|
+
data = await fetchData();
|
|
31
|
+
} catch (err) {
|
|
32
|
+
console.error(err);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
console.log(data);
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**After:** With `tryit`, handle errors linearly.
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
import { tryit } from 'tryit';
|
|
42
|
+
|
|
43
|
+
const [err, data] = await tryit(fetchData());
|
|
44
|
+
|
|
45
|
+
if (err) {
|
|
46
|
+
console.error('Something went wrong:', err);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// TypeScript knows 'data' is safe and defined here
|
|
51
|
+
console.log(data);
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Advanced Usage
|
|
55
|
+
|
|
56
|
+
### TypeScript Generics
|
|
57
|
+
|
|
58
|
+
`tryit` infers the return type automatically, but you can also pass a generic type explicitly.
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
interface User {
|
|
62
|
+
id: number;
|
|
63
|
+
name: string;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const [err, user] = await tryit<User>(api.getUser(1));
|
|
67
|
+
|
|
68
|
+
if (!err) {
|
|
69
|
+
// 'user' is typed as User
|
|
70
|
+
console.log(user.name);
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Handling Non-Standard Errors
|
|
75
|
+
|
|
76
|
+
Some libraries throw strings or plain objects instead of proper `Error` instances. `tryit` handles this by normalizing them into an `Error` object. The original thrown value is preserved as a JSON string in the `.meta` property.
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
// Suppose a library does this: Promise.reject({ code: "UNAUTH", msg: "Stop!" })
|
|
80
|
+
|
|
81
|
+
const [err, data] = await tryit(riskyOperation());
|
|
82
|
+
|
|
83
|
+
if (err) {
|
|
84
|
+
console.error(err.message); // "[object Object]"
|
|
85
|
+
|
|
86
|
+
// Access the original payload via .meta
|
|
87
|
+
if ((err as any).meta) {
|
|
88
|
+
const raw = JSON.parse((err as any).meta);
|
|
89
|
+
console.log(raw.code); // "UNAUTH"
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Invalid Inputs
|
|
95
|
+
|
|
96
|
+
If you accidentally pass something that isn't a Promise (like `null` or a string) to `tryit`, it won't crash. It resolves safely with an error.
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
const [err, data] = await tryit(null as any);
|
|
100
|
+
// err: Error("Argument must be a Promise or thenable")
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## API
|
|
104
|
+
|
|
105
|
+
### `tryit<T>(promise: Promise<T>)`
|
|
106
|
+
|
|
107
|
+
Wraps a Promise and returns a tuple.
|
|
108
|
+
|
|
109
|
+
- **Parameters**:
|
|
110
|
+
- `promise`: A `Promise` or thenable object to resolve.
|
|
111
|
+
|
|
112
|
+
- **Returns**: `Promise<[Error, null] | [null, T]>`
|
|
113
|
+
- Index `0`: An `Error` object if failed, otherwise `null`.
|
|
114
|
+
- Index `1`: The result data `T` if successful, otherwise `null`.
|
|
115
|
+
|
|
116
|
+
## License
|
|
117
|
+
|
|
118
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents the result tuple of the tryit function.
|
|
3
|
+
* Index 0 is the Error (or null if successful).
|
|
4
|
+
* Index 1 is the Result (or null if failed).
|
|
5
|
+
*/
|
|
6
|
+
export type TryitResult<T> = [Error, null] | [null, T];
|
|
7
|
+
/**
|
|
8
|
+
* A functional utility that wraps a Promise in a try-catch block and returns a standardized
|
|
9
|
+
* tuple of [Error, Result].
|
|
10
|
+
*
|
|
11
|
+
* - Checks if input is a valid Promise or thenable.
|
|
12
|
+
* - Catches all errors, ensuring the function never throws synchronously.
|
|
13
|
+
* - Normalizes non-Error throws into Error objects, preserving metadata in `error.meta` as a JSON string.
|
|
14
|
+
*
|
|
15
|
+
* @template T The type of the value resolved by the promise.
|
|
16
|
+
* @param {Promise<T>} promise The promise to execute.
|
|
17
|
+
* @returns {Promise<TryitResult<T>>} A promise resolving to [Error, null] or [null, Result].
|
|
18
|
+
*/
|
|
19
|
+
export declare function tryit<T>(promise: Promise<T>): Promise<TryitResult<T>>;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.tryit = tryit;
|
|
4
|
+
/**
|
|
5
|
+
* A functional utility that wraps a Promise in a try-catch block and returns a standardized
|
|
6
|
+
* tuple of [Error, Result].
|
|
7
|
+
*
|
|
8
|
+
* - Checks if input is a valid Promise or thenable.
|
|
9
|
+
* - Catches all errors, ensuring the function never throws synchronously.
|
|
10
|
+
* - Normalizes non-Error throws into Error objects, preserving metadata in `error.meta` as a JSON string.
|
|
11
|
+
*
|
|
12
|
+
* @template T The type of the value resolved by the promise.
|
|
13
|
+
* @param {Promise<T>} promise The promise to execute.
|
|
14
|
+
* @returns {Promise<TryitResult<T>>} A promise resolving to [Error, null] or [null, Result].
|
|
15
|
+
*/
|
|
16
|
+
async function tryit(promise) {
|
|
17
|
+
if (!promise || typeof promise.then !== 'function') {
|
|
18
|
+
return [new Error("Argument must be a Promise or thenable"), null];
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
const data = await promise;
|
|
22
|
+
return [null, data];
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
if (err instanceof Error) {
|
|
26
|
+
return [err, null];
|
|
27
|
+
}
|
|
28
|
+
const error = new Error(String(err));
|
|
29
|
+
try {
|
|
30
|
+
error.meta = JSON.stringify(err);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
// Ignore serialization errors (e.g., circular structures)
|
|
34
|
+
}
|
|
35
|
+
return [error, null];
|
|
36
|
+
}
|
|
37
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "trycatchless",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A tiny, functional try-catch wrapper for promises that returns a [error, data] tuple.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"test": "ts-node test/index.test.ts",
|
|
13
|
+
"prepublishOnly": "npm run build"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"promise",
|
|
17
|
+
"async",
|
|
18
|
+
"await",
|
|
19
|
+
"try",
|
|
20
|
+
"catch",
|
|
21
|
+
"error-handling",
|
|
22
|
+
"functional",
|
|
23
|
+
"utility"
|
|
24
|
+
],
|
|
25
|
+
"author": "",
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"typescript": "^5.0.0",
|
|
29
|
+
"ts-node": "^10.9.0",
|
|
30
|
+
"@types/node": "^20.0.0"
|
|
31
|
+
},
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=14"
|
|
34
|
+
}
|
|
35
|
+
}
|