update to work with Yjs@13.0.0-82

This commit is contained in:
Kevin Jahns 2019-05-07 14:07:40 +02:00
parent 8fcaca933d
commit e8647afafc
5 changed files with 73 additions and 73 deletions

View File

@ -33,9 +33,9 @@ import { WebsocketProvider } from 'yjs/provider/websocket.js'
const provider = new WebsocketProvider('http://localhost:1234') const provider = new WebsocketProvider('http://localhost:1234')
// open a websocket connection to http://localhost:1234/my-document-name // open a websocket connection to http://localhost:1234/my-document-name
const sharedDocument = provider.get('my-document-name') const Doc = provider.get('my-document-name')
sharedDocument.on('status', event => { Doc.on('status', event => {
console.log(event.status) // logs "connected" or "disconnected" console.log(event.status) // logs "connected" or "disconnected"
}) })
``` ```

View File

@ -35,20 +35,19 @@ const messageAwareness = 1
// const messageAuth = 2 // const messageAuth = 2
/** /**
* @param {Y.Transaction} transaction * @param {Uint8Array} update
* @param {any} origin
* @param {WSSharedDoc} doc * @param {WSSharedDoc} doc
*/ */
const afterTransaction = (transaction, doc) => { const updateHandler = (update, origin, doc) => {
if (transaction.updateMessage !== null) {
const encoder = encoding.createEncoder() const encoder = encoding.createEncoder()
encoding.writeVarUint(encoder, messageSync) encoding.writeVarUint(encoder, messageSync)
syncProtocol.writeUpdate(encoder, transaction.updateMessage) syncProtocol.writeUpdate(encoder, update)
const message = encoding.toBuffer(encoder) const message = encoding.toUint8Array(encoder)
doc.conns.forEach((_, conn) => send(doc, conn, message)) doc.conns.forEach((_, conn) => send(doc, conn, message))
} }
}
class WSSharedDoc extends Y.Y { class WSSharedDoc extends Y.Doc {
/** /**
* @param {string} name * @param {string} name
*/ */
@ -69,14 +68,14 @@ class WSSharedDoc extends Y.Y {
* @type {Map<number,number>} * @type {Map<number,number>}
*/ */
this.awarenessClock = new Map() this.awarenessClock = new Map()
this.on('afterTransaction', afterTransaction) this.on('update', updateHandler)
} }
} }
/** /**
* @param {any} conn * @param {any} conn
* @param {WSSharedDoc} doc * @param {WSSharedDoc} doc
* @param {ArrayBuffer} message * @param {Uint8Array} message
*/ */
const messageListener = (conn, doc, message) => { const messageListener = (conn, doc, message) => {
const encoder = encoding.createEncoder() const encoder = encoding.createEncoder()
@ -87,7 +86,7 @@ const messageListener = (conn, doc, message) => {
encoding.writeVarUint(encoder, messageSync) encoding.writeVarUint(encoder, messageSync)
syncProtocol.readSyncMessage(decoder, encoder, doc, null) syncProtocol.readSyncMessage(decoder, encoder, doc, null)
if (encoding.length(encoder) > 1) { if (encoding.length(encoder) > 1) {
send(doc, conn, encoding.toBuffer(encoder)) send(doc, conn, encoding.toUint8Array(encoder))
} }
break break
case messageAwareness: { case messageAwareness: {
@ -99,7 +98,7 @@ const messageListener = (conn, doc, message) => {
// @ts-ignore we received an update => so conn exists // @ts-ignore we received an update => so conn exists
doc.conns.get(conn).add(update.clientID) doc.conns.get(conn).add(update.clientID)
}) })
const buff = encoding.toBuffer(encoder) const buff = encoding.toUint8Array(encoder)
doc.conns.forEach((_, c) => { doc.conns.forEach((_, c) => {
send(doc, c, buff) send(doc, c, buff)
}) })
@ -128,7 +127,7 @@ const closeConn = (doc, conn) => {
doc.awarenessClock.delete(clientID) doc.awarenessClock.delete(clientID)
return { clientID, state: null, clock } return { clientID, state: null, clock }
})) }))
const buf = encoding.toBuffer(encoder) const buf = encoding.toUint8Array(encoder)
doc.conns.forEach((_, conn) => { doc.conns.forEach((_, conn) => {
send(doc, conn, buf) send(doc, conn, buf)
}) })
@ -146,7 +145,7 @@ const closeConn = (doc, conn) => {
/** /**
* @param {WSSharedDoc} doc * @param {WSSharedDoc} doc
* @param {any} conn * @param {any} conn
* @param {ArrayBuffer} m * @param {Uint8Array} m
*/ */
const send = (doc, conn, m) => { const send = (doc, conn, m) => {
if (conn.readyState !== wsReadyStateConnecting && conn.readyState !== wsReadyStateOpen) { if (conn.readyState !== wsReadyStateConnecting && conn.readyState !== wsReadyStateOpen) {
@ -179,7 +178,7 @@ exports.setupWSConnection = (conn, req) => {
}) })
doc.conns.set(conn, new Set()) doc.conns.set(conn, new Set())
// listen and reply to events // listen and reply to events
conn.on('message', /** @param {ArrayBuffer} message */ message => messageListener(conn, doc, message)) conn.on('message', /** @param {ArrayBuffer} message */ message => messageListener(conn, doc, new Uint8Array(message)))
conn.on('close', () => { conn.on('close', () => {
closeConn(doc, conn) closeConn(doc, conn)
}) })
@ -206,8 +205,8 @@ exports.setupWSConnection = (conn, req) => {
// send sync step 1 // send sync step 1
const encoder = encoding.createEncoder() const encoder = encoding.createEncoder()
encoding.writeVarUint(encoder, messageSync) encoding.writeVarUint(encoder, messageSync)
syncProtocol.writeSyncStep1(encoder, doc.store) syncProtocol.writeSyncStep1(encoder, doc)
send(doc, conn, encoding.toBuffer(encoder)) send(doc, conn, encoding.toUint8Array(encoder))
if (doc.awareness.size > 0) { if (doc.awareness.size > 0) {
const encoder = encoding.createEncoder() const encoder = encoding.createEncoder()
/** /**
@ -219,6 +218,6 @@ exports.setupWSConnection = (conn, req) => {
}) })
encoding.writeVarUint(encoder, messageAwareness) encoding.writeVarUint(encoder, messageAwareness)
awarenessProtocol.writeUsersStateChange(encoder, userStates) awarenessProtocol.writeUsersStateChange(encoder, userStates)
send(doc, conn, encoding.toBuffer(encoder)) send(doc, conn, encoding.toUint8Array(encoder))
} }
} }

24
package-lock.json generated
View File

@ -968,10 +968,9 @@
} }
}, },
"lib0": { "lib0": {
"version": "0.0.2", "version": "0.0.4",
"resolved": "https://registry.npmjs.org/lib0/-/lib0-0.0.2.tgz", "resolved": "https://registry.npmjs.org/lib0/-/lib0-0.0.4.tgz",
"integrity": "sha512-7bJgV2emHGRO5kpj66Gdc9SQKVfhDBLx0UIS/aU5P8R0179nRFHKDTYGvLlNloWbeUUARlqk3ndFIO4JbUy7Sw==", "integrity": "sha512-osSGIxFM0mUuVAclVOQAio4lq0YYk1xFfj6J+1i3u5az8rXAQKDil2skA19aiiG0sfAdasOtr8Mk+9Mrw10cfQ=="
"dev": true
}, },
"load-json-file": { "load-json-file": {
"version": "2.0.0", "version": "2.0.0",
@ -1700,17 +1699,20 @@
"dev": true "dev": true
}, },
"y-protocols": { "y-protocols": {
"version": "0.0.3", "version": "0.0.5",
"resolved": "https://registry.npmjs.org/y-protocols/-/y-protocols-0.0.3.tgz", "resolved": "https://registry.npmjs.org/y-protocols/-/y-protocols-0.0.5.tgz",
"integrity": "sha512-b6yUR4KuRN9ehf2b0/YyaxxO2bxk7ti5DDTg5Jm/FEtPf0Vk6s4ez5wIhkV1nA7bloz/NDmVpoCDPFX1zZORhg==" "integrity": "sha512-4ZKcDxM2A83ZeGi7WqqK+mS0QRFP0L7Xd8JLxjX+fZeWiUIfYin16f8/0liMaHvGOHgfpomQrQsZm4HCkObgmQ==",
"requires": {
"lib0": "0.0.4"
}
}, },
"yjs": { "yjs": {
"version": "13.0.0-81", "version": "13.0.0-82",
"resolved": "https://registry.npmjs.org/yjs/-/yjs-13.0.0-81.tgz", "resolved": "https://registry.npmjs.org/yjs/-/yjs-13.0.0-82.tgz",
"integrity": "sha512-wGTCXHsBIIGb2eswyl9HNY2TeoFy8jdqPGbGHsu9Ooo9+/LbTUz10XlEKp5/JHQ10fToMSEc1rf5wBu4g+TVNQ==", "integrity": "sha512-pU3siEW0j+pKynWtnT7wKYn6797rdM/FnxsgdjFKJhUzdmeN1vYYZ+hTtPVWg/v8cjIVWCcWebMJZ1IhqFm5yQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"lib0": "0.0.2" "lib0": "0.0.4"
} }
} }
} }

View File

@ -7,7 +7,7 @@
"sideEffects": false, "sideEffects": false,
"scripts": { "scripts": {
"start": "node ./bin/server.js", "start": "node ./bin/server.js",
"dist": "rm -rf dist/* && rollup -c", "dist": "rm -rf dist && rollup -c",
"test": "echo 'should lint here'", "test": "echo 'should lint here'",
"lint": "standard", "lint": "standard",
"preversion": "npm run test", "preversion": "npm run test",
@ -18,7 +18,8 @@
}, },
"files": [ "files": [
"dist/*", "dist/*",
"bin/*" "bin/*",
"src/*"
], ],
"repository": { "repository": {
"type": "git", "type": "git",
@ -34,17 +35,17 @@
}, },
"homepage": "https://github.com/y-js/y-websocket#readme", "homepage": "https://github.com/y-js/y-websocket#readme",
"dependencies": { "dependencies": {
"y-protocols": "0.0.3" "y-protocols": "0.0.5",
"lib0": "0.0.4"
}, },
"devDependencies": { "devDependencies": {
"rollup": "^1.1.2", "rollup": "^1.1.2",
"rollup-cli": "^1.0.9", "rollup-cli": "^1.0.9",
"standard": "^12.0.1", "standard": "^12.0.1",
"yjs": "13.0.0-81" "yjs": "13.0.0-82"
}, },
"peerDependenies": { "peerDependenies": {
"lib0": "*", "yjs": "13.0.0-82"
"yjs": "13.0.0-81"
}, },
"optionalDependencies": { "optionalDependencies": {
"ws": "^6.2.1" "ws": "^6.2.1"

View File

@ -24,14 +24,14 @@ const messageAuth = 2
const reconnectTimeout = 3000 const reconnectTimeout = 3000
/** /**
* @param {WebsocketsSharedDocument} doc * @param {WebsocketsDoc} doc
* @param {string} reason * @param {string} reason
*/ */
const permissionDeniedHandler = (doc, reason) => console.warn(`Permission denied to access ${doc.url}.\n${reason}`) const permissionDeniedHandler = (doc, reason) => console.warn(`Permission denied to access ${doc.url}.\n${reason}`)
/** /**
* @param {WebsocketsSharedDocument} doc * @param {WebsocketsDoc} doc
* @param {ArrayBuffer} buf * @param {Uint8Array} buf
* @return {encoding.Encoder} * @return {encoding.Encoder}
*/ */
const readMessage = (doc, buf) => { const readMessage = (doc, buf) => {
@ -55,7 +55,7 @@ const readMessage = (doc, buf) => {
} }
/** /**
* @param {WebsocketsSharedDocument} doc * @param {WebsocketsDoc} doc
* @param {string} url * @param {string} url
*/ */
const setupWS = (doc, url) => { const setupWS = (doc, url) => {
@ -63,9 +63,9 @@ const setupWS = (doc, url) => {
websocket.binaryType = 'arraybuffer' websocket.binaryType = 'arraybuffer'
doc.ws = websocket doc.ws = websocket
websocket.onmessage = event => { websocket.onmessage = event => {
const encoder = readMessage(doc, event.data) const encoder = readMessage(doc, new Uint8Array(event.data))
if (encoding.length(encoder) > 1) { if (encoding.length(encoder) > 1) {
websocket.send(encoding.toBuffer(encoder)) websocket.send(encoding.toUint8Array(encoder))
} }
} }
websocket.onclose = () => { websocket.onclose = () => {
@ -98,35 +98,33 @@ const setupWS = (doc, url) => {
// always send sync step 1 when connected // always send sync step 1 when connected
const encoder = encoding.createEncoder() const encoder = encoding.createEncoder()
encoding.writeVarUint(encoder, messageSync) encoding.writeVarUint(encoder, messageSync)
syncProtocol.writeSyncStep1(encoder, doc.store) syncProtocol.writeSyncStep1(encoder, doc)
websocket.send(encoding.toBuffer(encoder)) websocket.send(encoding.toUint8Array(encoder))
// force send stored awareness info // force send stored awareness info
doc.setAwarenessField(null, null) doc.setAwarenessField(null, null)
} }
} }
/** /**
* @param {Y.Transaction} transaction * @param {Uint8Array} update
* @param {WebsocketsSharedDocument} y * @param {any} origin
* @param {WebsocketsDoc} doc
*/ */
const broadcastUpdate = (transaction, y) => { const updateHandler = (update, origin, doc) => {
if (transaction.origin !== y.ws && transaction.updateMessage !== null) { if (origin !== doc.ws) {
const updateMessage = transaction.updateMessage
if (updateMessage !== null) {
const encoder = encoding.createEncoder() const encoder = encoding.createEncoder()
encoding.writeVarUint(encoder, messageSync) encoding.writeVarUint(encoder, messageSync)
syncProtocol.writeUpdate(encoder, updateMessage) syncProtocol.writeUpdate(encoder, update)
const buf = encoding.toBuffer(encoder) const buf = encoding.toUint8Array(encoder)
if (y.wsconnected) { if (doc.wsconnected) {
// @ts-ignore We know that wsconnected = true // @ts-ignore We know that wsconnected = true
y.ws.send(buf) doc.ws.send(buf)
}
bc.publish(y.url, buf)
} }
bc.publish(doc.url, buf)
} }
} }
class WebsocketsSharedDocument extends Y.Y { class WebsocketsDoc extends Y.Doc {
/** /**
* @param {string} url * @param {string} url
* @param {Object} opts * @param {Object} opts
@ -151,10 +149,10 @@ class WebsocketsSharedDocument extends Y.Y {
* @param {ArrayBuffer} data * @param {ArrayBuffer} data
*/ */
this._bcSubscriber = data => { this._bcSubscriber = data => {
const encoder = readMessage(this, data) // already muxed const encoder = readMessage(this, new Uint8Array(data))
this.mux(() => { this.mux(() => {
if (encoding.length(encoder) > 1) { if (encoding.length(encoder) > 1) {
bc.publish(url, encoding.toBuffer(encoder)) bc.publish(url, encoding.toUint8Array(encoder))
} }
}) })
} }
@ -165,7 +163,7 @@ class WebsocketsSharedDocument extends Y.Y {
if (this.ws !== null) { if (this.ws !== null) {
this.ws.close() this.ws.close()
bc.unsubscribe(this.url, this._bcSubscriber) bc.unsubscribe(this.url, this._bcSubscriber)
this.off('afterTransaction', broadcastUpdate) this.off('update', updateHandler)
} }
} }
connect () { connect () {
@ -177,10 +175,10 @@ class WebsocketsSharedDocument extends Y.Y {
this.mux(() => { this.mux(() => {
const encoder = encoding.createEncoder() const encoder = encoding.createEncoder()
encoding.writeVarUint(encoder, messageSync) encoding.writeVarUint(encoder, messageSync)
syncProtocol.writeSyncStep1(encoder, this.store) syncProtocol.writeSyncStep1(encoder, this)
bc.publish(this.url, encoding.toBuffer(encoder)) bc.publish(this.url, encoding.toUint8Array(encoder))
}) })
this.on('afterTransaction', broadcastUpdate) this.on('update', updateHandler)
} }
} }
getLocalAwarenessInfo () { getLocalAwarenessInfo () {
@ -203,7 +201,7 @@ class WebsocketsSharedDocument extends Y.Y {
const encoder = encoding.createEncoder() const encoder = encoding.createEncoder()
encoding.writeVarUint(encoder, messageAwareness) encoding.writeVarUint(encoder, messageAwareness)
awarenessProtocol.writeUsersStateChange(encoder, [{ clientID: this.clientID, state: this._localAwarenessState, clock }]) awarenessProtocol.writeUsersStateChange(encoder, [{ clientID: this.clientID, state: this._localAwarenessState, clock }])
const buf = encoding.toBuffer(encoder) const buf = encoding.toUint8Array(encoder)
// @ts-ignore we know that wsconnected = true // @ts-ignore we know that wsconnected = true
this.ws.send(buf) this.ws.send(buf)
} }
@ -231,19 +229,19 @@ export class WebsocketProvider {
} }
this.url = url + '/' this.url = url + '/'
/** /**
* @type {Map<string, WebsocketsSharedDocument>} * @type {Map<string, WebsocketsDoc>}
*/ */
this.docs = new Map() this.docs = new Map()
} }
/** /**
* @param {string} name * @param {string} name
* @param {Object} [opts] * @param {Object} [opts]
* @return {WebsocketsSharedDocument} * @return {WebsocketsDoc}
*/ */
get (name, opts) { get (name, opts) {
let doc = this.docs.get(name) let doc = this.docs.get(name)
if (doc === undefined) { if (doc === undefined) {
doc = new WebsocketsSharedDocument(this.url + name, opts) doc = new WebsocketsDoc(this.url + name, opts)
} }
return doc return doc
} }