import { AbortableContext, AbortableWrapper, IdentityWrapper } from './abortable'; import { RetryStrategyName, AsyncRetryDelayFn } from './types'; /** Options for retry wrapper */ export interface RetryOptions { /** Number of retry attempts (default: 3) */ retries?: number; /** Delay between retries: ms, strategy name, or custom function */ delay?: number | RetryStrategyName | AsyncRetryDelayFn; } /** Options for cache wrapper */ export interface CacheOptions { /** Time-to-live in milliseconds */ ttl: number; /** Custom key function (default: JSON.stringify of args) */ key?: (...args: any[]) => string; } /** Options for rate limit wrapper */ export interface RateLimitOptions { /** Maximum number of calls allowed in the window */ limit: number; /** Time window in milliseconds */ window: number; } /** Options for circuit breaker wrapper */ export interface CircuitBreakerOptions { /** Number of failures before opening circuit (default: 5) */ threshold?: number; /** Time in ms before attempting to close circuit (default: 30000) */ resetTimeout?: number; } /** * Lifecycle callbacks returned from observe's onStart handler. * * @template TResult - The result type of the observed function */ export type ObserveCallbacks = { /** Called when the function is aborted via AbortController */ onAbort?: () => void; /** Called when the function completes successfully */ onSuccess?: (result: TResult) => void; /** Called when the function throws an error (error is re-thrown after) */ onError?: (error: unknown) => void; /** Called after completion, regardless of success or error (like finally) */ onDone?: VoidFunction; }; /** * Callback invoked when the observed function starts execution. * Can return lifecycle callbacks for success/error/abort handling. * * @template TArgs - The argument types of the observed function * @template TResult - The result type of the observed function */ export type ObserveOnStart = (ctx: AbortableContext, ...args: TArgs) => void | ObserveCallbacks; /** * Retry on failure. * * @example * ```ts * // Retry 3 times with backoff delay * fn.use(retry(3)) * * // Retry 3 times with named strategy * fn.use(retry("linear")) * * // Retry 5 times with linear delay * fn.use(retry({ retries: 5, delay: "linear" })) * * // Custom delay function * fn.use(retry({ retries: 3, delay: (attempt) => attempt * 1000 })) * ``` */ export declare function retry(retries?: number): IdentityWrapper; export declare function retry(strategy: RetryStrategyName): IdentityWrapper; export declare function retry(options: RetryOptions): IdentityWrapper; /** * Catch and handle errors with a callback (without swallowing them). * * @example * ```ts * fn.use(catchError((error) => { * console.error("Failed:", error.message); * analytics.track("error", { message: error.message }); * })) * ``` */ export declare function catchError(callback: (error: Error, ctx: AbortableContext, ...args: any[]) => void): IdentityWrapper; /** * Add timeout to abort after specified milliseconds. * * @example * ```ts * // Abort after 5 seconds * fn.use(timeout(5000)) * * // With custom error message * fn.use(timeout(5000, "Request timed out")) * ``` */ export declare function timeout(ms: number, message?: string): IdentityWrapper; /** * Log function calls for debugging. * * Behavior varies by environment: * - **Development**: Always logs using `devLogger` (default: console) * - **Production**: Only logs if `proLogger` is provided * - `proLogger: true` → use `devLogger` in prod too * - `proLogger: customLogger` → use custom logger in prod * - `proLogger: undefined` → no logging in prod (no-op wrapper) * * @param name - Label for log messages (e.g., function name) * @param devLogger - Logger for development (default: console) * @param proLogger - Logger for production, or `true` to use devLogger * * @example * ```ts * // Basic: logs in dev only * fn.use(logging("getUser")) * // [getUser] calling with: ["123"] * // [getUser] success: { id: "123", name: "John" } * // [getUser] error: Error: Not found * * // Log in prod too (same logger) * fn.use(logging("getUser", console, true)) * * // Custom prod logger (e.g., error tracking service) * fn.use(logging("getUser", console, Sentry)) * ``` */ export declare function logging(name: string, devLogger?: Pick, proLogger?: Pick | boolean): IdentityWrapper; /** * Debounce calls - only execute after delay with no new calls. * * Note: This creates a shared timer, so multiple calls to the same * debounced function will share the debounce state. * * @example * ```ts * // Debounce search - only execute 300ms after last keystroke * const debouncedSearch = search.use(debounce(300)); * ``` */ export declare function debounce(ms: number): IdentityWrapper; /** * Throttle calls - only execute once per time window. * * @example * ```ts * // Throttle to max once per second * const throttledSave = save.use(throttle(1000)); * ``` */ export declare function throttle(ms: number): IdentityWrapper; /** * Return a fallback value on error instead of throwing. * * @example * ```ts * // Return null on error * fn.use(fallback(null)) * * // Return empty array on error * fn.use(fallback([])) * * // Dynamic fallback based on error * fn.use(fallback((error) => ({ error: error.message }))) * ``` */ export declare function fallback(value: T | ((error: Error, ctx: AbortableContext, ...args: any[]) => T)): IdentityWrapper; /** * Cache results with TTL. Results are cached by serialized arguments. * * Note: This creates a shared cache, so all calls to the same * cached function share the cache. * * @example * ```ts * // Cache for 5 minutes * fn.use(cache(5 * 60 * 1000)) * * // Cache with custom key function * fn.use(cache({ ttl: 60000, key: (id) => `user:${id}` })) * ``` */ export declare function cache(ttlOrOptions: number | CacheOptions): IdentityWrapper; /** * Rate limit calls - queue excess calls beyond the limit. * * Note: This creates shared state, so all calls to the same * rate-limited function share the rate limit. * * @example * ```ts * // Max 10 calls per second * fn.use(rateLimit({ limit: 10, window: 1000 })) * * // Max 100 calls per minute * fn.use(rateLimit({ limit: 100, window: 60000 })) * ``` */ export declare function rateLimit(options: RateLimitOptions): IdentityWrapper; /** * Circuit breaker - fail fast after repeated errors. * * States: * - closed: Normal operation, requests pass through * - open: Circuit tripped, requests fail immediately * - half-open: Testing if service recovered (allows one request) * * @example * ```ts * // Open after 5 failures, try again after 30s * fn.use(circuitBreaker()) * * // Custom threshold and reset timeout * fn.use(circuitBreaker({ threshold: 3, resetTimeout: 10000 })) * ``` */ export declare function circuitBreaker(options?: CircuitBreakerOptions): IdentityWrapper; /** * Create a simplified wrapper for argument/result transformations. * * Unlike regular wrappers, `map()` hides the `ctx` parameter, providing * a simple `next(...args)` function. Use this for transformations that * don't need access to the abort signal. * * @example * ```ts * // Transform return type: User → string * const getUserName = getUser.use( * map(async (next, id: string) => { * const user = await next(id); * return user.name; * }) * ); * * // Change argument signature: email → id lookup * const getUserByEmail = getUser.use( * map(async (next, email: string) => { * const id = await lookupUserId(email); * return next(id); * }) * ); * * // Combine multiple calls * const getUserWithPosts = getUser.use( * map(async (next, id: string) => { * const [user, posts] = await Promise.all([ * next(id), * fetchPosts(id), * ]); * return { ...user, posts }; * }) * ); * ``` */ export declare function map(mapper: (next: (...args: NoInfer) => Promise>, ...newArgs: TNewArgs) => Promise): AbortableWrapper; /** * Observe lifecycle events of an abortable function. * Useful for logging, analytics, loading indicators, or cleanup on abort. * * The `onStart` callback is invoked when the function starts. It can optionally * return an object with lifecycle callbacks: * - `onAbort` - Called when the function is aborted * - `onSuccess` - Called when the function completes successfully (receives result) * - `onError` - Called when the function throws (error is re-thrown after) * - `onDone` - Called after completion, regardless of outcome (like finally) * * @param onStart - Called when the function starts. Can return lifecycle callbacks. * * @example Simple logging (no callbacks returned) * ```ts * const fetchUser = abortable(async (ctx, id: string) => { ... }) * .use(observe((ctx, id) => { * console.log(`Fetching user ${id}`); * })); * ``` * * @example Abort handling * ```ts * const fetchUser = abortable(async (ctx, id: string) => { ... }) * .use(observe((ctx, id) => ({ * onAbort: () => console.log(`Fetch ${id} aborted`), * }))); * ``` * * @example Loading indicator with cleanup * ```ts * const fetchData = abortable(async () => { ... }) * .use(observe(() => { * showLoading(); * return { onDone: hideLoading }; * })); * ``` * * @example Full lifecycle * ```ts * const fetchUser = abortable(async (ctx, id: string) => { ... }) * .use(observe((ctx, id) => ({ * onAbort: () => console.log(`Aborted: ${id}`), * onSuccess: (user) => console.log(`Fetched: ${user.name}`), * onError: (err) => console.error(`Failed: ${err}`), * onDone: () => console.log('Completed'), * }))); * ``` */ export declare function observe(onStart: NoInfer>): AbortableWrapper; //# sourceMappingURL=wrappers.d.ts.map