Node SDK · Express middleware
The middleware attaches a per-request Event to req.event, auto-populates actor (via your resolver) and origin (from headers), and records the event after the response is sent — handlers just set action / target on req.event and the middleware does the rest.
Actor Resolver
The middleware needs a resolveActor: ActorResolver — a function that derives the Actor for a request. Sessions live in cookies, JWTs, headers, OAuth tokens — whatever your auth stack uses. Pair the resolver with a session middleware that plants identity on the request before the audit middleware runs.
import type { RequestHandler } from "express";
import { type ActorResolver } from "@everscribe/sdk-node/express";
declare module "express-serve-static-core" {
interface Request { user?: User }
}
// withSession plants the user on req. Real apps read a session cookie
// or JWT here.
const withSession: RequestHandler = (req, _res, next) => {
const id = req.headers["x-user-id"];
if (typeof id === "string") req.user = users[id];
next();
};
// resolveActor reads req.user (set by withSession) and turns it into
// an Actor for the audit middleware.
const resolveActor: ActorResolver = (req) => {
if (!req.user) return { type: "anonymous" };
return {
type: "user",
id: req.user.id,
displayName: req.user.name,
email: req.user.email,
};
};
ActorResolver type:
type ActorResolver = (req: Request) => Actor;
Wiring it up
Session middleware first, audit middleware second, then your routes. The resolver runs inside the audit middleware and reads what withSession planted:
import { expressMiddleware } from "@everscribe/sdk-node/express";
app.use(express.json());
app.use(withSession); // session first
app.use(expressMiddleware({ recorder: rec, resolveActor }));
Ordering matters. If the audit middleware runs first, the resolver sees an empty request and every event records as anonymous.