@liveblocks/yjs 1.9.6 → 1.9.7-awareness

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -90,19 +90,31 @@ var Awareness = class extends Observable {
90
90
  if (event.type === "leave") {
91
91
  this.emit("change", [
92
92
  { added: [], updated: [], removed: [event.user.connectionId] },
93
- "local"
93
+ "presence"
94
+ ]);
95
+ this.emit("update", [
96
+ { added: [], updated: [], removed: [event.user.connectionId] },
97
+ "presence"
94
98
  ]);
95
99
  }
96
100
  if (event.type === "enter") {
97
101
  this.emit("change", [
98
102
  { added: [event.user.connectionId], updated: [], removed: [] },
99
- "local"
103
+ "presence"
104
+ ]);
105
+ this.emit("update", [
106
+ { added: [event.user.connectionId], updated: [], removed: [] },
107
+ "presence"
100
108
  ]);
101
109
  }
102
110
  if (event.type === "update") {
103
111
  this.emit("change", [
104
112
  { added: [], updated: [event.user.connectionId], removed: [] },
105
- "local"
113
+ "presence"
114
+ ]);
115
+ this.emit("update", [
116
+ { added: [], updated: [event.user.connectionId], removed: [] },
117
+ "presence"
106
118
  ]);
107
119
  }
108
120
  });
@@ -121,23 +133,42 @@ var Awareness = class extends Observable {
121
133
  return presence[Y_PRESENCE_KEY];
122
134
  }
123
135
  setLocalState(state) {
124
- 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]]);
136
+ const presence = _optionalChain([this, 'access', _2 => _2.room, 'access', _3 => _3.getSelf, 'call', _4 => _4(), 'optionalAccess', _5 => _5.presence]);
137
+ if (state === null) {
138
+ if (presence === void 0) {
139
+ return;
140
+ }
141
+ this.room.updatePresence({ ...presence, [Y_PRESENCE_KEY]: null });
142
+ this.emit("update", [
143
+ { added: [], updated: [], removed: [this.clientID] },
144
+ "local"
145
+ ]);
146
+ return;
147
+ }
148
+ const yPresence = _optionalChain([presence, 'optionalAccess', _6 => _6[Y_PRESENCE_KEY]]);
149
+ const added = yPresence === void 0 ? [this.clientID] : [];
150
+ const updated = yPresence === void 0 ? [] : [this.clientID];
125
151
  this.room.updatePresence({
126
- __yjs: { ...presence || {}, ...state || {} }
152
+ [Y_PRESENCE_KEY]: {
153
+ ...yPresence || {},
154
+ ...state || {}
155
+ }
127
156
  });
157
+ this.emit("update", [{ added, updated, removed: [] }, "local"]);
128
158
  }
129
159
  setLocalStateField(field, value) {
130
160
  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]]);
131
161
  const update = { [field]: value };
132
162
  this.room.updatePresence({
133
- __yjs: { ...presence || {}, ...update }
163
+ [Y_PRESENCE_KEY]: { ...presence || {}, ...update }
134
164
  });
135
165
  }
136
166
  // Translate liveblocks presence to yjs awareness
