Server reference: @wordplus/realtime/server
Node 20 or later, and every edge runtime: it runs on Web Crypto and fetch. For PHP and Laravel, see the PHP reference; for Python, the Python reference. All three take the same options and answer the browser the same way.
createRealtime( options ) → Realtime
| Option | |
|---|
site, secret | your app's key and secret (WORDPLUS_SITE, WORDPLUS_SECRET) |
localKey | 64 hex characters of your own (WORDPLUS_LOCAL_KEY) (encryption) |
user( request ) | the request's user's id, or null: what route asks |
profile( user ) | { name, avatar?, url?, … } or null: their directory entry, their presence info and call info by default |
hasKeys( user ) | false cuts a user off every key |
generations | { get( name ), set( name, n ) }, for rotateChannel() and rotateUser() |
seal | false sends everything plain |
base | where your routes are, /api/realtime by default, for config() |
headers | headers the browser sends to your routes, such as a CSRF token, for config() |
worker, rooms | where your app serves the two files, for config() |
tokenTtl, callTokenTtl | seconds: 6 hours by default; a channels token at most a day, a calls token at most 6 hours |
server, api | WordPlus Cloud by default |
fetch | your own, for publishing |
Owners
| Method | |
|---|
channel( prefix, ( user, channel ) => answer ) | private and presence channels by the start of their names; false, true, or { id, info } (channels, presence) |
calls( prefix, ( user, call, withUser ) => answer ) | calls and rooms; false, true, or { info, publish, subscribe, admin, hidden } (calls) |
kind( kind, ( rest, user, label ) => boolean, newest? ) | keys of your own kind (encryption) |
Callbacks may be async. The longest prefix that fits decides.
Routes
| |
|---|
route | ( request: Request ) => Promise<Response>: POST …/auth, …/calls, …/keys, the action from the path's last part; Next.js export const POST = realtime.route |
node( ( req ) => user ) | ( req, res ) for Node's own servers and Express; a body express.json() parsed is taken as it is |
handle( action, body, user ) | → { status, body }: one route, for a framework of your own |
They take JSON POSTs only (415 otherwise): a page on another site can't send one without asking first, which it is never allowed. A refusal is an answer (denied), not an HTTP error.
| Method | What it answers |
|---|
authorize( channels, user ) | { token, exp, keys, denied } |
authorizeCall( request, user ) | { token, exp, key } or { denied } |
keysAnswer( labels, user ) | { keys, identity? } |
identity( user ) | { token, exp } or null |
token( channels, { user, info, ttl } ) | a channels token, signed as the auth route signs |
config( user ) | the browser's settings, with a signed-in user's keys and identity |
Publishing
| Method | |
|---|
publish( channels, event, data, { except, seal } ) | (publishing) |
publishBatch( [ { channels, event, data, except, seal } ] ) | 10 events a request |
channelInfo( channel ) | { subscriptions, members? } |
rotateChannel( channel ), rotateUser( user ) | moves a key on |
keys | the Keys: seal( text, label ), sealJson, open, entry( label ), dayLabel(), channelLabel( channel ) |
All throw RealtimeError (code, status) for the server's refusal (errors).