@liveblocks/yjs
Advanced tools
Comparing version 1.1.0-yjs5 to 1.1.1-internal2
@@ -5,5 +5,2 @@ import { Room, JsonObject, LsonObject, BaseUserMeta, Json } from '@liveblocks/client'; | ||
declare type LiveblocksYjsOptions = { | ||
httpEndpoint?: string; | ||
}; | ||
declare type MetaClientState = { | ||
@@ -13,7 +10,13 @@ clock: number; | ||
}; | ||
declare class Awareness extends Observable<any> { | ||
/** | ||
* This class will store Yjs awareness in Liveblock's presence under the __yjs key | ||
* IMPORTANT: The Yjs awareness protocol uses ydoc.clientId to reference users | ||
* to their respective documents. To avoid mapping Yjs clientIds to liveblock's connectionId, | ||
* we simply set the clientId of the doc to the connectionId. Then no further mapping is required | ||
*/ | ||
declare class Awareness extends Observable<unknown> { | ||
private room; | ||
doc: Y.Doc; | ||
clientID: number; | ||
states: Map<number, any>; | ||
states: Map<number, unknown>; | ||
meta: Map<number, MetaClientState>; | ||
@@ -27,18 +30,20 @@ _checkInterval: number; | ||
setLocalStateField(field: string, value: JsonObject | null): void; | ||
getStates(): Map<number, any>; | ||
getStates(): Map<number, unknown>; | ||
} | ||
declare class LiveblocksProvider<P extends JsonObject, S extends LsonObject, U extends BaseUserMeta, E extends Json> { | ||
declare class LiveblocksProvider<P extends JsonObject, S extends LsonObject, U extends BaseUserMeta, E extends Json> extends Observable<unknown> { | ||
private room; | ||
private httpEndpoint?; | ||
private lastUpdateDate; | ||
private doc; | ||
private unsubscribers; | ||
awareness: Awareness; | ||
constructor(room: Room<P, S, U, E>, doc: Y.Doc, config?: LiveblocksYjsOptions); | ||
private _synced; | ||
constructor(room: Room<P, S, U, E>, doc: Y.Doc); | ||
private syncDoc; | ||
get synced(): boolean; | ||
set synced(state: boolean); | ||
private updateHandler; | ||
private resyncHttp; | ||
destroy(): void; | ||
disconnect(): void; | ||
connect(): void; | ||
} | ||
export { Awareness, LiveblocksProvider as default }; |
@@ -17,22 +17,2 @@ "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; } }var __defProp = Object.defineProperty; | ||
}; | ||
var __async = (__this, __arguments, generator) => { | ||
return new Promise((resolve, reject) => { | ||
var fulfilled = (value) => { | ||
try { | ||
step(generator.next(value)); | ||
} catch (e) { | ||
reject(e); | ||
} | ||
}; | ||
var rejected = (value) => { | ||
try { | ||
step(generator.throw(value)); | ||
} catch (e) { | ||
reject(e); | ||
} | ||
}; | ||
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); | ||
step((generator = generator.apply(__this, __arguments)).next()); | ||
}); | ||
}; | ||
@@ -114,2 +94,3 @@ // src/index.ts | ||
var _yjs = require('yjs'); var Y = _interopRequireWildcard(_yjs); | ||
var Y_PRESENCE_KEY = "__yjs"; | ||
var Awareness = class extends Observable { | ||
@@ -123,3 +104,3 @@ constructor(doc, room) { | ||
// _checkInterval this would hold a timer to remove users, but Liveblock's presence already handles this | ||
// unfortunately it's expected to exist by various integrations. | ||
// unfortunately it's typed by various integrations | ||
this._checkInterval = 0; | ||
@@ -158,10 +139,10 @@ this.doc = doc; | ||
const presence = this.room.getPresence(); | ||
if (Object.keys(this.room.getPresence()).length === 0) { | ||
if (Object.keys(presence).length === 0 || typeof presence[Y_PRESENCE_KEY] === "undefined") { | ||
return null; | ||
} | ||
return presence["__yjs"]; | ||
return presence[Y_PRESENCE_KEY]; | ||
} | ||
setLocalState(state) { | ||
var _a; | ||
const presence = (_a = this.room.getSelf()) == null ? void 0 : _a.presence["__yjs"]; | ||
const presence = (_a = this.room.getSelf()) == null ? void 0 : _a.presence[Y_PRESENCE_KEY]; | ||
this.room.updatePresence({ | ||
@@ -173,3 +154,3 @@ __yjs: __spreadValues(__spreadValues({}, presence || {}), state || {}) | ||
var _a; | ||
const presence = (_a = this.room.getSelf()) == null ? void 0 : _a.presence["__yjs"]; | ||
const presence = (_a = this.room.getSelf()) == null ? void 0 : _a.presence[Y_PRESENCE_KEY]; | ||
const update = { [field]: value }; | ||
@@ -187,3 +168,3 @@ this.room.updatePresence({ | ||
currentValue.connectionId, | ||
currentValue.presence["__yjs"] || {} | ||
currentValue.presence[Y_PRESENCE_KEY] || {} | ||
); | ||
@@ -196,26 +177,22 @@ } | ||
}; | ||
var LiveblocksProvider = class { | ||
constructor(room, doc, config) { | ||
this.lastUpdateDate = null; | ||
var LiveblocksProvider = class extends Observable { | ||
constructor(room, doc) { | ||
var _a; | ||
super(); | ||
this.unsubscribers = []; | ||
this._synced = false; | ||
this.syncDoc = () => { | ||
var _a; | ||
this.synced = false; | ||
this.doc.clientID = ((_a = this.room.getSelf()) == null ? void 0 : _a.connectionId) || this.doc.clientID; | ||
this.awareness.clientID = this.doc.clientID; | ||
const encodedVector = _jsbase64.Base64.fromUint8Array(Y.encodeStateVector(this.doc)); | ||
this.room.getYDoc(encodedVector); | ||
this.room.fetchYDoc(encodedVector); | ||
}; | ||
this.updateHandler = (update, origin) => __async(this, null, function* () { | ||
this.updateHandler = (update, origin) => { | ||
if (origin !== "backend") { | ||
const encodedUpdate = _jsbase64.Base64.fromUint8Array(update); | ||
this.room.updateYDoc(encodedUpdate); | ||
if (this.httpEndpoint) { | ||
yield fetch(this.httpEndpoint, { | ||
method: "POST", | ||
body: encodedUpdate | ||
}); | ||
} | ||
} | ||
}); | ||
var _a; | ||
}; | ||
this.doc = doc; | ||
@@ -230,4 +207,4 @@ this.room = room; | ||
this.unsubscribers.push( | ||
this.room.events.connection.subscribe((e) => { | ||
if (e === "open") { | ||
this.room.events.status.subscribe((status) => { | ||
if (status === "connected") { | ||
this.syncDoc(); | ||
@@ -238,36 +215,20 @@ } | ||
this.unsubscribers.push( | ||
this.room.events.docUpdated.subscribe((update) => { | ||
this.room.events.ydoc.subscribe((update) => { | ||
Y.applyUpdate(this.doc, _jsbase64.Base64.toUint8Array(update), "backend"); | ||
this.synced = true; | ||
}) | ||
); | ||
if (config == null ? void 0 : config.httpEndpoint) { | ||
this.httpEndpoint = config.httpEndpoint + "?room=" + this.room.id; | ||
this.unsubscribers.push( | ||
this.room.events.customEvent.subscribe(({ event }) => { | ||
if ((event == null ? void 0 : event.type) === "REFRESH") { | ||
void this.resyncHttp(); | ||
} | ||
}) | ||
); | ||
void this.resyncHttp(); | ||
} | ||
this.syncDoc(); | ||
} | ||
resyncHttp() { | ||
return __async(this, null, function* () { | ||
if (!this.httpEndpoint) { | ||
return; | ||
} | ||
const response = yield fetch( | ||
`${this.httpEndpoint}${this.lastUpdateDate !== null ? `&after=${this.lastUpdateDate.toISOString()}` : ""}` | ||
); | ||
const { updates, lastUpdate } = yield response.json(); | ||
if (updates.length === 0) { | ||
return; | ||
} | ||
this.lastUpdateDate = new Date(lastUpdate); | ||
const update = Y.mergeUpdates(updates.map(_jsbase64.Base64.toUint8Array)); | ||
Y.applyUpdate(this.doc, update, "backend"); | ||
}); | ||
// 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() { | ||
@@ -278,2 +239,7 @@ this.doc.off("update", this.updateHandler); | ||
} | ||
// Some provider implementations expect to be able to call connect/disconnect, implement as noop | ||
disconnect() { | ||
} | ||
connect() { | ||
} | ||
}; | ||
@@ -280,0 +246,0 @@ |
{ | ||
"name": "@liveblocks/yjs", | ||
"version": "1.1.0-yjs5", | ||
"version": "1.1.1-internal2", | ||
"description": "An integration with . Liveblocks is the all-in-one toolkit to build collaborative products like Figma, Notion, and more.", | ||
@@ -14,5 +14,6 @@ "license": "Apache-2.0", | ||
"dev": "tsup --watch", | ||
"build": "tsup --format cjs,esm --dts --clean", | ||
"build": "tsup && cp dist/index.d.ts dist/index.d.mts", | ||
"format": "eslint --fix src/; prettier --write src/", | ||
"lint": "eslint src/", | ||
"lint:package": "publint --strict && attw --pack", | ||
"test": "jest --silent --verbose --color=always", | ||
@@ -24,10 +25,15 @@ "test:types": "tsd", | ||
".": { | ||
"require": "./dist/index.js", | ||
"import": "./dist/index.mjs", | ||
"types": "./dist/index.d.ts" | ||
"import": { | ||
"types": "./dist/index.d.mts", | ||
"default": "./dist/index.mjs" | ||
}, | ||
"require": { | ||
"types": "./dist/index.d.ts", | ||
"default": "./dist/index.js" | ||
} | ||
} | ||
}, | ||
"dependencies": { | ||
"@liveblocks/client": "1.1.0-yjs5", | ||
"@liveblocks/core": "1.1.0-yjs5", | ||
"@liveblocks/client": "1.1.1-internal2", | ||
"@liveblocks/core": "1.1.1-internal2", | ||
"js-base64": "^3.7.5" | ||
@@ -34,0 +40,0 @@ }, |
@@ -12,3 +12,3 @@ <p align="center"> | ||
Provides YJS integration to effortlessly back your YJS apps with Liveblocks | ||
Provides Yjs integration to effortlessly back your Yjs apps with Liveblocks | ||
@@ -15,0 +15,0 @@ ## Installation |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
6
0
21159
508
11
25
1
+ Added@liveblocks/client@1.1.1-internal2(transitive)
+ Added@liveblocks/core@1.1.1-internal2(transitive)
- Removed@liveblocks/client@1.1.0-yjs5(transitive)
- Removed@liveblocks/core@1.1.0-yjs5(transitive)