@liveblocks/yjs 1.2.0-internal3 → 1.2.0-internal5
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 +8 -28
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +7 -27
- package/dist/index.mjs.map +1 -0
- package/package.json +16 -16
package/dist/index.js
CHANGED
|
@@ -1,21 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } }
|
|
2
|
-
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
3
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
4
|
-
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
5
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
6
|
-
var __spreadValues = (a, b) => {
|
|
7
|
-
for (var prop in b || (b = {}))
|
|
8
|
-
if (__hasOwnProp.call(b, prop))
|
|
9
|
-
__defNormalProp(a, prop, b[prop]);
|
|
10
|
-
if (__getOwnPropSymbols)
|
|
11
|
-
for (var prop of __getOwnPropSymbols(b)) {
|
|
12
|
-
if (__propIsEnum.call(b, prop))
|
|
13
|
-
__defNormalProp(a, prop, b[prop]);
|
|
14
|
-
}
|
|
15
|
-
return a;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
// src/index.ts
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/index.ts
|
|
19
2
|
var _jsbase64 = require('js-base64');
|
|
20
3
|
|
|
21
4
|
// ../../node_modules/lib0/map.js
|
|
@@ -139,18 +122,16 @@ var Awareness = class extends Observable {
|
|
|
139
122
|
return presence[Y_PRESENCE_KEY];
|
|
140
123
|
}
|
|
141
124
|
setLocalState(state) {
|
|
142
|
-
|
|
143
|
-
const presence = (_a = this.room.getSelf()) == null ? void 0 : _a.presence[Y_PRESENCE_KEY];
|
|
125
|
+
const presence = _optionalChain([this, 'access', _ => _.room, 'access', _2 => _2.getSelf, 'call', _3 => _3(), 'optionalAccess', _4 => _4.presence, 'access', _5 => _5[Y_PRESENCE_KEY]]);
|
|
144
126
|
this.room.updatePresence({
|
|
145
|
-
__yjs:
|
|
127
|
+
__yjs: { ...presence || {}, ...state || {} }
|
|
146
128
|
});
|
|
147
129
|
}
|
|
148
130
|
setLocalStateField(field, value) {
|
|
149
|
-
|
|
150
|
-
const presence = (_a = this.room.getSelf()) == null ? void 0 : _a.presence[Y_PRESENCE_KEY];
|
|
131
|
+
const presence = _optionalChain([this, 'access', _6 => _6.room, 'access', _7 => _7.getSelf, 'call', _8 => _8(), 'optionalAccess', _9 => _9.presence, 'access', _10 => _10[Y_PRESENCE_KEY]]);
|
|
151
132
|
const update = { [field]: value };
|
|
152
133
|
this.room.updatePresence({
|
|
153
|
-
__yjs:
|
|
134
|
+
__yjs: { ...presence || {}, ...update }
|
|
154
135
|
});
|
|
155
136
|
}
|
|
156
137
|
// Translate liveblocks presence to yjs awareness
|
|
@@ -170,14 +151,12 @@ var Awareness = class extends Observable {
|
|
|
170
151
|
};
|
|
171
152
|
var LiveblocksProvider = class extends Observable {
|
|
172
153
|
constructor(room, doc) {
|
|
173
|
-
var _a;
|
|
174
154
|
super();
|
|
175
155
|
this.unsubscribers = [];
|
|
176
156
|
this._synced = false;
|
|
177
157
|
this.syncDoc = () => {
|
|
178
|
-
var _a;
|
|
179
158
|
this.synced = false;
|
|
180
|
-
this.doc.clientID = (
|
|
159
|
+
this.doc.clientID = _optionalChain([this, 'access', _11 => _11.room, 'access', _12 => _12.getSelf, 'call', _13 => _13(), 'optionalAccess', _14 => _14.connectionId]) || this.doc.clientID;
|
|
181
160
|
this.awareness.clientID = this.doc.clientID;
|
|
182
161
|
const encodedVector = _jsbase64.Base64.fromUint8Array(Y.encodeStateVector(this.doc));
|
|
183
162
|
this.room.fetchYDoc(encodedVector);
|
|
@@ -190,7 +169,7 @@ var LiveblocksProvider = class extends Observable {
|
|
|
190
169
|
};
|
|
191
170
|
this.doc = doc;
|
|
192
171
|
this.room = room;
|
|
193
|
-
const connectionId = (
|
|
172
|
+
const connectionId = _optionalChain([this, 'access', _15 => _15.room, 'access', _16 => _16.getSelf, 'call', _17 => _17(), 'optionalAccess', _18 => _18.connectionId]);
|
|
194
173
|
if (connectionId) {
|
|
195
174
|
this.doc.clientID = connectionId;
|
|
196
175
|
}
|
|
@@ -237,3 +216,4 @@ var LiveblocksProvider = class extends Observable {
|
|
|
237
216
|
|
|
238
217
|
|
|
239
218
|
exports.Awareness = Awareness; exports.default = LiveblocksProvider;
|
|
219
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +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"],"names":["create"],"mappings":"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","sourcesContent":["// 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 { Base64 } from \"js-base64\";\nimport { Observable } from \"lib0/observable\";\nimport * 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\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 doc: Y.Doc;\n\n private unsubscribers: Array<() => void> = [];\n\n public awareness: Awareness;\n\n private _synced = false;\n\n constructor(room: Room<P, S, U, E>, doc: Y.Doc) {\n super();\n this.doc = doc;\n this.room = room;\n\n // if we have a connectionId already during construction, use that\n const connectionId = this.room.getSelf()?.connectionId;\n if (connectionId) {\n this.doc.clientID = connectionId;\n }\n this.awareness = new Awareness(this.doc, this.room);\n this.doc.on(\"update\", this.updateHandler);\n\n this.unsubscribers.push(\n this.room.events.status.subscribe((status) => {\n if (status === \"connected\") {\n this.syncDoc();\n }\n })\n );\n\n this.unsubscribers.push(\n this.room.events.ydoc.subscribe((update: string) => {\n Y.applyUpdate(this.doc, Base64.toUint8Array(update), \"backend\");\n this.synced = true;\n })\n );\n this.syncDoc();\n }\n\n private syncDoc = () => {\n this.synced = false;\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.doc.clientID = this.room.getSelf()?.connectionId || this.doc.clientID;\n this.awareness.clientID = this.doc.clientID; // tell our awareness provider the new ID\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.room.fetchYDoc(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.room.updateYDoc(encodedUpdate);\n }\n };\n\n destroy(): void {\n this.doc.off(\"update\", this.updateHandler);\n this.unsubscribers.forEach((unsub) => unsub());\n this.awareness.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"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,20 +1,3 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
3
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
4
|
-
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
5
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
6
|
-
var __spreadValues = (a, b) => {
|
|
7
|
-
for (var prop in b || (b = {}))
|
|
8
|
-
if (__hasOwnProp.call(b, prop))
|
|
9
|
-
__defNormalProp(a, prop, b[prop]);
|
|
10
|
-
if (__getOwnPropSymbols)
|
|
11
|
-
for (var prop of __getOwnPropSymbols(b)) {
|
|
12
|
-
if (__propIsEnum.call(b, prop))
|
|
13
|
-
__defNormalProp(a, prop, b[prop]);
|
|
14
|
-
}
|
|
15
|
-
return a;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
1
|
// src/index.ts
|
|
19
2
|
import { Base64 } from "js-base64";
|
|
20
3
|
|
|
@@ -139,18 +122,16 @@ var Awareness = class extends Observable {
|
|
|
139
122
|
return presence[Y_PRESENCE_KEY];
|
|
140
123
|
}
|
|
141
124
|
setLocalState(state) {
|
|
142
|
-
|
|
143
|
-
const presence = (_a = this.room.getSelf()) == null ? void 0 : _a.presence[Y_PRESENCE_KEY];
|
|
125
|
+
const presence = this.room.getSelf()?.presence[Y_PRESENCE_KEY];
|
|
144
126
|
this.room.updatePresence({
|
|
145
|
-
__yjs:
|
|
127
|
+
__yjs: { ...presence || {}, ...state || {} }
|
|
146
128
|
});
|
|
147
129
|
}
|
|
148
130
|
setLocalStateField(field, value) {
|
|
149
|
-
|
|
150
|
-
const presence = (_a = this.room.getSelf()) == null ? void 0 : _a.presence[Y_PRESENCE_KEY];
|
|
131
|
+
const presence = this.room.getSelf()?.presence[Y_PRESENCE_KEY];
|
|
151
132
|
const update = { [field]: value };
|
|
152
133
|
this.room.updatePresence({
|
|
153
|
-
__yjs:
|
|
134
|
+
__yjs: { ...presence || {}, ...update }
|
|
154
135
|
});
|
|
155
136
|
}
|
|
156
137
|
// Translate liveblocks presence to yjs awareness
|
|
@@ -170,14 +151,12 @@ var Awareness = class extends Observable {
|
|
|
170
151
|
};
|
|
171
152
|
var LiveblocksProvider = class extends Observable {
|
|
172
153
|
constructor(room, doc) {
|
|
173
|
-
var _a;
|
|
174
154
|
super();
|
|
175
155
|
this.unsubscribers = [];
|
|
176
156
|
this._synced = false;
|
|
177
157
|
this.syncDoc = () => {
|
|
178
|
-
var _a;
|
|
179
158
|
this.synced = false;
|
|
180
|
-
this.doc.clientID =
|
|
159
|
+
this.doc.clientID = this.room.getSelf()?.connectionId || this.doc.clientID;
|
|
181
160
|
this.awareness.clientID = this.doc.clientID;
|
|
182
161
|
const encodedVector = Base64.fromUint8Array(Y.encodeStateVector(this.doc));
|
|
183
162
|
this.room.fetchYDoc(encodedVector);
|
|
@@ -190,7 +169,7 @@ var LiveblocksProvider = class extends Observable {
|
|
|
190
169
|
};
|
|
191
170
|
this.doc = doc;
|
|
192
171
|
this.room = room;
|
|
193
|
-
const connectionId =
|
|
172
|
+
const connectionId = this.room.getSelf()?.connectionId;
|
|
194
173
|
if (connectionId) {
|
|
195
174
|
this.doc.clientID = connectionId;
|
|
196
175
|
}
|
|
@@ -237,3 +216,4 @@ export {
|
|
|
237
216
|
Awareness,
|
|
238
217
|
LiveblocksProvider as default
|
|
239
218
|
};
|
|
219
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +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"],"sourcesContent":["// 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 { Base64 } from \"js-base64\";\nimport { Observable } from \"lib0/observable\";\nimport * 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\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 doc: Y.Doc;\n\n private unsubscribers: Array<() => void> = [];\n\n public awareness: Awareness;\n\n private _synced = false;\n\n constructor(room: Room<P, S, U, E>, doc: Y.Doc) {\n super();\n this.doc = doc;\n this.room = room;\n\n // if we have a connectionId already during construction, use that\n const connectionId = this.room.getSelf()?.connectionId;\n if (connectionId) {\n this.doc.clientID = connectionId;\n }\n this.awareness = new Awareness(this.doc, this.room);\n this.doc.on(\"update\", this.updateHandler);\n\n this.unsubscribers.push(\n this.room.events.status.subscribe((status) => {\n if (status === \"connected\") {\n this.syncDoc();\n }\n })\n );\n\n this.unsubscribers.push(\n this.room.events.ydoc.subscribe((update: string) => {\n Y.applyUpdate(this.doc, Base64.toUint8Array(update), \"backend\");\n this.synced = true;\n })\n );\n this.syncDoc();\n }\n\n private syncDoc = () => {\n this.synced = false;\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.doc.clientID = this.room.getSelf()?.connectionId || this.doc.clientID;\n this.awareness.clientID = this.doc.clientID; // tell our awareness provider the new ID\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.room.fetchYDoc(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.room.updateYDoc(encodedUpdate);\n }\n };\n\n destroy(): void {\n this.doc.off(\"update\", this.updateHandler);\n this.unsubscribers.forEach((unsub) => unsub());\n this.awareness.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"],"mappings":";AAWA,SAAS,cAAc;;;ACGhB,IAAM,SAAS,MAAM,oBAAI,IAAI;AAgC7B,IAAM,iBAAiB,CAAC,KAAK,KAAK,YAAY;AACnD,MAAI,MAAM,IAAI,IAAI,GAAG;AACrB,MAAI,QAAQ,QAAW;AACrB,QAAI,IAAI,KAAK,MAAM,QAAQ,CAAC;AAAA,EAC9B;AACA,SAAO;AACT;;;AC9CO,IAAMA,UAAS,MAAM,oBAAI,IAAI;;;AC6C7B,IAAM,OAAO,MAAM;AAgFnB,IAAM,UAAU,MAAM;;;ACpHtB,IAAM,aAAN,MAAiB;AAAA,EACtB,cAAe;AAKb,SAAK,aAAiB,OAAO;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,GAAI,MAAM,GAAG;AACX,IAAI,eAAe,KAAK,YAAY,MAAUC,OAAM,EAAE,IAAI,CAAC;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,KAAM,MAAM,GAAG;AAIb,UAAM,KAAK,IAAI,SAAS;AACtB,WAAK,IAAI,MAAM,EAAE;AACjB,QAAE,GAAG,IAAI;AAAA,IACX;AACA,SAAK,GAAG,MAAM,EAAE;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAK,MAAM,GAAG;AACZ,UAAM,YAAY,KAAK,WAAW,IAAI,IAAI;AAC1C,QAAI,cAAc,QAAW;AAC3B,gBAAU,OAAO,CAAC;AAClB,UAAI,UAAU,SAAS,GAAG;AACxB,aAAK,WAAW,OAAO,IAAI;AAAA,MAC7B;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,KAAM,MAAM,MAAM;AAEhB,WAAa,MAAM,KAAK,WAAW,IAAI,IAAI,KAAS,OAAO,GAAG,OAAO,CAAC,EAAE,QAAQ,OAAK,EAAE,GAAG,IAAI,CAAC;AAAA,EACjG;AAAA,EAEA,UAAW;AACT,SAAK,aAAiB,OAAO;AAAA,EAC/B;AACF;;;AJjEA,YAAY,OAAO;AAEnB,IAAM,iBAAiB;AAahB,IAAM,YAAN,cAAwB,WAAoB;AAAA,EAajD,YACE,KACA,MACA;AACA,UAAM;AAbR,SAAO,SAA+B,oBAAI,IAAI;AAG9C;AAAA;AAAA,SAAO,OAAqC,oBAAI,IAAI;AAGpD;AAAA;AAAA,SAAO,iBAAyB;AAQ9B,SAAK,MAAM;AACX,SAAK,OAAO;AACZ,SAAK,WAAW,IAAI;AACpB,SAAK,cAAc,KAAK,KAAK,OAAO,OAAO,UAAU,CAAC,EAAE,MAAM,MAAM;AAElE,UAAI,MAAM,SAAS,SAAS;AAE1B,aAAK,KAAK,UAAU;AAAA,UAClB,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC,MAAM,KAAK,YAAY,EAAE;AAAA,UAC7D;AAAA,QACF,CAAC;AAAA,MACH;AAEA,UAAI,MAAM,SAAS,SAAS;AAE1B,aAAK,KAAK,UAAU;AAAA,UAClB,EAAE,OAAO,CAAC,MAAM,KAAK,YAAY,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC,EAAE;AAAA,UAC7D;AAAA,QACF,CAAC;AAAA,MACH;AAEA,UAAI,MAAM,SAAS,UAAU;AAE3B,aAAK,KAAK,UAAU;AAAA,UAClB,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,MAAM,KAAK,YAAY,GAAG,SAAS,CAAC,EAAE;AAAA,UAC7D;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,UAAgB;AACd,SAAK,KAAK,WAAW,CAAC,IAAI,CAAC;AAC3B,SAAK,YAAY;AACjB,SAAK,cAAc,IAAI;AACvB,UAAM,QAAQ;AAAA,EAChB;AAAA,EAEA,gBAAmC;AACjC,UAAM,WAAW,KAAK,KAAK,YAAY;AACvC,QACE,OAAO,KAAK,QAAQ,EAAE,WAAW,KACjC,OAAO,SAAS,cAAc,MAAM,aACpC;AACA,aAAO;AAAA,IACT;AACA,WAAO,SAAS,cAAc;AAAA,EAChC;AAAA,EAEA,cAAc,OAAyC;AACrD,UAAM,WAAW,KAAK,KAAK,QAAQ,GAAG,SAAS,cAAc;AAC7D,SAAK,KAAK,eAAe;AAAA,MACvB,OAAO,EAAE,GAAK,YAA2B,CAAC,GAAI,GAAI,SAAS,CAAC,EAAG;AAAA,IACjE,CAAC;AAAA,EACH;AAAA,EAEA,mBAAmB,OAAe,OAAgC;AAChE,UAAM,WAAW,KAAK,KAAK,QAAQ,GAAG,SAAS,cAAc;AAC7D,UAAM,SAAS,EAAE,CAAC,KAAK,GAAG,MAAM;AAChC,SAAK,KAAK,eAAe;AAAA,MACvB,OAAO,EAAE,GAAK,YAA2B,CAAC,GAAI,GAAG,OAAO;AAAA,IAC1D,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,YAAkC;AAChC,UAAM,SAAS,KAAK,KAAK,UAAU;AACnC,UAAM,SAAS,OAAO,OAAO,CAAC,KAA2B,iBAAiB;AACxE,UAAI,aAAa,cAAc;AAE7B,YAAI;AAAA,UACF,aAAa;AAAA,UACb,aAAa,SAAS,cAAc,KAAK,CAAC;AAAA,QAC5C;AAAA,MACF;AACA,aAAO;AAAA,IACT,GAAG,oBAAI,IAAI,CAAC;AACZ,WAAO;AAAA,EACT;AACF;AAEA,IAAqB,qBAArB,cAKU,WAAoB;AAAA,EAU5B,YAAY,MAAwB,KAAY;AAC9C,UAAM;AAPR,SAAQ,gBAAmC,CAAC;AAI5C,SAAQ,UAAU;AAgClB,SAAQ,UAAU,MAAM;AACtB,WAAK,SAAS;AAMd,WAAK,IAAI,WAAW,KAAK,KAAK,QAAQ,GAAG,gBAAgB,KAAK,IAAI;AAClE,WAAK,UAAU,WAAW,KAAK,IAAI;AAInC,YAAM,gBAAgB,OAAO,eAAiB,oBAAkB,KAAK,GAAG,CAAC;AACzE,WAAK,KAAK,UAAU,aAAa;AAAA,IACnC;AAeA,SAAQ,gBAAgB,CAAC,QAAoB,WAAmB;AAC9D,UAAI,WAAW,WAAW;AACxB,cAAM,gBAAgB,OAAO,eAAe,MAAM;AAClD,aAAK,KAAK,WAAW,aAAa;AAAA,MACpC;AAAA,IACF;AA9DE,SAAK,MAAM;AACX,SAAK,OAAO;AAGZ,UAAM,eAAe,KAAK,KAAK,QAAQ,GAAG;AAC1C,QAAI,cAAc;AAChB,WAAK,IAAI,WAAW;AAAA,IACtB;AACA,SAAK,YAAY,IAAI,UAAU,KAAK,KAAK,KAAK,IAAI;AAClD,SAAK,IAAI,GAAG,UAAU,KAAK,aAAa;AAExC,SAAK,cAAc;AAAA,MACjB,KAAK,KAAK,OAAO,OAAO,UAAU,CAAC,WAAW;AAC5C,YAAI,WAAW,aAAa;AAC1B,eAAK,QAAQ;AAAA,QACf;AAAA,MACF,CAAC;AAAA,IACH;AAEA,SAAK,cAAc;AAAA,MACjB,KAAK,KAAK,OAAO,KAAK,UAAU,CAAC,WAAmB;AAClD,QAAE,cAAY,KAAK,KAAK,OAAO,aAAa,MAAM,GAAG,SAAS;AAC9D,aAAK,SAAS;AAAA,MAChB,CAAC;AAAA,IACH;AACA,SAAK,QAAQ;AAAA,EACf;AAAA;AAAA,EAmBA,IAAI,SAAkB;AACpB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,OAAO,OAAgB;AACzB,QAAI,KAAK,YAAY,OAAO;AAC1B,WAAK,UAAU;AACf,WAAK,KAAK,UAAU,CAAC,KAAK,CAAC;AAC3B,WAAK,KAAK,QAAQ,CAAC,KAAK,CAAC;AAAA,IAC3B;AAAA,EACF;AAAA,EASA,UAAgB;AACd,SAAK,IAAI,IAAI,UAAU,KAAK,aAAa;AACzC,SAAK,cAAc,QAAQ,CAAC,UAAU,MAAM,CAAC;AAC7C,SAAK,UAAU,QAAQ;AAAA,EACzB;AAAA;AAAA,EAGA,aAAmB;AAAA,EAEnB;AAAA,EAEA,UAAgB;AAAA,EAEhB;AACF;","names":["create","create"]}
|
package/package.json
CHANGED
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@liveblocks/yjs",
|
|
3
|
-
"version": "1.2.0-
|
|
3
|
+
"version": "1.2.0-internal5",
|
|
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",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": {
|
|
11
|
+
"types": "./dist/index.d.mts",
|
|
12
|
+
"default": "./dist/index.mjs"
|
|
13
|
+
},
|
|
14
|
+
"require": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"module": "./dist/index.mjs",
|
|
17
|
+
"default": "./dist/index.js"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
},
|
|
8
21
|
"files": [
|
|
9
22
|
"dist/**",
|
|
10
23
|
"README.md"
|
|
@@ -16,24 +29,11 @@
|
|
|
16
29
|
"lint": "eslint src/",
|
|
17
30
|
"lint:package": "publint --strict && attw --pack",
|
|
18
31
|
"test": "jest --silent --verbose --color=always",
|
|
19
|
-
"test:types": "tsd",
|
|
20
32
|
"test:watch": "jest --silent --verbose --color=always --watch"
|
|
21
33
|
},
|
|
22
|
-
"exports": {
|
|
23
|
-
".": {
|
|
24
|
-
"import": {
|
|
25
|
-
"types": "./dist/index.d.mts",
|
|
26
|
-
"default": "./dist/index.mjs"
|
|
27
|
-
},
|
|
28
|
-
"require": {
|
|
29
|
-
"types": "./dist/index.d.ts",
|
|
30
|
-
"default": "./dist/index.js"
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@liveblocks/client": "1.2.0-
|
|
36
|
-
"@liveblocks/core": "1.2.0-
|
|
35
|
+
"@liveblocks/client": "1.2.0-internal5",
|
|
36
|
+
"@liveblocks/core": "1.2.0-internal5",
|
|
37
37
|
"js-base64": "^3.7.5"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|