Configuration#

createRevuServer(options) returns a reporter. Only serverKey is required. Options never throw: invalid numeric values fall back to their defaults, and a missing, malformed or public key yields a disabled reporter that does nothing.

import { createRevuServer } from "@revu-ai/server";

const revu = createRevuServer({
  serverKey: process.env.REVU_SERVER_KEY,
  trustProxy: process.env.REVU_TRUST_PROXY, // "1", "2" or "true", read from the environment
  queryAllowlist: ["page"],
  ignorePaths: ["/admin", /^\/preview\//],
});

Options#

OptionDefaultDescription
serverKeyrequiredSecret server key for one environment, revu_sk_prod_... (or _stg_, _dev_). Missing, malformed or public keys disable the reporter.
endpointhttps://api.revu.aiREVU API base URL. Events go to {endpoint}/v1/behavior/server-events. Override it to point at a local or staging server.
debugfalseLog internal errors and send outcomes to console.warn, including REVU's per-hit counts for each send. Silent otherwise.
trustProxyfalsefalse: socket address only. A number n: n trusted proxies, take the nth X-Forwarded-For entry from the right. true: leftmost entry (any client can set it, prefer a hop count or ipHeader). String forms ("true", "2") are accepted for values read from the environment. When on, the reported host also comes from X-Forwarded-Host.
ipHeadernoneSingle-value client IP header set by your trusted edge (cf-connecting-ip, x-real-ip, ...). Used only when trustProxy is on. When set, it replaces X-Forwarded-For: a request without it falls back to the socket address.
queryAllowlist[]Query parameters kept on the reported path. Everything else is stripped.
ignorePaths[]Extra paths never reported: prefixes ("/admin") or RegExp. Added to the built-in ignores.
shouldReportnoneYour own last check, (request) => boolean, for rules the path cannot express (a header, a host, the client address). It runs only for hits that pass every built-in filter and ignorePaths, and gets the same request track() got. false drops the hit. Keep it synchronous. A check that throws drops the hit.
flushIntervalMs5000Send cadence. 0 turns the timer off.
flushAt20Queue length that triggers an early send.
minSendIntervalMs1000Shortest gap between two sends. Hits that arrive within it go out together, so a burst becomes one request. A hit after a quiet interval is sent at once. 0 never waits. The exit flush and shutdown() never wait.
maxBatchSize100Hits per request, at most 500.
maxQueueSize1000Queue cap. When full, the oldest hit is dropped.
timeoutMs3000Per-request timeout.
retryDelayMs1000Delay before the single retry.
backoffMs30000Pause after a failed or throttled send. Doubles per consecutive failure, resets on success.
maxBackoffMs300000Upper bound for the pause.
shutdownTimeoutMs5000Longest shutdown() waits.
flushOnExittrueFlush on the process beforeExit event (Node, Bun).
fetchglobal fetchCustom fetch implementation.

The client IP options are explained with worked setups in Client IP and proxies. The delivery options are explained in Delivery and performance.

The reporter#

MethodDescription
track(request)Filter, build and queue one hit. Synchronous. Returns true when queued.
flush()Send what is queued now. Resolves when drained or paused. Never rejects.
shutdown()Stop accepting hits and make a final bounded flush.

The adapters call track() for you. Call it yourself only for a server without an adapter, see Calling track() yourself.

Exported helpers#

The package also exports the pure helpers the reporter uses, for custom integrations:

  • isPageRequest - the page rules from What is reported.
  • looksAutomated - the user-agent pre-filter.
  • resolveClientIp and normalizeIp - the client IP rules from Client IP and proxies.
  • VERSION, DEFAULT_ENDPOINT and INGEST_PATH.

Types#

Every option, method and adapter is typed. The .d.ts declarations ship with the package and are generated from the JSDoc in the source, so editor hints and these docs describe the same surface.