@liveblocks/yjs 1.1.0-yjs5 → 1.1.1-dual1

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/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
 
10
10
  # `@liveblocks/yjs`
11
11
 
12
- Provides YJS integration to effortlessly back your YJS apps with Liveblocks
12
+ Provides Yjs integration to effortlessly back your Yjs apps with Liveblocks
13
13
 
14
14
  ## Installation
15
15
 
@@ -0,0 +1,46 @@
1
+ import { Room, JsonObject, LsonObject, BaseUserMeta, Json } from '@liveblocks/client';
2
+ import { Observable } from 'lib0/observable';
3
+ import * as Y from 'yjs';
4
+
5
+ declare type MetaClientState = {
6
+ clock: number;
7
+ lastUpdated: number;
8
+ };
9
+ /**
10
+ * This class will store Yjs awareness in Liveblock's presence under the __yjs key
11
+ * IMPORTANT: The Yjs awareness protocol uses ydoc.clientId to reference users
12
+ * to their respective documents. To avoid mapping Yjs clientIds to liveblock's connectionId,
13
+ * we simply set the clientId of the doc to the connectionId. Then no further mapping is required
14
+ */
15
+ declare class Awareness extends Observable<unknown> {
16
+ private room;
17
+ doc: Y.Doc;
18
+ clientID: number;
19
+ states: Map<number, unknown>;
20
+ meta: Map<number, MetaClientState>;
21
+ _checkInterval: number;
22
+ private othersUnsub;
23
+ constructor(doc: Y.Doc, room: Room<JsonObject, LsonObject, BaseUserMeta, Json>);
24
+ destroy(): void;
25
+ getLocalState(): JsonObject | null;
26
+ setLocalState(state: Partial<JsonObject> | null): void;
27
+ setLocalStateField(field: string, value: JsonObject | null): void;
28
+ getStates(): Map<number, unknown>;
29
+ }
30
+ declare class LiveblocksProvider<P extends JsonObject, S extends LsonObject, U extends BaseUserMeta, E extends Json> extends Observable<unknown> {
31
+ private room;
32
+ private doc;
33
+ private unsubscribers;
34
+ awareness: Awareness;
35
+ private _synced;
36
+ constructor(room: Room<P, S, U, E>, doc: Y.Doc);
37
+ private syncDoc;
38
+ get synced(): boolean;
39
+ set synced(state: boolean);
40
+ private updateHandler;
41
+ destroy(): void;
42
+ disconnect(): void;
43
+ connect(): void;
44
+ }
45
+
46
+ export { Awareness, LiveblocksProvider as default };
package/dist/index.d.ts CHANGED
@@ -2,18 +2,21 @@ import { Room, JsonObject, LsonObject, BaseUserMeta, Json } from '@liveblocks/cl
2
2
  import { Observable } from 'lib0/observable';
3
3
  import * as Y from 'yjs';
4
4
 
5
- declare type LiveblocksYjsOptions = {
6
- httpEndpoint?: string;
7
- };
8
5
  declare type MetaClientState = {
9
6
  clock: number;
10
7
  lastUpdated: number;
11
8
  };
12
- declare class Awareness extends Observable<any> {
9
+ /**
10
+ * This class will store Yjs awareness in Liveblock's presence under the __yjs key
11
+ * IMPORTANT: The Yjs awareness protocol uses ydoc.clientId to reference users
12
+ * to their respective documents. To avoid mapping Yjs clientIds to liveblock's connectionId,
13
+ * we simply set the clientId of the doc to the connectionId. Then no further mapping is required
14
+ */
15
+ declare class Awareness extends Observable<unknown> {
13
16
  private room;
14
17
  doc: Y.Doc;
15
18
  clientID: number;
16
- states: Map<number, any>;
19
+ states: Map<number, unknown>;
17
20
  meta: Map<number, MetaClientState>;
18
21
  _checkInterval: number;
19
22
  private othersUnsub;
@@ -22,20 +25,22 @@ declare class Awareness extends Observable<any> {
22
25
  getLocalState(): JsonObject | null;
23
26
  setLocalState(state: Partial<JsonObject> | null): void;
24
27
  setLocalStateField(field: string, value: JsonObject | null): void;
25
- getStates(): Map<number, any>;
28
+ getStates(): Map<number, unknown>;
26
29
  }
27
- declare class LiveblocksProvider<P extends JsonObject, S extends LsonObject, U extends BaseUserMeta, E extends Json> {
30
+ declare class LiveblocksProvider<P extends JsonObject, S extends LsonObject, U extends BaseUserMeta, E extends Json> extends Observable<unknown> {
28
31
  private room;
29
- private httpEndpoint?;
30
- private lastUpdateDate;
31
32
  private doc;
32
33
  private unsubscribers;
33
34
  awareness: Awareness;
34
- constructor(room: Room<P, S, U, E>, doc: Y.Doc, config?: LiveblocksYjsOptions);
35
+ private _synced;
36
+ constructor(room: Room<P, S, U, E>, doc: Y.Doc);
35
37
  private syncDoc;
38
+ get synced(): boolean;
39
+ set synced(state: boolean);
36
40
  private updateHandler;
37
- private resyncHttp;
38
41
  destroy(): void;
42
+ disconnect(): void;
43
+ connect(): void;
39
44
  }
40
45
 
41
46
  export { Awareness, LiveblocksProvider as default };
package/dist/index.js CHANGED
@@ -1,273 +1,2 @@
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; } }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
- var __async = (__this, __arguments, generator) => {
18
- return new Promise((resolve, reject) => {
19
- var fulfilled = (value) => {
20
- try {
21
- step(generator.next(value));
22
- } catch (e) {
23
- reject(e);
24
- }
25
- };
26
- var rejected = (value) => {
27
- try {
28
- step(generator.throw(value));
29
- } catch (e) {
30
- reject(e);
31
- }
32
- };
33
- var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
34
- step((generator = generator.apply(__this, __arguments)).next());
35
- });
36
- };
37
-
38
- // src/index.ts
39
- var _jsbase64 = require('js-base64');
40
-
41
- // ../../node_modules/lib0/map.js
42
- var create = () => /* @__PURE__ */ new Map();
43
- var setIfUndefined = (map, key, createT) => {
44
- let set = map.get(key);
45
- if (set === void 0) {
46
- map.set(key, set = createT());
47
- }
48
- return set;
49
- };
50
-
51
- // ../../node_modules/lib0/set.js
52
- var create2 = () => /* @__PURE__ */ new Set();
53
-
54
- // ../../node_modules/lib0/array.js
55
- var from = Array.from;
56
- var isArray = Array.isArray;
57
-
58
- // ../../node_modules/lib0/observable.js
59
- var Observable = class {
60
- constructor() {
61
- this._observers = create();
62
- }
63
- /**
64
- * @param {N} name
65
- * @param {function} f
66
- */
67
- on(name, f) {
68
- setIfUndefined(this._observers, name, create2).add(f);
69
- }
70
- /**
71
- * @param {N} name
72
- * @param {function} f
73
- */
74
- once(name, f) {
75
- const _f = (...args) => {
76
- this.off(name, _f);
77
- f(...args);
78
- };
79
- this.on(name, _f);
80
- }
81
- /**
82
- * @param {N} name
83
- * @param {function} f
84
- */
85
- off(name, f) {
86
- const observers = this._observers.get(name);
87
- if (observers !== void 0) {
88
- observers.delete(f);
89
- if (observers.size === 0) {
90
- this._observers.delete(name);
91
- }
92
- }
93
- }
94
- /**
95
- * Emit a named event. All registered event listeners that listen to the
96
- * specified name will receive the event.
97
- *
98
- * @todo This should catch exceptions
99
- *
100
- * @param {N} name The event name.
101
- * @param {Array<any>} args The arguments that are applied to the event listener.
102
- */
103
- emit(name, args) {
104
- return from((this._observers.get(name) || create()).values()).forEach((f) => f(...args));
105
- }
106
- destroy() {
107
- this._observers = create();
108
- }
109
- };
110
-
111
- // src/index.ts
112
- var _yjs = require('yjs'); var Y = _interopRequireWildcard(_yjs);
113
- var Awareness = class extends Observable {
114
- constructor(doc, room) {
115
- super();
116
- this.states = /* @__PURE__ */ new Map();
117
- // Meta is used to keep track and timeout users who disconnect. Liveblocks provides this for us, so we don't need to
118
- // manage it here. Unfortunately, it's expected to exist by various integrations, so it's an empty map.
119
- this.meta = /* @__PURE__ */ new Map();
120
- // _checkInterval this would hold a timer to remove users, but Liveblock's presence already handles this
121
- // unfortunately it's expected to exist by various integrations.
122
- this._checkInterval = 0;
123
- this.doc = doc;
124
- this.room = room;
125
- this.clientID = doc.clientID;
126
- this.othersUnsub = this.room.events.others.subscribe(({ event }) => {
127
- if (event.type === "leave") {
128
- this.emit("change", [
129
- { added: [], updated: [], removed: [event.user.connectionId] },
130
- "local"
131
- ]);
132
- }
133
- if (event.type === "enter") {
134
- this.emit("change", [
135
- { added: [event.user.connectionId], updated: [], removed: [] },
136
- "local"
137
- ]);
138
- }
139
- if (event.type === "update") {
140
- this.emit("change", [
141
- { added: [], updated: [event.user.connectionId], removed: [] },
142
- "local"
143
- ]);
144
- }
145
- });
146
- }
147
- destroy() {
148
- this.emit("destroy", [this]);
149
- this.othersUnsub();
150
- this.setLocalState(null);
151
- super.destroy();
152
- }
153
- getLocalState() {
154
- const presence = this.room.getPresence();
155
- if (Object.keys(this.room.getPresence()).length === 0) {
156
- return null;
157
- }
158
- return presence["__yjs"];
159
- }
160
- setLocalState(state) {
161
- var _a;
162
- const presence = (_a = this.room.getSelf()) == null ? void 0 : _a.presence["__yjs"];
163
- this.room.updatePresence({
164
- __yjs: __spreadValues(__spreadValues({}, presence || {}), state || {})
165
- });
166
- }
167
- setLocalStateField(field, value) {
168
- var _a;
169
- const presence = (_a = this.room.getSelf()) == null ? void 0 : _a.presence["__yjs"];
170
- const update = { [field]: value };
171
- this.room.updatePresence({
172
- __yjs: __spreadValues(__spreadValues({}, presence || {}), update)
173
- });
174
- }
175
- // Translate liveblocks presence to yjs awareness
176
- getStates() {
177
- const others = this.room.getOthers();
178
- const states = others.reduce((acc, currentValue) => {
179
- if (currentValue.connectionId) {
180
- acc.set(
181
- currentValue.connectionId,
182
- currentValue.presence["__yjs"] || {}
183
- );
184
- }
185
- return acc;
186
- }, /* @__PURE__ */ new Map());
187
- return states;
188
- }
189
- };
190
- var LiveblocksProvider = class {
191
- constructor(room, doc, config) {
192
- this.lastUpdateDate = null;
193
- this.unsubscribers = [];
194
- this.syncDoc = () => {
195
- var _a;
196
- this.doc.clientID = ((_a = this.room.getSelf()) == null ? void 0 : _a.connectionId) || this.doc.clientID;
197
- this.awareness.clientID = this.doc.clientID;
198
- const encodedVector = _jsbase64.Base64.fromUint8Array(Y.encodeStateVector(this.doc));
199
- this.room.getYDoc(encodedVector);
200
- };
201
- this.updateHandler = (update, origin) => __async(this, null, function* () {
202
- if (origin !== "backend") {
203
- const encodedUpdate = _jsbase64.Base64.fromUint8Array(update);
204
- this.room.updateYDoc(encodedUpdate);
205
- if (this.httpEndpoint) {
206
- yield fetch(this.httpEndpoint, {
207
- method: "POST",
208
- body: encodedUpdate
209
- });
210
- }
211
- }
212
- });
213
- var _a;
214
- this.doc = doc;
215
- this.room = room;
216
- const connectionId = (_a = this.room.getSelf()) == null ? void 0 : _a.connectionId;
217
- if (connectionId) {
218
- this.doc.clientID = connectionId;
219
- }
220
- this.awareness = new Awareness(this.doc, this.room);
221
- this.doc.on("update", this.updateHandler);
222
- this.unsubscribers.push(
223
- this.room.events.connection.subscribe((e) => {
224
- if (e === "open") {
225
- this.syncDoc();
226
- }
227
- })
228
- );
229
- this.unsubscribers.push(
230
- this.room.events.docUpdated.subscribe((update) => {
231
- Y.applyUpdate(this.doc, _jsbase64.Base64.toUint8Array(update), "backend");
232
- })
233
- );
234
- if (config == null ? void 0 : config.httpEndpoint) {
235
- this.httpEndpoint = config.httpEndpoint + "?room=" + this.room.id;
236
- this.unsubscribers.push(
237
- this.room.events.customEvent.subscribe(({ event }) => {
238
- if ((event == null ? void 0 : event.type) === "REFRESH") {
239
- void this.resyncHttp();
240
- }
241
- })
242
- );
243
- void this.resyncHttp();
244
- }
245
- this.syncDoc();
246
- }
247
- resyncHttp() {
248
- return __async(this, null, function* () {
249
- if (!this.httpEndpoint) {
250
- return;
251
- }
252
- const response = yield fetch(
253
- `${this.httpEndpoint}${this.lastUpdateDate !== null ? `&after=${this.lastUpdateDate.toISOString()}` : ""}`
254
- );
255
- const { updates, lastUpdate } = yield response.json();
256
- if (updates.length === 0) {
257
- return;
258
- }
259
- this.lastUpdateDate = new Date(lastUpdate);
260
- const update = Y.mergeUpdates(updates.map(_jsbase64.Base64.toUint8Array));
261
- Y.applyUpdate(this.doc, update, "backend");
262
- });
263
- }
264
- destroy() {
265
- this.doc.off("update", this.updateHandler);
266
- this.unsubscribers.forEach((unsub) => unsub());
267
- this.awareness.destroy();
268
- }
269
- };
270
-
271
-
272
-
273
- exports.Awareness = Awareness; exports.default = LiveblocksProvider;
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; } }var g=Object.defineProperty;var m=Object.getOwnPropertySymbols;var _=Object.prototype.hasOwnProperty,j=Object.prototype.propertyIsEnumerable;var b=(n,s,e)=>s in n?g(n,s,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[s]=e,i=(n,s)=>{for(var e in s||(s={}))_.call(s,e)&&b(n,e,s[e]);if(m)for(var e of m(s))j.call(s,e)&&b(n,e,s[e]);return n};var _jsbase64 = require('js-base64');var p=()=>new Map;var y=(n,s,e)=>{let t=n.get(s);return t===void 0&&n.set(s,t=e()),t};var x=()=>new Set;var v=Array.from;var D=Array.isArray;var a=class{constructor(){this._observers=p()}on(s,e){y(this._observers,s,x).add(e)}once(s,e){let t=(...o)=>{this.off(s,t),e(...o)};this.on(s,t)}off(s,e){let t=this._observers.get(s);t!==void 0&&(t.delete(e),t.size===0&&this._observers.delete(s))}emit(s,e){return v((this._observers.get(s)||p()).values()).forEach(t=>t(...e))}destroy(){this._observers=p()}};var _yjs = require('yjs'); var u = _interopRequireWildcard(_yjs);var d="__yjs",h= exports.Awareness =class extends a{constructor(e,t){super();this.states=new Map;this.meta=new Map;this._checkInterval=0;this.doc=e,this.room=t,this.clientID=e.clientID,this.othersUnsub=this.room.events.others.subscribe(({event:o})=>{o.type==="leave"&&this.emit("change",[{added:[],updated:[],removed:[o.user.connectionId]},"local"]),o.type==="enter"&&this.emit("change",[{added:[o.user.connectionId],updated:[],removed:[]},"local"]),o.type==="update"&&this.emit("change",[{added:[],updated:[o.user.connectionId],removed:[]},"local"])})}destroy(){this.emit("destroy",[this]),this.othersUnsub(),this.setLocalState(null),super.destroy()}getLocalState(){let e=this.room.getPresence();return Object.keys(e).length===0||typeof e[d]=="undefined"?null:e[d]}setLocalState(e){var o;let t=(o=this.room.getSelf())==null?void 0:o.presence[d];this.room.updatePresence({__yjs:i(i({},t||{}),e||{})})}setLocalStateField(e,t){var c;let o=(c=this.room.getSelf())==null?void 0:c.presence[d],r={[e]:t};this.room.updatePresence({__yjs:i(i({},o||{}),r)})}getStates(){return this.room.getOthers().reduce((o,r)=>(r.connectionId&&o.set(r.connectionId,r.presence[d]||{}),o),new Map)}},f= exports.default =class extends a{constructor(e,t){var r;super();this.unsubscribers=[];this._synced=!1;this.syncDoc=()=>{var t;this.synced=!1,this.doc.clientID=((t=this.room.getSelf())==null?void 0:t.connectionId)||this.doc.clientID,this.awareness.clientID=this.doc.clientID;let e=_jsbase64.Base64.fromUint8Array(u.encodeStateVector(this.doc));this.room.fetchYDoc(e)};this.updateHandler=(e,t)=>{if(t!=="backend"){let o=_jsbase64.Base64.fromUint8Array(e);this.room.updateYDoc(o)}};this.doc=t,this.room=e;let o=(r=this.room.getSelf())==null?void 0:r.connectionId;o&&(this.doc.clientID=o),this.awareness=new h(this.doc,this.room),this.doc.on("update",this.updateHandler),this.unsubscribers.push(this.room.events.status.subscribe(c=>{c==="connected"&&this.syncDoc()})),this.unsubscribers.push(this.room.events.ydoc.subscribe(c=>{u.applyUpdate(this.doc,_jsbase64.Base64.toUint8Array(c),"backend"),this.synced=!0})),this.syncDoc()}get synced(){return this._synced}set synced(e){this._synced!==e&&(this._synced=e,this.emit("synced",[e]),this.emit("sync",[e]))}destroy(){this.doc.off("update",this.updateHandler),this.unsubscribers.forEach(e=>e()),this.awareness.destroy()}disconnect(){}connect(){}};exports.Awareness = h; exports.default = f;
2
+ //# 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":["Base64","create","setIfUndefined","map","key","createT","set","from","isArray","Observable","name","f","_f","args","observers","Y","Y_PRESENCE_KEY","Awareness","doc","room","event","presence","state","_a","__spreadValues","field","value","update","acc","currentValue","LiveblocksProvider","encodedVector","origin","encodedUpdate","connectionId","status","unsub"],"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,273 +1,2 @@
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
- var __async = (__this, __arguments, generator) => {
18
- return new Promise((resolve, reject) => {
19
- var fulfilled = (value) => {
20
- try {
21
- step(generator.next(value));
22
- } catch (e) {
23
- reject(e);
24
- }
25
- };
26
- var rejected = (value) => {
27
- try {
28
- step(generator.throw(value));
29
- } catch (e) {
30
- reject(e);
31
- }
32
- };
33
- var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
34
- step((generator = generator.apply(__this, __arguments)).next());
35
- });
36
- };
37
-
38
- // src/index.ts
39
- import { Base64 } from "js-base64";
40
-
41
- // ../../node_modules/lib0/map.js
42
- var create = () => /* @__PURE__ */ new Map();
43
- var setIfUndefined = (map, key, createT) => {
44
- let set = map.get(key);
45
- if (set === void 0) {
46
- map.set(key, set = createT());
47
- }
48
- return set;
49
- };
50
-
51
- // ../../node_modules/lib0/set.js
52
- var create2 = () => /* @__PURE__ */ new Set();
53
-
54
- // ../../node_modules/lib0/array.js
55
- var from = Array.from;
56
- var isArray = Array.isArray;
57
-
58
- // ../../node_modules/lib0/observable.js
59
- var Observable = class {
60
- constructor() {
61
- this._observers = create();
62
- }
63
- /**
64
- * @param {N} name
65
- * @param {function} f
66
- */
67
- on(name, f) {
68
- setIfUndefined(this._observers, name, create2).add(f);
69
- }
70
- /**
71
- * @param {N} name
72
- * @param {function} f
73
- */
74
- once(name, f) {
75
- const _f = (...args) => {
76
- this.off(name, _f);
77
- f(...args);
78
- };
79
- this.on(name, _f);
80
- }
81
- /**
82
- * @param {N} name
83
- * @param {function} f
84
- */
85
- off(name, f) {
86
- const observers = this._observers.get(name);
87
- if (observers !== void 0) {
88
- observers.delete(f);
89
- if (observers.size === 0) {
90
- this._observers.delete(name);
91
- }
92
- }
93
- }
94
- /**
95
- * Emit a named event. All registered event listeners that listen to the
96
- * specified name will receive the event.
97
- *
98
- * @todo This should catch exceptions
99
- *
100
- * @param {N} name The event name.
101
- * @param {Array<any>} args The arguments that are applied to the event listener.
102
- */
103
- emit(name, args) {
104
- return from((this._observers.get(name) || create()).values()).forEach((f) => f(...args));
105
- }
106
- destroy() {
107
- this._observers = create();
108
- }
109
- };
110
-
111
- // src/index.ts
112
- import * as Y from "yjs";
113
- var Awareness = class extends Observable {
114
- constructor(doc, room) {
115
- super();
116
- this.states = /* @__PURE__ */ new Map();
117
- // Meta is used to keep track and timeout users who disconnect. Liveblocks provides this for us, so we don't need to
118
- // manage it here. Unfortunately, it's expected to exist by various integrations, so it's an empty map.
119
- this.meta = /* @__PURE__ */ new Map();
120
- // _checkInterval this would hold a timer to remove users, but Liveblock's presence already handles this
121
- // unfortunately it's expected to exist by various integrations.
122
- this._checkInterval = 0;
123
- this.doc = doc;
124
- this.room = room;
125
- this.clientID = doc.clientID;
126
- this.othersUnsub = this.room.events.others.subscribe(({ event }) => {
127
- if (event.type === "leave") {
128
- this.emit("change", [
129
- { added: [], updated: [], removed: [event.user.connectionId] },
130
- "local"
131
- ]);
132
- }
133
- if (event.type === "enter") {
134
- this.emit("change", [
135
- { added: [event.user.connectionId], updated: [], removed: [] },
136
- "local"
137
- ]);
138
- }
139
- if (event.type === "update") {
140
- this.emit("change", [
141
- { added: [], updated: [event.user.connectionId], removed: [] },
142
- "local"
143
- ]);
144
- }
145
- });
146
- }
147
- destroy() {
148
- this.emit("destroy", [this]);
149
- this.othersUnsub();
150
- this.setLocalState(null);
151
- super.destroy();
152
- }
153
- getLocalState() {
154
- const presence = this.room.getPresence();
155
- if (Object.keys(this.room.getPresence()).length === 0) {
156
- return null;
157
- }
158
- return presence["__yjs"];
159
- }
160
- setLocalState(state) {
161
- var _a;
162
- const presence = (_a = this.room.getSelf()) == null ? void 0 : _a.presence["__yjs"];
163
- this.room.updatePresence({
164
- __yjs: __spreadValues(__spreadValues({}, presence || {}), state || {})
165
- });
166
- }
167
- setLocalStateField(field, value) {
168
- var _a;
169
- const presence = (_a = this.room.getSelf()) == null ? void 0 : _a.presence["__yjs"];
170
- const update = { [field]: value };
171
- this.room.updatePresence({
172
- __yjs: __spreadValues(__spreadValues({}, presence || {}), update)
173
- });
174
- }
175
- // Translate liveblocks presence to yjs awareness
176
- getStates() {
177
- const others = this.room.getOthers();
178
- const states = others.reduce((acc, currentValue) => {
179
- if (currentValue.connectionId) {
180
- acc.set(
181
- currentValue.connectionId,
182
- currentValue.presence["__yjs"] || {}
183
- );
184
- }
185
- return acc;
186
- }, /* @__PURE__ */ new Map());
187
- return states;
188
- }
189
- };
190
- var LiveblocksProvider = class {
191
- constructor(room, doc, config) {
192
- this.lastUpdateDate = null;
193
- this.unsubscribers = [];
194
- this.syncDoc = () => {
195
- var _a;
196
- this.doc.clientID = ((_a = this.room.getSelf()) == null ? void 0 : _a.connectionId) || this.doc.clientID;
197
- this.awareness.clientID = this.doc.clientID;
198
- const encodedVector = Base64.fromUint8Array(Y.encodeStateVector(this.doc));
199
- this.room.getYDoc(encodedVector);
200
- };
201
- this.updateHandler = (update, origin) => __async(this, null, function* () {
202
- if (origin !== "backend") {
203
- const encodedUpdate = Base64.fromUint8Array(update);
204
- this.room.updateYDoc(encodedUpdate);
205
- if (this.httpEndpoint) {
206
- yield fetch(this.httpEndpoint, {
207
- method: "POST",
208
- body: encodedUpdate
209
- });
210
- }
211
- }
212
- });
213
- var _a;
214
- this.doc = doc;
215
- this.room = room;
216
- const connectionId = (_a = this.room.getSelf()) == null ? void 0 : _a.connectionId;
217
- if (connectionId) {
218
- this.doc.clientID = connectionId;
219
- }
220
- this.awareness = new Awareness(this.doc, this.room);
221
- this.doc.on("update", this.updateHandler);
222
- this.unsubscribers.push(
223
- this.room.events.connection.subscribe((e) => {
224
- if (e === "open") {
225
- this.syncDoc();
226
- }
227
- })
228
- );
229
- this.unsubscribers.push(
230
- this.room.events.docUpdated.subscribe((update) => {
231
- Y.applyUpdate(this.doc, Base64.toUint8Array(update), "backend");
232
- })
233
- );
234
- if (config == null ? void 0 : config.httpEndpoint) {
235
- this.httpEndpoint = config.httpEndpoint + "?room=" + this.room.id;
236
- this.unsubscribers.push(
237
- this.room.events.customEvent.subscribe(({ event }) => {
238
- if ((event == null ? void 0 : event.type) === "REFRESH") {
239
- void this.resyncHttp();
240
- }
241
- })
242
- );
243
- void this.resyncHttp();
244
- }
245
- this.syncDoc();
246
- }
247
- resyncHttp() {
248
- return __async(this, null, function* () {
249
- if (!this.httpEndpoint) {
250
- return;
251
- }
252
- const response = yield fetch(
253
- `${this.httpEndpoint}${this.lastUpdateDate !== null ? `&after=${this.lastUpdateDate.toISOString()}` : ""}`
254
- );
255
- const { updates, lastUpdate } = yield response.json();
256
- if (updates.length === 0) {
257
- return;
258
- }
259
- this.lastUpdateDate = new Date(lastUpdate);
260
- const update = Y.mergeUpdates(updates.map(Base64.toUint8Array));
261
- Y.applyUpdate(this.doc, update, "backend");
262
- });
263
- }
264
- destroy() {
265
- this.doc.off("update", this.updateHandler);
266
- this.unsubscribers.forEach((unsub) => unsub());
267
- this.awareness.destroy();
268
- }
269
- };
270
- export {
271
- Awareness,
272
- LiveblocksProvider as default
273
- };
1
+ var g=Object.defineProperty;var m=Object.getOwnPropertySymbols;var _=Object.prototype.hasOwnProperty,j=Object.prototype.propertyIsEnumerable;var b=(n,s,e)=>s in n?g(n,s,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[s]=e,i=(n,s)=>{for(var e in s||(s={}))_.call(s,e)&&b(n,e,s[e]);if(m)for(var e of m(s))j.call(s,e)&&b(n,e,s[e]);return n};import{Base64 as l}from"js-base64";var p=()=>new Map;var y=(n,s,e)=>{let t=n.get(s);return t===void 0&&n.set(s,t=e()),t};var x=()=>new Set;var v=Array.from;var D=Array.isArray;var a=class{constructor(){this._observers=p()}on(s,e){y(this._observers,s,x).add(e)}once(s,e){let t=(...o)=>{this.off(s,t),e(...o)};this.on(s,t)}off(s,e){let t=this._observers.get(s);t!==void 0&&(t.delete(e),t.size===0&&this._observers.delete(s))}emit(s,e){return v((this._observers.get(s)||p()).values()).forEach(t=>t(...e))}destroy(){this._observers=p()}};import*as u from"yjs";var d="__yjs",h=class extends a{constructor(e,t){super();this.states=new Map;this.meta=new Map;this._checkInterval=0;this.doc=e,this.room=t,this.clientID=e.clientID,this.othersUnsub=this.room.events.others.subscribe(({event:o})=>{o.type==="leave"&&this.emit("change",[{added:[],updated:[],removed:[o.user.connectionId]},"local"]),o.type==="enter"&&this.emit("change",[{added:[o.user.connectionId],updated:[],removed:[]},"local"]),o.type==="update"&&this.emit("change",[{added:[],updated:[o.user.connectionId],removed:[]},"local"])})}destroy(){this.emit("destroy",[this]),this.othersUnsub(),this.setLocalState(null),super.destroy()}getLocalState(){let e=this.room.getPresence();return Object.keys(e).length===0||typeof e[d]=="undefined"?null:e[d]}setLocalState(e){var o;let t=(o=this.room.getSelf())==null?void 0:o.presence[d];this.room.updatePresence({__yjs:i(i({},t||{}),e||{})})}setLocalStateField(e,t){var c;let o=(c=this.room.getSelf())==null?void 0:c.presence[d],r={[e]:t};this.room.updatePresence({__yjs:i(i({},o||{}),r)})}getStates(){return this.room.getOthers().reduce((o,r)=>(r.connectionId&&o.set(r.connectionId,r.presence[d]||{}),o),new Map)}},f=class extends a{constructor(e,t){var r;super();this.unsubscribers=[];this._synced=!1;this.syncDoc=()=>{var t;this.synced=!1,this.doc.clientID=((t=this.room.getSelf())==null?void 0:t.connectionId)||this.doc.clientID,this.awareness.clientID=this.doc.clientID;let e=l.fromUint8Array(u.encodeStateVector(this.doc));this.room.fetchYDoc(e)};this.updateHandler=(e,t)=>{if(t!=="backend"){let o=l.fromUint8Array(e);this.room.updateYDoc(o)}};this.doc=t,this.room=e;let o=(r=this.room.getSelf())==null?void 0:r.connectionId;o&&(this.doc.clientID=o),this.awareness=new h(this.doc,this.room),this.doc.on("update",this.updateHandler),this.unsubscribers.push(this.room.events.status.subscribe(c=>{c==="connected"&&this.syncDoc()})),this.unsubscribers.push(this.room.events.ydoc.subscribe(c=>{u.applyUpdate(this.doc,l.toUint8Array(c),"backend"),this.synced=!0})),this.syncDoc()}get synced(){return this._synced}set synced(e){this._synced!==e&&(this._synced=e,this.emit("synced",[e]),this.emit("sync",[e]))}destroy(){this.doc.off("update",this.updateHandler),this.unsubscribers.forEach(e=>e()),this.awareness.destroy()}disconnect(){}connect(){}};export{h as Awareness,f as default};
2
+ //# 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":"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","names":["Base64","create","setIfUndefined","map","key","createT","set","create","from","isArray","Observable","create","name","f","setIfUndefined","_f","args","observers","from","Y","Y_PRESENCE_KEY","Awareness","Observable","doc","room","event","presence","state","_a","__spreadValues","field","value","update","acc","currentValue","LiveblocksProvider","encodedVector","Base64","origin","encodedUpdate","connectionId","status","unsub"]}
package/package.json CHANGED
@@ -1,33 +1,40 @@
1
1
  {
2
2
  "name": "@liveblocks/yjs",
3
- "version": "1.1.0-yjs5",
3
+ "version": "1.1.1-dual1",
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"
11
24
  ],
12
25
  "scripts": {
13
26
  "dev": "tsup --watch",
14
- "build": "tsup --format cjs,esm --dts --clean",
27
+ "build": "tsup && cp dist/index.d.ts dist/index.d.mts",
15
28
  "format": "eslint --fix src/; prettier --write src/",
16
29
  "lint": "eslint src/",
30
+ "lint:package": "publint --strict && attw --pack",
17
31
  "test": "jest --silent --verbose --color=always",
18
32
  "test:types": "tsd",
19
33
  "test:watch": "jest --silent --verbose --color=always --watch"
20
34
  },
21
- "exports": {
22
- ".": {
23
- "require": "./dist/index.js",
24
- "import": "./dist/index.mjs",
25
- "types": "./dist/index.d.ts"
26
- }
27
- },
28
35
  "dependencies": {
29
- "@liveblocks/client": "1.1.0-yjs5",
30
- "@liveblocks/core": "1.1.0-yjs5",
36
+ "@liveblocks/client": "1.1.1-dual1",
37
+ "@liveblocks/core": "1.1.1-dual1",
31
38
  "js-base64": "^3.7.5"
32
39
  },
33
40
  "peerDependencies": {