Skip to content

Instantly share code, notes, and snippets.

@ansarizafar
Forked from garth/readme.md
Created January 12, 2024 13:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ansarizafar/d8de01a3d585d94e6f2742c211749e24 to your computer and use it in GitHub Desktop.
Save ansarizafar/d8de01a3d585d94e6f2742c211749e24 to your computer and use it in GitHub Desktop.
A Yjs provider for socketsupply

You can use it the same as you do with other yjs providers, but you have to pass it a socket which can be created with someting like this:

// set the peer id
const peerId = window.localStorage.getItem('peerId') ?? (await Encryption.createId())
window.localStorage.setItem('peerId', peerId)

// set the signing keys
const keySeed = window.localStorage.getItem('keySeed') ?? createId()
window.localStorage.setItem('keySeed', keySeed)
const signingKeys = await Encryption.createKeyPair(keySeed)

// set the cluster id
const clusterId = await Encryption.createClusterId(CLUSTER_ID_SEED)

// create the network socket
const socket = await network({ peerId, clusterId, signingKeys })
import * as Y from 'yjs'
import { Observable } from 'lib0/observable'
import { Encryption } from 'socket:network'
import { applyAwarenessUpdate, Awareness, encodeAwarenessUpdate, removeAwarenessStates } from 'y-protocols/awareness.js'
import { Buffer } from 'buffer'
export class SocketProvider extends Observable<string> {
doc: Y.Doc
awareness: Awareness
cluster: any
constructor(socket: any, roomname: string, doc: Y.Doc) {
super()
this.doc = doc
this.awareness = new Awareness(this.doc)
const _this = this
void Encryption.createSharedKey(roomname).then((sharedKey) => {
socket.subcluster({ sharedKey }).then((cluster: any) => {
_this.cluster = cluster
_this.cluster.on('verify', _this._verifyHandler)
_this.cluster.on('update', _this._clusterUpdateHandler)
_this.doc.on('update', _this._docUpdateHandler)
_this.cluster.on('awareness', _this._clusterAwarenessHandler)
_this.awareness.on('update', _this._awarenessUpdateHandler)
_this.cluster.emit('verify', Buffer.from(Y.encodeStateVector(_this.doc).buffer))
})
})
}
_verifyHandler = (vector: Buffer) => {
const update = Y.encodeStateAsUpdate(this.doc, new Uint8Array(vector.buffer))
if (update.byteLength > 2) {
this.cluster.emit('update', Buffer.from(update.buffer))
}
}
_clusterUpdateHandler = (update: Buffer, _packetPublish: any) => {
Y.applyUpdate(this.doc, new Uint8Array(update.buffer), 'socket')
}
_docUpdateHandler = (update: Uint8Array, origin: any) => {
if (origin !== 'socket') {
this.cluster.emit('update', Buffer.from(update.buffer))
}
}
_clusterAwarenessHandler = (update: Buffer) => {
applyAwarenessUpdate(this.awareness, new Uint8Array(update.buffer), 'socket')
}
_awarenessUpdateHandler = ({ added, updated, removed }: { added: []; updated: []; removed: [] }, origin: any) => {
if (origin !== 'socket') {
this.cluster.emit(
'awareness',
Buffer.from(encodeAwarenessUpdate(this.awareness, [...added, ...updated, ...removed]).buffer),
)
}
}
destroy() {
this.doc.off('update', this._docUpdateHandler)
removeAwarenessStates(
this.awareness,
Array.from(this.awareness.getStates().keys()).filter((client) => client !== this.doc.clientID),
'provider',
)
this.awareness.destroy()
// this.cluster.destroy()
super.destroy()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment