Y-SweetAPI Reference@y-sweet/client

@y-sweet/client

JavaScript/TypeScript library for connecting a Yjs Doc with a Y-Sweet server in order to sync and persist document updates.

Installation

npm install @y-sweet/client

The @y-sweet/client library is primarily used to connect a given Yjs document to a Y-Sweet server so that changes to the Yjs document are synced across all clients and, optionally, so that the document is persisted to S3 storage.

createYjsProvider(doc, docId, authEndpoint, [options])

Connecting the Yjs document to Y-Sweet is done with the createYjsProvider() function, which takes a Yjs document, a doc ID, an AuthEndpoint, and some optional parameters. It returns a promise which, when awaited, resolves to a YSweetProvider. Note that it is often not necessary to directly interact with the YSweetProvider.

my-app.ts
import { createYjsProvider } from '@y-sweet/client'
 
const doc = new Y.Doc()
const docId = 'my-doc-id'
await createYjsProvider(doc, docId, '/api/auth')

The AuthEndpoint is used by the provider to get a ClientToken that authorizes the client to read and write to the shared document. The AuthEndpoint may either be a string (a full URL or just a path) or an async function that returns a ClientToken. If you are using a meta-framework like NextJS or Remix, you can implement this auth endpoint as an API route, or you can use a server framework like ExpressJS or Hono.

Here’s an example of how the auth endpoint might be implemented using Hono:

my-server.ts
import { DocumentManager } from '@y-sweet/sdk'
import { Hono } from 'hono'
import { cors } from 'hono/cors'
import { serve } from '@hono/node-server'
 
const docManager = new DocumentManager(process.env.CONNECTION_STRING)
 
const app = new Hono()
app.use('/api/auth', cors())
app.post('/api/auth', async (c) => {
  const body = await c.req.json()
  const docId = body.docId
  // At this point, in a production app, you'd want to authenticate the user
  // and make sure they have access to the given doc
  const clientToken = await docManager.getOrCreateDocAndToken(docId)
  return c.json(clientToken)
})
serve(app)

Comparison to WebsocketProvider (y-websocket)

y-websocket is a popular WebSocket provider for Yjs. YSweetProvider aims to provide a compatible interface to WebsocketProvider where it makes sense. This section outlines the differences between the two providers.

Constructor arguments

As its first argument, WebsocketProvider takes a WebSocket URL. YSweetProvider takes an auth URL, which is a POST endpoint that it expects to return a ClientToken. It is that ClientToken that contains the WebSocket URL. This approach allows YSweetProvider to reauthenticate when its token expires. Read more about auth endpoints.

Both constructors take an optional params object, and most of WebsocketProvider parameters also work with YSweetProvider (except for some that don’t apply to Y-Sweet).

WebsocketProvider ParameterSupported in YSweetProviderMeaning
connectAutomatically connect upon initialization.
paramsURL parameters to add to the WebSocket URL. Not applicable to Y-Sweet.
awarenessYjs Awareness instance.
WebSocketPolyfillWebSocket constructor to use (normally for non-browser environments)
resyncIntervalResync is not necessary over a proper TCP connection.
disableBcBroadcastChannel is enabled automatically if offline support is enabled.

YSweetProvider additionally supports several other parameters:

  • initialClientToken - provides a ClientToken to avoid the initial trip to the auth endpoint. If a connection does not succeed (e.g. the token has expired), the provider will still attempt to connect via the auth endpoint.
  • offlineSupport - enables storing and loading document data locally from IndexedDB. When the user reconnects to the Y-Sweet server, all their local changes will be synced.

Provider fields

WebsocketProvider FieldSupported in YSweetProviderMeaning
wsconnectedWhether the WebSocket is connected. Equivalent to this.status === STATUS_CONNECTED || this.status === STATUS_HANDSHAKING
wsconnectingWhether the WebSocket is connecting. Equivalent to this.status === STATUS_CONNECTING
syncedWhether the document is synced. Equivalent to this.status === STATUS_CONNECTED
shouldConnectWhether the WebSocket should connect. Equivalent to this.status !== STATUS_OFFLINE
bcConnectedBroadcast channel is not supported.
paramsURL parameters to add to the WebSocket URL. Not applicable to Y-Sweet.

YSweetProvider additionally supports a field called hasLocalChanges, which is a boolean that indicates whether there are local changes that have not yet been synced to the server.

Provider methods

WebsocketProvider MethodSupported in YSweetProviderMeaning
connectConnect to the WebSocket.
disconnectDisconnect from the WebSocket.
destroyCleanup before the provider is destroyed.
onAdd an event listener.

All WebsocketProvider events are supported in .on() (sync, status, connection-close, connection-error).

Two new events are additionally available:

  • local-changes - emitted with a boolean when the document’s hasLocalChanges state changes
  • connection-status - emitted when the connection status changes

Note that for consistency with WebsocketProvider, the sync event is only concerned with the initial handshake sync of each connection lifecycle. The local-changes event is probably what you’re looking for if you want to show the user whether their changes have been synced to the server.

Connection statuses

The connection-status events provide a richer set of statuses than the status events, which are limited to y-websocket statuses. The equivalents are shown below:

YSweetProvider StatusWebsocketProvider Status
offlinedisconnected
connectingconnecting
handshakingconnecting
errordisconnected
connectedconnected

Types

createYjsProvider(
  doc: Y.Doc,
  docId: string,
  authEndpoint: string | () => Promise<ClientToken>,
  options: YSweetProviderParams
): YSweetProvider
type AuthEndpoint = string | () => Promise<ClientToken>
type ClientToken = {
  url: string
  baseUrl: string
  docId: string
  token?: string
}
type YSweetProviderParams = {
  connect?: boolean
  awareness?: Awareness
  WebSocketPolyfill?: WebSocketPolyfillType
  initialClientToken?: ClientToken
}
Built by Jamsocket.