
Security News
Happy Birthday, Shai-Hulud
It has been one year since Shai-Hulud made its first appearance on npm.
@crashbytes/effect
Advanced tools
Result type, retry, timeout, and structured errors for TypeScript. Zero dependencies.
Result type, retry, timeout, and structured errors for TypeScript. Zero dependencies.
npm install @crashbytes/effect
Represent success and failure without throwing exceptions.
import { ok, err, isOk, map, unwrap, tryCatch, tryCatchAsync } from '@crashbytes/effect'
import type { Result } from '@crashbytes/effect'
// Create results
const success = ok(42) // { ok: true, value: 42 }
const failure = err('fail') // { ok: false, error: 'fail' }
// Type guards
if (isOk(success)) {
console.log(success.value) // 42
}
// Transform values
const doubled = map(ok(21), x => x * 2) // ok(42)
// Unwrap with a default
import { unwrapOr } from '@crashbytes/effect'
const value = unwrapOr(failure, 0) // 0
// Wrap throwing functions
const result = tryCatch(() => JSON.parse('{"a":1}'))
// Wrap async functions
const asyncResult = await tryCatchAsync(() => fetch('/api/data').then(r => r.json()))
Retry async operations with configurable backoff strategies.
import { retry } from '@crashbytes/effect'
const data = await retry(
() => fetch('/api/data').then(r => r.json()),
{
maxAttempts: 3,
delayMs: 1000,
backoff: 'exponential', // 'fixed' | 'linear' | 'exponential'
onRetry: (error, attempt) => {
console.log(`Attempt ${attempt} failed:`, error)
},
}
)
Wrap promises with a timeout.
import { timeout, TimeoutError } from '@crashbytes/effect'
try {
const result = await timeout(
() => fetch('/api/slow-endpoint'),
{ ms: 5000, message: 'API call took too long' }
)
} catch (e) {
if (e instanceof TimeoutError) {
console.log('Timed out!')
}
}
Create errors with machine-readable codes and contextual metadata.
import { AppError, isAppError } from '@crashbytes/effect'
const error = new AppError({
code: 'USER_NOT_FOUND',
message: 'User with ID 123 was not found',
context: { userId: '123' },
})
// Serialize for logging or API responses
console.log(JSON.stringify(error.toJSON()))
// Type guard
if (isAppError(error)) {
console.log(error.code) // 'USER_NOT_FOUND'
}
| Function | Description |
|---|---|
ok(value) | Create a success result |
err(error) | Create a failure result |
isOk(result) | Type guard for success |
isErr(result) | Type guard for failure |
map(result, fn) | Transform the success value |
mapErr(result, fn) | Transform the error value |
flatMap(result, fn) | Chain result-returning functions |
unwrap(result) | Extract value or throw error |
unwrapOr(result, default) | Extract value or return default |
tryCatch(fn) | Wrap a sync function in a Result |
tryCatchAsync(fn) | Wrap an async function in a Result |
| Function | Description |
|---|---|
retry(fn, options) | Retry an async function with backoff |
RetryOptions:
maxAttempts - Maximum number of attemptsdelayMs - Base delay in milliseconds (default: 100)backoff - Backoff strategy: 'fixed', 'linear', or 'exponential' (default: 'fixed')onRetry - Callback invoked on each retry with the error and attempt number| Function / Class | Description |
|---|---|
timeout(fn, options) | Wrap a promise with a timeout |
TimeoutError | Error thrown when timeout is exceeded |
TimeoutOptions:
ms - Timeout in millisecondsmessage - Custom error message| Function / Class | Description |
|---|---|
AppError | Error class with code, message, cause, and context |
isAppError(value) | Type guard for AppError |
type Ok<T> = { readonly ok: true; readonly value: T }
type Err<E> = { readonly ok: false; readonly error: E }
type Result<T, E = Error> = Ok<T> | Err<E>
interface RetryOptions { ... }
interface TimeoutOptions { ... }
interface StructuredError { ... }
MIT
FAQs
Result type, retry, timeout, and structured errors for TypeScript. Zero dependencies.
The npm package @crashbytes/effect receives a total of 20 weekly downloads. As such, @crashbytes/effect popularity was classified as not popular.
We found that @crashbytes/effect demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Security News
It has been one year since Shai-Hulud made its first appearance on npm.

Research
/Security News
Operators behind PolinRider used a compromised GitHub account to plant malware in four development versions of a Packagist package with 700,000+ downloads.

Security News
GitHub Actions now supports cache-mode, a least-privilege control on the Actions cache aimed at the cache poisoning technique behind recent compromises.