Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@liveblocks/yjs

Package Overview
Dependencies
Maintainers
6
Versions
212
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@liveblocks/yjs - npm Package Compare versions

Comparing version 1.1.0-yjs5 to 1.1.1-dual1

dist/index.d.mts

27

dist/index.d.ts

@@ -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 };

@@ -1,273 +0,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 __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
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());
});
};
// src/index.ts
var _jsbase64 = require('js-base64');
// ../../node_modules/lib0/map.js
var create = () => /* @__PURE__ */ new Map();
var setIfUndefined = (map, key, createT) => {
let set = map.get(key);
if (set === void 0) {
map.set(key, set = createT());
}
return set;
};
// ../../node_modules/lib0/set.js
var create2 = () => /* @__PURE__ */ new Set();
// ../../node_modules/lib0/array.js
var from = Array.from;
var isArray = Array.isArray;
// ../../node_modules/lib0/observable.js
var Observable = class {
constructor() {
this._observers = create();
}
/**
* @param {N} name
* @param {function} f
*/
on(name, f) {
setIfUndefined(this._observers, name, create2).add(f);
}
/**
* @param {N} name
* @param {function} f
*/
once(name, f) {
const _f = (...args) => {
this.off(name, _f);
f(...args);
};
this.on(name, _f);
}
/**
* @param {N} name
* @param {function} f
*/
off(name, f) {
const observers = this._observers.get(name);
if (observers !== void 0) {
observers.delete(f);
if (observers.size === 0) {
this._observers.delete(name);
}
}
}
/**
* Emit a named event. All registered event listeners that listen to the
* specified name will receive the event.
*
* @todo This should catch exceptions
*
* @param {N} name The event name.
* @param {Array<any>} args The arguments that are applied to the event listener.
*/
emit(name, args) {
return from((this._observers.get(name) || create()).values()).forEach((f) => f(...args));
}
destroy() {
this._observers = create();
}
};
// src/index.ts
var _yjs = require('yjs'); var Y = _interopRequireWildcard(_yjs);
var Awareness = class extends Observable {
constructor(doc, room) {
super();
this.states = /* @__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
// manage it here. Unfortunately, it's expected to exist by various integrations, so it's an empty map.
this.meta = /* @__PURE__ */ new Map();
// _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.
this._checkInterval = 0;
this.doc = doc;
this.room = room;
this.clientID = doc.clientID;
this.othersUnsub = this.room.events.others.subscribe(({ event }) => {
if (event.type === "leave") {
this.emit("change", [
{ added: [], updated: [], removed: [event.user.connectionId] },
"local"
]);
}
if (event.type === "enter") {
this.emit("change", [
{ added: [event.user.connectionId], updated: [], removed: [] },
"local"
]);
}
if (event.type === "update") {
this.emit("change", [
{ added: [], updated: [event.user.connectionId], removed: [] },
"local"
]);
}
});
}
destroy() {
this.emit("destroy", [this]);
this.othersUnsub();
this.setLocalState(null);
super.destroy();
}
getLocalState() {
const presence = this.room.getPresence();
if (Object.keys(this.room.getPresence()).length === 0) {
return null;
}
return presence["__yjs"];
}
setLocalState(state) {
var _a;
const presence = (_a = this.room.getSelf()) == null ? void 0 : _a.presence["__yjs"];
this.room.updatePresence({
__yjs: __spreadValues(__spreadValues({}, presence || {}), state || {})
});
}
setLocalStateField(field, value) {
var _a;
const presence = (_a = this.room.getSelf()) == null ? void 0 : _a.presence["__yjs"];
const update = { [field]: value };
this.room.updatePresence({
__yjs: __spreadValues(__spreadValues({}, presence || {}), update)
});
}
// Translate liveblocks presence to yjs awareness
getStates() {
const others = this.room.getOthers();
const states = others.reduce((acc, currentValue) => {
if (currentValue.connectionId) {
acc.set(
currentValue.connectionId,
currentValue.presence["__yjs"] || {}
);
}
return acc;
}, /* @__PURE__ */ new Map());
return states;
}
};
var LiveblocksProvider = class {
constructor(room, doc, config) {
this.lastUpdateDate = null;
this.unsubscribers = [];
this.syncDoc = () => {
var _a;
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.updateHandler = (update, origin) => __async(this, null, function* () {
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;
this.room = room;
const connectionId = (_a = this.room.getSelf()) == null ? void 0 : _a.connectionId;
if (connectionId) {
this.doc.clientID = connectionId;
}
this.awareness = new Awareness(this.doc, this.room);
this.doc.on("update", this.updateHandler);
this.unsubscribers.push(
this.room.events.connection.subscribe((e) => {
if (e === "open") {
this.syncDoc();
}
})
);
this.unsubscribers.push(
this.room.events.docUpdated.subscribe((update) => {
Y.applyUpdate(this.doc, _jsbase64.Base64.toUint8Array(update), "backend");
})
);
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");
});
}
destroy() {
this.doc.off("update", this.updateHandler);
this.unsubscribers.forEach((unsub) => unsub());
this.awareness.destroy();
}
};
exports.Awareness = Awareness; exports.default = LiveblocksProvider;
"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 g=Object.defineProperty;var m=Object.getOwnPropertySymbols;var _=Object.prototype.hasOwnProperty,j=Object.prototype.propertyIsEnumerable;var b=(n,s,e)=>s in n?g(n,s,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[s]=e,i=(n,s)=>{for(var e in s||(s={}))_.call(s,e)&&b(n,e,s[e]);if(m)for(var e of m(s))j.call(s,e)&&b(n,e,s[e]);return n};var _jsbase64 = require('js-base64');var p=()=>new Map;var y=(n,s,e)=>{let t=n.get(s);return t===void 0&&n.set(s,t=e()),t};var x=()=>new Set;var v=Array.from;var D=Array.isArray;var a=class{constructor(){this._observers=p()}on(s,e){y(this._observers,s,x).add(e)}once(s,e){let t=(...o)=>{this.off(s,t),e(...o)};this.on(s,t)}off(s,e){let t=this._observers.get(s);t!==void 0&&(t.delete(e),t.size===0&&this._observers.delete(s))}emit(s,e){return v((this._observers.get(s)||p()).values()).forEach(t=>t(...e))}destroy(){this._observers=p()}};var _yjs = require('yjs'); var u = _interopRequireWildcard(_yjs);var d="__yjs",h= exports.Awareness =class extends a{constructor(e,t){super();this.states=new Map;this.meta=new Map;this._checkInterval=0;this.doc=e,this.room=t,this.clientID=e.clientID,this.othersUnsub=this.room.events.others.subscribe(({event:o})=>{o.type==="leave"&&this.emit("change",[{added:[],updated:[],removed:[o.user.connectionId]},"local"]),o.type==="enter"&&this.emit("change",[{added:[o.user.connectionId],updated:[],removed:[]},"local"]),o.type==="update"&&this.emit("change",[{added:[],updated:[o.user.connectionId],removed:[]},"local"])})}destroy(){this.emit("destroy",[this]),this.othersUnsub(),this.setLocalState(null),super.destroy()}getLocalState(){let e=this.room.getPresence();return Object.keys(e).length===0||typeof e[d]=="undefined"?null:e[d]}setLocalState(e){var o;let t=(o=this.room.getSelf())==null?void 0:o.presence[d];this.room.updatePresence({__yjs:i(i({},t||{}),e||{})})}setLocalStateField(e,t){var c;let o=(c=this.room.getSelf())==null?void 0:c.presence[d],r={[e]:t};this.room.updatePresence({__yjs:i(i({},o||{}),r)})}getStates(){return this.room.getOthers().reduce((o,r)=>(r.connectionId&&o.set(r.connectionId,r.presence[d]||{}),o),new Map)}},f= exports.default =class extends a{constructor(e,t){var r;super();this.unsubscribers=[];this._synced=!1;this.syncDoc=()=>{var t;this.synced=!1,this.doc.clientID=((t=this.room.getSelf())==null?void 0:t.connectionId)||this.doc.clientID,this.awareness.clientID=this.doc.clientID;let e=_jsbase64.Base64.fromUint8Array(u.encodeStateVector(this.doc));this.room.fetchYDoc(e)};this.updateHandler=(e,t)=>{if(t!=="backend"){let o=_jsbase64.Base64.fromUint8Array(e);this.room.updateYDoc(o)}};this.doc=t,this.room=e;let o=(r=this.room.getSelf())==null?void 0:r.connectionId;o&&(this.doc.clientID=o),this.awareness=new h(this.doc,this.room),this.doc.on("update",this.updateHandler),this.unsubscribers.push(this.room.events.status.subscribe(c=>{c==="connected"&&this.syncDoc()})),this.unsubscribers.push(this.room.events.ydoc.subscribe(c=>{u.applyUpdate(this.doc,_jsbase64.Base64.toUint8Array(c),"backend"),this.synced=!0})),this.syncDoc()}get synced(){return this._synced}set synced(e){this._synced!==e&&(this._synced=e,this.emit("synced",[e]),this.emit("sync",[e]))}destroy(){this.doc.off("update",this.updateHandler),this.unsubscribers.forEach(e=>e()),this.awareness.destroy()}disconnect(){}connect(){}};exports.Awareness = h; exports.default = f;
//# sourceMappingURL=index.js.map
{
"name": "@liveblocks/yjs",
"version": "1.1.0-yjs5",
"version": "1.1.1-dual1",
"description": "An integration with . Liveblocks is the all-in-one toolkit to build collaborative products like Figma, Notion, and more.",

@@ -8,2 +8,15 @@ "license": "Apache-2.0",

"types": "./dist/index.d.ts",
"exports": {
".": {
"import": {
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
},
"require": {
"types": "./dist/index.d.ts",
"module": "./dist/index.mjs",
"default": "./dist/index.js"
}
}
},
"files": [

@@ -15,5 +28,6 @@ "dist/**",

"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",

@@ -23,12 +37,5 @@ "test:types": "tsd",

},
"exports": {
".": {
"require": "./dist/index.js",
"import": "./dist/index.mjs",
"types": "./dist/index.d.ts"
}
},
"dependencies": {
"@liveblocks/client": "1.1.0-yjs5",
"@liveblocks/core": "1.1.0-yjs5",
"@liveblocks/client": "1.1.1-dual1",
"@liveblocks/core": "1.1.1-dual1",
"js-base64": "^3.7.5"

@@ -35,0 +42,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

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc