await-me 1.0.3
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 +220 -0
- package/example.cjs +54 -0
- package/example.js +54 -0
- package/package.json +33 -0
- package/src/index.ts +34 -0
- package/tsconfig.json +15 -0
- package/tsup.config.ts +21 -0
package/README.md
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# š”ļø await-me
|
|
2
|
+
|
|
3
|
+
**Production-ready, zero-dependency async error handling for JavaScript**
|
|
4
|
+
The pre-bundled, browser & legacy-Node friendly distribution of [**await-me-ts**](https://www.npmjs.com/package/await-me-ts).
|
|
5
|
+
|
|
6
|
+
Stop writing repetitive `try/catch`.
|
|
7
|
+
Write clean, linear code that handles errors declaratively ā works everywhere modern JavaScript runs.
|
|
8
|
+
|
|
9
|
+
### For TypeScript developers ā important note
|
|
10
|
+
|
|
11
|
+
This package (`await-me`) is the transpiled, bundled version optimized for broad compatibility (Node ā„7, browsers, etc.).
|
|
12
|
+
|
|
13
|
+
If you're using **modern TypeScript** (especially Node.js 22+ with `--experimental-strip-types` or a proper build setup), prefer the original source package:
|
|
14
|
+
|
|
15
|
+
ā [**await-me-ts** ā full type safety & generics](https://www.npmjs.com/package/await-me-ts)
|
|
16
|
+
|
|
17
|
+
**Why prefer await-me-ts in TypeScript?**
|
|
18
|
+
|
|
19
|
+
- Proper generics: `valueOf<User>() ā User | false`
|
|
20
|
+
- Better inference & autocompletion
|
|
21
|
+
- No `any`/`unknown` surprises
|
|
22
|
+
|
|
23
|
+
In `await-me` (this package), types are looser ā still fully functional, just less strict.
|
|
24
|
+
|
|
25
|
+
### Quick TypeScript vs JavaScript comparison
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
// With await-me-ts (recommended for TS)
|
|
29
|
+
const user = await valueOf<User>(
|
|
30
|
+
fetchUser(id),
|
|
31
|
+
"User not found"
|
|
32
|
+
); // ā User | false
|
|
33
|
+
|
|
34
|
+
if (!user) return;
|
|
35
|
+
// user: User (narrowed)
|
|
36
|
+
|
|
37
|
+
// With await-me (this package)
|
|
38
|
+
const user = await valueOf(
|
|
39
|
+
fetchUser(id),
|
|
40
|
+
"User not found"
|
|
41
|
+
); // ā any | false
|
|
42
|
+
|
|
43
|
+
if (!user) return;
|
|
44
|
+
// user: any
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Quick Start ā The Most Popular Helpers
|
|
48
|
+
|
|
49
|
+
```js
|
|
50
|
+
// ESM
|
|
51
|
+
import { valueOf, isSuccess, toResult, create, STYLES } from 'await-me';
|
|
52
|
+
|
|
53
|
+
// CommonJS
|
|
54
|
+
const { valueOf, isSuccess, toResult, create, STYLES } = require('await-me');
|
|
55
|
+
|
|
56
|
+
// Browser global
|
|
57
|
+
<script src="https://cdn.jsdelivr.net/npm/await-me/dist/index.global.js"></script>
|
|
58
|
+
// Then: const { valueOf } = WaitForMe;
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### The "Big Three" Helpers ā with TS hints
|
|
62
|
+
|
|
63
|
+
| Helper | Success return (JS) | Success return (TS with await-me-ts) | Failure return | Best for |
|
|
64
|
+
|--------------|----------------------------------|--------------------------------------|------------------------|--------------------------------------|
|
|
65
|
+
| `valueOf` | value | `T` | `false` | Most data fetching |
|
|
66
|
+
| `isSuccess` | `true` | `true` | `false` | Mutations, status checks |
|
|
67
|
+
| `toResult` | `{ success: true, data: value }` | `{ success: true, data: T }` | `{ success: false, ... }` | Falsy-success cases |
|
|
68
|
+
|
|
69
|
+
### Real-world examples (JS + more TS snippets)
|
|
70
|
+
|
|
71
|
+
**1. Data fetch ā most common pattern**
|
|
72
|
+
|
|
73
|
+
```js
|
|
74
|
+
// JavaScript
|
|
75
|
+
const profile = await valueOf(
|
|
76
|
+
fetch(`/api/users/${userId}`).then(r => r.json()),
|
|
77
|
+
"Could not load profile"
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
if (!profile) {
|
|
81
|
+
showError("Profile not available");
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
// TypeScript (with await-me-ts)
|
|
88
|
+
interface UserProfile { id: number; name: string; email: string }
|
|
89
|
+
|
|
90
|
+
const profile = await valueOf<UserProfile>(
|
|
91
|
+
fetch(`/api/users/${userId}`).then(r => r.json()),
|
|
92
|
+
"Could not load profile"
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
if (!profile) return showError("Profile not available");
|
|
96
|
+
// profile: UserProfile (type safe)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**2. Mutation with feedback**
|
|
100
|
+
|
|
101
|
+
```js
|
|
102
|
+
// JavaScript
|
|
103
|
+
if (await isSuccess(
|
|
104
|
+
fetch('/api/cart', {
|
|
105
|
+
method: 'POST',
|
|
106
|
+
body: JSON.stringify(cartItems)
|
|
107
|
+
}),
|
|
108
|
+
{ success: "Added to cart!", error: "Update failed" }
|
|
109
|
+
)) {
|
|
110
|
+
updateCartCount();
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
// TypeScript (with await-me-ts)
|
|
116
|
+
const success = await isSuccess(
|
|
117
|
+
updateCart(cartItems),
|
|
118
|
+
{ success: "Added to cart!" }
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
if (success) {
|
|
122
|
+
// TypeScript knows this branch only runs on success
|
|
123
|
+
updateCartCount();
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
**3. Safe handling of falsy values**
|
|
128
|
+
|
|
129
|
+
```js
|
|
130
|
+
// JavaScript
|
|
131
|
+
const result = await toResult(fetch('/api/flags').then(r => r.json()));
|
|
132
|
+
|
|
133
|
+
if (!result.success) {
|
|
134
|
+
console.warn("Flags unavailable", result.error);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const darkMode = result.data?.darkMode ?? false;
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
```ts
|
|
142
|
+
// TypeScript (with await-me-ts)
|
|
143
|
+
interface Flags { darkMode: boolean; betaFeatures: boolean }
|
|
144
|
+
|
|
145
|
+
const result = await toResult<Flags>(fetch('/api/flags').then(r => r.json()));
|
|
146
|
+
|
|
147
|
+
if (!result.success) return;
|
|
148
|
+
|
|
149
|
+
const darkMode: boolean = result.data.darkMode ?? false;
|
|
150
|
+
// Full type safety on data
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
**4. Custom handler with conditional shielding**
|
|
154
|
+
|
|
155
|
+
```ts
|
|
156
|
+
// TypeScript (with await-me-ts)
|
|
157
|
+
const safeApi = createAsyncHandler({
|
|
158
|
+
returnStyle: RETURN_STYLES.FALSE_STYLE,
|
|
159
|
+
conditionalHandlerChain: [
|
|
160
|
+
{
|
|
161
|
+
ifTrue: (e: { status?: number }) => e.status === 404,
|
|
162
|
+
doIt: () => console.log("Not found ā silent")
|
|
163
|
+
}
|
|
164
|
+
]
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
// JavaScript version (this package)
|
|
168
|
+
const safeApi = create({
|
|
169
|
+
returnStyle: STYLES.FALSE_STYLE,
|
|
170
|
+
conditionalHandlerChain: [
|
|
171
|
+
{ ifTrue: e => e?.status === 404, doIt: () => {} }
|
|
172
|
+
]
|
|
173
|
+
});
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Go-style example (popular among backend developers)
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
// TypeScript (await-me-ts)
|
|
180
|
+
const [err, user] = await createAsyncHandler({ returnStyle: RETURN_STYLES.GO_STYLE })(
|
|
181
|
+
fetchUser(userId)
|
|
182
|
+
); // ā [Error | null, User | null]
|
|
183
|
+
|
|
184
|
+
if (err) {
|
|
185
|
+
if (err.code === 404) return showNotFound();
|
|
186
|
+
// err: Error (type safe)
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
```js
|
|
191
|
+
// JavaScript (this package)
|
|
192
|
+
const [err, user] = await create({ returnStyle: STYLES.GO_STYLE })(fetchUser(userId));
|
|
193
|
+
|
|
194
|
+
if (err) {
|
|
195
|
+
// err is any
|
|
196
|
+
if (err?.code === 404) return showNotFound();
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Installation
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
npm install await-me
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
CDN:
|
|
207
|
+
|
|
208
|
+
```html
|
|
209
|
+
<script src="https://cdn.jsdelivr.net/npm/await-me@latest/dist/index.global.js"></script>
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Final note for TypeScript users
|
|
213
|
+
|
|
214
|
+
If you want the **best possible developer experience** with full generics, inference, and zero `any` surprises ā install `await-me-ts` instead:
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
npm install await-me-ts
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Happy error shielding in both JS and TS! š”ļøāØ
|
package/example.cjs
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
const { WaitForMe } = require('./dist/index.cjs');
|
|
2
|
+
|
|
3
|
+
// --- Mock Utilities ---
|
|
4
|
+
const mockFetch = (shouldSucceed, data, errorCode) =>
|
|
5
|
+
new Promise((resolve, reject) => {
|
|
6
|
+
setTimeout(() => {
|
|
7
|
+
if (shouldSucceed) {
|
|
8
|
+
resolve(data);
|
|
9
|
+
} else {
|
|
10
|
+
const error = new Error("Request Failed");
|
|
11
|
+
error.code = errorCode || 500;
|
|
12
|
+
reject(error);
|
|
13
|
+
}
|
|
14
|
+
}, 50);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
async function runAdHocTest() {
|
|
18
|
+
console.log("š Starting Ad-Hoc Test for await-me Bundle\n");
|
|
19
|
+
|
|
20
|
+
// 1. Test the Barrel Class Constants
|
|
21
|
+
console.log(`Checking STYLES: ${Object.keys(WaitForMe.STYLES).join(', ')}`);
|
|
22
|
+
|
|
23
|
+
// 2. Test the "Safe" Handler (FALSE_STYLE)
|
|
24
|
+
const safeFetcher = WaitForMe.create({
|
|
25
|
+
returnStyle: WaitForMe.STYLES.FALSE_STYLE,
|
|
26
|
+
defaultHandler: (e) => console.log(`[Shield] Caught expected error: ${e.message}`)
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
console.log("\nScenario A: Successful Data Fetch");
|
|
30
|
+
const data = await safeFetcher(mockFetch(true, { id: 42, name: "Gemini" }));
|
|
31
|
+
console.log(`Result: ${JSON.stringify(data)} (Success expected)`);
|
|
32
|
+
|
|
33
|
+
console.log("\nScenario B: Shielded Error (500)");
|
|
34
|
+
const failedResult = await safeFetcher(mockFetch(false));
|
|
35
|
+
console.log(`Result: ${failedResult} (Boolean 'false' expected)`);
|
|
36
|
+
|
|
37
|
+
// 3. Test the Derivative 'valueOf'
|
|
38
|
+
console.log("\nScenario C: Using valueOf Derivative");
|
|
39
|
+
const value = await WaitForMe.valueOf(mockFetch(true, "Direct Value"));
|
|
40
|
+
console.log(`Value: ${value}`);
|
|
41
|
+
|
|
42
|
+
// 4. Test Go-Style handling via Barrel
|
|
43
|
+
const goHandler = WaitForMe.create({ returnStyle: WaitForMe.STYLES.GO_STYLE });
|
|
44
|
+
const [err, result] = await goHandler(mockFetch(false, null, 401));
|
|
45
|
+
|
|
46
|
+
if (err) {
|
|
47
|
+
console.log(`\nScenario D: Go-Style Error Check`);
|
|
48
|
+
console.log(`Error Code: ${err.code} - Handled successfully without try/catch.`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
console.log("\nā
Ad-Hoc Test Completed.");
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
runAdHocTest().catch(console.error);
|
package/example.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { WaitForMe } from './dist/index.js';
|
|
2
|
+
|
|
3
|
+
// --- Mock Utilities ---
|
|
4
|
+
const mockFetch = (shouldSucceed, data, errorCode) =>
|
|
5
|
+
new Promise((resolve, reject) => {
|
|
6
|
+
setTimeout(() => {
|
|
7
|
+
if (shouldSucceed) {
|
|
8
|
+
resolve(data);
|
|
9
|
+
} else {
|
|
10
|
+
const error = new Error("Request Failed");
|
|
11
|
+
error.code = errorCode || 500;
|
|
12
|
+
reject(error);
|
|
13
|
+
}
|
|
14
|
+
}, 50);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
async function runAdHocTest() {
|
|
18
|
+
console.log("š Starting Ad-Hoc Test for await-me Bundle\n");
|
|
19
|
+
|
|
20
|
+
// 1. Test the Barrel Class Constants
|
|
21
|
+
console.log(`Checking STYLES: ${Object.keys(WaitForMe.STYLES).join(', ')}`);
|
|
22
|
+
|
|
23
|
+
// 2. Test the "Safe" Handler (FALSE_STYLE)
|
|
24
|
+
const safeFetcher = WaitForMe.create({
|
|
25
|
+
returnStyle: WaitForMe.STYLES.FALSE_STYLE,
|
|
26
|
+
defaultHandler: (e) => console.log(`[Shield] Caught expected error: ${e.message}`)
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
console.log("\nScenario A: Successful Data Fetch");
|
|
30
|
+
const data = await safeFetcher(mockFetch(true, { id: 42, name: "Gemini" }));
|
|
31
|
+
console.log(`Result: ${JSON.stringify(data)} (Success expected)`);
|
|
32
|
+
|
|
33
|
+
console.log("\nScenario B: Shielded Error (500)");
|
|
34
|
+
const failedResult = await safeFetcher(mockFetch(false));
|
|
35
|
+
console.log(`Result: ${failedResult} (Boolean 'false' expected)`);
|
|
36
|
+
|
|
37
|
+
// 3. Test the Derivative 'valueOf'
|
|
38
|
+
console.log("\nScenario C: Using valueOf Derivative");
|
|
39
|
+
const value = await WaitForMe.valueOf(mockFetch(true, "Direct Value"));
|
|
40
|
+
console.log(`Value: ${value}`);
|
|
41
|
+
|
|
42
|
+
// 4. Test Go-Style handling via Barrel
|
|
43
|
+
const goHandler = WaitForMe.create({ returnStyle: WaitForMe.STYLES.GO_STYLE });
|
|
44
|
+
const [err, result] = await goHandler(mockFetch(false, null, 401));
|
|
45
|
+
|
|
46
|
+
if (err) {
|
|
47
|
+
console.log(`\nScenario D: Go-Style Error Check`);
|
|
48
|
+
console.log(`Error Code: ${err.code} - Handled successfully without try/catch.`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
console.log("\nā
Ad-Hoc Test Completed.");
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
runAdHocTest().catch(console.error);
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "await-me",
|
|
3
|
+
"version": "1.0.3",
|
|
4
|
+
"description": "Browser-compatible, ES2015 target distribution of await-me-ts. Supports Node.js 7+.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"browser": "./dist/index.global.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"engines": {
|
|
11
|
+
"node": ">=7.0.0"
|
|
12
|
+
},
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"import": "./dist/index.js",
|
|
17
|
+
"require": "./dist/index.cjs",
|
|
18
|
+
"script": "./dist/index.global.js"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsup",
|
|
23
|
+
"release": "npm run build && npm version patch && npm publish"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"await-me-ts": "^1.0.1"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"tsup": "^8.5.1",
|
|
30
|
+
"typescript": "^5.9.3",
|
|
31
|
+
"@types/node": "^22.10.2"
|
|
32
|
+
}
|
|
33
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createAsyncHandler,
|
|
3
|
+
RETURN_STYLES,
|
|
4
|
+
valueOf,
|
|
5
|
+
isSuccess,
|
|
6
|
+
toResult
|
|
7
|
+
} from 'await-me-ts';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Symmetric Reflection:
|
|
11
|
+
* We export the exact functions from the core engine.
|
|
12
|
+
*/
|
|
13
|
+
export {
|
|
14
|
+
createAsyncHandler,
|
|
15
|
+
valueOf,
|
|
16
|
+
isSuccess,
|
|
17
|
+
toResult,
|
|
18
|
+
RETURN_STYLES as STYLES // Alias for convenience, while keeping core name
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Optional: The Barrel Namespace
|
|
23
|
+
* Provides the same symmetry for those who prefer dot-notation.
|
|
24
|
+
*/
|
|
25
|
+
export const WaitForMe = {
|
|
26
|
+
create: createAsyncHandler,
|
|
27
|
+
valueOf,
|
|
28
|
+
isSuccess,
|
|
29
|
+
toResult,
|
|
30
|
+
STYLES: RETURN_STYLES
|
|
31
|
+
} as const;
|
|
32
|
+
|
|
33
|
+
// Re-export all types from core for full IDE support
|
|
34
|
+
export * from 'await-me-ts';
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "es2022",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"outDir": "dist",
|
|
7
|
+
"esModuleInterop": true,
|
|
8
|
+
"forceConsistentCasingInFileNames": true,
|
|
9
|
+
"strict": false,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"declaration": true
|
|
12
|
+
},
|
|
13
|
+
"include": ["src/**/*"],
|
|
14
|
+
"exclude": ["node_modules", "dist" ,"public"]
|
|
15
|
+
}
|
package/tsup.config.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { defineConfig } from 'tsup';
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
entry: {
|
|
5
|
+
'index': 'src/index.ts'
|
|
6
|
+
},
|
|
7
|
+
// Added 'iife' for direct <script> tag support in browsers
|
|
8
|
+
format: ['cjs', 'esm', 'iife'],
|
|
9
|
+
globalName: 'WaitForMeJS',
|
|
10
|
+
dts: true,
|
|
11
|
+
splitting: false,
|
|
12
|
+
sourcemap: true,
|
|
13
|
+
clean: true,
|
|
14
|
+
outDir: 'dist',
|
|
15
|
+
// Lowered target to ES2015 for maximum compatibility
|
|
16
|
+
target: 'es2015',
|
|
17
|
+
minify: true,
|
|
18
|
+
bundle: true,
|
|
19
|
+
noExternal: ['await-me-ts'],
|
|
20
|
+
skipNodeModulesBundle: false,
|
|
21
|
+
});
|