Middleware
Wrap the fetch call to intercept, modify, or short-circuit requests and responses
How It Works
A middleware is a function that takes the next handler and returns a new handler that wraps it. Middlewares compose like an onion — the first in the array executes first on the way in and last on the way out.
type FetchLike = (url: string, init: RequestInit) => Promise<Response>;
type Middleware = (next: FetchLike) => FetchLike;Using Built-in Middlewares
import { createClient } from '@cleverbrush/client';
import { retry } from '@cleverbrush/client/retry';
import { timeout } from '@cleverbrush/client/timeout';
import { dedupe } from '@cleverbrush/client/dedupe';
import { throttlingCache } from '@cleverbrush/client/cache';
const client = createClient(api, {
middlewares: [
retry({ limit: 3 }),
timeout({ timeout: 10000 }),
dedupe(),
throttlingCache({ throttle: 2000 }),
],
});Writing a Custom Middleware
import type { Middleware } from '@cleverbrush/client';
const logger: Middleware = (next) => async (url, init) => {
const start = performance.now();
console.log('→', init.method, url);
const res = await next(url, init);
console.log('←', res.status, `(${(performance.now() - start).toFixed(0)}ms)`);
return res;
};Composition Order
Middlewares are applied in array order. For resilience, a typical order is:
middlewares: [
retry(), // outermost — retries the entire inner chain
timeout(), // aborts if a single attempt takes too long
dedupe(), // deduplicates concurrent identical requests
throttlingCache(), // serves cached responses within TTL
]