Server API
Direct server-side state manipulation with SyncServer.
Access and manipulate sync state from the server side. SyncServer provides zone handles for reading/writing state, overriding hosts, and sending messages -- useful in API routes, bot events, cron jobs, or any server-side code.
SyncServer
Import from @robojs/sync/server:
import { SyncServer } from '@robojs/sync/server'import { SyncServer } from '@robojs/sync/server'| Method | Description |
|---|---|
start() | Start the WebSocket server (called automatically on Robo startup) |
getSocketServer() | Get the underlying ws.WebSocketServer instance |
getZone(key) | Get a zone handle for direct state manipulation |
Server zones
Get a zone handle to read and write state from the server.
const zone = SyncServer.getZone<GameState>(['game', 'room1'])const zone = SyncServer.getZone(['game', 'room1'])| Method | Signature | Description |
|---|---|---|
getState() | () => T | undefined | Get current state |
setState(data) | (data: T) => void | Set state and broadcast to all subscribers |
setHost(clientId) | (clientId: string | null) => void | Override host (null clears) |
getHost() | () => string | undefined | Get current host ID |
getClients() | () => Client[] | Get all subscribed clients |
broadcast(payload) | (payload: unknown) => void | Broadcast to all subscribers |
send(clientId, payload) | (clientId: string, payload: unknown) => void | Send to specific client |
Reading state
const zone = SyncServer.getZone(['game', 'room1'])
const state = zone.getState()
const host = zone.getHost()
const clients = zone.getClients()
console.log('State:', state)
console.log('Host:', host)
console.log('Players:', clients.length)const zone = SyncServer.getZone(['game', 'room1'])
const state = zone.getState()
const host = zone.getHost()
const clients = zone.getClients()
console.log('State:', state)
console.log('Host:', host)
console.log('Players:', clients.length)Writing state
Updates broadcast automatically to all subscribed clients.
const zone = SyncServer.getZone(['game', 'room1'])
zone.setState({
phase: 'playing',
round: 2,
startedAt: Date.now()
})const zone = SyncServer.getZone(['game', 'room1'])
zone.setState({
phase: 'playing',
round: 2,
startedAt: Date.now()
})Host management
Override or clear the host. Useful for admin actions or automated game management.
const zone = SyncServer.getZone(['game', 'room1'])
// Assign host
zone.setHost('client-abc')
// Clear host
zone.setHost(null)const zone = SyncServer.getZone(['game', 'room1'])
// Assign host
zone.setHost('client-abc')
// Clear host
zone.setHost(null)setHost verifies the target client is subscribed to the key. If the client isn't subscribed, the operation is silently ignored with a warning log.
Sending messages
Server broadcasts arrive on the client with client.id === '__server__'.
const zone = SyncServer.getZone(['game', 'room1'])
// Broadcast to all subscribers
zone.broadcast({ event: 'countdown', seconds: 5 })
// Send to specific client
zone.send('client-abc', { message: 'You win' })const zone = SyncServer.getZone(['game', 'room1'])
// Broadcast to all subscribers
zone.broadcast({ event: 'countdown', seconds: 5 })
// Send to specific client
zone.send('client-abc', { message: 'You win' })Client-side handling:
useSyncBroadcast((payload, { client }) => {
if (client.id === '__server__') {
console.log('Server says:', payload)
}
}, ['game', 'room1'])useSyncBroadcast((payload, { client }) => {
if (client.id === '__server__') {
console.log('Server says:', payload)
}
}, ['game', 'room1'])Use cases
API route integration
import { SyncServer } from '@robojs/sync/server'
export default function handler(req, res) {
const zone = SyncServer.getZone(['game', req.query.roomId])
zone.setState({ score: 0, phase: 'lobby' })
zone.broadcast({ type: 'game_reset' })
return { success: true }
}import { SyncServer } from '@robojs/sync/server'
export default function handler(req, res) {
const zone = SyncServer.getZone(['game', req.query.roomId])
zone.setState({ score: 0, phase: 'lobby' })
zone.broadcast({ type: 'game_reset' })
return { success: true }
}Cron job
import { SyncServer } from '@robojs/sync/server'
export default () => {
setInterval(() => {
const zone = SyncServer.getZone(['dashboard', 'stats'])
zone.setState({
serverTime: Date.now(),
uptime: process.uptime()
})
}, 5000)
}import { SyncServer } from '@robojs/sync/server'
export default () => {
setInterval(() => {
const zone = SyncServer.getZone(['dashboard', 'stats'])
zone.setState({
serverTime: Date.now(),
uptime: process.uptime()
})
}, 5000)
}Raw WebSocket access
For advanced scenarios, access the underlying ws.WebSocketServer:
const wss = SyncServer.getSocketServer()
if (wss) {
console.log('Connected clients:', wss.clients.size)
}const wss = SyncServer.getSocketServer()
if (wss) {
console.log('Connected clients:', wss.clients.size)
}