@liveblocks/yjs
Advanced tools
Comparing version
@@ -1,2 +0,3 @@ | ||
import { Room, JsonObject, LsonObject, BaseUserMeta, Json } from '@liveblocks/client'; | ||
import { JsonObject, LsonObject, BaseUserMeta, Json, BaseMetadata, Room, User } from '@liveblocks/client'; | ||
import { BaseMetadata as BaseMetadata$1 } from '@liveblocks/core'; | ||
import { Observable } from 'lib0/observable'; | ||
@@ -15,11 +16,12 @@ import * as Y from 'yjs'; | ||
*/ | ||
declare class Awareness extends Observable<unknown> { | ||
declare class Awareness<P extends JsonObject, S extends LsonObject, U extends BaseUserMeta, E extends Json, M extends BaseMetadata> extends Observable<unknown> { | ||
private room; | ||
doc: Y.Doc; | ||
clientID: number; | ||
states: Map<number, unknown>; | ||
actorToClientMap: Map<number, number>; | ||
meta: Map<number, MetaClientState>; | ||
_checkInterval: number; | ||
private othersUnsub; | ||
constructor(doc: Y.Doc, room: Room<JsonObject, LsonObject, BaseUserMeta, Json>); | ||
constructor(doc: Y.Doc, room: Room<P, S, U, E, M>); | ||
rebuildActorToClientMap(others: readonly User<JsonObject, BaseUserMeta>[]): void; | ||
destroy(): void; | ||
@@ -58,3 +60,3 @@ getLocalState(): JsonObject | null; | ||
}; | ||
declare class LiveblocksProvider<P extends JsonObject, S extends LsonObject, U extends BaseUserMeta, E extends Json> extends Observable<unknown> { | ||
declare class LiveblocksProvider<P extends JsonObject, S extends LsonObject, U extends BaseUserMeta, E extends Json, M extends BaseMetadata$1> extends Observable<unknown> { | ||
private room; | ||
@@ -64,6 +66,6 @@ private rootDoc; | ||
private unsubscribers; | ||
awareness: Awareness; | ||
awareness: Awareness<P, S, U, E, M>; | ||
rootDocHandler: yDocHandler; | ||
subdocHandlers: Map<string, yDocHandler>; | ||
constructor(room: Room<P, S, U, E>, doc: Y.Doc, options?: ProviderOptions | undefined); | ||
constructor(room: Room<P, S, U, E, M>, doc: Y.Doc, options?: ProviderOptions | undefined); | ||
private handleSubdocs; | ||
@@ -70,0 +72,0 @@ private updateDoc; |
@@ -76,2 +76,3 @@ "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 Y_PRESENCE_KEY = "__yjs"; | ||
var Y_PRESENCE_ID_KEY = "__yjs_clientid"; | ||
var Awareness = class extends Observable { | ||
@@ -81,2 +82,4 @@ constructor(doc, room) { | ||
this.states = /* @__PURE__ */ new Map(); | ||
// used to map liveblock's ActorId to Yjs ClientID, both unique numbers representing a client | ||
this.actorToClientMap = /* @__PURE__ */ new Map(); | ||
// Meta is used to keep track and timeout users who disconnect. Liveblocks provides this for us, so we don't need to | ||
@@ -90,24 +93,47 @@ // manage it here. Unfortunately, it's expected to exist by various integrations, so it's an empty map. | ||
this.room = room; | ||
this.clientID = doc.clientID; | ||
this.room.updatePresence({ | ||
[Y_PRESENCE_ID_KEY]: this.doc.clientID | ||
}); | ||
this.othersUnsub = this.room.events.others.subscribe((event) => { | ||
let updates; | ||
this.rebuildActorToClientMap(event.others); | ||
if (event.type === "leave") { | ||
this.emit("change", [ | ||
{ added: [], updated: [], removed: [event.user.connectionId] }, | ||
"local" | ||
]); | ||
const targetClientId = this.actorToClientMap.get( | ||
event.user.connectionId | ||
); | ||
if (targetClientId !== void 0) { | ||
updates = { added: [], updated: [], removed: [targetClientId] }; | ||
} | ||
this.rebuildActorToClientMap(event.others); | ||
} | ||
if (event.type === "enter") { | ||
this.emit("change", [ | ||
{ added: [event.user.connectionId], updated: [], removed: [] }, | ||
"local" | ||
]); | ||
if (event.type === "enter" || event.type === "update") { | ||
this.rebuildActorToClientMap(event.others); | ||
const targetClientId = this.actorToClientMap.get( | ||
event.user.connectionId | ||
); | ||
if (targetClientId !== void 0) { | ||
updates = { | ||
added: event.type === "enter" ? [targetClientId] : [], | ||
updated: event.type === "update" ? [targetClientId] : [], | ||
removed: [] | ||
}; | ||
} | ||
} | ||
if (event.type === "update") { | ||
this.emit("change", [ | ||
{ added: [], updated: [event.user.connectionId], removed: [] }, | ||
"local" | ||
]); | ||
if (updates !== void 0) { | ||
this.emit("change", [updates, "presence"]); | ||
this.emit("update", [updates, "presence"]); | ||
} | ||
}); | ||
} | ||
rebuildActorToClientMap(others) { | ||
this.actorToClientMap.clear(); | ||
others.forEach((user) => { | ||
if (user.presence[Y_PRESENCE_ID_KEY] !== void 0) { | ||
this.actorToClientMap.set( | ||
user.connectionId, | ||
user.presence[Y_PRESENCE_ID_KEY] | ||
); | ||
} | ||
}); | ||
} | ||
destroy() { | ||
@@ -127,6 +153,24 @@ this.emit("destroy", [this]); | ||
setLocalState(state) { | ||
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]]); | ||
const presence = _optionalChain([this, 'access', _2 => _2.room, 'access', _3 => _3.getSelf, 'call', _4 => _4(), 'optionalAccess', _5 => _5.presence]); | ||
if (state === null) { | ||
if (presence === void 0) { | ||
return; | ||
} | ||
this.room.updatePresence({ ...presence, [Y_PRESENCE_KEY]: null }); | ||
this.emit("update", [ | ||
{ added: [], updated: [], removed: [this.doc.clientID] }, | ||
"local" | ||
]); | ||
return; | ||
} | ||
const yPresence = _optionalChain([presence, 'optionalAccess', _6 => _6[Y_PRESENCE_KEY]]); | ||
const added = yPresence === void 0 ? [this.doc.clientID] : []; | ||
const updated = yPresence === void 0 ? [] : [this.doc.clientID]; | ||
this.room.updatePresence({ | ||
__yjs: { ...presence || {}, ...state || {} } | ||
[Y_PRESENCE_KEY]: { | ||
...yPresence || {}, | ||
...state || {} | ||
} | ||
}); | ||
this.emit("update", [{ added, updated, removed: [] }, "local"]); | ||
} | ||
@@ -137,3 +181,3 @@ setLocalStateField(field, value) { | ||
this.room.updatePresence({ | ||
__yjs: { ...presence || {}, ...update } | ||
[Y_PRESENCE_KEY]: { ...presence || {}, ...update } | ||
}); | ||
@@ -144,11 +188,14 @@ } | ||
const others = this.room.getOthers(); | ||
const states = others.reduce((acc, currentValue) => { | ||
if (currentValue.connectionId) { | ||
acc.set( | ||
currentValue.connectionId, | ||
currentValue.presence[Y_PRESENCE_KEY] || {} | ||
); | ||
const states = others.reduce((acc, otherUser) => { | ||
const otherPresence = otherUser.presence[Y_PRESENCE_KEY]; | ||
const otherClientId = otherUser.presence[Y_PRESENCE_ID_KEY]; | ||
if (otherPresence !== void 0 && otherClientId !== void 0) { | ||
acc.set(otherClientId, otherPresence || {}); | ||
} | ||
return acc; | ||
}, /* @__PURE__ */ new Map()); | ||
const localPresence = _optionalChain([this, 'access', _12 => _12.room, 'access', _13 => _13.getSelf, 'call', _14 => _14(), 'optionalAccess', _15 => _15.presence, 'access', _16 => _16[Y_PRESENCE_KEY]]); | ||
if (localPresence !== void 0) { | ||
states.set(this.doc.clientID, localPresence); | ||
} | ||
return states; | ||
@@ -231,3 +278,3 @@ } | ||
var PKG_NAME = "@liveblocks/yjs"; | ||
var PKG_VERSION = "1.19.0-test1"; | ||
var PKG_VERSION = "2.0.0-alpha1"; | ||
var PKG_FORMAT = "cjs"; | ||
@@ -260,3 +307,3 @@ | ||
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()]); | ||
_optionalChain([this, 'access', _17 => _17.subdocHandlers, 'access', _18 => _18.get, 'call', _19 => _19(subdoc.guid), 'optionalAccess', _20 => _20.destroy, 'call', _21 => _21()]); | ||
this.subdocHandlers.delete(subdoc.guid); | ||
@@ -274,3 +321,3 @@ } | ||
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()]); | ||
_optionalChain([this, 'access', _22 => _22.subdocHandlers, 'access', _23 => _23.get, 'call', _24 => _24(subdoc.guid), 'optionalAccess', _25 => _25.syncDoc, 'call', _26 => _26()]); | ||
return; | ||
@@ -297,4 +344,2 @@ } | ||
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(); | ||
@@ -314,6 +359,2 @@ for (const [_, handler] of this.subdocHandlers) { | ||
}); | ||
const connectionId = _optionalChain([this, 'access', _26 => _26.room, 'access', _27 => _27.getSelf, 'call', _28 => _28(), 'optionalAccess', _29 => _29.connectionId]); | ||
if (connectionId) { | ||
this.rootDoc.clientID = connectionId; | ||
} | ||
this.awareness = new Awareness(this.rootDoc, this.room); | ||
@@ -337,3 +378,3 @@ this.unsubscribers.push( | ||
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 })]); | ||
_optionalChain([this, 'access', _27 => _27.subdocHandlers, 'access', _28 => _28.get, 'call', _29 => _29(guid), 'optionalAccess', _30 => _30.handleServerUpdate, 'call', _31 => _31({ update, stateVector })]); | ||
} else { | ||
@@ -340,0 +381,0 @@ this.rootDocHandler.handleServerUpdate({ update, stateVector }); |
{ | ||
"name": "@liveblocks/yjs", | ||
"version": "1.19.0-test1", | ||
"version": "2.0.0-alpha1", | ||
"description": "An integration with . Liveblocks is the all-in-one toolkit to build collaborative products like Figma, Notion, and more.", | ||
"license": "Apache-2.0", | ||
"type": "commonjs", | ||
"main": "./dist/index.js", | ||
@@ -27,3 +28,3 @@ "types": "./dist/index.d.ts", | ||
"dev": "tsup --watch", | ||
"build": "tsup && cp dist/index.d.ts dist/index.d.mts", | ||
"build": "tsup", | ||
"format": "eslint --fix src/; prettier --write src/", | ||
@@ -36,4 +37,4 @@ "lint": "eslint src/", | ||
"dependencies": { | ||
"@liveblocks/client": "1.19.0-test1", | ||
"@liveblocks/core": "1.19.0-test1", | ||
"@liveblocks/client": "2.0.0-alpha1", | ||
"@liveblocks/core": "2.0.0-alpha1", | ||
"js-base64": "^3.7.5" | ||
@@ -40,0 +41,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
104261
17.43%874
10.63%+ Added
+ Added
- Removed
- Removed