137
167
  getStates() {
138
168
  const others = this.room.getOthers();
169
+ const presence = _optionalChain([this, 'access', _12 => _12.room, 'access', _13 => _13.getSelf, 'call', _14 => _14(), 'optionalAccess', _15 => _15.presence, 'access', _16 => _16[Y_PRESENCE_KEY]]);
139
170
  const states = others.reduce((acc, currentValue) => {
140
- if (currentValue.connectionId) {
171
+ if (currentValue.connectionId && currentValue.presence[Y_PRESENCE_KEY] !== void 0) {
141
172
  acc.set(
142
173
  currentValue.connectionId,
143
174
  currentValue.presence[Y_PRESENCE_KEY] || {}
@@ -145,6 +176,9 @@ var Awareness = class extends Observable {
145
176
  }
146
177
  return acc;
147
178
  }, /* @__PURE__ */ new Map());
179
+ if (presence !== void 0) {
180
+ states.set(this.clientID, presence);
181
+ }
148
182
  return states;
149
183
  }
150
184
  };
@@ -222,7 +256,7 @@ var yDocHandler = class extends Observable {
222
256
 
223
257
  // src/version.ts
224
258
  var PKG_NAME = "@liveblocks/yjs";
225
- var PKG_VERSION = "1.9.6";
259
+ var PKG_VERSION = "1.9.7-awareness";
226
260
  var PKG_FORMAT = "cjs";
227
261
 
228
262
  // src/index.ts
@@ -250,7 +284,7 @@ var LiveblocksProvider = class extends Observable {
250
284
  }
251
285
  for (const subdoc of removed) {
252
286
  if (this.subdocHandlers.has(subdoc.guid)) {
253
- _optionalChain([this, 'access', _12 => _12.subdocHandlers, 'access', _13 => _13.get, 'call', _14 => _14(subdoc.guid), 'optionalAccess', _15 => _15.destroy, 'call', _16 => _16()]);
287
+ _optionalChain([this, 'access', _17 => _17.subdocHandlers, 'access', _18 => _18.get, 'call', _19 => _19(subdoc.guid), 'optionalAccess', _20 => _20.destroy, 'call', _21 => _21()]);
254
288
  this.subdocHandlers.delete(subdoc.guid);
255
289
  }
256
290
  }
@@ -263,7 +297,7 @@ var LiveblocksProvider = class extends Observable {
263
297
  };
264
298
  this.createSubdocHandler = (subdoc) => {
265
299
  if (this.subdocHandlers.has(subdoc.guid)) {
266
- _optionalChain([this, 'access', _17 => _17.subdocHandlers, 'access', _18 => _18.get, 'call', _19 => _19(subdoc.guid), 'optionalAccess', _20 => _20.syncDoc, 'call', _21 => _21()]);
300
+ _optionalChain([this, 'access', _22 => _22.subdocHandlers, 'access', _23 => _23.get, 'call', _24 => _24(subdoc.guid), 'optionalAccess', _25 => _25.syncDoc, 'call', _26 => _26()]);
267
301
  return;
268
302
  }
269
303
  const handler = new yDocHandler({
@@ -285,7 +319,7 @@ var LiveblocksProvider = class extends Observable {
285
319
  return false;
286
320
  };
287
321
  this.syncDoc = () => {
288
- this.rootDoc.clientID = _optionalChain([this, 'access', _22 => _22.room, 'access', _23 => _23.getSelf, 'call', _24 => _24(), 'optionalAccess', _25 => _25.connectionId]) || this.rootDoc.clientID;
322
+ this.rootDoc.clientID = _optionalChain([this, 'access', _27 => _27.room, 'access', _28 => _28.getSelf, 'call', _29 => _29(), 'optionalAccess', _30 => _30.connectionId]) || this.rootDoc.clientID;
289
323
  this.awareness.clientID = this.rootDoc.clientID;
290
324
  this.rootDocHandler.syncDoc();
291
325
  for (const [_, handler] of this.subdocHandlers) {
@@ -301,7 +335,7 @@ var LiveblocksProvider = class extends Observable {
301
335
  updateDoc: this.updateDoc,
302
336
  fetchDoc: this.fetchDoc
303
337
  });
304
- const connectionId = _optionalChain([this, 'access', _26 => _26.room, 'access', _27 => _27.getSelf, 'call', _28 => _28(), 'optionalAccess', _29 => _29.connectionId]);
338
+ const connectionId = _optionalChain([this, 'access', _31 => _31.room, 'access', _32 => _32.getSelf, 'call', _33 => _33(), 'optionalAccess', _34 => _34.connectionId]);
305
339
  if (connectionId) {
306
340
  this.rootDoc.clientID = connectionId;
307
341
  }
@@ -323,7 +357,7 @@ var LiveblocksProvider = class extends Observable {
323
357
  }
324
358
  const { stateVector, update, guid } = message;
325
359
  if (guid !== void 0) {
326
- _optionalChain([this, 'access', _30 => _30.subdocHandlers, 'access', _31 => _31.get, 'call', _32 => _32(guid), 'optionalAccess', _33 => _33.handleServerUpdate, 'call', _34 => _34({ update, stateVector })]);
360
+ _optionalChain([this, 'access', _35 => _35.subdocHandlers, 'access', _36 => _36.get, 'call', _37 => _37(guid), 'optionalAccess', _38 => _38.handleServerUpdate, 'call', _39 => _39({ update, stateVector })]);
327
361
  } else {
328
362
  this.rootDocHandler.handleServerUpdate({ update, stateVector });
329
363
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../../../node_modules/lib0/map.js","../../../node_modules/lib0/set.js","../../../node_modules/lib0/array.js","../../../node_modules/lib0/observable.js","../src/awareness.ts","../src/doc.ts","../src/version.ts"],"names":["create"],"mappings":"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","sourcesContent":["import type {\n BaseUserMeta,\n Json,\n JsonObject,\n LsonObject,\n Room,\n} from \"@liveblocks/client\";\nimport { ClientMsgCode, detectDupes } from \"@liveblocks/core\";\nimport { Observable } from \"lib0/observable\";\nimport type * as Y from \"yjs\";\n\nimport { Awareness } from \"./awareness\";\nimport yDocHandler from \"./doc\";\nimport { PKG_FORMAT, PKG_NAME, PKG_VERSION } from \"./version\";\n\ndetectDupes(PKG_NAME, PKG_VERSION, PKG_FORMAT);\n\ntype ProviderOptions = {\n autoloadSubdocs: boolean;\n};\n\nconst DefaultOptions: ProviderOptions = {\n autoloadSubdocs: false,\n};\n\nexport default class LiveblocksProvider<\n P extends JsonObject,\n S extends LsonObject,\n U extends BaseUserMeta,\n E extends Json,\n> extends Observable<unknown> {\n private room: Room<P, S, U, E>;\n private rootDoc: Y.Doc;\n private options: ProviderOptions;\n\n private unsubscribers: Array<() => void> = [];\n\n public awareness: Awareness;\n\n public rootDocHandler: yDocHandler;\n public subdocHandlers: Map<string, yDocHandler> = new Map();\n\n constructor(\n room: Room<P, S, U, E>,\n doc: Y.Doc,\n options: ProviderOptions | undefined = DefaultOptions\n ) {\n super();\n this.rootDoc = doc;\n this.room = room;\n this.options = options;\n this.rootDocHandler = new yDocHandler({\n doc,\n isRoot: true,\n updateDoc: this.updateDoc,\n fetchDoc: this.fetchDoc,\n });\n // if we have a connectionId already during construction, use that\n const connectionId = this.room.getSelf()?.connectionId;\n if (connectionId) {\n this.rootDoc.clientID = connectionId;\n }\n this.awareness = new Awareness(this.rootDoc, this.room);\n\n this.unsubscribers.push(\n this.room.events.status.subscribe((status) => {\n if (status === \"connected\") {\n this.rootDocHandler.syncDoc();\n } else {\n this.rootDocHandler.synced = false;\n }\n })\n );\n\n this.unsubscribers.push(\n this.room.events.ydoc.subscribe((message) => {\n const { type } = message;\n if (type === ClientMsgCode.UPDATE_YDOC) {\n // don't apply updates that came from the client\n return;\n }\n const { stateVector, update, guid } = message;\n // find the right doc and update\n if (guid !== undefined) {\n this.subdocHandlers\n .get(guid)\n ?.handleServerUpdate({ update, stateVector });\n } else {\n this.rootDocHandler.handleServerUpdate({ update, stateVector });\n }\n })\n );\n\n this.rootDocHandler.on(\"synced\", () => {\n const state = this.rootDocHandler.synced;\n for (const [_, handler] of this.subdocHandlers) {\n handler.syncDoc();\n }\n this.emit(\"synced\", [state]);\n this.emit(\"sync\", [state]);\n });\n this.rootDoc.on(\"subdocs\", this.handleSubdocs);\n this.syncDoc();\n }\n\n private handleSubdocs = ({\n loaded,\n removed,\n added,\n }: {\n loaded: Y.Doc[];\n removed: Y.Doc[];\n added: Y.Doc[];\n }) => {\n loaded.forEach(this.createSubdocHandler);\n if (this.options.autoloadSubdocs) {\n for (const subdoc of added) {\n if (!this.subdocHandlers.has(subdoc.guid)) {\n subdoc.load();\n }\n }\n }\n for (const subdoc of removed) {\n if (this.subdocHandlers.has(subdoc.guid)) {\n this.subdocHandlers.get(subdoc.guid)?.destroy();\n this.subdocHandlers.delete(subdoc.guid);\n }\n }\n };\n\n private updateDoc = (update: string, guid?: string) => {\n this.room.updateYDoc(update, guid);\n };\n\n private fetchDoc = (vector: string, guid?: string) => {\n this.room.fetchYDoc(vector, guid);\n };\n\n private createSubdocHandler = (subdoc: Y.Doc): void => {\n if (this.subdocHandlers.has(subdoc.guid)) {\n // if we already handle this subdoc, just fetch it again\n this.subdocHandlers.get(subdoc.guid)?.syncDoc();\n return;\n }\n const handler = new yDocHandler({\n doc: subdoc,\n isRoot: false,\n updateDoc: this.updateDoc,\n fetchDoc: this.fetchDoc,\n });\n this.subdocHandlers.set(subdoc.guid, handler);\n };\n\n // attempt to load a subdoc of a given guid\n public loadSubdoc = (guid: string): boolean => {\n for (const subdoc of this.rootDoc.subdocs) {\n if (subdoc.guid === guid) {\n subdoc.load();\n return true;\n }\n }\n // should we throw instead?\n return false;\n };\n\n private syncDoc = () => {\n /**\n * If the connection changes, set the new id, this is used by awareness.\n * yjs' only requirement for clientID is that it's truly unique and a number.\n * Liveblock's connectionID satisfies those constraints\n * */\n this.rootDoc.clientID =\n this.room.getSelf()?.connectionId || this.rootDoc.clientID;\n this.awareness.clientID = this.rootDoc.clientID; // tell our awareness provider the new ID\n\n this.rootDocHandler.syncDoc();\n for (const [_, handler] of this.subdocHandlers) {\n handler.syncDoc();\n }\n };\n\n // The sync'd property is required by some provider implementations\n get synced(): boolean {\n return this.rootDocHandler.synced;\n }\n\n destroy(): void {\n this.unsubscribers.forEach((unsub) => unsub());\n this.awareness.destroy();\n this.rootDocHandler.destroy();\n this._observers = new Map();\n for (const [_, handler] of this.subdocHandlers) {\n handler.destroy();\n }\n this.subdocHandlers.clear();\n super.destroy();\n }\n\n // Some provider implementations expect to be able to call connect/disconnect, implement as noop\n disconnect(): void {\n // This is a noop for liveblocks as connections are managed by the room\n }\n\n connect(): void {\n // This is a noop for liveblocks as connections are managed by the room\n }\n}\n","/**\n * Utility module to work with key-value stores.\n *\n * @module map\n */\n\n/**\n * Creates a new Map instance.\n *\n * @function\n * @return {Map<any, any>}\n *\n * @function\n */\nexport const create = () => new Map()\n\n/**\n * Copy a Map object into a fresh Map object.\n *\n * @function\n * @template X,Y\n * @param {Map<X,Y>} m\n * @return {Map<X,Y>}\n */\nexport const copy = m => {\n const r = create()\n m.forEach((v, k) => { r.set(k, v) })\n return r\n}\n\n/**\n * Get map property. Create T if property is undefined and set T on map.\n *\n * ```js\n * const listeners = map.setIfUndefined(events, 'eventName', set.create)\n * listeners.add(listener)\n * ```\n *\n * @function\n * @template V,K\n * @template {Map<K,V>} MAP\n * @param {MAP} map\n * @param {K} key\n * @param {function():V} createT\n * @return {V}\n */\nexport const setIfUndefined = (map, key, createT) => {\n let set = map.get(key)\n if (set === undefined) {\n map.set(key, set = createT())\n }\n return set\n}\n\n/**\n * Creates an Array and populates it with the content of all key-value pairs using the `f(value, key)` function.\n *\n * @function\n * @template K\n * @template V\n * @template R\n * @param {Map<K,V>} m\n * @param {function(V,K):R} f\n * @return {Array<R>}\n */\nexport const map = (m, f) => {\n const res = []\n for (const [key, value] of m) {\n res.push(f(value, key))\n }\n return res\n}\n\n/**\n * Tests whether any key-value pairs pass the test implemented by `f(value, key)`.\n *\n * @todo should rename to some - similarly to Array.some\n *\n * @function\n * @template K\n * @template V\n * @param {Map<K,V>} m\n * @param {function(V,K):boolean} f\n * @return {boolean}\n */\nexport const any = (m, f) => {\n for (const [key, value] of m) {\n if (f(value, key)) {\n return true\n }\n }\n return false\n}\n\n/**\n * Tests whether all key-value pairs pass the test implemented by `f(value, key)`.\n *\n * @function\n * @template K\n * @template V\n * @param {Map<K,V>} m\n * @param {function(V,K):boolean} f\n * @return {boolean}\n */\nexport const all = (m, f) => {\n for (const [key, value] of m) {\n if (!f(value, key)) {\n return false\n }\n }\n return true\n}\n","/**\n * Utility module to work with sets.\n *\n * @module set\n */\n\nexport const create = () => new Set()\n\n/**\n * @template T\n * @param {Set<T>} set\n * @return {Array<T>}\n */\nexport const toArray = set => Array.from(set)\n\n/**\n * @template T\n * @param {Set<T>} set\n * @return {T}\n */\nexport const first = set =>\n set.values().next().value || undefined\n\n/**\n * @template T\n * @param {Iterable<T>} entries\n * @return {Set<T>}\n */\nexport const from = entries => new Set(entries)\n","/**\n * Utility module to work with Arrays.\n *\n * @module array\n */\n\nimport * as set from './set.js'\n\n/**\n * Return the last element of an array. The element must exist\n *\n * @template L\n * @param {ArrayLike<L>} arr\n * @return {L}\n */\nexport const last = arr => arr[arr.length - 1]\n\n/**\n * @template C\n * @return {Array<C>}\n */\nexport const create = () => /** @type {Array<C>} */ ([])\n\n/**\n * @template D\n * @param {Array<D>} a\n * @return {Array<D>}\n */\nexport const copy = a => /** @type {Array<D>} */ (a.slice())\n\n/**\n * Append elements from src to dest\n *\n * @template M\n * @param {Array<M>} dest\n * @param {Array<M>} src\n */\nexport const appendTo = (dest, src) => {\n for (let i = 0; i < src.length; i++) {\n dest.push(src[i])\n }\n}\n\n/**\n * Transforms something array-like to an actual Array.\n *\n * @function\n * @template T\n * @param {ArrayLike<T>|Iterable<T>} arraylike\n * @return {T}\n */\nexport const from = Array.from\n\n/**\n * True iff condition holds on every element in the Array.\n *\n * @function\n * @template ITEM\n * @template {ArrayLike<ITEM>} ARR\n *\n * @param {ARR} arr\n * @param {function(ITEM, number, ARR):boolean} f\n * @return {boolean}\n */\nexport const every = (arr, f) => {\n for (let i = 0; i < arr.length; i++) {\n if (!f(arr[i], i, arr)) {\n return false\n }\n }\n return true\n}\n\n/**\n * True iff condition holds on some element in the Array.\n *\n * @function\n * @template S\n * @template {ArrayLike<S>} ARR\n * @param {ARR} arr\n * @param {function(S, number, ARR):boolean} f\n * @return {boolean}\n */\nexport const some = (arr, f) => {\n for (let i = 0; i < arr.length; i++) {\n if (f(arr[i], i, arr)) {\n return true\n }\n }\n return false\n}\n\n/**\n * @template ELEM\n *\n * @param {ArrayLike<ELEM>} a\n * @param {ArrayLike<ELEM>} b\n * @return {boolean}\n */\nexport const equalFlat = (a, b) => a.length === b.length && every(a, (item, index) => item === b[index])\n\n/**\n * @template ELEM\n * @param {Array<Array<ELEM>>} arr\n * @return {Array<ELEM>}\n */\nexport const flatten = arr => fold(arr, /** @type {Array<ELEM>} */ ([]), (acc, val) => acc.concat(val))\n\n/**\n * @template T\n * @param {number} len\n * @param {function(number, Array<T>):T} f\n * @return {Array<T>}\n */\nexport const unfold = (len, f) => {\n const array = new Array(len)\n for (let i = 0; i < len; i++) {\n array[i] = f(i, array)\n }\n return array\n}\n\n/**\n * @template T\n * @template RESULT\n * @param {Array<T>} arr\n * @param {RESULT} seed\n * @param {function(RESULT, T, number):RESULT} folder\n */\nexport const fold = (arr, seed, folder) => arr.reduce(folder, seed)\n\nexport const isArray = Array.isArray\n\n/**\n * @template T\n * @param {Array<T>} arr\n * @return {Array<T>}\n */\nexport const unique = arr => from(set.from(arr))\n\n/**\n * @template T\n * @template M\n * @param {ArrayLike<T>} arr\n * @param {function(T):M} mapper\n * @return {Array<T>}\n */\nexport const uniqueBy = (arr, mapper) => {\n /**\n * @type {Set<M>}\n */\n const happened = set.create()\n /**\n * @type {Array<T>}\n */\n const result = []\n for (let i = 0; i < arr.length; i++) {\n const el = arr[i]\n const mapped = mapper(el)\n if (!happened.has(mapped)) {\n happened.add(mapped)\n result.push(el)\n }\n }\n return result\n}\n","/**\n * Observable class prototype.\n *\n * @module observable\n */\n\nimport * as map from './map.js'\nimport * as set from './set.js'\nimport * as array from './array.js'\n\n/**\n * Handles named events.\n *\n * @template N\n */\nexport class Observable {\n constructor () {\n /**\n * Some desc.\n * @type {Map<N, any>}\n */\n this._observers = map.create()\n }\n\n /**\n * @param {N} name\n * @param {function} f\n */\n on (name, f) {\n map.setIfUndefined(this._observers, name, set.create).add(f)\n }\n\n /**\n * @param {N} name\n * @param {function} f\n */\n once (name, f) {\n /**\n * @param {...any} args\n */\n const _f = (...args) => {\n this.off(name, _f)\n f(...args)\n }\n this.on(name, _f)\n }\n\n /**\n * @param {N} name\n * @param {function} f\n */\n off (name, f) {\n const observers = this._observers.get(name)\n if (observers !== undefined) {\n observers.delete(f)\n if (observers.size === 0) {\n this._observers.delete(name)\n }\n }\n }\n\n /**\n * Emit a named event. All registered event listeners that listen to the\n * specified name will receive the event.\n *\n * @todo This should catch exceptions\n *\n * @param {N} name The event name.\n * @param {Array<any>} args The arguments that are applied to the event listener.\n */\n emit (name, args) {\n // copy all listeners to an array first to make sure that no event is emitted to listeners that are subscribed while the event handler is called.\n return array.from((this._observers.get(name) || map.create()).values()).forEach(f => f(...args))\n }\n\n destroy () {\n this._observers = map.create()\n }\n}\n","// TODO: apparently Yjs is full of anys or something, see if we can fix this\n/* eslint-disable @typescript-eslint/no-unsafe-call */\n/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n/* eslint-disable @typescript-eslint/no-unsafe-assignment */\nimport type {\n BaseUserMeta,\n Json,\n JsonObject,\n LsonObject,\n Room,\n} from \"@liveblocks/client\";\nimport { Observable } from \"lib0/observable\";\nimport type * as Y from \"yjs\";\n\nconst Y_PRESENCE_KEY = \"__yjs\";\n\ntype MetaClientState = {\n clock: number;\n lastUpdated: number;\n};\n\n/**\n * This class will store Yjs awareness in Liveblock's presence under the __yjs key\n * IMPORTANT: The Yjs awareness protocol uses ydoc.clientId to reference users\n * to their respective documents. To avoid mapping Yjs clientIds to liveblock's connectionId,\n * we simply set the clientId of the doc to the connectionId. Then no further mapping is required\n */\nexport class Awareness extends Observable<unknown> {\n private room: Room<JsonObject, LsonObject, BaseUserMeta, Json>;\n public doc: Y.Doc;\n public clientID: number;\n public states: Map<number, unknown> = new Map();\n // Meta is used to keep track and timeout users who disconnect. Liveblocks provides this for us, so we don't need to\n // manage it here. Unfortunately, it's expected to exist by various integrations, so it's an empty map.\n public meta: Map<number, MetaClientState> = new Map();\n // _checkInterval this would hold a timer to remove users, but Liveblock's presence already handles this\n // unfortunately it's typed by various integrations\n public _checkInterval: number = 0;\n\n private othersUnsub: () => void;\n constructor(\n doc: Y.Doc,\n room: Room<JsonObject, LsonObject, BaseUserMeta, Json>\n ) {\n super();\n this.doc = doc;\n this.room = room;\n this.clientID = doc.clientID;\n this.othersUnsub = this.room.events.others.subscribe((event) => {\n // When others are changed, we emit an event that contains arrays added/updated/removed.\n if (event.type === \"leave\") {\n // REMOVED\n this.emit(\"change\", [\n { added: [], updated: [], removed: [event.user.connectionId] },\n \"local\",\n ]);\n }\n\n if (event.type === \"enter\") {\n // ADDED\n this.emit(\"change\", [\n { added: [event.user.connectionId], updated: [], removed: [] },\n \"local\",\n ]);\n }\n\n if (event.type === \"update\") {\n // UPDATED\n this.emit(\"change\", [\n { added: [], updated: [event.user.connectionId], removed: [] },\n \"local\",\n ]);\n }\n });\n }\n\n destroy(): void {\n this.emit(\"destroy\", [this]);\n this.othersUnsub();\n this.setLocalState(null);\n super.destroy();\n }\n\n getLocalState(): JsonObject | null {\n const presence = this.room.getPresence();\n if (\n Object.keys(presence).length === 0 ||\n typeof presence[Y_PRESENCE_KEY] === \"undefined\"\n ) {\n return null;\n }\n return presence[Y_PRESENCE_KEY] as JsonObject | null;\n }\n\n setLocalState(state: Partial<JsonObject> | null): void {\n const presence = this.room.getSelf()?.presence[Y_PRESENCE_KEY];\n this.room.updatePresence({\n __yjs: { ...((presence as JsonObject) || {}), ...(state || {}) },\n });\n }\n\n setLocalStateField(field: string, value: JsonObject | null): void {\n const presence = this.room.getSelf()?.presence[Y_PRESENCE_KEY];\n const update = { [field]: value } as Partial<JsonObject>;\n this.room.updatePresence({\n __yjs: { ...((presence as JsonObject) || {}), ...update },\n });\n }\n\n // Translate liveblocks presence to yjs awareness\n getStates(): Map<number, unknown> {\n const others = this.room.getOthers();\n const states = others.reduce((acc: Map<number, unknown>, currentValue) => {\n if (currentValue.connectionId) {\n // connectionId == actorId == yjs.clientId\n acc.set(\n currentValue.connectionId,\n currentValue.presence[Y_PRESENCE_KEY] || {}\n );\n }\n return acc;\n }, new Map());\n return states;\n }\n}\n","import { Base64 } from \"js-base64\";\nimport { Observable } from \"lib0/observable\";\nimport * as Y from \"yjs\";\n\nexport default class yDocHandler extends Observable<unknown> {\n private unsubscribers: Array<() => void> = [];\n\n private _synced = false;\n private doc: Y.Doc;\n private updateRoomDoc: (update: string) => void;\n private fetchRoomDoc: (vector: string) => void;\n\n constructor({\n doc,\n isRoot,\n updateDoc,\n fetchDoc,\n }: {\n doc: Y.Doc;\n isRoot: boolean;\n updateDoc: (update: string, guid?: string) => void;\n fetchDoc: (vector: string, guid?: string) => void;\n }) {\n super();\n this.doc = doc;\n // this.doc.load(); // this just emits a load event, it doesn't actually load anything\n this.doc.on(\"update\", this.updateHandler);\n this.updateRoomDoc = (update: string) => {\n updateDoc(update, isRoot ? undefined : this.doc.guid);\n };\n this.fetchRoomDoc = (vector: string) => {\n fetchDoc(vector, isRoot ? undefined : this.doc.guid);\n };\n\n this.syncDoc();\n }\n\n public handleServerUpdate = ({\n update,\n stateVector,\n }: {\n update: string;\n stateVector: string | null;\n }): void => {\n // apply update from the server\n Y.applyUpdate(this.doc, Base64.toUint8Array(update), \"backend\");\n // if this update is the result of a fetch, the state vector is included\n if (stateVector) {\n // Use server state to calculate a diff and send it\n try {\n const localUpdate = Y.encodeStateAsUpdate(\n this.doc,\n Base64.toUint8Array(stateVector)\n );\n this.updateRoomDoc(Base64.fromUint8Array(localUpdate));\n } catch (e) {\n // something went wrong encoding local state to send to the server\n console.warn(e);\n }\n // now that we've sent our local and received from server, we're in sync\n // calling `syncDoc` again will sync up the documents\n this.synced = true;\n }\n };\n\n public syncDoc = (): void => {\n this.synced = false;\n\n // The state vector is sent to the server so it knows what to send back\n // if you don't send it, it returns everything\n const encodedVector = Base64.fromUint8Array(Y.encodeStateVector(this.doc));\n this.fetchRoomDoc(encodedVector);\n };\n\n // The sync'd property is required by some provider implementations\n get synced(): boolean {\n return this._synced;\n }\n\n set synced(state: boolean) {\n if (this._synced !== state) {\n this._synced = state;\n this.emit(\"synced\", [state]);\n this.emit(\"sync\", [state]);\n }\n }\n\n private updateHandler = (update: Uint8Array, origin: string) => {\n if (origin !== \"backend\") {\n const encodedUpdate = Base64.fromUint8Array(update);\n this.updateRoomDoc(encodedUpdate);\n }\n };\n\n destroy(): void {\n this.doc.off(\"update\", this.updateHandler);\n this.unsubscribers.forEach((unsub) => unsub());\n this._observers = new Map();\n this.doc.destroy();\n }\n}\n","declare const __VERSION__: string;\ndeclare const TSUP_FORMAT: string;\n\nexport const PKG_NAME = \"@liveblocks/yjs\";\nexport const PKG_VERSION = typeof __VERSION__ === \"string\" && __VERSION__;\nexport const PKG_FORMAT = typeof TSUP_FORMAT === \"string\" && TSUP_FORMAT;\n"]}
1
+ {"version":3,"sources":["../src/index.ts","../../../node_modules/lib0/map.js","../../../node_modules/lib0/set.js","../../../node_modules/lib0/array.js","../../../node_modules/lib0/observable.js","../src/awareness.ts","../src/doc.ts","../src/version.ts"],"names":["create"],"mappings":"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","sourcesContent":["import type {\n BaseUserMeta,\n Json,\n JsonObject,\n LsonObject,\n Room,\n} from \"@liveblocks/client\";\nimport { ClientMsgCode, detectDupes } from \"@liveblocks/core\";\nimport { Observable } from \"lib0/observable\";\nimport type * as Y from \"yjs\";\n\nimport { Awareness } from \"./awareness\";\nimport yDocHandler from \"./doc\";\nimport { PKG_FORMAT, PKG_NAME, PKG_VERSION } from \"./version\";\n\ndetectDupes(PKG_NAME, PKG_VERSION, PKG_FORMAT);\n\ntype ProviderOptions = {\n autoloadSubdocs: boolean;\n};\n\nconst DefaultOptions: ProviderOptions = {\n autoloadSubdocs: false,\n};\n\nexport default class LiveblocksProvider<\n P extends JsonObject,\n S extends LsonObject,\n U extends BaseUserMeta,\n E extends Json,\n> extends Observable<unknown> {\n private room: Room<P, S, U, E>;\n private rootDoc: Y.Doc;\n private options: ProviderOptions;\n\n private unsubscribers: Array<() => void> = [];\n\n public awareness: Awareness;\n\n public rootDocHandler: yDocHandler;\n public subdocHandlers: Map<string, yDocHandler> = new Map();\n\n constructor(\n room: Room<P, S, U, E>,\n doc: Y.Doc,\n options: ProviderOptions | undefined = DefaultOptions\n ) {\n super();\n this.rootDoc = doc;\n this.room = room;\n this.options = options;\n this.rootDocHandler = new yDocHandler({\n doc,\n isRoot: true,\n updateDoc: this.updateDoc,\n fetchDoc: this.fetchDoc,\n });\n // if we have a connectionId already during construction, use that\n const connectionId = this.room.getSelf()?.connectionId;\n if (connectionId) {\n this.rootDoc.clientID = connectionId;\n }\n this.awareness = new Awareness(this.rootDoc, this.room);\n\n this.unsubscribers.push(\n this.room.events.status.subscribe((status) => {\n if (status === \"connected\") {\n this.rootDocHandler.syncDoc();\n } else {\n this.rootDocHandler.synced = false;\n }\n })\n );\n\n this.unsubscribers.push(\n this.room.events.ydoc.subscribe((message) => {\n const { type } = message;\n if (type === ClientMsgCode.UPDATE_YDOC) {\n // don't apply updates that came from the client\n return;\n }\n const { stateVector, update, guid } = message;\n // find the right doc and update\n if (guid !== undefined) {\n this.subdocHandlers\n .get(guid)\n ?.handleServerUpdate({ update, stateVector });\n } else {\n this.rootDocHandler.handleServerUpdate({ update, stateVector });\n }\n })\n );\n\n this.rootDocHandler.on(\"synced\", () => {\n const state = this.rootDocHandler.synced;\n for (const [_, handler] of this.subdocHandlers) {\n handler.syncDoc();\n }\n this.emit(\"synced\", [state]);\n this.emit(\"sync\", [state]);\n });\n this.rootDoc.on(\"subdocs\", this.handleSubdocs);\n this.syncDoc();\n }\n\n private handleSubdocs = ({\n loaded,\n removed,\n added,\n }: {\n loaded: Y.Doc[];\n removed: Y.Doc[];\n added: Y.Doc[];\n }) => {\n loaded.forEach(this.createSubdocHandler);\n if (this.options.autoloadSubdocs) {\n for (const subdoc of added) {\n if (!this.subdocHandlers.has(subdoc.guid)) {\n subdoc.load();\n }\n }\n }\n for (const subdoc of removed) {\n if (this.subdocHandlers.has(subdoc.guid)) {\n this.subdocHandlers.get(subdoc.guid)?.destroy();\n this.subdocHandlers.delete(subdoc.guid);\n }\n }\n };\n\n private updateDoc = (update: string, guid?: string) => {\n this.room.updateYDoc(update, guid);\n };\n\n private fetchDoc = (vector: string, guid?: string) => {\n this.room.fetchYDoc(vector, guid);\n };\n\n private createSubdocHandler = (subdoc: Y.Doc): void => {\n if (this.subdocHandlers.has(subdoc.guid)) {\n // if we already handle this subdoc, just fetch it again\n this.subdocHandlers.get(subdoc.guid)?.syncDoc();\n return;\n }\n const handler = new yDocHandler({\n doc: subdoc,\n isRoot: false,\n updateDoc: this.updateDoc,\n fetchDoc: this.fetchDoc,\n });\n this.subdocHandlers.set(subdoc.guid, handler);\n };\n\n // attempt to load a subdoc of a given guid\n public loadSubdoc = (guid: string): boolean => {\n for (const subdoc of this.rootDoc.subdocs) {\n if (subdoc.guid === guid) {\n subdoc.load();\n return true;\n }\n }\n // should we throw instead?\n return false;\n };\n\n private syncDoc = () => {\n /**\n * If the connection changes, set the new id, this is used by awareness.\n * yjs' only requirement for clientID is that it's truly unique and a number.\n * Liveblock's connectionID satisfies those constraints\n * */\n this.rootDoc.clientID =\n this.room.getSelf()?.connectionId || this.rootDoc.clientID;\n this.awareness.clientID = this.rootDoc.clientID; // tell our awareness provider the new ID\n\n this.rootDocHandler.syncDoc();\n for (const [_, handler] of this.subdocHandlers) {\n handler.syncDoc();\n }\n };\n\n // The sync'd property is required by some provider implementations\n get synced(): boolean {\n return this.rootDocHandler.synced;\n }\n\n destroy(): void {\n this.unsubscribers.forEach((unsub) => unsub());\n this.awareness.destroy();\n this.rootDocHandler.destroy();\n this._observers = new Map();\n for (const [_, handler] of this.subdocHandlers) {\n handler.destroy();\n }\n this.subdocHandlers.clear();\n super.destroy();\n }\n\n // Some provider implementations expect to be able to call connect/disconnect, implement as noop\n disconnect(): void {\n // This is a noop for liveblocks as connections are managed by the room\n }\n\n connect(): void {\n // This is a noop for liveblocks as connections are managed by the room\n }\n}\n","/**\n * Utility module to work with key-value stores.\n *\n * @module map\n */\n\n/**\n * Creates a new Map instance.\n *\n * @function\n * @return {Map<any, any>}\n *\n * @function\n */\nexport const create = () => new Map()\n\n/**\n * Copy a Map object into a fresh Map object.\n *\n * @function\n * @template X,Y\n * @param {Map<X,Y>} m\n * @return {Map<X,Y>}\n */\nexport const copy = m => {\n const r = create()\n m.forEach((v, k) => { r.set(k, v) })\n return r\n}\n\n/**\n * Get map property. Create T if property is undefined and set T on map.\n *\n * ```js\n * const listeners = map.setIfUndefined(events, 'eventName', set.create)\n * listeners.add(listener)\n * ```\n *\n * @function\n * @template V,K\n * @template {Map<K,V>} MAP\n * @param {MAP} map\n * @param {K} key\n * @param {function():V} createT\n * @return {V}\n */\nexport const setIfUndefined = (map, key, createT) => {\n let set = map.get(key)\n if (set === undefined) {\n map.set(key, set = createT())\n }\n return set\n}\n\n/**\n * Creates an Array and populates it with the content of all key-value pairs using the `f(value, key)` function.\n *\n * @function\n * @template K\n * @template V\n * @template R\n * @param {Map<K,V>} m\n * @param {function(V,K):R} f\n * @return {Array<R>}\n */\nexport const map = (m, f) => {\n const res = []\n for (const [key, value] of m) {\n res.push(f(value, key))\n }\n return res\n}\n\n/**\n * Tests whether any key-value pairs pass the test implemented by `f(value, key)`.\n *\n * @todo should rename to some - similarly to Array.some\n *\n * @function\n * @template K\n * @template V\n * @param {Map<K,V>} m\n * @param {function(V,K):boolean} f\n * @return {boolean}\n */\nexport const any = (m, f) => {\n for (const [key, value] of m) {\n if (f(value, key)) {\n return true\n }\n }\n return false\n}\n\n/**\n * Tests whether all key-value pairs pass the test implemented by `f(value, key)`.\n *\n * @function\n * @template K\n * @template V\n * @param {Map<K,V>} m\n * @param {function(V,K):boolean} f\n * @return {boolean}\n */\nexport const all = (m, f) => {\n for (const [key, value] of m) {\n if (!f(value, key)) {\n return false\n }\n }\n return true\n}\n","/**\n * Utility module to work with sets.\n *\n * @module set\n */\n\nexport const create = () => new Set()\n\n/**\n * @template T\n * @param {Set<T>} set\n * @return {Array<T>}\n */\nexport const toArray = set => Array.from(set)\n\n/**\n * @template T\n * @param {Set<T>} set\n * @return {T}\n */\nexport const first = set =>\n set.values().next().value || undefined\n\n/**\n * @template T\n * @param {Iterable<T>} entries\n * @return {Set<T>}\n */\nexport const from = entries => new Set(entries)\n","/**\n * Utility module to work with Arrays.\n *\n * @module array\n */\n\nimport * as set from './set.js'\n\n/**\n * Return the last element of an array. The element must exist\n *\n * @template L\n * @param {ArrayLike<L>} arr\n * @return {L}\n */\nexport const last = arr => arr[arr.length - 1]\n\n/**\n * @template C\n * @return {Array<C>}\n */\nexport const create = () => /** @type {Array<C>} */ ([])\n\n/**\n * @template D\n * @param {Array<D>} a\n * @return {Array<D>}\n */\nexport const copy = a => /** @type {Array<D>} */ (a.slice())\n\n/**\n * Append elements from src to dest\n *\n * @template M\n * @param {Array<M>} dest\n * @param {Array<M>} src\n */\nexport const appendTo = (dest, src) => {\n for (let i = 0; i < src.length; i++) {\n dest.push(src[i])\n }\n}\n\n/**\n * Transforms something array-like to an actual Array.\n *\n * @function\n * @template T\n * @param {ArrayLike<T>|Iterable<T>} arraylike\n * @return {T}\n */\nexport const from = Array.from\n\n/**\n * True iff condition holds on every element in the Array.\n *\n * @function\n * @template ITEM\n * @template {ArrayLike<ITEM>} ARR\n *\n * @param {ARR} arr\n * @param {function(ITEM, number, ARR):boolean} f\n * @return {boolean}\n */\nexport const every = (arr, f) => {\n for (let i = 0; i < arr.length; i++) {\n if (!f(arr[i], i, arr)) {\n return false\n }\n }\n return true\n}\n\n/**\n * True iff condition holds on some element in the Array.\n *\n * @function\n * @template S\n * @template {ArrayLike<S>} ARR\n * @param {ARR} arr\n * @param {function(S, number, ARR):boolean} f\n * @return {boolean}\n */\nexport const some = (arr, f) => {\n for (let i = 0; i < arr.length; i++) {\n if (f(arr[i], i, arr)) {\n return true\n }\n }\n return false\n}\n\n/**\n * @template ELEM\n *\n * @param {ArrayLike<ELEM>} a\n * @param {ArrayLike<ELEM>} b\n * @return {boolean}\n */\nexport const equalFlat = (a, b) => a.length === b.length && every(a, (item, index) => item === b[index])\n\n/**\n * @template ELEM\n * @param {Array<Array<ELEM>>} arr\n * @return {Array<ELEM>}\n */\nexport const flatten = arr => fold(arr, /** @type {Array<ELEM>} */ ([]), (acc, val) => acc.concat(val))\n\n/**\n * @template T\n * @param {number} len\n * @param {function(number, Array<T>):T} f\n * @return {Array<T>}\n */\nexport const unfold = (len, f) => {\n const array = new Array(len)\n for (let i = 0; i < len; i++) {\n array[i] = f(i, array)\n }\n return array\n}\n\n/**\n * @template T\n * @template RESULT\n * @param {Array<T>} arr\n * @param {RESULT} seed\n * @param {function(RESULT, T, number):RESULT} folder\n */\nexport const fold = (arr, seed, folder) => arr.reduce(folder, seed)\n\nexport const isArray = Array.isArray\n\n/**\n * @template T\n * @param {Array<T>} arr\n * @return {Array<T>}\n */\nexport const unique = arr => from(set.from(arr))\n\n/**\n * @template T\n * @template M\n * @param {ArrayLike<T>} arr\n * @param {function(T):M} mapper\n * @return {Array<T>}\n */\nexport const uniqueBy = (arr, mapper) => {\n /**\n * @type {Set<M>}\n */\n const happened = set.create()\n /**\n * @type {Array<T>}\n */\n const result = []\n for (let i = 0; i < arr.length; i++) {\n const el = arr[i]\n const mapped = mapper(el)\n if (!happened.has(mapped)) {\n happened.add(mapped)\n result.push(el)\n }\n }\n return result\n}\n","/**\n * Observable class prototype.\n *\n * @module observable\n */\n\nimport * as map from './map.js'\nimport * as set from './set.js'\nimport * as array from './array.js'\n\n/**\n * Handles named events.\n *\n * @template N\n */\nexport class Observable {\n constructor () {\n /**\n * Some desc.\n * @type {Map<N, any>}\n */\n this._observers = map.create()\n }\n\n /**\n * @param {N} name\n * @param {function} f\n */\n on (name, f) {\n map.setIfUndefined(this._observers, name, set.create).add(f)\n }\n\n /**\n * @param {N} name\n * @param {function} f\n */\n once (name, f) {\n /**\n * @param {...any} args\n */\n const _f = (...args) => {\n this.off(name, _f)\n f(...args)\n }\n this.on(name, _f)\n }\n\n /**\n * @param {N} name\n * @param {function} f\n */\n off (name, f) {\n const observers = this._observers.get(name)\n if (observers !== undefined) {\n observers.delete(f)\n if (observers.size === 0) {\n this._observers.delete(name)\n }\n }\n }\n\n /**\n * Emit a named event. All registered event listeners that listen to the\n * specified name will receive the event.\n *\n * @todo This should catch exceptions\n *\n * @param {N} name The event name.\n * @param {Array<any>} args The arguments that are applied to the event listener.\n */\n emit (name, args) {\n // copy all listeners to an array first to make sure that no event is emitted to listeners that are subscribed while the event handler is called.\n return array.from((this._observers.get(name) || map.create()).values()).forEach(f => f(...args))\n }\n\n destroy () {\n this._observers = map.create()\n }\n}\n","// TODO: apparently Yjs is full of anys or something, see if we can fix this\n/* eslint-disable @typescript-eslint/no-unsafe-call */\n/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n/* eslint-disable @typescript-eslint/no-unsafe-assignment */\nimport type {\n BaseUserMeta,\n Json,\n JsonObject,\n LsonObject,\n Room,\n} from \"@liveblocks/client\";\nimport { Observable } from \"lib0/observable\";\nimport type * as Y from \"yjs\";\n\nconst Y_PRESENCE_KEY = \"__yjs\";\n\ntype MetaClientState = {\n clock: number;\n lastUpdated: number;\n};\n\n/**\n * This class will store Yjs awareness in Liveblock's presence under the __yjs key\n * IMPORTANT: The Yjs awareness protocol uses ydoc.clientId to reference users\n * to their respective documents. To avoid mapping Yjs clientIds to liveblock's connectionId,\n * we simply set the clientId of the doc to the connectionId. Then no further mapping is required\n */\nexport class Awareness extends Observable<unknown> {\n private room: Room<JsonObject, LsonObject, BaseUserMeta, Json>;\n public doc: Y.Doc;\n public clientID: number;\n public states: Map<number, unknown> = new Map();\n // Meta is used to keep track and timeout users who disconnect. Liveblocks provides this for us, so we don't need to\n // manage it here. Unfortunately, it's expected to exist by various integrations, so it's an empty map.\n public meta: Map<number, MetaClientState> = new Map();\n // _checkInterval this would hold a timer to remove users, but Liveblock's presence already handles this\n // unfortunately it's typed by various integrations\n public _checkInterval: number = 0;\n\n private othersUnsub: () => void;\n constructor(\n doc: Y.Doc,\n room: Room<JsonObject, LsonObject, BaseUserMeta, Json>\n ) {\n super();\n this.doc = doc;\n this.room = room;\n this.clientID = doc.clientID;\n this.othersUnsub = this.room.events.others.subscribe((event) => {\n // When others are changed, we emit an event that contains arrays added/updated/removed.\n if (event.type === \"leave\") {\n // REMOVED\n this.emit(\"change\", [\n { added: [], updated: [], removed: [event.user.connectionId] },\n \"presence\",\n ]);\n this.emit(\"update\", [\n { added: [], updated: [], removed: [event.user.connectionId] },\n \"presence\",\n ]);\n }\n\n if (event.type === \"enter\") {\n // ADDED\n this.emit(\"change\", [\n { added: [event.user.connectionId], updated: [], removed: [] },\n \"presence\",\n ]);\n this.emit(\"update\", [\n { added: [event.user.connectionId], updated: [], removed: [] },\n \"presence\",\n ]);\n }\n\n if (event.type === \"update\") {\n // UPDATED\n this.emit(\"change\", [\n { added: [], updated: [event.user.connectionId], removed: [] },\n \"presence\",\n ]);\n this.emit(\"update\", [\n { added: [], updated: [event.user.connectionId], removed: [] },\n \"presence\",\n ]);\n }\n });\n }\n\n destroy(): void {\n this.emit(\"destroy\", [this]);\n this.othersUnsub();\n this.setLocalState(null);\n super.destroy();\n }\n\n getLocalState(): JsonObject | null {\n const presence = this.room.getPresence();\n if (\n Object.keys(presence).length === 0 ||\n typeof presence[Y_PRESENCE_KEY] === \"undefined\"\n ) {\n return null;\n }\n return presence[Y_PRESENCE_KEY] as JsonObject | null;\n }\n\n setLocalState(state: Partial<JsonObject> | null): void {\n const presence = this.room.getSelf()?.presence;\n if (state === null) {\n if (presence === undefined) {\n // if presence is already undefined, we don't need to change anything here\n return;\n }\n this.room.updatePresence({ ...presence, [Y_PRESENCE_KEY]: null });\n this.emit(\"update\", [\n { added: [], updated: [], removed: [this.clientID] },\n \"local\",\n ]);\n return;\n }\n // if presence was undefined, it's added, if not, it's updated\n const yPresence = presence?.[Y_PRESENCE_KEY];\n const added = yPresence === undefined ? [this.clientID] : [];\n const updated = yPresence === undefined ? [] : [this.clientID];\n this.room.updatePresence({\n [Y_PRESENCE_KEY]: {\n ...((yPresence as JsonObject) || {}),\n ...(state || {}),\n },\n });\n this.emit(\"update\", [{ added, updated, removed: [] }, \"local\"]);\n }\n\n setLocalStateField(field: string, value: JsonObject | null): void {\n const presence = this.room.getSelf()?.presence[Y_PRESENCE_KEY];\n const update = { [field]: value } as Partial<JsonObject>;\n this.room.updatePresence({\n [Y_PRESENCE_KEY]: { ...((presence as JsonObject) || {}), ...update },\n });\n }\n\n // Translate liveblocks presence to yjs awareness\n getStates(): Map<number, unknown> {\n const others = this.room.getOthers();\n const presence = this.room.getSelf()?.presence[Y_PRESENCE_KEY];\n const states = others.reduce((acc: Map<number, unknown>, currentValue) => {\n if (\n currentValue.connectionId &&\n currentValue.presence[Y_PRESENCE_KEY] !== undefined\n ) {\n // connectionId == actorId == yjs.clientId\n acc.set(\n currentValue.connectionId,\n currentValue.presence[Y_PRESENCE_KEY] || {}\n );\n }\n return acc;\n }, new Map());\n if (presence !== undefined) {\n states.set(this.clientID, presence);\n }\n return states;\n }\n}\n","import { Base64 } from \"js-base64\";\nimport { Observable } from \"lib0/observable\";\nimport * as Y from \"yjs\";\n\nexport default class yDocHandler extends Observable<unknown> {\n private unsubscribers: Array<() => void> = [];\n\n private _synced = false;\n private doc: Y.Doc;\n private updateRoomDoc: (update: string) => void;\n private fetchRoomDoc: (vector: string) => void;\n\n constructor({\n doc,\n isRoot,\n updateDoc,\n fetchDoc,\n }: {\n doc: Y.Doc;\n isRoot: boolean;\n updateDoc: (update: string, guid?: string) => void;\n fetchDoc: (vector: string, guid?: string) => void;\n }) {\n super();\n this.doc = doc;\n // this.doc.load(); // this just emits a load event, it doesn't actually load anything\n this.doc.on(\"update\", this.updateHandler);\n this.updateRoomDoc = (update: string) => {\n updateDoc(update, isRoot ? undefined : this.doc.guid);\n };\n this.fetchRoomDoc = (vector: string) => {\n fetchDoc(vector, isRoot ? undefined : this.doc.guid);\n };\n\n this.syncDoc();\n }\n\n public handleServerUpdate = ({\n update,\n stateVector,\n }: {\n update: string;\n stateVector: string | null;\n }): void => {\n // apply update from the server\n Y.applyUpdate(this.doc, Base64.toUint8Array(update), \"backend\");\n // if this update is the result of a fetch, the state vector is included\n if (stateVector) {\n // Use server state to calculate a diff and send it\n try {\n const localUpdate = Y.encodeStateAsUpdate(\n this.doc,\n Base64.toUint8Array(stateVector)\n );\n this.updateRoomDoc(Base64.fromUint8Array(localUpdate));\n } catch (e) {\n // something went wrong encoding local state to send to the server\n console.warn(e);\n }\n // now that we've sent our local and received from server, we're in sync\n // calling `syncDoc` again will sync up the documents\n this.synced = true;\n }\n };\n\n public syncDoc = (): void => {\n this.synced = false;\n\n // The state vector is sent to the server so it knows what to send back\n // if you don't send it, it returns everything\n const encodedVector = Base64.fromUint8Array(Y.encodeStateVector(this.doc));\n this.fetchRoomDoc(encodedVector);\n };\n\n // The sync'd property is required by some provider implementations\n get synced(): boolean {\n return this._synced;\n }\n\n set synced(state: boolean) {\n if (this._synced !== state) {\n this._synced = state;\n this.emit(\"synced\", [state]);\n this.emit(\"sync\", [state]);\n }\n }\n\n private updateHandler = (update: Uint8Array, origin: string) => {\n if (origin !== \"backend\") {\n const encodedUpdate = Base64.fromUint8Array(update);\n this.updateRoomDoc(encodedUpdate);\n }\n };\n\n destroy(): void {\n this.doc.off(\"update\", this.updateHandler);\n this.unsubscribers.forEach((unsub) => unsub());\n this._observers = new Map();\n this.doc.destroy();\n }\n}\n","declare const __VERSION__: string;\ndeclare const TSUP_FORMAT: string;\n\nexport const PKG_NAME = \"@liveblocks/yjs\";\nexport const PKG_VERSION = typeof __VERSION__ === \"string\" && __VERSION__;\nexport const PKG_FORMAT = typeof TSUP_FORMAT === \"string\" && TSUP_FORMAT;\n"]}
package/dist/index.mjs CHANGED
@@ -90,19 +90,31 @@ var Awareness = class extends Observable {
90
90
  if (event.type === "leave") {
91
91
  this.emit("change", [
92
92
  { added: [], updated: [], removed: [event.user.connectionId] },
93
- "local"
93
+ "presence"
94
+ ]);
95
+ this.emit("update", [
96
+ { added: [], updated: [], removed: [event.user.connectionId] },
97
+ "presence"
94
98
  ]);
95
99
  }
96
100
  if (event.type === "enter") {
97
101
  this.emit("change", [
98
102
  { added: [event.user.connectionId], updated: [], removed: [] },
99
- "local"
103
+ "presence"
104
+ ]);
105
+ this.emit("update", [
106
+ { added: [event.user.connectionId], updated: [], removed: [] },
107
+ "presence"
100
108
  ]);
101
109
  }
102
110
  if (event.type === "update") {
103
111
  this.emit("change", [
104
112
  { added: [], updated: [event.user.connectionId], removed: [] },
105
- "local"
113
+ "presence"
114
+ ]);
115
+ this.emit("update", [
116
+ { added: [], updated: [event.user.connectionId], removed: [] },
117
+ "presence"
106
118
  ]);
107
119
  }
108
120
  });
@@ -121,23 +133,42 @@ var Awareness = class extends Observable {
121
133
  return presence[Y_PRESENCE_KEY];
122
134
  }
123
135
  setLocalState(state) {
124
- const presence = this.room.getSelf()?.presence[Y_PRESENCE_KEY];
136
+ const presence = this.room.getSelf()?.presence;
137
+ if (state === null) {
138
+ if (presence === void 0) {
139
+ return;
140
+ }
141
+ this.room.updatePresence({ ...presence, [Y_PRESENCE_KEY]: null });
142
+ this.emit("update", [
143
+ { added: [], updated: [], removed: [this.clientID] },
144
+ "local"
145
+ ]);
146
+ return;
147
+ }
148
+ const yPresence = presence?.[Y_PRESENCE_KEY];
149
+ const added = yPresence === void 0 ? [this.clientID] : [];
150
+ const updated = yPresence === void 0 ? [] : [this.clientID];
125
151
  this.room.updatePresence({
126
- __yjs: { ...presence || {}, ...state || {} }
152
+ [Y_PRESENCE_KEY]: {
153
+ ...yPresence || {},
154
+ ...state || {}
155
+ }
127
156
  });
157
+ this.emit("update", [{ added, updated, removed: [] }, "local"]);
128
158
  }
129
159
  setLocalStateField(field, value) {
130
160
  const presence = this.room.getSelf()?.presence[Y_PRESENCE_KEY];
131
161
  const update = { [field]: value };
132
162
  this.room.updatePresence({
133
- __yjs: { ...presence || {}, ...update }
163
+ [Y_PRESENCE_KEY]: { ...presence || {}, ...update }
134
164
  });
135
165
  }
136
166
  // Translate liveblocks presence to yjs awareness
137
167
  getStates() {
138
168
  const others = this.room.getOthers();
169
+ const presence = this.room.getSelf()?.presence[Y_PRESENCE_KEY];
139
170
  const states = others.reduce((acc, currentValue) => {
140
- if (currentValue.connectionId) {
171
+ if (currentValue.connectionId && currentValue.presence[Y_PRESENCE_KEY] !== void 0) {
141
172
  acc.set(
142
173
  currentValue.connectionId,
143
174
  currentValue.presence[Y_PRESENCE_KEY] || {}
@@ -145,6 +176,9 @@ var Awareness = class extends Observable {
145
176
  }
146
177
  return acc;
147
178
  }, /* @__PURE__ */ new Map());
179
+ if (presence !== void 0) {
180
+ states.set(this.clientID, presence);
181
+ }
148
182
  return states;
149
183
  }
150
184
  };
@@ -222,7 +256,7 @@ var yDocHandler = class extends Observable {
222
256
 
223
257
  // src/version.ts
224
258
  var PKG_NAME = "@liveblocks/yjs";
225
- var PKG_VERSION = "1.9.6";
259
+ var PKG_VERSION = "1.9.7-awareness";
226
260
  var PKG_FORMAT = "esm";
227
261
 
228
262
  // src/index.ts
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../../../node_modules/lib0/map.js","../../../node_modules/lib0/set.js","../../../node_modules/lib0/array.js","../../../node_modules/lib0/observable.js","../src/awareness.ts","../src/doc.ts","../src/version.ts"],"sourcesContent":["import type {\n BaseUserMeta,\n Json,\n JsonObject,\n LsonObject,\n Room,\n} from \"@liveblocks/client\";\nimport { ClientMsgCode, detectDupes } from \"@liveblocks/core\";\nimport { Observable } from \"lib0/observable\";\nimport type * as Y from \"yjs\";\n\nimport { Awareness } from \"./awareness\";\nimport yDocHandler from \"./doc\";\nimport { PKG_FORMAT, PKG_NAME, PKG_VERSION } from \"./version\";\n\ndetectDupes(PKG_NAME, PKG_VERSION, PKG_FORMAT);\n\ntype ProviderOptions = {\n autoloadSubdocs: boolean;\n};\n\nconst DefaultOptions: ProviderOptions = {\n autoloadSubdocs: false,\n};\n\nexport default class LiveblocksProvider<\n P extends JsonObject,\n S extends LsonObject,\n U extends BaseUserMeta,\n E extends Json,\n> extends Observable<unknown> {\n private room: Room<P, S, U, E>;\n private rootDoc: Y.Doc;\n private options: ProviderOptions;\n\n private unsubscribers: Array<() => void> = [];\n\n public awareness: Awareness;\n\n public rootDocHandler: yDocHandler;\n public subdocHandlers: Map<string, yDocHandler> = new Map();\n\n constructor(\n room: Room<P, S, U, E>,\n doc: Y.Doc,\n options: ProviderOptions | undefined = DefaultOptions\n ) {\n super();\n this.rootDoc = doc;\n this.room = room;\n this.options = options;\n this.rootDocHandler = new yDocHandler({\n doc,\n isRoot: true,\n updateDoc: this.updateDoc,\n fetchDoc: this.fetchDoc,\n });\n // if we have a connectionId already during construction, use that\n const connectionId = this.room.getSelf()?.connectionId;\n if (connectionId) {\n this.rootDoc.clientID = connectionId;\n }\n this.awareness = new Awareness(this.rootDoc, this.room);\n\n this.unsubscribers.push(\n this.room.events.status.subscribe((status) => {\n if (status === \"connected\") {\n this.rootDocHandler.syncDoc();\n } else {\n this.rootDocHandler.synced = false;\n }\n })\n );\n\n this.unsubscribers.push(\n this.room.events.ydoc.subscribe((message) => {\n const { type } = message;\n if (type === ClientMsgCode.UPDATE_YDOC) {\n // don't apply updates that came from the client\n return;\n }\n const { stateVector, update, guid } = message;\n // find the right doc and update\n if (guid !== undefined) {\n this.subdocHandlers\n .get(guid)\n ?.handleServerUpdate({ update, stateVector });\n } else {\n this.rootDocHandler.handleServerUpdate({ update, stateVector });\n }\n })\n );\n\n this.rootDocHandler.on(\"synced\", () => {\n const state = this.rootDocHandler.synced;\n for (const [_, handler] of this.subdocHandlers) {\n handler.syncDoc();\n }\n this.emit(\"synced\", [state]);\n this.emit(\"sync\", [state]);\n });\n this.rootDoc.on(\"subdocs\", this.handleSubdocs);\n this.syncDoc();\n }\n\n private handleSubdocs = ({\n loaded,\n removed,\n added,\n }: {\n loaded: Y.Doc[];\n removed: Y.Doc[];\n added: Y.Doc[];\n }) => {\n loaded.forEach(this.createSubdocHandler);\n if (this.options.autoloadSubdocs) {\n for (const subdoc of added) {\n if (!this.subdocHandlers.has(subdoc.guid)) {\n subdoc.load();\n }\n }\n }\n for (const subdoc of removed) {\n if (this.subdocHandlers.has(subdoc.guid)) {\n this.subdocHandlers.get(subdoc.guid)?.destroy();\n this.subdocHandlers.delete(subdoc.guid);\n }\n }\n };\n\n private updateDoc = (update: string, guid?: string) => {\n this.room.updateYDoc(update, guid);\n };\n\n private fetchDoc = (vector: string, guid?: string) => {\n this.room.fetchYDoc(vector, guid);\n };\n\n private createSubdocHandler = (subdoc: Y.Doc): void => {\n if (this.subdocHandlers.has(subdoc.guid)) {\n // if we already handle this subdoc, just fetch it again\n this.subdocHandlers.get(subdoc.guid)?.syncDoc();\n return;\n }\n const handler = new yDocHandler({\n doc: subdoc,\n isRoot: false,\n updateDoc: this.updateDoc,\n fetchDoc: this.fetchDoc,\n });\n this.subdocHandlers.set(subdoc.guid, handler);\n };\n\n // attempt to load a subdoc of a given guid\n public loadSubdoc = (guid: string): boolean => {\n for (const subdoc of this.rootDoc.subdocs) {\n if (subdoc.guid === guid) {\n subdoc.load();\n return true;\n }\n }\n // should we throw instead?\n return false;\n };\n\n private syncDoc = () => {\n /**\n * If the connection changes, set the new id, this is used by awareness.\n * yjs' only requirement for clientID is that it's truly unique and a number.\n * Liveblock's connectionID satisfies those constraints\n * */\n this.rootDoc.clientID =\n this.room.getSelf()?.connectionId || this.rootDoc.clientID;\n this.awareness.clientID = this.rootDoc.clientID; // tell our awareness provider the new ID\n\n this.rootDocHandler.syncDoc();\n for (const [_, handler] of this.subdocHandlers) {\n handler.syncDoc();\n }\n };\n\n // The sync'd property is required by some provider implementations\n get synced(): boolean {\n return this.rootDocHandler.synced;\n }\n\n destroy(): void {\n this.unsubscribers.forEach((unsub) => unsub());\n this.awareness.destroy();\n this.rootDocHandler.destroy();\n this._observers = new Map();\n for (const [_, handler] of this.subdocHandlers) {\n handler.destroy();\n }\n this.subdocHandlers.clear();\n super.destroy();\n }\n\n // Some provider implementations expect to be able to call connect/disconnect, implement as noop\n disconnect(): void {\n // This is a noop for liveblocks as connections are managed by the room\n }\n\n connect(): void {\n // This is a noop for liveblocks as connections are managed by the room\n }\n}\n","/**\n * Utility module to work with key-value stores.\n *\n * @module map\n */\n\n/**\n * Creates a new Map instance.\n *\n * @function\n * @return {Map<any, any>}\n *\n * @function\n */\nexport const create = () => new Map()\n\n/**\n * Copy a Map object into a fresh Map object.\n *\n * @function\n * @template X,Y\n * @param {Map<X,Y>} m\n * @return {Map<X,Y>}\n */\nexport const copy = m => {\n const r = create()\n m.forEach((v, k) => { r.set(k, v) })\n return r\n}\n\n/**\n * Get map property. Create T if property is undefined and set T on map.\n *\n * ```js\n * const listeners = map.setIfUndefined(events, 'eventName', set.create)\n * listeners.add(listener)\n * ```\n *\n * @function\n * @template V,K\n * @template {Map<K,V>} MAP\n * @param {MAP} map\n * @param {K} key\n * @param {function():V} createT\n * @return {V}\n */\nexport const setIfUndefined = (map, key, createT) => {\n let set = map.get(key)\n if (set === undefined) {\n map.set(key, set = createT())\n }\n return set\n}\n\n/**\n * Creates an Array and populates it with the content of all key-value pairs using the `f(value, key)` function.\n *\n * @function\n * @template K\n * @template V\n * @template R\n * @param {Map<K,V>} m\n * @param {function(V,K):R} f\n * @return {Array<R>}\n */\nexport const map = (m, f) => {\n const res = []\n for (const [key, value] of m) {\n res.push(f(value, key))\n }\n return res\n}\n\n/**\n * Tests whether any key-value pairs pass the test implemented by `f(value, key)`.\n *\n * @todo should rename to some - similarly to Array.some\n *\n * @function\n * @template K\n * @template V\n * @param {Map<K,V>} m\n * @param {function(V,K):boolean} f\n * @return {boolean}\n */\nexport const any = (m, f) => {\n for (const [key, value] of m) {\n if (f(value, key)) {\n return true\n }\n }\n return false\n}\n\n/**\n * Tests whether all key-value pairs pass the test implemented by `f(value, key)`.\n *\n * @function\n * @template K\n * @template V\n * @param {Map<K,V>} m\n * @param {function(V,K):boolean} f\n * @return {boolean}\n */\nexport const all = (m, f) => {\n for (const [key, value] of m) {\n if (!f(value, key)) {\n return false\n }\n }\n return true\n}\n","/**\n * Utility module to work with sets.\n *\n * @module set\n */\n\nexport const create = () => new Set()\n\n/**\n * @template T\n * @param {Set<T>} set\n * @return {Array<T>}\n */\nexport const toArray = set => Array.from(set)\n\n/**\n * @template T\n * @param {Set<T>} set\n * @return {T}\n */\nexport const first = set =>\n set.values().next().value || undefined\n\n/**\n * @template T\n * @param {Iterable<T>} entries\n * @return {Set<T>}\n */\nexport const from = entries => new Set(entries)\n","/**\n * Utility module to work with Arrays.\n *\n * @module array\n */\n\nimport * as set from './set.js'\n\n/**\n * Return the last element of an array. The element must exist\n *\n * @template L\n * @param {ArrayLike<L>} arr\n * @return {L}\n */\nexport const last = arr => arr[arr.length - 1]\n\n/**\n * @template C\n * @return {Array<C>}\n */\nexport const create = () => /** @type {Array<C>} */ ([])\n\n/**\n * @template D\n * @param {Array<D>} a\n * @return {Array<D>}\n */\nexport const copy = a => /** @type {Array<D>} */ (a.slice())\n\n/**\n * Append elements from src to dest\n *\n * @template M\n * @param {Array<M>} dest\n * @param {Array<M>} src\n */\nexport const appendTo = (dest, src) => {\n for (let i = 0; i < src.length; i++) {\n dest.push(src[i])\n }\n}\n\n/**\n * Transforms something array-like to an actual Array.\n *\n * @function\n * @template T\n * @param {ArrayLike<T>|Iterable<T>} arraylike\n * @return {T}\n */\nexport const from = Array.from\n\n/**\n * True iff condition holds on every element in the Array.\n *\n * @function\n * @template ITEM\n * @template {ArrayLike<ITEM>} ARR\n *\n * @param {ARR} arr\n * @param {function(ITEM, number, ARR):boolean} f\n * @return {boolean}\n */\nexport const every = (arr, f) => {\n for (let i = 0; i < arr.length; i++) {\n if (!f(arr[i], i, arr)) {\n return false\n }\n }\n return true\n}\n\n/**\n * True iff condition holds on some element in the Array.\n *\n * @function\n * @template S\n * @template {ArrayLike<S>} ARR\n * @param {ARR} arr\n * @param {function(S, number, ARR):boolean} f\n * @return {boolean}\n */\nexport const some = (arr, f) => {\n for (let i = 0; i < arr.length; i++) {\n if (f(arr[i], i, arr)) {\n return true\n }\n }\n return false\n}\n\n/**\n * @template ELEM\n *\n * @param {ArrayLike<ELEM>} a\n * @param {ArrayLike<ELEM>} b\n * @return {boolean}\n */\nexport const equalFlat = (a, b) => a.length === b.length && every(a, (item, index) => item === b[index])\n\n/**\n * @template ELEM\n * @param {Array<Array<ELEM>>} arr\n * @return {Array<ELEM>}\n */\nexport const flatten = arr => fold(arr, /** @type {Array<ELEM>} */ ([]), (acc, val) => acc.concat(val))\n\n/**\n * @template T\n * @param {number} len\n * @param {function(number, Array<T>):T} f\n * @return {Array<T>}\n */\nexport const unfold = (len, f) => {\n const array = new Array(len)\n for (let i = 0; i < len; i++) {\n array[i] = f(i, array)\n }\n return array\n}\n\n/**\n * @template T\n * @template RESULT\n * @param {Array<T>} arr\n * @param {RESULT} seed\n * @param {function(RESULT, T, number):RESULT} folder\n */\nexport const fold = (arr, seed, folder) => arr.reduce(folder, seed)\n\nexport const isArray = Array.isArray\n\n/**\n * @template T\n * @param {Array<T>} arr\n * @return {Array<T>}\n */\nexport const unique = arr => from(set.from(arr))\n\n/**\n * @template T\n * @template M\n * @param {ArrayLike<T>} arr\n * @param {function(T):M} mapper\n * @return {Array<T>}\n */\nexport const uniqueBy = (arr, mapper) => {\n /**\n * @type {Set<M>}\n */\n const happened = set.create()\n /**\n * @type {Array<T>}\n */\n const result = []\n for (let i = 0; i < arr.length; i++) {\n const el = arr[i]\n const mapped = mapper(el)\n if (!happened.has(mapped)) {\n happened.add(mapped)\n result.push(el)\n }\n }\n return result\n}\n","/**\n * Observable class prototype.\n *\n * @module observable\n */\n\nimport * as map from './map.js'\nimport * as set from './set.js'\nimport * as array from './array.js'\n\n/**\n * Handles named events.\n *\n * @template N\n */\nexport class Observable {\n constructor () {\n /**\n * Some desc.\n * @type {Map<N, any>}\n */\n this._observers = map.create()\n }\n\n /**\n * @param {N} name\n * @param {function} f\n */\n on (name, f) {\n map.setIfUndefined(this._observers, name, set.create).add(f)\n }\n\n /**\n * @param {N} name\n * @param {function} f\n */\n once (name, f) {\n /**\n * @param {...any} args\n */\n const _f = (...args) => {\n this.off(name, _f)\n f(...args)\n }\n this.on(name, _f)\n }\n\n /**\n * @param {N} name\n * @param {function} f\n */\n off (name, f) {\n const observers = this._observers.get(name)\n if (observers !== undefined) {\n observers.delete(f)\n if (observers.size === 0) {\n this._observers.delete(name)\n }\n }\n }\n\n /**\n * Emit a named event. All registered event listeners that listen to the\n * specified name will receive the event.\n *\n * @todo This should catch exceptions\n *\n * @param {N} name The event name.\n * @param {Array<any>} args The arguments that are applied to the event listener.\n */\n emit (name, args) {\n // copy all listeners to an array first to make sure that no event is emitted to listeners that are subscribed while the event handler is called.\n return array.from((this._observers.get(name) || map.create()).values()).forEach(f => f(...args))\n }\n\n destroy () {\n this._observers = map.create()\n }\n}\n","// TODO: apparently Yjs is full of anys or something, see if we can fix this\n/* eslint-disable @typescript-eslint/no-unsafe-call */\n/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n/* eslint-disable @typescript-eslint/no-unsafe-assignment */\nimport type {\n BaseUserMeta,\n Json,\n JsonObject,\n LsonObject,\n Room,\n} from \"@liveblocks/client\";\nimport { Observable } from \"lib0/observable\";\nimport type * as Y from \"yjs\";\n\nconst Y_PRESENCE_KEY = \"__yjs\";\n\ntype MetaClientState = {\n clock: number;\n lastUpdated: number;\n};\n\n/**\n * This class will store Yjs awareness in Liveblock's presence under the __yjs key\n * IMPORTANT: The Yjs awareness protocol uses ydoc.clientId to reference users\n * to their respective documents. To avoid mapping Yjs clientIds to liveblock's connectionId,\n * we simply set the clientId of the doc to the connectionId. Then no further mapping is required\n */\nexport class Awareness extends Observable<unknown> {\n private room: Room<JsonObject, LsonObject, BaseUserMeta, Json>;\n public doc: Y.Doc;\n public clientID: number;\n public states: Map<number, unknown> = new Map();\n // Meta is used to keep track and timeout users who disconnect. Liveblocks provides this for us, so we don't need to\n // manage it here. Unfortunately, it's expected to exist by various integrations, so it's an empty map.\n public meta: Map<number, MetaClientState> = new Map();\n // _checkInterval this would hold a timer to remove users, but Liveblock's presence already handles this\n // unfortunately it's typed by various integrations\n public _checkInterval: number = 0;\n\n private othersUnsub: () => void;\n constructor(\n doc: Y.Doc,\n room: Room<JsonObject, LsonObject, BaseUserMeta, Json>\n ) {\n super();\n this.doc = doc;\n this.room = room;\n this.clientID = doc.clientID;\n this.othersUnsub = this.room.events.others.subscribe((event) => {\n // When others are changed, we emit an event that contains arrays added/updated/removed.\n if (event.type === \"leave\") {\n // REMOVED\n this.emit(\"change\", [\n { added: [], updated: [], removed: [event.user.connectionId] },\n \"local\",\n ]);\n }\n\n if (event.type === \"enter\") {\n // ADDED\n this.emit(\"change\", [\n { added: [event.user.connectionId], updated: [], removed: [] },\n \"local\",\n ]);\n }\n\n if (event.type === \"update\") {\n // UPDATED\n this.emit(\"change\", [\n { added: [], updated: [event.user.connectionId], removed: [] },\n \"local\",\n ]);\n }\n });\n }\n\n destroy(): void {\n this.emit(\"destroy\", [this]);\n this.othersUnsub();\n this.setLocalState(null);\n super.destroy();\n }\n\n getLocalState(): JsonObject | null {\n const presence = this.room.getPresence();\n if (\n Object.keys(presence).length === 0 ||\n typeof presence[Y_PRESENCE_KEY] === \"undefined\"\n ) {\n return null;\n }\n return presence[Y_PRESENCE_KEY] as JsonObject | null;\n }\n\n setLocalState(state: Partial<JsonObject> | null): void {\n const presence = this.room.getSelf()?.presence[Y_PRESENCE_KEY];\n this.room.updatePresence({\n __yjs: { ...((presence as JsonObject) || {}), ...(state || {}) },\n });\n }\n\n setLocalStateField(field: string, value: JsonObject | null): void {\n const presence = this.room.getSelf()?.presence[Y_PRESENCE_KEY];\n const update = { [field]: value } as Partial<JsonObject>;\n this.room.updatePresence({\n __yjs: { ...((presence as JsonObject) || {}), ...update },\n });\n }\n\n // Translate liveblocks presence to yjs awareness\n getStates(): Map<number, unknown> {\n const others = this.room.getOthers();\n const states = others.reduce((acc: Map<number, unknown>, currentValue) => {\n if (currentValue.connectionId) {\n // connectionId == actorId == yjs.clientId\n acc.set(\n currentValue.connectionId,\n currentValue.presence[Y_PRESENCE_KEY] || {}\n );\n }\n return acc;\n }, new Map());\n return states;\n }\n}\n","import { Base64 } from \"js-base64\";\nimport { Observable } from \"lib0/observable\";\nimport * as Y from \"yjs\";\n\nexport default class yDocHandler extends Observable<unknown> {\n private unsubscribers: Array<() => void> = [];\n\n private _synced = false;\n private doc: Y.Doc;\n private updateRoomDoc: (update: string) => void;\n private fetchRoomDoc: (vector: string) => void;\n\n constructor({\n doc,\n isRoot,\n updateDoc,\n fetchDoc,\n }: {\n doc: Y.Doc;\n isRoot: boolean;\n updateDoc: (update: string, guid?: string) => void;\n fetchDoc: (vector: string, guid?: string) => void;\n }) {\n super();\n this.doc = doc;\n // this.doc.load(); // this just emits a load event, it doesn't actually load anything\n this.doc.on(\"update\", this.updateHandler);\n this.updateRoomDoc = (update: string) => {\n updateDoc(update, isRoot ? undefined : this.doc.guid);\n };\n this.fetchRoomDoc = (vector: string) => {\n fetchDoc(vector, isRoot ? undefined : this.doc.guid);\n };\n\n this.syncDoc();\n }\n\n public handleServerUpdate = ({\n update,\n stateVector,\n }: {\n update: string;\n stateVector: string | null;\n }): void => {\n // apply update from the server\n Y.applyUpdate(this.doc, Base64.toUint8Array(update), \"backend\");\n // if this update is the result of a fetch, the state vector is included\n if (stateVector) {\n // Use server state to calculate a diff and send it\n try {\n const localUpdate = Y.encodeStateAsUpdate(\n this.doc,\n Base64.toUint8Array(stateVector)\n );\n this.updateRoomDoc(Base64.fromUint8Array(localUpdate));\n } catch (e) {\n // something went wrong encoding local state to send to the server\n console.warn(e);\n }\n // now that we've sent our local and received from server, we're in sync\n // calling `syncDoc` again will sync up the documents\n this.synced = true;\n }\n };\n\n public syncDoc = (): void => {\n this.synced = false;\n\n // The state vector is sent to the server so it knows what to send back\n // if you don't send it, it returns everything\n const encodedVector = Base64.fromUint8Array(Y.encodeStateVector(this.doc));\n this.fetchRoomDoc(encodedVector);\n };\n\n // The sync'd property is required by some provider implementations\n get synced(): boolean {\n return this._synced;\n }\n\n set synced(state: boolean) {\n if (this._synced !== state) {\n this._synced = state;\n this.emit(\"synced\", [state]);\n this.emit(\"sync\", [state]);\n }\n }\n\n private updateHandler = (update: Uint8Array, origin: string) => {\n if (origin !== \"backend\") {\n const encodedUpdate = Base64.fromUint8Array(update);\n this.updateRoomDoc(encodedUpdate);\n }\n };\n\n destroy(): void {\n this.doc.off(\"update\", this.updateHandler);\n this.unsubscribers.forEach((unsub) => unsub());\n this._observers = new Map();\n this.doc.destroy();\n }\n}\n","declare const __VERSION__: string;\ndeclare const TSUP_FORMAT: string;\n\nexport const PKG_NAME = \"@liveblocks/yjs\";\nexport const PKG_VERSION = typeof __VERSION__ === \"string\" && __VERSION__;\nexport const PKG_FORMAT = typeof TSUP_FORMAT === \"string\" && TSUP_FORMAT;\n"],"mappings":"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","names":["create","create"]}
1
+ {"version":3,"sources":["../src/index.ts","../../../node_modules/lib0/map.js","../../../node_modules/lib0/set.js","../../../node_modules/lib0/array.js","../../../node_modules/lib0/observable.js","../src/awareness.ts","../src/doc.ts","../src/version.ts"],"sourcesContent":["import type {\n BaseUserMeta,\n Json,\n JsonObject,\n LsonObject,\n Room,\n} from \"@liveblocks/client\";\nimport { ClientMsgCode, detectDupes } from \"@liveblocks/core\";\nimport { Observable } from \"lib0/observable\";\nimport type * as Y from \"yjs\";\n\nimport { Awareness } from \"./awareness\";\nimport yDocHandler from \"./doc\";\nimport { PKG_FORMAT, PKG_NAME, PKG_VERSION } from \"./version\";\n\ndetectDupes(PKG_NAME, PKG_VERSION, PKG_FORMAT);\n\ntype ProviderOptions = {\n autoloadSubdocs: boolean;\n};\n\nconst DefaultOptions: ProviderOptions = {\n autoloadSubdocs: false,\n};\n\nexport default class LiveblocksProvider<\n P extends JsonObject,\n S extends LsonObject,\n U extends BaseUserMeta,\n E extends Json,\n> extends Observable<unknown> {\n private room: Room<P, S, U, E>;\n private rootDoc: Y.Doc;\n private options: ProviderOptions;\n\n private unsubscribers: Array<() => void> = [];\n\n public awareness: Awareness;\n\n public rootDocHandler: yDocHandler;\n public subdocHandlers: Map<string, yDocHandler> = new Map();\n\n constructor(\n room: Room<P, S, U, E>,\n doc: Y.Doc,\n options: ProviderOptions | undefined = DefaultOptions\n ) {\n super();\n this.rootDoc = doc;\n this.room = room;\n this.options = options;\n this.rootDocHandler = new yDocHandler({\n doc,\n isRoot: true,\n updateDoc: this.updateDoc,\n fetchDoc: this.fetchDoc,\n });\n // if we have a connectionId already during construction, use that\n const connectionId = this.room.getSelf()?.connectionId;\n if (connectionId) {\n this.rootDoc.clientID = connectionId;\n }\n this.awareness = new Awareness(this.rootDoc, this.room);\n\n this.unsubscribers.push(\n this.room.events.status.subscribe((status) => {\n if (status === \"connected\") {\n this.rootDocHandler.syncDoc();\n } else {\n this.rootDocHandler.synced = false;\n }\n })\n );\n\n this.unsubscribers.push(\n this.room.events.ydoc.subscribe((message) => {\n const { type } = message;\n if (type === ClientMsgCode.UPDATE_YDOC) {\n // don't apply updates that came from the client\n return;\n }\n const { stateVector, update, guid } = message;\n // find the right doc and update\n if (guid !== undefined) {\n this.subdocHandlers\n .get(guid)\n ?.handleServerUpdate({ update, stateVector });\n } else {\n this.rootDocHandler.handleServerUpdate({ update, stateVector });\n }\n })\n );\n\n this.rootDocHandler.on(\"synced\", () => {\n const state = this.rootDocHandler.synced;\n for (const [_, handler] of this.subdocHandlers) {\n handler.syncDoc();\n }\n this.emit(\"synced\", [state]);\n this.emit(\"sync\", [state]);\n });\n this.rootDoc.on(\"subdocs\", this.handleSubdocs);\n this.syncDoc();\n }\n\n private handleSubdocs = ({\n loaded,\n removed,\n added,\n }: {\n loaded: Y.Doc[];\n removed: Y.Doc[];\n added: Y.Doc[];\n }) => {\n loaded.forEach(this.createSubdocHandler);\n if (this.options.autoloadSubdocs) {\n for (const subdoc of added) {\n if (!this.subdocHandlers.has(subdoc.guid)) {\n subdoc.load();\n }\n }\n }\n for (const subdoc of removed) {\n if (this.subdocHandlers.has(subdoc.guid)) {\n this.subdocHandlers.get(subdoc.guid)?.destroy();\n this.subdocHandlers.delete(subdoc.guid);\n }\n }\n };\n\n private updateDoc = (update: string, guid?: string) => {\n this.room.updateYDoc(update, guid);\n };\n\n private fetchDoc = (vector: string, guid?: string) => {\n this.room.fetchYDoc(vector, guid);\n };\n\n private createSubdocHandler = (subdoc: Y.Doc): void => {\n if (this.subdocHandlers.has(subdoc.guid)) {\n // if we already handle this subdoc, just fetch it again\n this.subdocHandlers.get(subdoc.guid)?.syncDoc();\n return;\n }\n const handler = new yDocHandler({\n doc: subdoc,\n isRoot: false,\n updateDoc: this.updateDoc,\n fetchDoc: this.fetchDoc,\n });\n this.subdocHandlers.set(subdoc.guid, handler);\n };\n\n // attempt to load a subdoc of a given guid\n public loadSubdoc = (guid: string): boolean => {\n for (const subdoc of this.rootDoc.subdocs) {\n if (subdoc.guid === guid) {\n subdoc.load();\n return true;\n }\n }\n // should we throw instead?\n return false;\n };\n\n private syncDoc = () => {\n /**\n * If the connection changes, set the new id, this is used by awareness.\n * yjs' only requirement for clientID is that it's truly unique and a number.\n * Liveblock's connectionID satisfies those constraints\n * */\n this.rootDoc.clientID =\n this.room.getSelf()?.connectionId || this.rootDoc.clientID;\n this.awareness.clientID = this.rootDoc.clientID; // tell our awareness provider the new ID\n\n this.rootDocHandler.syncDoc();\n for (const [_, handler] of this.subdocHandlers) {\n handler.syncDoc();\n }\n };\n\n // The sync'd property is required by some provider implementations\n get synced(): boolean {\n return this.rootDocHandler.synced;\n }\n\n destroy(): void {\n this.unsubscribers.forEach((unsub) => unsub());\n this.awareness.destroy();\n this.rootDocHandler.destroy();\n this._observers = new Map();\n for (const [_, handler] of this.subdocHandlers) {\n handler.destroy();\n }\n this.subdocHandlers.clear();\n super.destroy();\n }\n\n // Some provider implementations expect to be able to call connect/disconnect, implement as noop\n disconnect(): void {\n // This is a noop for liveblocks as connections are managed by the room\n }\n\n connect(): void {\n // This is a noop for liveblocks as connections are managed by the room\n }\n}\n","/**\n * Utility module to work with key-value stores.\n *\n * @module map\n */\n\n/**\n * Creates a new Map instance.\n *\n * @function\n * @return {Map<any, any>}\n *\n * @function\n */\nexport const create = () => new Map()\n\n/**\n * Copy a Map object into a fresh Map object.\n *\n * @function\n * @template X,Y\n * @param {Map<X,Y>} m\n * @return {Map<X,Y>}\n */\nexport const copy = m => {\n const r = create()\n m.forEach((v, k) => { r.set(k, v) })\n return r\n}\n\n/**\n * Get map property. Create T if property is undefined and set T on map.\n *\n * ```js\n * const listeners = map.setIfUndefined(events, 'eventName', set.create)\n * listeners.add(listener)\n * ```\n *\n * @function\n * @template V,K\n * @template {Map<K,V>} MAP\n * @param {MAP} map\n * @param {K} key\n * @param {function():V} createT\n * @return {V}\n */\nexport const setIfUndefined = (map, key, createT) => {\n let set = map.get(key)\n if (set === undefined) {\n map.set(key, set = createT())\n }\n return set\n}\n\n/**\n * Creates an Array and populates it with the content of all key-value pairs using the `f(value, key)` function.\n *\n * @function\n * @template K\n * @template V\n * @template R\n * @param {Map<K,V>} m\n * @param {function(V,K):R} f\n * @return {Array<R>}\n */\nexport const map = (m, f) => {\n const res = []\n for (const [key, value] of m) {\n res.push(f(value, key))\n }\n return res\n}\n\n/**\n * Tests whether any key-value pairs pass the test implemented by `f(value, key)`.\n *\n * @todo should rename to some - similarly to Array.some\n *\n * @function\n * @template K\n * @template V\n * @param {Map<K,V>} m\n * @param {function(V,K):boolean} f\n * @return {boolean}\n */\nexport const any = (m, f) => {\n for (const [key, value] of m) {\n if (f(value, key)) {\n return true\n }\n }\n return false\n}\n\n/**\n * Tests whether all key-value pairs pass the test implemented by `f(value, key)`.\n *\n * @function\n * @template K\n * @template V\n * @param {Map<K,V>} m\n * @param {function(V,K):boolean} f\n * @return {boolean}\n */\nexport const all = (m, f) => {\n for (const [key, value] of m) {\n if (!f(value, key)) {\n return false\n }\n }\n return true\n}\n","/**\n * Utility module to work with sets.\n *\n * @module set\n */\n\nexport const create = () => new Set()\n\n/**\n * @template T\n * @param {Set<T>} set\n * @return {Array<T>}\n */\nexport const toArray = set => Array.from(set)\n\n/**\n * @template T\n * @param {Set<T>} set\n * @return {T}\n */\nexport const first = set =>\n set.values().next().value || undefined\n\n/**\n * @template T\n * @param {Iterable<T>} entries\n * @return {Set<T>}\n */\nexport const from = entries => new Set(entries)\n","/**\n * Utility module to work with Arrays.\n *\n * @module array\n */\n\nimport * as set from './set.js'\n\n/**\n * Return the last element of an array. The element must exist\n *\n * @template L\n * @param {ArrayLike<L>} arr\n * @return {L}\n */\nexport const last = arr => arr[arr.length - 1]\n\n/**\n * @template C\n * @return {Array<C>}\n */\nexport const create = () => /** @type {Array<C>} */ ([])\n\n/**\n * @template D\n * @param {Array<D>} a\n * @return {Array<D>}\n */\nexport const copy = a => /** @type {Array<D>} */ (a.slice())\n\n/**\n * Append elements from src to dest\n *\n * @template M\n * @param {Array<M>} dest\n * @param {Array<M>} src\n */\nexport const appendTo = (dest, src) => {\n for (let i = 0; i < src.length; i++) {\n dest.push(src[i])\n }\n}\n\n/**\n * Transforms something array-like to an actual Array.\n *\n * @function\n * @template T\n * @param {ArrayLike<T>|Iterable<T>} arraylike\n * @return {T}\n */\nexport const from = Array.from\n\n/**\n * True iff condition holds on every element in the Array.\n *\n * @function\n * @template ITEM\n * @template {ArrayLike<ITEM>} ARR\n *\n * @param {ARR} arr\n * @param {function(ITEM, number, ARR):boolean} f\n * @return {boolean}\n */\nexport const every = (arr, f) => {\n for (let i = 0; i < arr.length; i++) {\n if (!f(arr[i], i, arr)) {\n return false\n }\n }\n return true\n}\n\n/**\n * True iff condition holds on some element in the Array.\n *\n * @function\n * @template S\n * @template {ArrayLike<S>} ARR\n * @param {ARR} arr\n * @param {function(S, number, ARR):boolean} f\n * @return {boolean}\n */\nexport const some = (arr, f) => {\n for (let i = 0; i < arr.length; i++) {\n if (f(arr[i], i, arr)) {\n return true\n }\n }\n return false\n}\n\n/**\n * @template ELEM\n *\n * @param {ArrayLike<ELEM>} a\n * @param {ArrayLike<ELEM>} b\n * @return {boolean}\n */\nexport const equalFlat = (a, b) => a.length === b.length && every(a, (item, index) => item === b[index])\n\n/**\n * @template ELEM\n * @param {Array<Array<ELEM>>} arr\n * @return {Array<ELEM>}\n */\nexport const flatten = arr => fold(arr, /** @type {Array<ELEM>} */ ([]), (acc, val) => acc.concat(val))\n\n/**\n * @template T\n * @param {number} len\n * @param {function(number, Array<T>):T} f\n * @return {Array<T>}\n */\nexport const unfold = (len, f) => {\n const array = new Array(len)\n for (let i = 0; i < len; i++) {\n array[i] = f(i, array)\n }\n return array\n}\n\n/**\n * @template T\n * @template RESULT\n * @param {Array<T>} arr\n * @param {RESULT} seed\n * @param {function(RESULT, T, number):RESULT} folder\n */\nexport const fold = (arr, seed, folder) => arr.reduce(folder, seed)\n\nexport const isArray = Array.isArray\n\n/**\n * @template T\n * @param {Array<T>} arr\n * @return {Array<T>}\n */\nexport const unique = arr => from(set.from(arr))\n\n/**\n * @template T\n * @template M\n * @param {ArrayLike<T>} arr\n * @param {function(T):M} mapper\n * @return {Array<T>}\n */\nexport const uniqueBy = (arr, mapper) => {\n /**\n * @type {Set<M>}\n */\n const happened = set.create()\n /**\n * @type {Array<T>}\n */\n const result = []\n for (let i = 0; i < arr.length; i++) {\n const el = arr[i]\n const mapped = mapper(el)\n if (!happened.has(mapped)) {\n happened.add(mapped)\n result.push(el)\n }\n }\n return result\n}\n","/**\n * Observable class prototype.\n *\n * @module observable\n */\n\nimport * as map from './map.js'\nimport * as set from './set.js'\nimport * as array from './array.js'\n\n/**\n * Handles named events.\n *\n * @template N\n */\nexport class Observable {\n constructor () {\n /**\n * Some desc.\n * @type {Map<N, any>}\n */\n this._observers = map.create()\n }\n\n /**\n * @param {N} name\n * @param {function} f\n */\n on (name, f) {\n map.setIfUndefined(this._observers, name, set.create).add(f)\n }\n\n /**\n * @param {N} name\n * @param {function} f\n */\n once (name, f) {\n /**\n * @param {...any} args\n */\n const _f = (...args) => {\n this.off(name, _f)\n f(...args)\n }\n this.on(name, _f)\n }\n\n /**\n * @param {N} name\n * @param {function} f\n */\n off (name, f) {\n const observers = this._observers.get(name)\n if (observers !== undefined) {\n observers.delete(f)\n if (observers.size === 0) {\n this._observers.delete(name)\n }\n }\n }\n\n /**\n * Emit a named event. All registered event listeners that listen to the\n * specified name will receive the event.\n *\n * @todo This should catch exceptions\n *\n * @param {N} name The event name.\n * @param {Array<any>} args The arguments that are applied to the event listener.\n */\n emit (name, args) {\n // copy all listeners to an array first to make sure that no event is emitted to listeners that are subscribed while the event handler is called.\n return array.from((this._observers.get(name) || map.create()).values()).forEach(f => f(...args))\n }\n\n destroy () {\n this._observers = map.create()\n }\n}\n","// TODO: apparently Yjs is full of anys or something, see if we can fix this\n/* eslint-disable @typescript-eslint/no-unsafe-call */\n/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n/* eslint-disable @typescript-eslint/no-unsafe-assignment */\nimport type {\n BaseUserMeta,\n Json,\n JsonObject,\n LsonObject,\n Room,\n} from \"@liveblocks/client\";\nimport { Observable } from \"lib0/observable\";\nimport type * as Y from \"yjs\";\n\nconst Y_PRESENCE_KEY = \"__yjs\";\n\ntype MetaClientState = {\n clock: number;\n lastUpdated: number;\n};\n\n/**\n * This class will store Yjs awareness in Liveblock's presence under the __yjs key\n * IMPORTANT: The Yjs awareness protocol uses ydoc.clientId to reference users\n * to their respective documents. To avoid mapping Yjs clientIds to liveblock's connectionId,\n * we simply set the clientId of the doc to the connectionId. Then no further mapping is required\n */\nexport class Awareness extends Observable<unknown> {\n private room: Room<JsonObject, LsonObject, BaseUserMeta, Json>;\n public doc: Y.Doc;\n public clientID: number;\n public states: Map<number, unknown> = new Map();\n // Meta is used to keep track and timeout users who disconnect. Liveblocks provides this for us, so we don't need to\n // manage it here. Unfortunately, it's expected to exist by various integrations, so it's an empty map.\n public meta: Map<number, MetaClientState> = new Map();\n // _checkInterval this would hold a timer to remove users, but Liveblock's presence already handles this\n // unfortunately it's typed by various integrations\n public _checkInterval: number = 0;\n\n private othersUnsub: () => void;\n constructor(\n doc: Y.Doc,\n room: Room<JsonObject, LsonObject, BaseUserMeta, Json>\n ) {\n super();\n this.doc = doc;\n this.room = room;\n this.clientID = doc.clientID;\n this.othersUnsub = this.room.events.others.subscribe((event) => {\n // When others are changed, we emit an event that contains arrays added/updated/removed.\n if (event.type === \"leave\") {\n // REMOVED\n this.emit(\"change\", [\n { added: [], updated: [], removed: [event.user.connectionId] },\n \"presence\",\n ]);\n this.emit(\"update\", [\n { added: [], updated: [], removed: [event.user.connectionId] },\n \"presence\",\n ]);\n }\n\n if (event.type === \"enter\") {\n // ADDED\n this.emit(\"change\", [\n { added: [event.user.connectionId], updated: [], removed: [] },\n \"presence\",\n ]);\n this.emit(\"update\", [\n { added: [event.user.connectionId], updated: [], removed: [] },\n \"presence\",\n ]);\n }\n\n if (event.type === \"update\") {\n // UPDATED\n this.emit(\"change\", [\n { added: [], updated: [event.user.connectionId], removed: [] },\n \"presence\",\n ]);\n this.emit(\"update\", [\n { added: [], updated: [event.user.connectionId], removed: [] },\n \"presence\",\n ]);\n }\n });\n }\n\n destroy(): void {\n this.emit(\"destroy\", [this]);\n this.othersUnsub();\n this.setLocalState(null);\n super.destroy();\n }\n\n getLocalState(): JsonObject | null {\n const presence = this.room.getPresence();\n if (\n Object.keys(presence).length === 0 ||\n typeof presence[Y_PRESENCE_KEY] === \"undefined\"\n ) {\n return null;\n }\n return presence[Y_PRESENCE_KEY] as JsonObject | null;\n }\n\n setLocalState(state: Partial<JsonObject> | null): void {\n const presence = this.room.getSelf()?.presence;\n if (state === null) {\n if (presence === undefined) {\n // if presence is already undefined, we don't need to change anything here\n return;\n }\n this.room.updatePresence({ ...presence, [Y_PRESENCE_KEY]: null });\n this.emit(\"update\", [\n { added: [], updated: [], removed: [this.clientID] },\n \"local\",\n ]);\n return;\n }\n // if presence was undefined, it's added, if not, it's updated\n const yPresence = presence?.[Y_PRESENCE_KEY];\n const added = yPresence === undefined ? [this.clientID] : [];\n const updated = yPresence === undefined ? [] : [this.clientID];\n this.room.updatePresence({\n [Y_PRESENCE_KEY]: {\n ...((yPresence as JsonObject) || {}),\n ...(state || {}),\n },\n });\n this.emit(\"update\", [{ added, updated, removed: [] }, \"local\"]);\n }\n\n setLocalStateField(field: string, value: JsonObject | null): void {\n const presence = this.room.getSelf()?.presence[Y_PRESENCE_KEY];\n const update = { [field]: value } as Partial<JsonObject>;\n this.room.updatePresence({\n [Y_PRESENCE_KEY]: { ...((presence as JsonObject) || {}), ...update },\n });\n }\n\n // Translate liveblocks presence to yjs awareness\n getStates(): Map<number, unknown> {\n const others = this.room.getOthers();\n const presence = this.room.getSelf()?.presence[Y_PRESENCE_KEY];\n const states = others.reduce((acc: Map<number, unknown>, currentValue) => {\n if (\n currentValue.connectionId &&\n currentValue.presence[Y_PRESENCE_KEY] !== undefined\n ) {\n // connectionId == actorId == yjs.clientId\n acc.set(\n currentValue.connectionId,\n currentValue.presence[Y_PRESENCE_KEY] || {}\n );\n }\n return acc;\n }, new Map());\n if (presence !== undefined) {\n states.set(this.clientID, presence);\n }\n return states;\n }\n}\n","import { Base64 } from \"js-base64\";\nimport { Observable } from \"lib0/observable\";\nimport * as Y from \"yjs\";\n\nexport default class yDocHandler extends Observable<unknown> {\n private unsubscribers: Array<() => void> = [];\n\n private _synced = false;\n private doc: Y.Doc;\n private updateRoomDoc: (update: string) => void;\n private fetchRoomDoc: (vector: string) => void;\n\n constructor({\n doc,\n isRoot,\n updateDoc,\n fetchDoc,\n }: {\n doc: Y.Doc;\n isRoot: boolean;\n updateDoc: (update: string, guid?: string) => void;\n fetchDoc: (vector: string, guid?: string) => void;\n }) {\n super();\n this.doc = doc;\n // this.doc.load(); // this just emits a load event, it doesn't actually load anything\n this.doc.on(\"update\", this.updateHandler);\n this.updateRoomDoc = (update: string) => {\n updateDoc(update, isRoot ? undefined : this.doc.guid);\n };\n this.fetchRoomDoc = (vector: string) => {\n fetchDoc(vector, isRoot ? undefined : this.doc.guid);\n };\n\n this.syncDoc();\n }\n\n public handleServerUpdate = ({\n update,\n stateVector,\n }: {\n update: string;\n stateVector: string | null;\n }): void => {\n // apply update from the server\n Y.applyUpdate(this.doc, Base64.toUint8Array(update), \"backend\");\n // if this update is the result of a fetch, the state vector is included\n if (stateVector) {\n // Use server state to calculate a diff and send it\n try {\n const localUpdate = Y.encodeStateAsUpdate(\n this.doc,\n Base64.toUint8Array(stateVector)\n );\n this.updateRoomDoc(Base64.fromUint8Array(localUpdate));\n } catch (e) {\n // something went wrong encoding local state to send to the server\n console.warn(e);\n }\n // now that we've sent our local and received from server, we're in sync\n // calling `syncDoc` again will sync up the documents\n this.synced = true;\n }\n };\n\n public syncDoc = (): void => {\n this.synced = false;\n\n // The state vector is sent to the server so it knows what to send back\n // if you don't send it, it returns everything\n const encodedVector = Base64.fromUint8Array(Y.encodeStateVector(this.doc));\n this.fetchRoomDoc(encodedVector);\n };\n\n // The sync'd property is required by some provider implementations\n get synced(): boolean {\n return this._synced;\n }\n\n set synced(state: boolean) {\n if (this._synced !== state) {\n this._synced = state;\n this.emit(\"synced\", [state]);\n this.emit(\"sync\", [state]);\n }\n }\n\n private updateHandler = (update: Uint8Array, origin: string) => {\n if (origin !== \"backend\") {\n const encodedUpdate = Base64.fromUint8Array(update);\n this.updateRoomDoc(encodedUpdate);\n }\n };\n\n destroy(): void {\n this.doc.off(\"update\", this.updateHandler);\n this.unsubscribers.forEach((unsub) => unsub());\n this._observers = new Map();\n this.doc.destroy();\n }\n}\n","declare const __VERSION__: string;\ndeclare const TSUP_FORMAT: string;\n\nexport const PKG_NAME = \"@liveblocks/yjs\";\nexport const PKG_VERSION = typeof __VERSION__ === \"string\" && __VERSION__;\nexport const PKG_FORMAT = typeof TSUP_FORMAT === \"string\" && TSUP_FORMAT;\n"],"mappings":"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","names":["create","create"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liveblocks/yjs",
3
- "version": "1.9.6",
3
+ "version": "1.9.7-awareness",
4
4
  "description": "An integration with . Liveblocks is the all-in-one toolkit to build collaborative products like Figma, Notion, and more.",
5
5
  "license": "Apache-2.0",
6
6
  "main": "./dist/index.js",
@@ -24,7 +24,7 @@
24
24
  ],
25
25
  "scripts": {
26
26
  "dev": "tsup --watch",
27
- "build": "tsup && cp dist/index.d.ts dist/index.d.mts",
27
+ "build": "tsup",
28
28
  "format": "eslint --fix src/; prettier --write src/",
29
29
  "lint": "eslint src/",
30
30
  "lint:package": "publint --strict && attw --pack --ignore-rules cjs-only-exports-default",
@@ -32,8 +32,8 @@
32
32
  "test:watch": "jest --silent --verbose --color=always --watch"
33
33
  },
34
34
  "dependencies": {
35
- "@liveblocks/client": "1.9.6",
36
- "@liveblocks/core": "1.9.6",
35
+ "@liveblocks/client": "1.9.7-awareness",
36
+ "@liveblocks/core": "1.9.7-awareness",
37
37
  "js-base64": "^3.7.5"
38
38
  },
39
39
  "peerDependencies": {
@@ -42,7 +42,8 @@
42
42
  "devDependencies": {
43
43
  "@liveblocks/eslint-config": "*",
44
44
  "@liveblocks/jest-config": "*",
45
- "@testing-library/jest-dom": "^5.16.5"
45
+ "@testing-library/jest-dom": "^5.16.5",
46
+ "msw": "^0.36.8"
46
47
  },
47
48
  "sideEffects": false,
48
49
  "bugs": {