Stone.jsDocs
Paradigm

Adapters

Node WebSocket

The server side of realtime on Node. @stone-js/node-ws-adapter runs a ws server and bridges every socket to @stone-js/realtime: each connection joins the shared connection store, so a broadcast from anywhere reaches it, and its lifecycle drives your @On* gateways. Your domain code stays the agnostic one; the socket is the context.

#Install

terminalbash
npm i @stone-js/node-ws-adapter @stone-js/realtime
npm i ws   # the WebSocket server (optional peer, imported lazily)

#Enable it

Stack the adapter on top of @stone-js/realtime. The adapter binds a server on stone.adapter.url (default ws://localhost:8080); realtime provides the broadcaster, channels and presence.

app/Application.tsdeclarativeimperative
import { StoneApp } from '@stone-js/core'
import { Realtime } from '@stone-js/realtime'
import { NodeWs } from '@stone-js/node-ws-adapter'

@NodeWs({ url: 'ws://localhost:8080' })
@Realtime({ driver: 'memory' })
@StoneApp({ name: 'chat' })
export class Application {}
import { defineStoneApp } from '@stone-js/core'
import { realtimeBlueprint } from '@stone-js/realtime'
import { nodeWsAdapterBlueprint } from '@stone-js/node-ws-adapter'

export const App = defineStoneApp(
  { name: 'chat' },
  [realtimeBlueprint, nodeWsAdapterBlueprint]
)

#Gateways react to sockets

A gateway is a plain, dependency-injected class. The adapter dispatches connection lifecycle and channel events into it, one method each:

app/Chat.tsts
import { RealtimeGateway, OnConnect, OnDisconnect, OnEvent, connectionOf } from '@stone-js/realtime'

@RealtimeGateway()
export class Chat {
  constructor (private readonly realtime) {}

  @OnConnect()    onConnect (_, event) { const connection = connectionOf(event) /* authorize, greet… */ }
  @OnDisconnect() onLeave (_, event)   { /* clean up presence… */ }

  @OnEvent('room:1', 'message')
  async onMessage (payload, event) {
    await this.realtime.to('room:1').emit('message', payload)   // fans out to every subscriber
  }
}

#The frame protocol

Clients speak a tiny JSON protocol, the same one the isomorphic RealtimeClientemits: a control frame to join or leave a channel, and a data frame to send an event.

wire.jsonts
{ "type": "subscribe",   "channel": "room:1" }
{ "type": "unsubscribe", "channel": "room:1" }
{ "channel": "room:1", "event": "message", "payload": { "text": "hi" } }

#Configuration

keyTypeDescription
stone.adapter.urlws://localhost:8080The bind URL (host + port).
stone.adapter.server{}Options forwarded to the ws WebSocketServer (e.g. attach to an http server).
stone.adapter.shutdownGracePeriod10000How long connected clients have to leave on stop before they are dropped.

Stone.js

Your app exists in every runtime. Until you run it.

An open-source project by Stone Foundation
Created by Mr. Stone (Evens Pierre)