RealtimeAppOptions
Options for the RealtimeApp plugin.
Properties
adapter?
optionaladapter?:"none"|"redis"
Socket.io adapter for multi-instance deployments.
- 'none': single-instance mode, no adapter (default)
- 'redis': use Redis adapter (requires redisUrl or VALKEY_URL env var)
For MongoDB adapter or custom adapters, configure the Socket.io instance directly via getIo() after server creation.
betterAuth?
optionalbetterAuth?:BetterAuthSocketOptions
Enables the Better Auth session validator for socket authentication, tried after the
legacy JWT validator. Pass the instance returned by createBetterAuth (and optionally
the app user model so decodedToken.id/admin match the REST identity).
changeStream?
optionalchangeStream?:ChangeStreamConfig
Change stream watcher configuration
cors?
optionalcors?:object
CORS configuration for Socket.io
methods?
optionalmethods?:string[]
origin
origin:
string|string[]
debug?
optionaldebug?:boolean
Enable debug logging
redisUrl?
optionalredisUrl?:string
Redis URL for the Redis adapter
sessionRevalidationIntervalMs?
optionalsessionRevalidationIntervalMs?:number
Interval in ms for the periodic socket session re-validation sweep (D1): re-checks
JWT expiry / Better Auth session validity and the user's disabled flag for every
connected socket, disconnecting (sync:auth-expired then disconnect(true)) any
socket that fails. Also refreshes socket.data.fullUser (D2) and re-resolves sync
stream membership, leaving rooms for streams no longer held (D4). Default 60_000ms;
set to 0 to disable the sweep entirely (e.g. in tests).
SocketServer?
optionalSocketServer?: typeofServer
Test seam: Socket.IO server constructor. Defaults to socket.io's Server.
Prefer this over mock.module("socket.io") — bun's module mocks are process-wide
and break later files that need a real Socket.IO server (sync integration, etc.).
startChangeStreamWatcher?
optionalstartChangeStreamWatcher?: (io,config,debug) =>void
Test seam: change-stream watcher starter. Defaults to the real
startChangeStreamWatcher. Same rationale as SocketServer — avoid
process-wide mock.module of ./changeStreamWatcher.
Start watching MongoDB change streams and emitting real-time events.
Task 9.16: the stream is supervised — an error/close/end schedules a re-open with
exponential backoff, resuming from the last seen token. Call
stopChangeStreamWatcher to end supervision.
Parameters
io
Server
config?
ChangeStreamConfig = {}
debug?
boolean = false
Returns
void
sync?
optionalsync?:SyncAppOptions
Explicit SyncAppOptions override for the sync socket handlers. Normally omitted — the options registered by the SyncApp plugin are used automatically.
tokenIssuer?
optionaltokenIssuer?:string
JWT issuer required for socket authentication (default: process.env.TOKEN_ISSUER),
for parity with the HTTP JWT path's jwt.verify(token, secret, {issuer}) (D1).
Omit (and leave TOKEN_ISSUER unset) to skip the issuer check.
tokenSecret?
optionaltokenSecret?:string
JWT secret for socket authentication (default: process.env.TOKEN_SECRET)
userModel?
optionaluserModel?:UserModel
The application's Mongoose user model. When provided, the full user document is
loaded once at handshake (by the decoded token's id) and cached on
socket.data.fullUser, then refreshed by the periodic session re-validation sweep
(D1). Authorization for realtime/sync subscriptions and mutations uses this full
document instead of the synthetic {_id, admin, id} shape derived from the token
alone — required for any permission check or getUserScopes resolver that reads
fields beyond admin (e.g. organizationIds for tenant-scoped sync). Without it,
socket-side authorization falls back to the synthetic shape (pre-D2 behavior).