Simple backend for y-websocket
The Websocket Provider is a solid choice if you want a central source that handles authentication and authorization. Websockets also send header information and cookies, so you can use existing authentication mechanisms with this server.
Important
y-websocket-server is intended as a development server or as a
starting point for building your own backend. It is intentionally small
and easy to read - fork it, copy it, or adapt setupWSConnection into your
own Node server.
For a production-ready backend with persistence, scaling, authentication, presence, webhooks, and more, look at one of the full-featured providers:
- YHub - the official Yjs backend
- Hocuspocus - batteries-included backend from the Tiptap team
- See the Yjs docs for a full list of connection providers.
npm i @y/websocket-serverThis repository implements a basic server that you can adopt to your specific use-case. (source code)
Start a y-websocket server:
HOST=localhost PORT=1234 npx y-websocketimport * as Y from 'yjs'
import { WebsocketProvider } from 'y-websocket'
const doc = new Y.Doc()
const wsProvider = new WebsocketProvider('ws://localhost:1234', 'my-roomname', doc)
wsProvider.on('status', event => {
console.log(event.status) // logs "connected" or "disconnected"
})Start a y-websocket server:
HOST=localhost PORT=1234 npx y-websocketSince npm symlinks the y-websocket executable from your local ./node_modules/.bin folder, you can simply run npx. The PORT environment variable already defaults to 1234, and HOST defaults to localhost.
Documents live in memory by default and are lost when the server restarts.
Persistence is now configured programmatically rather than through an
env variable. Import setPersistence from @y/websocket-server/utils and
plug in any storage backend that implements bindState and writeState:
import { setPersistence } from '@y/websocket-server/utils'
setPersistence({
bindState: async (docName, ydoc) => {
// Called when a Y.Doc is first accessed.
// Load the persisted state for `docName` and apply it to `ydoc`.
//
// It is recommended to also subscribe to `ydoc.on('update', update => ...)`
// here so you can persist updates incrementally as they happen, rather
// than only on shutdown.
},
writeState: async (docName, ydoc) => {
// Called when the last connected client disconnects from this document
// (i.e. the session is closing). Flush / persist any remaining state.
}
})If you need durable, production-grade persistence, use YHub or Hocuspocus instead of rolling your own.
Send a debounced callback to an HTTP server (POST) on document update. Note that this implementation doesn't implement a retry logic in case the CALLBACK_URL does not work.
Can take the following ENV variables:
CALLBACK_URL: Callback server URLCALLBACK_DEBOUNCE_WAIT: Debounce time between callbacks (in ms). Defaults to 2000 msCALLBACK_DEBOUNCE_MAXWAIT: Maximum time to wait before callback. Defaults to 10 secondsCALLBACK_TIMEOUT: Timeout for the HTTP call. Defaults to 5 secondsCALLBACK_OBJECTS: JSON of shared objects to get data ('{"SHARED_OBJECT_NAME":"SHARED_OBJECT_TYPE}')
CALLBACK_URL=http://localhost:3000/ CALLBACK_OBJECTS='{"prosemirror":"XmlFragment"}' npm startThis sends a debounced callback to localhost:3000 2 seconds after receiving an update (default DEBOUNCE_WAIT) with the data of an XmlFragment named "prosemirror" in the body.
A Dockerfile is included for convenience. Build and run:
docker build -t y-websocket-server .
docker run -p 1234:1234 y-websocket-serverThe container binds to :: (all interfaces) on port 1234 by default.
The MIT License © Kevin Jahns