TypeScript signature
function withLatencyAll<T extends object>( client: T, profile: LatencyPreset | LatencyOptions ): T
The return type is the same as the input type — a new object with the same shape as client, but with every async method wrapped. Non-async methods are passed through unchanged.
Function parameters
| param | type | default | description |
|---|---|---|---|
| client | object | — | Any JavaScript object. All methods that return a Promise will be wrapped. The original object is not mutated — a new object with wrapped methods is returned. |
| profile | LatencyPreset | LatencyOptions | — | The same latency profile is applied to all wrapped methods. Pass a preset string or a custom LatencyOptions object. |
What withLatencyAll returns
withLatencyAll returns a new object (not a Proxy) with the same prototype chain as the original client. Each method is inspected at wrap time: if calling it with no arguments returns a Promise (or if it is detected as an async function), it is wrapped with withLatency. Synchronous methods are passed through unchanged.
this binding is preserved — each wrapped method is bound to the original client object, so class methods that reference this.someProperty or this.db continue to work correctly.
Which methods get wrapped
At wrap time, withLatencyAll enumerates the own and inherited enumerable methods on the object. A method is wrapped if it is a function and either:
- It is declared with the
asynckeyword (detected viafn.constructor.name === 'AsyncFunction'). - It explicitly returns a
Promiseinstance.
Synchronous methods — getters, event emitters, configuration accessors — are included on the returned object unchanged. If a method is conditionally async, it will only be wrapped if it is flagged as an async function at the time withLatencyAll is called.
Code examples
import { createClient } from 'redis' import { withLatencyAll } from 'slowdep' const redis = createClient() await redis.connect() // Wrap every async method — get, set, del, hGet, etc. const slowRedis = withLatencyAll(redis, 'redis') // Use exactly like the original client await slowRedis.set('key', 'value') const val = await slowRedis.get('key')
import { Pool } from 'pg' import { withLatencyAll } from 'slowdep' const pool = new Pool({ connectionString: process.env.DATABASE_URL }) // Wrap the pool — query, connect, end all get latency const slowPool = withLatencyAll(pool, 'postgres') const { rows } = await slowPool.query( 'SELECT * FROM users WHERE active = $1', [true] )
import { withLatencyAll } from 'slowdep' class PaymentService { async createCharge(amount: number) { /* ... */ } async refund(chargeId: string) { /* ... */ } formatAmount(cents: number) { return cents / 100 } // sync — not wrapped } const payments = new PaymentService() // createCharge and refund get Stripe latency; formatAmount is unchanged const slowPayments = withLatencyAll(payments, 'stripe') const charge = await slowPayments.createCharge(1000) const label = slowPayments.formatAmount(1000) // still synchronous
Things to be aware of
Only methods that return a Promise are wrapped. Synchronous methods — property accessors, formatters, event emitters — appear on the returned object as-is. Calling them will not add latency.
Each wrapped method is bound to the original client instance. You do not need to call .bind() manually. This means class methods that access this.db, this.config, or other instance properties will work correctly through the wrapped object.
withLatencyAll applies one profile to every async method on the client. If you need different latency for different methods (e.g., reads vs writes), use withLatency to wrap each method individually with its own profile.
Like withLatency, withLatencyAll should only be used in development and test environments. Use an environment check: process.env.NODE_ENV !== 'production' ? withLatencyAll(client, preset) : client.