y-socket.io
Version:
Socket IO Connector for Yjs (Inspired by y-websocket)
161 lines (159 loc) • 7.69 kB
JavaScript
"use strict";
var U = Object.create;
var d = Object.defineProperty;
var S = Object.getOwnPropertyDescriptor;
var C = Object.getOwnPropertyNames;
var m = Object.getPrototypeOf, g = Object.prototype.hasOwnProperty;
var _ = (n, o) => {
for (var e in o)
d(n, e, { get: o[e], enumerable: !0 });
}, b = (n, o, e, t) => {
if (o && typeof o == "object" || typeof o == "function")
for (let r of C(o))
!g.call(n, r) && r !== e && d(n, r, { get: () => o[r], enumerable: !(t = S(o, r)) || t.enumerable });
return n;
};
var l = (n, o, e) => (e = n != null ? U(m(n)) : {}, b(
o || !n || !n.__esModule ? d(e, "default", { value: n, enumerable: !0 }) : e,
n
)), P = (n) => b(d({}, "__esModule", { value: !0 }), n);
// src/index.ts
var I = {};
_(I, {
SocketIOProvider: () => p
});
module.exports = P(I);
// src/client/provider.ts
var s = l(require("yjs")), i = l(require("lib0/broadcastchannel")), a = l(require("y-protocols/awareness")), w = require("lib0/observable"), f = require("socket.io-client"), p = class extends w.Observable {
constructor(e, t, r = new s.Doc(), {
autoConnect: y = !0,
awareness: c = new a.Awareness(r),
resyncInterval: v = -1,
disableBc: A = !1,
auth: k = {}
}, u = void 0) {
super();
this.bcconnected = !1;
this._synced = !1;
this.resyncInterval = null;
this.initSyncListeners = () => {
this.socket.on("sync-step-1", (e, t) => {
t(s.encodeStateAsUpdate(this.doc, new Uint8Array(e))), this.synced = !0;
}), this.socket.on("sync-update", this.onSocketSyncUpdate);
};
this.initAwarenessListeners = () => {
this.socket.on("awareness-update", (e) => {
a.applyAwarenessUpdate(this.awareness, new Uint8Array(e), this);
});
};
this.initSystemListeners = () => {
typeof window != "undefined" ? window.addEventListener("beforeunload", this.beforeUnloadHandler) : typeof process != "undefined" && process.on("exit", this.beforeUnloadHandler);
};
this.onSocketConnection = (e = -1) => {
this.emit("status", [{ status: "connected" }]), this.socket.emit("sync-step-1", s.encodeStateVector(this.doc), (t) => {
s.applyUpdate(this.doc, new Uint8Array(t), this);
}), this.awareness.getLocalState() !== null && this.socket.emit("awareness-update", a.encodeAwarenessUpdate(this.awareness, [this.doc.clientID])), e > 0 && (this.resyncInterval = setInterval(() => {
this.socket.disconnected || this.socket.emit("sync-step-1", s.encodeStateVector(this.doc), (t) => {
s.applyUpdate(this.doc, new Uint8Array(t), this);
});
}, e));
};
this.onSocketDisconnection = (e) => {
this.emit("connection-close", [e, this]), this.synced = !1, a.removeAwarenessStates(this.awareness, Array.from(this.awareness.getStates().keys()).filter((t) => t !== this.doc.clientID), this), this.emit("status", [{ status: "disconnected" }]);
};
this.onSocketConnectionError = (e) => {
this.emit("connection-error", [e, this]);
};
this.onUpdateDoc = (e, t) => {
t !== this && (this.socket.emit("sync-update", e), this.bcconnected && i.publish(this._broadcastChannel, {
type: "sync-update",
data: e
}, this));
};
this.onSocketSyncUpdate = (e) => {
s.applyUpdate(this.doc, new Uint8Array(e), this);
};
this.awarenessUpdate = ({ added: e, updated: t, removed: r }, y) => {
let c = e.concat(t).concat(r);
this.socket.emit("awareness-update", a.encodeAwarenessUpdate(this.awareness, c)), this.bcconnected && i.publish(this._broadcastChannel, {
type: "awareness-update",
data: a.encodeAwarenessUpdate(this.awareness, c)
}, this);
};
this.beforeUnloadHandler = () => {
a.removeAwarenessStates(this.awareness, [this.doc.clientID], "window unload");
};
this.connectBc = () => {
this.bcconnected || (i.subscribe(this._broadcastChannel, this.onBroadcastChannelMessage), this.bcconnected = !0), i.publish(this._broadcastChannel, { type: "sync-step-1", data: s.encodeStateVector(this.doc) }, this), i.publish(this._broadcastChannel, { type: "sync-step-2", data: s.encodeStateAsUpdate(this.doc) }, this), i.publish(this._broadcastChannel, { type: "query-awareness", data: null }, this), i.publish(this._broadcastChannel, { type: "awareness-update", data: a.encodeAwarenessUpdate(this.awareness, [this.doc.clientID]) }, this);
};
this.disconnectBc = () => {
i.publish(this._broadcastChannel, {
type: "awareness-update",
data: a.encodeAwarenessUpdate(this.awareness, [this.doc.clientID], /* @__PURE__ */ new Map())
}, this), this.bcconnected && (i.unsubscribe(this._broadcastChannel, this.onBroadcastChannelMessage), this.bcconnected = !1);
};
this.onBroadcastChannelMessage = (e, t) => {
if (t !== this && e.type.length > 0)
switch (e.type) {
case "sync-step-1":
i.publish(this._broadcastChannel, {
type: "sync-step-2",
data: s.encodeStateAsUpdate(this.doc, e.data)
}, this);
break;
case "sync-step-2":
s.applyUpdate(this.doc, new Uint8Array(e.data), this);
break;
case "sync-update":
s.applyUpdate(this.doc, new Uint8Array(e.data), this);
break;
case "query-awareness":
i.publish(this._broadcastChannel, {
type: "awareness-update",
data: a.encodeAwarenessUpdate(this.awareness, Array.from(this.awareness.getStates().keys()))
}, this);
break;
case "awareness-update":
a.applyAwarenessUpdate(this.awareness, new Uint8Array(e.data), this);
break;
default:
break;
}
};
for (; e[e.length - 1] === "/"; )
e = e.slice(0, e.length - 1);
this._url = e, this.roomName = t, this.doc = r, this.awareness = c, this._broadcastChannel = `${e}/${t}`, this.disableBc = A, this._socketIoOptions = u, this.socket = (0, f.io)(`${this.url}/yjs|${t}`, {
autoConnect: !1,
transports: ["websocket"],
forceNew: !0,
auth: k,
...u
}), this.doc.on("update", this.onUpdateDoc), this.socket.on("connect", () => this.onSocketConnection(v)), this.socket.on("disconnect", (h) => this.onSocketDisconnection(h)), this.socket.on("connect_error", (h) => this.onSocketConnectionError(h)), this.initSyncListeners(), this.initAwarenessListeners(), this.initSystemListeners(), c.on("update", this.awarenessUpdate), y && this.connect();
}
get broadcastChannel() {
return this._broadcastChannel;
}
get url() {
return this._url;
}
get synced() {
return this._synced;
}
set synced(e) {
this._synced !== e && (this._synced = e, this.emit("synced", [e]), this.emit("sync", [e]));
}
connect() {
this.socket.connected || (this.emit("status", [{ status: "connecting" }]), this.socket.connect(), this.disableBc || this.connectBc(), this.synced = !1);
}
disconnect() {
this.socket.connected && (this.disconnectBc(), this.socket.disconnect());
}
destroy() {
this.resyncInterval != null && clearInterval(this.resyncInterval), this.disconnect(), typeof window != "undefined" ? window.removeEventListener("beforeunload", this.beforeUnloadHandler) : typeof process != "undefined" && process.off("exit", this.beforeUnloadHandler), this.awareness.off("update", this.awarenessUpdate), this.awareness.destroy(), this.doc.off("update", this.onUpdateDoc), super.destroy();
}
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
SocketIOProvider
});
//# sourceMappingURL=index.js.map