Eliminate messy try/catch blocks and temporary scope variables. Write cleaner, fully-typed asynchronous code from top to bottom.
Everything you need to keep your backend code clean, safe, and robust.
Extremely lightweight with zero external bloat. Perfect for serverless functions, edge workers, and high-performance apps.
Built from the ground up for TypeScript. Result types are automatically inferred straight from your promises.
No more declaring let data; outside scopes just to access it later. Keep your data flow immutable and clean.
Choose your preferred package manager to install safe-await-tuple:
Instead of wrapping your logic in nested try/catch blocks, pass your promise directly to safe():
import { safe } from 'safe-await-tuple';
async function handleLogin(req, res) {
// Returns a tuple: [error, result]
const [err, user] = await safe(database.findUserByEmail(req.body.email));
if (err) {
return res.status(500).json({ error: err.message });
}
// user is fully typed and ready
return res.status(200).json({ success: true, user });
}
See how safe-await-tuple transforms your daily code architecture across all our current and upcoming versions.
Cleanly handle nested async operations without scope pollution.
const [err, response] = await safe(
fetch('https://api.example.com/data')
);
if (err) {
console.error('Network request failed:', err.message);
return fallbackData;
}
const [jsonErr, data] = await safe(response.json());
if (jsonErr) {
console.error('Failed to parse JSON');
return null;
}
Perfect for native Node.js async operations.
import { promises as fs } from 'fs';
const [err, fileContent] = await safe(fs.readFile('/path/to/config.json', 'utf-8'));
if (err) {
throw new Error(`Configuration missing: ${err.message}`);
}
const config = JSON.parse(fileContent);
Stop crashing your app with faulty JSON.parse(). The safeSync() utility brings tuple error handling to synchronous blocks.
import { safeSync } from 'safe-await-tuple';
function parseConfig(rawJson: string) {
const [error, config] = safeSync(() => JSON.parse(rawJson));
if (error) {
console.error("Invalid JSON:", error.message);
return null;
}
return config;
}
Bulletproof Promise.all. Run multiple async operations concurrently without fear of one rejection crashing the whole batch.
import { safeAll } from 'safe-await-tuple';
// Returns an array of tuples so you can handle partial successes
const results = await safeAll([
fetchUser(1),
fetchUser(2)
]);
const successfulUsers = results
.filter(([err]) => !err)
.map(([_, user]) => user);
Go beyond standard Error objects. Pass custom error types via generics so your editor knows exactly what properties are available.
import { safe } from 'safe-await-tuple';
// 'err' is strongly typed as HttpError, not just Error
const [err, data] = await safe(apiCall());
if (err) {
console.log(err.statusCode); // Typed and auto-completed
}
Set up global error interceptors to automatically push caught errors to Sentry, Datadog, or custom logging dashboards.
import { configureSafe } from 'safe-await-tuple';
// Configure once at app startup
configureSafe({
onError: (err) => Sentry.captureException(err)
});
// Automatically logs to Sentry in the background if it fails
const [err, data] = await safe(riskyOperation());
Designed with strict type guards out of the box. No extra configuration needed in your tsconfig.json other than standard strict settings.