@liveblocks/yjs
Advanced tools
Comparing version 1.4.8 to 1.5.0-subdoc
@@ -30,13 +30,45 @@ import { Room, JsonObject, LsonObject, BaseUserMeta, Json } from '@liveblocks/client'; | ||
} | ||
declare class yDocHandler extends Observable<unknown> { | ||
private unsubscribers; | ||
private _synced; | ||
private doc; | ||
private updateRoomDoc; | ||
private fetchRoomDoc; | ||
constructor({ doc, isRoot, updateDoc, fetchDoc, }: { | ||
doc: Y.Doc; | ||
isRoot: boolean; | ||
updateDoc: (update: string, guid?: string) => void; | ||
fetchDoc: (vector: string, guid?: string) => void; | ||
}); | ||
handleServerUpdate: ({ update, stateVector, }: { | ||
update: string; | ||
stateVector: string | null; | ||
}) => void; | ||
syncDoc: () => void; | ||
get synced(): boolean; | ||
set synced(state: boolean); | ||
private updateHandler; | ||
destroy(): void; | ||
} | ||
declare type ProviderOptions = { | ||
autoloadSubdocs: boolean; | ||
}; | ||
declare class LiveblocksProvider<P extends JsonObject, S extends LsonObject, U extends BaseUserMeta, E extends Json> extends Observable<unknown> { | ||
private room; | ||
private doc; | ||
private rootDoc; | ||
private options; | ||
private unsubscribers; | ||
awareness: Awareness; | ||
private _synced; | ||
constructor(room: Room<P, S, U, E>, doc: Y.Doc); | ||
rootDocHandler: yDocHandler; | ||
subdocHandlers: Map<string, yDocHandler>; | ||
constructor(room: Room<P, S, U, E>, doc: Y.Doc, options?: ProviderOptions | undefined); | ||
private handleSubdocs; | ||
private updateDoc; | ||
private fetchDoc; | ||
private createSubdocHandler; | ||
loadSubdoc: (guid: string) => boolean; | ||
private syncDoc; | ||
get synced(): boolean; | ||
set synced(state: boolean); | ||
private updateHandler; | ||
destroy(): void; | ||
@@ -47,2 +79,2 @@ disconnect(): void; | ||
export { Awareness, LiveblocksProvider as default }; | ||
export { LiveblocksProvider as default }; |
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/index.ts | ||
var _core = require('@liveblocks/core'); | ||
var _jsbase64 = require('js-base64'); | ||
@@ -75,12 +74,3 @@ // ../../node_modules/lib0/map.js | ||
// src/index.ts | ||
var _yjs = require('yjs'); var Y = _interopRequireWildcard(_yjs); | ||
// src/version.ts | ||
var PKG_NAME = "@liveblocks/yjs"; | ||
var PKG_VERSION = "1.4.8"; | ||
var PKG_FORMAT = "cjs"; | ||
// src/index.ts | ||
_core.detectDupes.call(void 0, PKG_NAME, PKG_VERSION, PKG_FORMAT); | ||
// src/awareness.ts | ||
var Y_PRESENCE_KEY = "__yjs"; | ||
@@ -100,3 +90,3 @@ var Awareness = class extends Observable { | ||
this.clientID = doc.clientID; | ||
this.othersUnsub = this.room.events.others.subscribe(({ event }) => { | ||
this.othersUnsub = this.room.events.others.subscribe((event) => { | ||
if (event.type === "leave") { | ||
@@ -136,3 +126,3 @@ this.emit("change", [ | ||
setLocalState(state) { | ||
const presence = _optionalChain([this, 'access', _ => _.room, 'access', _2 => _2.getSelf, 'call', _3 => _3(), 'optionalAccess', _4 => _4.presence, 'access', _5 => _5[Y_PRESENCE_KEY]]); | ||
const presence = _optionalChain([this, 'access', _2 => _2.room, 'access', _3 => _3.getSelf, 'call', _4 => _4(), 'optionalAccess', _5 => _5.presence, 'access', _6 => _6[Y_PRESENCE_KEY]]); | ||
this.room.updatePresence({ | ||
@@ -143,3 +133,3 @@ __yjs: { ...presence || {}, ...state || {} } | ||
setLocalStateField(field, value) { | ||
const presence = _optionalChain([this, 'access', _6 => _6.room, 'access', _7 => _7.getSelf, 'call', _8 => _8(), 'optionalAccess', _9 => _9.presence, 'access', _10 => _10[Y_PRESENCE_KEY]]); | ||
const presence = _optionalChain([this, 'access', _7 => _7.room, 'access', _8 => _8.getSelf, 'call', _9 => _9(), 'optionalAccess', _10 => _10.presence, 'access', _11 => _11[Y_PRESENCE_KEY]]); | ||
const update = { [field]: value }; | ||
@@ -165,13 +155,47 @@ this.room.updatePresence({ | ||
}; | ||
var LiveblocksProvider = class extends Observable { | ||
constructor(room, doc) { | ||
// src/doc.ts | ||
var _jsbase64 = require('js-base64'); | ||
var _yjs = require('yjs'); var Y = _interopRequireWildcard(_yjs); | ||
// src/version.ts | ||
var PKG_NAME = "@liveblocks/yjs"; | ||
var PKG_VERSION = "1.5.0-subdoc"; | ||
var PKG_FORMAT = "cjs"; | ||
// src/doc.ts | ||
_core.detectDupes.call(void 0, PKG_NAME, PKG_VERSION, PKG_FORMAT); | ||
var yDocHandler = class extends Observable { | ||
constructor({ | ||
doc, | ||
isRoot, | ||
updateDoc, | ||
fetchDoc | ||
}) { | ||
super(); | ||
this.unsubscribers = []; | ||
this._synced = false; | ||
this.handleServerUpdate = ({ | ||
update, | ||
stateVector | ||
}) => { | ||
Y.applyUpdate(this.doc, _jsbase64.Base64.toUint8Array(update), "backend"); | ||
if (stateVector) { | ||
try { | ||
const localUpdate = Y.encodeStateAsUpdate( | ||
this.doc, | ||
_jsbase64.Base64.toUint8Array(stateVector) | ||
); | ||
this.updateRoomDoc(_jsbase64.Base64.fromUint8Array(localUpdate)); | ||
} catch (e) { | ||
console.warn(e); | ||
} | ||
this.synced = true; | ||
} | ||
}; | ||
this.syncDoc = () => { | ||
this.synced = false; | ||
this.doc.clientID = _optionalChain([this, 'access', _11 => _11.room, 'access', _12 => _12.getSelf, 'call', _13 => _13(), 'optionalAccess', _14 => _14.connectionId]) || this.doc.clientID; | ||
this.awareness.clientID = this.doc.clientID; | ||
const encodedVector = _jsbase64.Base64.fromUint8Array(Y.encodeStateVector(this.doc)); | ||
this.room.fetchYDoc(encodedVector); | ||
this.fetchRoomDoc(encodedVector); | ||
}; | ||
@@ -181,19 +205,121 @@ this.updateHandler = (update, origin) => { | ||
const encodedUpdate = _jsbase64.Base64.fromUint8Array(update); | ||
this.room.updateYDoc(encodedUpdate); | ||
this.updateRoomDoc(encodedUpdate); | ||
} | ||
}; | ||
this.doc = doc; | ||
this.doc.on("update", this.updateHandler); | ||
this.updateRoomDoc = (update) => { | ||
updateDoc(update, isRoot ? void 0 : this.doc.guid); | ||
}; | ||
this.fetchRoomDoc = (vector) => { | ||
fetchDoc(vector, isRoot ? void 0 : this.doc.guid); | ||
}; | ||
this.syncDoc(); | ||
} | ||
// The sync'd property is required by some provider implementations | ||
get synced() { | ||
return this._synced; | ||
} | ||
set synced(state) { | ||
if (this._synced !== state) { | ||
this._synced = state; | ||
this.emit("synced", [state]); | ||
this.emit("sync", [state]); | ||
} | ||
} | ||
destroy() { | ||
this.doc.off("update", this.updateHandler); | ||
this.unsubscribers.forEach((unsub) => unsub()); | ||
this._observers = /* @__PURE__ */ new Map(); | ||
this.doc.destroy(); | ||
} | ||
}; | ||
// src/index.ts | ||
_core.detectDupes.call(void 0, PKG_NAME, PKG_VERSION, PKG_FORMAT); | ||
var DefaultOptions = { | ||
autoloadSubdocs: false | ||
}; | ||
var LiveblocksProvider = class extends Observable { | ||
constructor(room, doc, options = DefaultOptions) { | ||
super(); | ||
this.unsubscribers = []; | ||
this.subdocHandlers = /* @__PURE__ */ new Map(); | ||
this.handleSubdocs = ({ | ||
loaded, | ||
removed, | ||
added | ||
}) => { | ||
loaded.forEach(this.createSubdocHandler); | ||
if (this.options.autoloadSubdocs) { | ||
for (const subdoc of added) { | ||
if (!this.subdocHandlers.has(subdoc.guid)) { | ||
subdoc.load(); | ||
} | ||
} | ||
} | ||
for (const subdoc of removed) { | ||
if (this.subdocHandlers.has(subdoc.guid)) { | ||
_optionalChain([this, 'access', _12 => _12.subdocHandlers, 'access', _13 => _13.get, 'call', _14 => _14(subdoc.guid), 'optionalAccess', _15 => _15.destroy, 'call', _16 => _16()]); | ||
this.subdocHandlers.delete(subdoc.guid); | ||
} | ||
} | ||
}; | ||
this.updateDoc = (update, guid) => { | ||
this.room.updateYDoc(update, guid); | ||
}; | ||
this.fetchDoc = (vector, guid) => { | ||
this.room.fetchYDoc(vector, guid); | ||
}; | ||
this.createSubdocHandler = (subdoc) => { | ||
if (this.subdocHandlers.has(subdoc.guid)) { | ||
_optionalChain([this, 'access', _17 => _17.subdocHandlers, 'access', _18 => _18.get, 'call', _19 => _19(subdoc.guid), 'optionalAccess', _20 => _20.syncDoc, 'call', _21 => _21()]); | ||
return; | ||
} | ||
const handler = new yDocHandler({ | ||
doc: subdoc, | ||
isRoot: false, | ||
updateDoc: this.updateDoc, | ||
fetchDoc: this.fetchDoc | ||
}); | ||
this.subdocHandlers.set(subdoc.guid, handler); | ||
}; | ||
// attempt to load a subdoc of a given guid | ||
this.loadSubdoc = (guid) => { | ||
for (const subdoc of this.rootDoc.subdocs) { | ||
if (subdoc.guid === guid) { | ||
subdoc.load(); | ||
return true; | ||
} | ||
} | ||
return false; | ||
}; | ||
this.syncDoc = () => { | ||
this.rootDoc.clientID = _optionalChain([this, 'access', _22 => _22.room, 'access', _23 => _23.getSelf, 'call', _24 => _24(), 'optionalAccess', _25 => _25.connectionId]) || this.rootDoc.clientID; | ||
this.awareness.clientID = this.rootDoc.clientID; | ||
this.rootDocHandler.syncDoc(); | ||
for (const [_, handler] of this.subdocHandlers) { | ||
handler.syncDoc(); | ||
} | ||
}; | ||
this.rootDoc = doc; | ||
this.room = room; | ||
const connectionId = _optionalChain([this, 'access', _15 => _15.room, 'access', _16 => _16.getSelf, 'call', _17 => _17(), 'optionalAccess', _18 => _18.connectionId]); | ||
this.options = options; | ||
this.rootDocHandler = new yDocHandler({ | ||
doc, | ||
isRoot: true, | ||
updateDoc: this.updateDoc, | ||
fetchDoc: this.fetchDoc | ||
}); | ||
const connectionId = _optionalChain([this, 'access', _26 => _26.room, 'access', _27 => _27.getSelf, 'call', _28 => _28(), 'optionalAccess', _29 => _29.connectionId]); | ||
if (connectionId) { | ||
this.doc.clientID = connectionId; | ||
this.rootDoc.clientID = connectionId; | ||
} | ||
this.awareness = new Awareness(this.doc, this.room); | ||
this.doc.on("update", this.updateHandler); | ||
this.awareness = new Awareness(this.rootDoc, this.room); | ||
this.unsubscribers.push( | ||
this.room.events.status.subscribe((status) => { | ||
if (status === "connected") { | ||
this.syncDoc(); | ||
this.rootDocHandler.syncDoc(); | ||
} else { | ||
this.synced = false; | ||
this.rootDocHandler.synced = false; | ||
} | ||
@@ -204,22 +330,23 @@ }) | ||
this.room.events.ydoc.subscribe((message) => { | ||
const { type, update } = message; | ||
const { type } = message; | ||
if (type === _core.ClientMsgCode.UPDATE_YDOC) { | ||
return; | ||
} | ||
Y.applyUpdate(this.doc, _jsbase64.Base64.toUint8Array(update), "backend"); | ||
const { stateVector } = message; | ||
if (stateVector) { | ||
try { | ||
const localUpdate = Y.encodeStateAsUpdate( | ||
this.doc, | ||
_jsbase64.Base64.toUint8Array(stateVector) | ||
); | ||
this.room.updateYDoc(_jsbase64.Base64.fromUint8Array(localUpdate)); | ||
} catch (e) { | ||
console.warn(e); | ||
} | ||
this.synced = true; | ||
const { stateVector, update, guid } = message; | ||
if (guid !== void 0) { | ||
_optionalChain([this, 'access', _30 => _30.subdocHandlers, 'access', _31 => _31.get, 'call', _32 => _32(guid), 'optionalAccess', _33 => _33.handleServerUpdate, 'call', _34 => _34({ update, stateVector })]); | ||
} else { | ||
this.rootDocHandler.handleServerUpdate({ update, stateVector }); | ||
} | ||
}) | ||
); | ||
this.rootDocHandler.on("synced", () => { | ||
const state = this.rootDocHandler.synced; | ||
for (const [_, handler] of this.subdocHandlers) { | ||
handler.syncDoc(); | ||
} | ||
this.emit("synced", [state]); | ||
this.emit("sync", [state]); | ||
}); | ||
this.rootDoc.on("subdocs", this.handleSubdocs); | ||
this.syncDoc(); | ||
@@ -229,15 +356,13 @@ } | ||
get synced() { | ||
return this._synced; | ||
return this.rootDocHandler.synced; | ||
} | ||
set synced(state) { | ||
if (this._synced !== state) { | ||
this._synced = state; | ||
this.emit("synced", [state]); | ||
this.emit("sync", [state]); | ||
} | ||
} | ||
destroy() { | ||
this.doc.off("update", this.updateHandler); | ||
this.unsubscribers.forEach((unsub) => unsub()); | ||
this.awareness.destroy(); | ||
this.rootDocHandler.destroy(); | ||
this._observers = /* @__PURE__ */ new Map(); | ||
for (const [_, handler] of this.subdocHandlers) { | ||
handler.destroy(); | ||
} | ||
this.subdocHandlers.clear(); | ||
super.destroy(); | ||
@@ -253,4 +378,3 @@ } | ||
exports.Awareness = Awareness; exports.default = LiveblocksProvider; | ||
exports.default = LiveblocksProvider; | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "@liveblocks/yjs", | ||
"version": "1.4.8", | ||
"version": "1.5.0-subdoc", | ||
"description": "An integration with . Liveblocks is the all-in-one toolkit to build collaborative products like Figma, Notion, and more.", | ||
@@ -35,4 +35,4 @@ "license": "Apache-2.0", | ||
"dependencies": { | ||
"@liveblocks/client": "1.4.8", | ||
"@liveblocks/core": "1.4.8", | ||
"@liveblocks/client": "1.5.0-subdoc", | ||
"@liveblocks/core": "1.5.0-subdoc", | ||
"js-base64": "^3.7.5" | ||
@@ -39,0 +39,0 @@ }, |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
89474
795
1
+ Added@liveblocks/client@1.5.0-subdoc(transitive)
+ Added@liveblocks/core@1.5.0-subdoc(transitive)
- Removed@liveblocks/client@1.4.8(transitive)
- Removed@liveblocks/core@1.4.8(transitive)