API Reference
activityLog(options)
Express middleware factory. Logs each request automatically.
import { activityLog } from '@actinode/express-activitylog'
app.use(activityLog(options))Options
| Option | Type | Default | Description |
|---|---|---|---|
adapter | ActivityAdapter | — | Required. The database adapter to write logs to. |
getUserId | (req: Request) => string | undefined | undefined | Extract the authenticated user's ID from the request. Used as the causer. |
getDescription | (req: Request) => string | `${req.method} ${req.path}` | Build the log description from the request. |
skip | (req: Request) => boolean | undefined | Return true to skip logging for a given request. |
mask | MaskConfig | undefined | Masking configuration applied to req.body. Default sensitive fields are always masked even without this option. |
Adapter errors are swallowed silently — a logging failure never breaks the request.
activity(adapter)
Returns an ActivityLogger for manual, fluent log creation.
import { activity } from '@actinode/express-activitylog'
await activity(adapter).log('something happened')ActivityLogger methods
All methods (except log) return this for chaining.
.by(causer)
Set the causer — the entity that performed the action.
.by(req.user)causer must have id: string | number and constructor.name (any class instance satisfies this). The causer's class name is stored as causerType.
.on(subject)
Set the subject — the entity the action was performed on.
.on(post)Same shape requirement as .by(). The subject's class name is stored as subjectType.
.withProperties(properties)
Attach arbitrary metadata to the log entry.
.withProperties({ ip: req.ip, plan: 'pro' })| Param | Type |
|---|---|
properties | Record<string, unknown> |
.mask(fields)
Mask specific fields on this log entry. Applies a field-level denyList to the properties set via .withProperties(). Call it after .withProperties() and before .log().
await activity(adapter)
.by(user)
.on(post)
.withProperties({ title: 'Hello', secret: 'draft-key' })
.mask(['secret'])
.log('created post')| Param | Type | Description |
|---|---|---|
fields | string[] | Fields to replace with the default replacement string (***masked***). |
TIP
.mask() supports field-level denyList only. For allowList, per-model config, or a custom replacement, use the mask option on activityLog().
.log(description)
Persist the log entry. Must be called last. Returns Promise<void>.
await activity(adapter)
.by(user)
.on(post)
.withProperties({ reason: 'spam' })
.log('deleted post')prismaAdapter(prisma)
Creates an adapter backed by Prisma.
import { prismaAdapter } from '@actinode/express-activitylog'
const adapter = prismaAdapter(prisma)| Param | Type | Description |
|---|---|---|
prisma | PrismaClientLike | Any Prisma client instance with an activityLog model. |
mongooseAdapter(mongoose)
Creates an adapter backed by Mongoose.
import { mongooseAdapter } from '@actinode/express-activitylog'
const adapter = mongooseAdapter(mongoose)| Param | Type | Description |
|---|---|---|
mongoose | MongooseLike | The mongoose module (or a compatible object). |
The adapter registers the ActivityLog model on first call. If the model is already registered it is reused.
Masking types
interface MaskConfig {
denyList?: string[] // mask these fields
allowList?: string[] // keep only these, mask everything else
replacement?: string // default: '***masked***'
deep?: boolean // recurse into nested objects/arrays, default: true
models?: Record<string, ModelMaskConfig> // per-model overrides keyed by class name
}
interface ModelMaskConfig {
denyList?: string[] // overrides global denyList for this model
allowList?: string[] // overrides global allowList for this model
}| Field | Type | Default | Description |
|---|---|---|---|
denyList | string[] | undefined | Fields to mask. Merged with the 11 default sensitive fields. |
allowList | string[] | undefined | Fields to keep. Everything else is masked. Applied after denyList. |
replacement | string | '***masked***' | The string used in place of a masked value. |
deep | boolean | true | When true, recursively masks nested objects and arrays. |
models | Record<string, ModelMaskConfig> | undefined | Per-model overrides. Keys match the class constructor name of the causer or subject. |
Types
interface ActivityPayload {
description: string
causerId?: string
causerType?: string
subjectId?: string
subjectType?: string
properties?: Record<string, unknown>
createdAt: Date
}
interface ActivityAdapter {
save(payload: ActivityPayload): Promise<void>
}
interface HasId {
id: string | number
}
interface ActivityLogOptions {
adapter: ActivityAdapter
getUserId?: (req: Request) => string | undefined
getDescription?: (req: Request) => string
skip?: (req: Request) => boolean
mask?: MaskConfig
}
interface PrismaClientLike {
activityLog: {
create(args: { data: Record<string, unknown> }): Promise<unknown>
}
}
interface MongooseLike {
model(name: string, schema?: unknown): MongooseModelLike
Schema: new (definition: Record<string, unknown>, options?: Record<string, unknown>) => unknown
}
interface MongooseModelLike {
create(doc: Record<string, unknown>): Promise<unknown>
}