Service API
Inject the service with the SESSION_SERVICE token; pass your payload shape as the generic:
constructor(
@Inject(SESSION_SERVICE) private readonly sessions: ISessionService<AppSession>,
) {}Introspection
getSession(sessionId)
Returns ISessionInfo<T> | null — the parsed middleware payload plus plugin metadata. Reading a session enforces the absolute lifetime cap (a capped-out session is destroyed and reported as null).
const info = await sessions.getSession(req.sessionID);
// info.data -> your payload (typed T)
// info.metadata -> { userId?, ip?, userAgent?, createdAt, lastSeenAt, expiresAt } | nullgetSessionsByUser(userId)
The device page: every live session of a user, with metadata.
import { Controller, Get, Inject, Req } from '@nestjs/common';
import { SESSION_SERVICE } from '@nestjs-redisx/session';
import type { ISessionService } from '@nestjs-redisx/session';
import { AppSession } from './types';
interface SessionRequest {
sessionID: string;
session: { passport?: { user?: string } };
}
@Controller('account')
export class DevicePageController {
constructor(@Inject(SESSION_SERVICE) private readonly sessions: ISessionService<AppSession>) {}
// GitHub-style "Sessions" page: every device with IP, browser, and activity.
@Get('sessions')
async devicePage(@Req() req: SessionRequest) {
const userId = req.session.passport?.user;
const devices = await this.sessions.getSessionsByUser(userId!);
return devices.map((device) => ({
id: device.id,
current: device.id === req.sessionID,
ip: device.metadata?.ip,
userAgent: device.metadata?.userAgent,
signedInAt: device.metadata?.createdAt,
lastActiveAt: device.metadata?.lastSeenAt,
}));
}
}count() / countByUser(userId)
Live totals from the global / per-user index. Expired entries are swept by score before counting, so numbers stay accurate as sessions expire naturally.
Revocation
revoke(sessionId)
Terminates one session; returns true when a session existed. The owner's next request is treated as unauthenticated.
revokeAll(userId)
Password change / compromise response — terminates every session of the user; returns the number revoked.
revokeAllExcept(userId, currentSessionId)
The real product button: "log out everywhere else". A naked revokeAll logs out the clicker too.
import { Injectable, Inject } from '@nestjs/common';
import { SESSION_SERVICE } from '@nestjs-redisx/session';
import type { ISessionService } from '@nestjs-redisx/session';
@Injectable()
export class SessionSecurityService {
constructor(@Inject(SESSION_SERVICE) private readonly sessions: ISessionService) {}
// The "log out everywhere else" button: keeps the clicking device signed in.
logoutOtherDevices(userId: string, currentSessionId: string): Promise<number> {
return this.sessions.revokeAllExcept(userId, currentSessionId);
}
// Password change / account compromise: terminate everything.
async onPasswordChanged(userId: string): Promise<number> {
return this.sessions.revokeAll(userId);
}
// Support/admin: terminate one specific session by ID.
async revokeSingle(sessionId: string): Promise<boolean> {
return this.sessions.revoke(sessionId);
}
// Live counters for dashboards.
async stats(userId: string): Promise<{ total: number; forUser: number }> {
return {
total: await this.sessions.count(),
forUser: await this.sessions.countByUser(userId),
};
}
}Activity
recordActivity(sessionId, { ip?, userAgent? })
Stamps request-scoped attributes onto the session metadata and refreshes lastSeenAt. No-op for missing sessions. See Store Adapters — Activity Stamping for the middleware one-liner.
Errors
All errors extend SessionError (which extends RedisXError):
| Error | Code | When |
|---|---|---|
SessionStoreError | SESSION_STORE_ERROR | Redis/Lua failure in any store operation |
InvalidSessionConfigError | SESSION_CONFIG_INVALID | Invalid plugin options (thrown at bootstrap) |
SessionLimitExceededError | SESSION_LIMIT_EXCEEDED | Seat limit hit under the reject policy |
SessionMiddlewareMissingError | SESSION_MIDDLEWARE_MISSING | toExpressStore() without express-session installed |
SessionSerializationError | SESSION_SERIALIZATION_FAILED | Payload not JSON-serializable |