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.js

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

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