@liveblocks/core 0.19.0 → 0.19.1-test1
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.d.ts +19 -19
- package/dist/index.js +498 -485
- package/package.json +9 -6
- package/dist/index.mjs +0 -37
package/dist/index.d.ts
CHANGED
|
@@ -18,25 +18,6 @@ declare function isJsonScalar(data: Json): data is JsonScalar;
|
|
|
18
18
|
declare function isJsonArray(data: Json): data is JsonArray;
|
|
19
19
|
declare function isJsonObject(data: Json): data is JsonObject;
|
|
20
20
|
|
|
21
|
-
declare type AppOnlyAuthToken = {
|
|
22
|
-
appId: string;
|
|
23
|
-
roomId?: never;
|
|
24
|
-
scopes: string[];
|
|
25
|
-
};
|
|
26
|
-
declare type RoomAuthToken = {
|
|
27
|
-
appId: string;
|
|
28
|
-
roomId: string;
|
|
29
|
-
scopes: string[];
|
|
30
|
-
actor: number;
|
|
31
|
-
maxConnectionsPerRoom?: number;
|
|
32
|
-
id?: string;
|
|
33
|
-
info?: Json;
|
|
34
|
-
};
|
|
35
|
-
declare type AuthToken = AppOnlyAuthToken | RoomAuthToken;
|
|
36
|
-
declare function isAppOnlyAuthToken(data: JsonObject): data is AppOnlyAuthToken;
|
|
37
|
-
declare function isRoomAuthToken(data: JsonObject): data is RoomAuthToken;
|
|
38
|
-
declare function isAuthToken(data: JsonObject): data is AuthToken;
|
|
39
|
-
|
|
40
21
|
declare enum OpCode {
|
|
41
22
|
INIT = 0,
|
|
42
23
|
SET_PARENT_KEY = 1,
|
|
@@ -522,6 +503,25 @@ declare type Resolve<T> = T extends (...args: unknown[]) => unknown ? T : {
|
|
|
522
503
|
[K in keyof T]: T[K];
|
|
523
504
|
};
|
|
524
505
|
|
|
506
|
+
declare type AppOnlyAuthToken = {
|
|
507
|
+
appId: string;
|
|
508
|
+
roomId?: never;
|
|
509
|
+
scopes: string[];
|
|
510
|
+
};
|
|
511
|
+
declare type RoomAuthToken = {
|
|
512
|
+
appId: string;
|
|
513
|
+
roomId: string;
|
|
514
|
+
scopes: string[];
|
|
515
|
+
actor: number;
|
|
516
|
+
maxConnectionsPerRoom?: number;
|
|
517
|
+
id?: string;
|
|
518
|
+
info?: Json;
|
|
519
|
+
};
|
|
520
|
+
declare type AuthToken = AppOnlyAuthToken | RoomAuthToken;
|
|
521
|
+
declare function isAppOnlyAuthToken(data: JsonObject): data is AppOnlyAuthToken;
|
|
522
|
+
declare function isRoomAuthToken(data: JsonObject): data is RoomAuthToken;
|
|
523
|
+
declare function isAuthToken(data: JsonObject): data is AuthToken;
|
|
524
|
+
|
|
525
525
|
declare enum ClientMsgCode {
|
|
526
526
|
UPDATE_PRESENCE = 100,
|
|
527
527
|
BROADCAST_EVENT = 103,
|
package/dist/index.js
CHANGED
|
@@ -50,108 +50,6 @@ var __async = (__this, __arguments, generator) => {
|
|
|
50
50
|
});
|
|
51
51
|
};
|
|
52
52
|
|
|
53
|
-
// src/lib/utils.ts
|
|
54
|
-
function isPlainObject(blob) {
|
|
55
|
-
return blob !== null && typeof blob === "object" && Object.prototype.toString.call(blob) === "[object Object]";
|
|
56
|
-
}
|
|
57
|
-
function fromEntries(iterable) {
|
|
58
|
-
const obj = {};
|
|
59
|
-
for (const [key, val] of iterable) {
|
|
60
|
-
obj[key] = val;
|
|
61
|
-
}
|
|
62
|
-
return obj;
|
|
63
|
-
}
|
|
64
|
-
function entries(obj) {
|
|
65
|
-
return Object.entries(obj);
|
|
66
|
-
}
|
|
67
|
-
function tryParseJson(rawMessage) {
|
|
68
|
-
try {
|
|
69
|
-
return JSON.parse(rawMessage);
|
|
70
|
-
} catch (e) {
|
|
71
|
-
return void 0;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
function b64decode(b64value) {
|
|
75
|
-
try {
|
|
76
|
-
const formattedValue = b64value.replace(/-/g, "+").replace(/_/g, "/");
|
|
77
|
-
const decodedValue = decodeURIComponent(
|
|
78
|
-
atob(formattedValue).split("").map(function(c) {
|
|
79
|
-
return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
|
|
80
|
-
}).join("")
|
|
81
|
-
);
|
|
82
|
-
return decodedValue;
|
|
83
|
-
} catch (err) {
|
|
84
|
-
return atob(b64value);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
function compact(items) {
|
|
88
|
-
return items.filter(
|
|
89
|
-
(item) => item !== null && item !== void 0
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
|
-
function compactObject(obj) {
|
|
93
|
-
const newObj = __spreadValues({}, obj);
|
|
94
|
-
Object.keys(obj).forEach((k) => {
|
|
95
|
-
const key = k;
|
|
96
|
-
if (newObj[key] === void 0) {
|
|
97
|
-
delete newObj[key];
|
|
98
|
-
}
|
|
99
|
-
});
|
|
100
|
-
return newObj;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// src/AuthToken.ts
|
|
104
|
-
function hasJwtMeta(data) {
|
|
105
|
-
if (!isPlainObject(data)) {
|
|
106
|
-
return false;
|
|
107
|
-
}
|
|
108
|
-
const { iat, exp } = data;
|
|
109
|
-
return typeof iat === "number" && typeof exp === "number";
|
|
110
|
-
}
|
|
111
|
-
function isTokenExpired(token) {
|
|
112
|
-
const now = Date.now() / 1e3;
|
|
113
|
-
return now > token.exp - 300 || now < token.iat + 300;
|
|
114
|
-
}
|
|
115
|
-
function isStringList(value) {
|
|
116
|
-
return Array.isArray(value) && value.every((i) => typeof i === "string");
|
|
117
|
-
}
|
|
118
|
-
function isAppOnlyAuthToken(data) {
|
|
119
|
-
return typeof data.appId === "string" && data.roomId === void 0 && isStringList(data.scopes);
|
|
120
|
-
}
|
|
121
|
-
function isRoomAuthToken(data) {
|
|
122
|
-
return typeof data.appId === "string" && typeof data.roomId === "string" && typeof data.actor === "number" && (data.id === void 0 || typeof data.id === "string") && isStringList(data.scopes) && (data.maxConnectionsPerRoom === void 0 || typeof data.maxConnectionsPerRoom === "number");
|
|
123
|
-
}
|
|
124
|
-
function isAuthToken(data) {
|
|
125
|
-
return isAppOnlyAuthToken(data) || isRoomAuthToken(data);
|
|
126
|
-
}
|
|
127
|
-
function parseJwtToken(token) {
|
|
128
|
-
const tokenParts = token.split(".");
|
|
129
|
-
if (tokenParts.length !== 3) {
|
|
130
|
-
throw new Error("Authentication error: invalid JWT token");
|
|
131
|
-
}
|
|
132
|
-
const data = tryParseJson(b64decode(tokenParts[1]));
|
|
133
|
-
if (data && hasJwtMeta(data)) {
|
|
134
|
-
return data;
|
|
135
|
-
} else {
|
|
136
|
-
throw new Error("Authentication error: missing JWT metadata");
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
function parseRoomAuthToken(tokenString) {
|
|
140
|
-
const data = parseJwtToken(tokenString);
|
|
141
|
-
if (data && isRoomAuthToken(data)) {
|
|
142
|
-
const _a = data, {
|
|
143
|
-
maxConnections: _legacyField
|
|
144
|
-
} = _a, token = __objRest(_a, [
|
|
145
|
-
"maxConnections"
|
|
146
|
-
]);
|
|
147
|
-
return token;
|
|
148
|
-
} else {
|
|
149
|
-
throw new Error(
|
|
150
|
-
"Authentication error: we expected a room token but did not get one. Hint: if you are using a callback, ensure the room is passed when creating the token. For more information: https://liveblocks.io/docs/api-reference/liveblocks-client#createClientCallback"
|
|
151
|
-
);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
53
|
// src/lib/fancy-console.ts
|
|
156
54
|
var badge = "background:radial-gradient(106.94% 108.33% at -10% -5%,#ff1aa3 0,#ff881a 100%);border-radius:3px;color:#fff;padding:2px 5px;font-family:sans-serif;font-weight:600";
|
|
157
55
|
var bold = "font-weight:600";
|
|
@@ -209,10 +107,12 @@ function assertNever(_value, errmsg) {
|
|
|
209
107
|
throw new Error(errmsg);
|
|
210
108
|
}
|
|
211
109
|
function assert(condition, errmsg) {
|
|
212
|
-
if (process.env.NODE_ENV !== "production"
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
110
|
+
if (process.env.NODE_ENV !== "production") {
|
|
111
|
+
if (!condition) {
|
|
112
|
+
const err = new Error(errmsg);
|
|
113
|
+
err.name = "Assertion failure";
|
|
114
|
+
throw err;
|
|
115
|
+
}
|
|
216
116
|
}
|
|
217
117
|
}
|
|
218
118
|
function nn(value, errmsg = "Expected value to be non-nullable") {
|
|
@@ -372,6 +272,71 @@ var AbstractCrdt = class {
|
|
|
372
272
|
}
|
|
373
273
|
};
|
|
374
274
|
|
|
275
|
+
// src/lib/utils.ts
|
|
276
|
+
function isPlainObject(blob) {
|
|
277
|
+
return blob !== null && typeof blob === "object" && Object.prototype.toString.call(blob) === "[object Object]";
|
|
278
|
+
}
|
|
279
|
+
function fromEntries(iterable) {
|
|
280
|
+
const obj = {};
|
|
281
|
+
for (const [key, val] of iterable) {
|
|
282
|
+
obj[key] = val;
|
|
283
|
+
}
|
|
284
|
+
return obj;
|
|
285
|
+
}
|
|
286
|
+
function entries(obj) {
|
|
287
|
+
return Object.entries(obj);
|
|
288
|
+
}
|
|
289
|
+
function tryParseJson(rawMessage) {
|
|
290
|
+
try {
|
|
291
|
+
return JSON.parse(rawMessage);
|
|
292
|
+
} catch (e) {
|
|
293
|
+
return void 0;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
function b64decode(b64value) {
|
|
297
|
+
try {
|
|
298
|
+
const formattedValue = b64value.replace(/-/g, "+").replace(/_/g, "/");
|
|
299
|
+
const decodedValue = decodeURIComponent(
|
|
300
|
+
atob(formattedValue).split("").map(function(c) {
|
|
301
|
+
return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
|
|
302
|
+
}).join("")
|
|
303
|
+
);
|
|
304
|
+
return decodedValue;
|
|
305
|
+
} catch (err) {
|
|
306
|
+
return atob(b64value);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
function compact(items) {
|
|
310
|
+
return items.filter(
|
|
311
|
+
(item) => item !== null && item !== void 0
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
function compactObject(obj) {
|
|
315
|
+
const newObj = __spreadValues({}, obj);
|
|
316
|
+
Object.keys(obj).forEach((k) => {
|
|
317
|
+
const key = k;
|
|
318
|
+
if (newObj[key] === void 0) {
|
|
319
|
+
delete newObj[key];
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
return newObj;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// src/protocol/SerializedCrdt.ts
|
|
326
|
+
var CrdtType = /* @__PURE__ */ ((CrdtType2) => {
|
|
327
|
+
CrdtType2[CrdtType2["OBJECT"] = 0] = "OBJECT";
|
|
328
|
+
CrdtType2[CrdtType2["LIST"] = 1] = "LIST";
|
|
329
|
+
CrdtType2[CrdtType2["MAP"] = 2] = "MAP";
|
|
330
|
+
CrdtType2[CrdtType2["REGISTER"] = 3] = "REGISTER";
|
|
331
|
+
return CrdtType2;
|
|
332
|
+
})(CrdtType || {});
|
|
333
|
+
function isRootCrdt(crdt) {
|
|
334
|
+
return crdt.type === 0 /* OBJECT */ && !isChildCrdt(crdt);
|
|
335
|
+
}
|
|
336
|
+
function isChildCrdt(crdt) {
|
|
337
|
+
return crdt.parentId !== void 0 && crdt.parentKey !== void 0;
|
|
338
|
+
}
|
|
339
|
+
|
|
375
340
|
// src/lib/position.ts
|
|
376
341
|
var min = 32;
|
|
377
342
|
var max = 126;
|
|
@@ -476,21 +441,6 @@ function comparePosition(posA, posB) {
|
|
|
476
441
|
);
|
|
477
442
|
}
|
|
478
443
|
|
|
479
|
-
// src/protocol/SerializedCrdt.ts
|
|
480
|
-
var CrdtType = /* @__PURE__ */ ((CrdtType2) => {
|
|
481
|
-
CrdtType2[CrdtType2["OBJECT"] = 0] = "OBJECT";
|
|
482
|
-
CrdtType2[CrdtType2["LIST"] = 1] = "LIST";
|
|
483
|
-
CrdtType2[CrdtType2["MAP"] = 2] = "MAP";
|
|
484
|
-
CrdtType2[CrdtType2["REGISTER"] = 3] = "REGISTER";
|
|
485
|
-
return CrdtType2;
|
|
486
|
-
})(CrdtType || {});
|
|
487
|
-
function isRootCrdt(crdt) {
|
|
488
|
-
return crdt.type === 0 /* OBJECT */ && !isChildCrdt(crdt);
|
|
489
|
-
}
|
|
490
|
-
function isChildCrdt(crdt) {
|
|
491
|
-
return crdt.parentId !== void 0 && crdt.parentKey !== void 0;
|
|
492
|
-
}
|
|
493
|
-
|
|
494
444
|
// src/crdts/LiveRegister.ts
|
|
495
445
|
var LiveRegister = class extends AbstractCrdt {
|
|
496
446
|
constructor(data) {
|
|
@@ -1709,298 +1659,54 @@ var LiveMap = class extends AbstractCrdt {
|
|
|
1709
1659
|
}
|
|
1710
1660
|
};
|
|
1711
1661
|
|
|
1712
|
-
// src/
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
default:
|
|
1727
|
-
return assertNever(op, "Unknown creation Op");
|
|
1662
|
+
// src/crdts/LiveObject.ts
|
|
1663
|
+
var LiveObject = class extends AbstractCrdt {
|
|
1664
|
+
constructor(obj = {}) {
|
|
1665
|
+
super();
|
|
1666
|
+
this._propToLastUpdate = /* @__PURE__ */ new Map();
|
|
1667
|
+
for (const key in obj) {
|
|
1668
|
+
const value = obj[key];
|
|
1669
|
+
if (value === void 0) {
|
|
1670
|
+
continue;
|
|
1671
|
+
} else if (isLiveNode(value)) {
|
|
1672
|
+
value._setParentLink(this, key);
|
|
1673
|
+
}
|
|
1674
|
+
}
|
|
1675
|
+
this._map = new Map(Object.entries(obj));
|
|
1728
1676
|
}
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1677
|
+
_toOps(parentId, parentKey, pool) {
|
|
1678
|
+
if (this._id === void 0) {
|
|
1679
|
+
throw new Error("Cannot serialize item is not attached");
|
|
1680
|
+
}
|
|
1681
|
+
const opId = pool == null ? void 0 : pool.generateOpId();
|
|
1682
|
+
const ops = [];
|
|
1683
|
+
const op = parentId !== void 0 && parentKey !== void 0 ? {
|
|
1684
|
+
type: 4 /* CREATE_OBJECT */,
|
|
1685
|
+
id: this._id,
|
|
1686
|
+
opId,
|
|
1687
|
+
parentId,
|
|
1688
|
+
parentKey,
|
|
1689
|
+
data: {}
|
|
1690
|
+
} : { type: 4 /* CREATE_OBJECT */, id: this._id, opId, data: {} };
|
|
1691
|
+
ops.push(op);
|
|
1692
|
+
for (const [key, value] of this._map) {
|
|
1693
|
+
if (isLiveNode(value)) {
|
|
1694
|
+
ops.push(...value._toOps(this._id, key, pool));
|
|
1695
|
+
} else {
|
|
1696
|
+
op.data[key] = value;
|
|
1697
|
+
}
|
|
1698
|
+
}
|
|
1699
|
+
return ops;
|
|
1733
1700
|
}
|
|
1734
|
-
|
|
1735
|
-
|
|
1701
|
+
static _deserialize([id, item], parentToChildren, pool) {
|
|
1702
|
+
const liveObj = new LiveObject(item.data);
|
|
1703
|
+
liveObj._attach(id, pool);
|
|
1704
|
+
return this._deserializeChildren(liveObj, parentToChildren, pool);
|
|
1736
1705
|
}
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
case 0 /* OBJECT */: {
|
|
1742
|
-
return LiveObject._deserialize([id, crdt], parentToChildren, pool);
|
|
1743
|
-
}
|
|
1744
|
-
case 1 /* LIST */: {
|
|
1745
|
-
return LiveList._deserialize([id, crdt], parentToChildren, pool);
|
|
1746
|
-
}
|
|
1747
|
-
case 2 /* MAP */: {
|
|
1748
|
-
return LiveMap._deserialize([id, crdt], parentToChildren, pool);
|
|
1749
|
-
}
|
|
1750
|
-
case 3 /* REGISTER */: {
|
|
1751
|
-
return LiveRegister._deserialize([id, crdt], parentToChildren, pool);
|
|
1752
|
-
}
|
|
1753
|
-
default: {
|
|
1754
|
-
throw new Error("Unexpected CRDT type");
|
|
1755
|
-
}
|
|
1756
|
-
}
|
|
1757
|
-
}
|
|
1758
|
-
function deserializeToLson([id, crdt], parentToChildren, pool) {
|
|
1759
|
-
switch (crdt.type) {
|
|
1760
|
-
case 0 /* OBJECT */: {
|
|
1761
|
-
return LiveObject._deserialize([id, crdt], parentToChildren, pool);
|
|
1762
|
-
}
|
|
1763
|
-
case 1 /* LIST */: {
|
|
1764
|
-
return LiveList._deserialize([id, crdt], parentToChildren, pool);
|
|
1765
|
-
}
|
|
1766
|
-
case 2 /* MAP */: {
|
|
1767
|
-
return LiveMap._deserialize([id, crdt], parentToChildren, pool);
|
|
1768
|
-
}
|
|
1769
|
-
case 3 /* REGISTER */: {
|
|
1770
|
-
return crdt.data;
|
|
1771
|
-
}
|
|
1772
|
-
default: {
|
|
1773
|
-
throw new Error("Unexpected CRDT type");
|
|
1774
|
-
}
|
|
1775
|
-
}
|
|
1776
|
-
}
|
|
1777
|
-
function isLiveStructure(value) {
|
|
1778
|
-
return isLiveList(value) || isLiveMap(value) || isLiveObject(value);
|
|
1779
|
-
}
|
|
1780
|
-
function isLiveNode(value) {
|
|
1781
|
-
return isLiveStructure(value) || isLiveRegister(value);
|
|
1782
|
-
}
|
|
1783
|
-
function isLiveList(value) {
|
|
1784
|
-
return value instanceof LiveList;
|
|
1785
|
-
}
|
|
1786
|
-
function isLiveMap(value) {
|
|
1787
|
-
return value instanceof LiveMap;
|
|
1788
|
-
}
|
|
1789
|
-
function isLiveObject(value) {
|
|
1790
|
-
return value instanceof LiveObject;
|
|
1791
|
-
}
|
|
1792
|
-
function isLiveRegister(value) {
|
|
1793
|
-
return value instanceof LiveRegister;
|
|
1794
|
-
}
|
|
1795
|
-
function liveNodeToLson(obj) {
|
|
1796
|
-
if (obj instanceof LiveRegister) {
|
|
1797
|
-
return obj.data;
|
|
1798
|
-
} else if (obj instanceof LiveList || obj instanceof LiveMap || obj instanceof LiveObject) {
|
|
1799
|
-
return obj;
|
|
1800
|
-
} else {
|
|
1801
|
-
return assertNever(obj, "Unknown AbstractCrdt");
|
|
1802
|
-
}
|
|
1803
|
-
}
|
|
1804
|
-
function lsonToLiveNode(value) {
|
|
1805
|
-
if (value instanceof LiveObject || value instanceof LiveMap || value instanceof LiveList) {
|
|
1806
|
-
return value;
|
|
1807
|
-
} else {
|
|
1808
|
-
return new LiveRegister(value);
|
|
1809
|
-
}
|
|
1810
|
-
}
|
|
1811
|
-
function getTreesDiffOperations(currentItems, newItems) {
|
|
1812
|
-
const ops = [];
|
|
1813
|
-
currentItems.forEach((_, id) => {
|
|
1814
|
-
if (!newItems.get(id)) {
|
|
1815
|
-
ops.push({
|
|
1816
|
-
type: 5 /* DELETE_CRDT */,
|
|
1817
|
-
id
|
|
1818
|
-
});
|
|
1819
|
-
}
|
|
1820
|
-
});
|
|
1821
|
-
newItems.forEach((crdt, id) => {
|
|
1822
|
-
const currentCrdt = currentItems.get(id);
|
|
1823
|
-
if (currentCrdt) {
|
|
1824
|
-
if (crdt.type === 0 /* OBJECT */) {
|
|
1825
|
-
if (currentCrdt.type !== 0 /* OBJECT */ || JSON.stringify(crdt.data) !== JSON.stringify(currentCrdt.data)) {
|
|
1826
|
-
ops.push({
|
|
1827
|
-
type: 3 /* UPDATE_OBJECT */,
|
|
1828
|
-
id,
|
|
1829
|
-
data: crdt.data
|
|
1830
|
-
});
|
|
1831
|
-
}
|
|
1832
|
-
}
|
|
1833
|
-
if (crdt.parentKey !== currentCrdt.parentKey) {
|
|
1834
|
-
ops.push({
|
|
1835
|
-
type: 1 /* SET_PARENT_KEY */,
|
|
1836
|
-
id,
|
|
1837
|
-
parentKey: nn(crdt.parentKey, "Parent key must not be missing")
|
|
1838
|
-
});
|
|
1839
|
-
}
|
|
1840
|
-
} else {
|
|
1841
|
-
switch (crdt.type) {
|
|
1842
|
-
case 3 /* REGISTER */:
|
|
1843
|
-
ops.push({
|
|
1844
|
-
type: 8 /* CREATE_REGISTER */,
|
|
1845
|
-
id,
|
|
1846
|
-
parentId: crdt.parentId,
|
|
1847
|
-
parentKey: crdt.parentKey,
|
|
1848
|
-
data: crdt.data
|
|
1849
|
-
});
|
|
1850
|
-
break;
|
|
1851
|
-
case 1 /* LIST */:
|
|
1852
|
-
ops.push({
|
|
1853
|
-
type: 2 /* CREATE_LIST */,
|
|
1854
|
-
id,
|
|
1855
|
-
parentId: crdt.parentId,
|
|
1856
|
-
parentKey: crdt.parentKey
|
|
1857
|
-
});
|
|
1858
|
-
break;
|
|
1859
|
-
case 0 /* OBJECT */:
|
|
1860
|
-
ops.push(
|
|
1861
|
-
crdt.parentId ? {
|
|
1862
|
-
type: 4 /* CREATE_OBJECT */,
|
|
1863
|
-
id,
|
|
1864
|
-
parentId: crdt.parentId,
|
|
1865
|
-
parentKey: crdt.parentKey,
|
|
1866
|
-
data: crdt.data
|
|
1867
|
-
} : { type: 4 /* CREATE_OBJECT */, id, data: crdt.data }
|
|
1868
|
-
);
|
|
1869
|
-
break;
|
|
1870
|
-
case 2 /* MAP */:
|
|
1871
|
-
ops.push({
|
|
1872
|
-
type: 7 /* CREATE_MAP */,
|
|
1873
|
-
id,
|
|
1874
|
-
parentId: crdt.parentId,
|
|
1875
|
-
parentKey: crdt.parentKey
|
|
1876
|
-
});
|
|
1877
|
-
break;
|
|
1878
|
-
}
|
|
1879
|
-
}
|
|
1880
|
-
});
|
|
1881
|
-
return ops;
|
|
1882
|
-
}
|
|
1883
|
-
function mergeObjectStorageUpdates(first, second) {
|
|
1884
|
-
const updates = first.updates;
|
|
1885
|
-
for (const [key, value] of entries(second.updates)) {
|
|
1886
|
-
updates[key] = value;
|
|
1887
|
-
}
|
|
1888
|
-
return __spreadProps(__spreadValues({}, second), {
|
|
1889
|
-
updates
|
|
1890
|
-
});
|
|
1891
|
-
}
|
|
1892
|
-
function mergeMapStorageUpdates(first, second) {
|
|
1893
|
-
const updates = first.updates;
|
|
1894
|
-
for (const [key, value] of entries(second.updates)) {
|
|
1895
|
-
updates[key] = value;
|
|
1896
|
-
}
|
|
1897
|
-
return __spreadProps(__spreadValues({}, second), {
|
|
1898
|
-
updates
|
|
1899
|
-
});
|
|
1900
|
-
}
|
|
1901
|
-
function mergeListStorageUpdates(first, second) {
|
|
1902
|
-
const updates = first.updates;
|
|
1903
|
-
return __spreadProps(__spreadValues({}, second), {
|
|
1904
|
-
updates: updates.concat(second.updates)
|
|
1905
|
-
});
|
|
1906
|
-
}
|
|
1907
|
-
function mergeStorageUpdates(first, second) {
|
|
1908
|
-
if (!first) {
|
|
1909
|
-
return second;
|
|
1910
|
-
}
|
|
1911
|
-
if (first.type === "LiveObject" && second.type === "LiveObject") {
|
|
1912
|
-
return mergeObjectStorageUpdates(first, second);
|
|
1913
|
-
} else if (first.type === "LiveMap" && second.type === "LiveMap") {
|
|
1914
|
-
return mergeMapStorageUpdates(first, second);
|
|
1915
|
-
} else if (first.type === "LiveList" && second.type === "LiveList") {
|
|
1916
|
-
return mergeListStorageUpdates(first, second);
|
|
1917
|
-
} else {
|
|
1918
|
-
}
|
|
1919
|
-
return second;
|
|
1920
|
-
}
|
|
1921
|
-
function isPlain(value) {
|
|
1922
|
-
const type = typeof value;
|
|
1923
|
-
return value === void 0 || value === null || type === "string" || type === "boolean" || type === "number" || Array.isArray(value) || isPlainObject(value);
|
|
1924
|
-
}
|
|
1925
|
-
function findNonSerializableValue(value, path = "") {
|
|
1926
|
-
if (!isPlain) {
|
|
1927
|
-
return {
|
|
1928
|
-
path: path || "root",
|
|
1929
|
-
value
|
|
1930
|
-
};
|
|
1931
|
-
}
|
|
1932
|
-
if (typeof value !== "object" || value === null) {
|
|
1933
|
-
return false;
|
|
1934
|
-
}
|
|
1935
|
-
for (const [key, nestedValue] of Object.entries(value)) {
|
|
1936
|
-
const nestedPath = path ? path + "." + key : key;
|
|
1937
|
-
if (!isPlain(nestedValue)) {
|
|
1938
|
-
return {
|
|
1939
|
-
path: nestedPath,
|
|
1940
|
-
value: nestedValue
|
|
1941
|
-
};
|
|
1942
|
-
}
|
|
1943
|
-
if (typeof nestedValue === "object") {
|
|
1944
|
-
const nonSerializableNestedValue = findNonSerializableValue(
|
|
1945
|
-
nestedValue,
|
|
1946
|
-
nestedPath
|
|
1947
|
-
);
|
|
1948
|
-
if (nonSerializableNestedValue) {
|
|
1949
|
-
return nonSerializableNestedValue;
|
|
1950
|
-
}
|
|
1951
|
-
}
|
|
1952
|
-
}
|
|
1953
|
-
return false;
|
|
1954
|
-
}
|
|
1955
|
-
|
|
1956
|
-
// src/crdts/LiveObject.ts
|
|
1957
|
-
var LiveObject = class extends AbstractCrdt {
|
|
1958
|
-
constructor(obj = {}) {
|
|
1959
|
-
super();
|
|
1960
|
-
this._propToLastUpdate = /* @__PURE__ */ new Map();
|
|
1961
|
-
for (const key in obj) {
|
|
1962
|
-
const value = obj[key];
|
|
1963
|
-
if (value === void 0) {
|
|
1964
|
-
continue;
|
|
1965
|
-
} else if (isLiveNode(value)) {
|
|
1966
|
-
value._setParentLink(this, key);
|
|
1967
|
-
}
|
|
1968
|
-
}
|
|
1969
|
-
this._map = new Map(Object.entries(obj));
|
|
1970
|
-
}
|
|
1971
|
-
_toOps(parentId, parentKey, pool) {
|
|
1972
|
-
if (this._id === void 0) {
|
|
1973
|
-
throw new Error("Cannot serialize item is not attached");
|
|
1974
|
-
}
|
|
1975
|
-
const opId = pool == null ? void 0 : pool.generateOpId();
|
|
1976
|
-
const ops = [];
|
|
1977
|
-
const op = parentId !== void 0 && parentKey !== void 0 ? {
|
|
1978
|
-
type: 4 /* CREATE_OBJECT */,
|
|
1979
|
-
id: this._id,
|
|
1980
|
-
opId,
|
|
1981
|
-
parentId,
|
|
1982
|
-
parentKey,
|
|
1983
|
-
data: {}
|
|
1984
|
-
} : { type: 4 /* CREATE_OBJECT */, id: this._id, opId, data: {} };
|
|
1985
|
-
ops.push(op);
|
|
1986
|
-
for (const [key, value] of this._map) {
|
|
1987
|
-
if (isLiveNode(value)) {
|
|
1988
|
-
ops.push(...value._toOps(this._id, key, pool));
|
|
1989
|
-
} else {
|
|
1990
|
-
op.data[key] = value;
|
|
1991
|
-
}
|
|
1992
|
-
}
|
|
1993
|
-
return ops;
|
|
1994
|
-
}
|
|
1995
|
-
static _deserialize([id, item], parentToChildren, pool) {
|
|
1996
|
-
const liveObj = new LiveObject(item.data);
|
|
1997
|
-
liveObj._attach(id, pool);
|
|
1998
|
-
return this._deserializeChildren(liveObj, parentToChildren, pool);
|
|
1999
|
-
}
|
|
2000
|
-
static _deserializeChildren(liveObj, parentToChildren, pool) {
|
|
2001
|
-
const children = parentToChildren.get(nn(liveObj._id));
|
|
2002
|
-
if (children === void 0) {
|
|
2003
|
-
return liveObj;
|
|
1706
|
+
static _deserializeChildren(liveObj, parentToChildren, pool) {
|
|
1707
|
+
const children = parentToChildren.get(nn(liveObj._id));
|
|
1708
|
+
if (children === void 0) {
|
|
1709
|
+
return liveObj;
|
|
2004
1710
|
}
|
|
2005
1711
|
for (const [id, crdt] of children) {
|
|
2006
1712
|
const child = deserializeToLson([id, crdt], parentToChildren, pool);
|
|
@@ -2307,79 +2013,323 @@ var LiveObject = class extends AbstractCrdt {
|
|
|
2307
2013
|
}
|
|
2308
2014
|
return;
|
|
2309
2015
|
}
|
|
2310
|
-
const ops = [];
|
|
2311
|
-
const reverseOps = [];
|
|
2312
|
-
const opId = this._pool.generateOpId();
|
|
2313
|
-
const updatedProps = {};
|
|
2314
|
-
const reverseUpdateOp = {
|
|
2315
|
-
id: this._id,
|
|
2316
|
-
type: 3 /* UPDATE_OBJECT */,
|
|
2317
|
-
data: {}
|
|
2318
|
-
};
|
|
2319
|
-
const updateDelta = {};
|
|
2320
|
-
for (const key in patch) {
|
|
2321
|
-
const newValue = patch[key];
|
|
2322
|
-
if (newValue === void 0) {
|
|
2323
|
-
continue;
|
|
2016
|
+
const ops = [];
|
|
2017
|
+
const reverseOps = [];
|
|
2018
|
+
const opId = this._pool.generateOpId();
|
|
2019
|
+
const updatedProps = {};
|
|
2020
|
+
const reverseUpdateOp = {
|
|
2021
|
+
id: this._id,
|
|
2022
|
+
type: 3 /* UPDATE_OBJECT */,
|
|
2023
|
+
data: {}
|
|
2024
|
+
};
|
|
2025
|
+
const updateDelta = {};
|
|
2026
|
+
for (const key in patch) {
|
|
2027
|
+
const newValue = patch[key];
|
|
2028
|
+
if (newValue === void 0) {
|
|
2029
|
+
continue;
|
|
2030
|
+
}
|
|
2031
|
+
const oldValue = this._map.get(key);
|
|
2032
|
+
if (isLiveNode(oldValue)) {
|
|
2033
|
+
reverseOps.push(...oldValue._toOps(this._id, key));
|
|
2034
|
+
oldValue._detach();
|
|
2035
|
+
} else if (oldValue === void 0) {
|
|
2036
|
+
reverseOps.push({ type: 6 /* DELETE_OBJECT_KEY */, id: this._id, key });
|
|
2037
|
+
} else {
|
|
2038
|
+
reverseUpdateOp.data[key] = oldValue;
|
|
2039
|
+
}
|
|
2040
|
+
if (isLiveNode(newValue)) {
|
|
2041
|
+
newValue._setParentLink(this, key);
|
|
2042
|
+
newValue._attach(this._pool.generateId(), this._pool);
|
|
2043
|
+
const newAttachChildOps = newValue._toOps(this._id, key, this._pool);
|
|
2044
|
+
const createCrdtOp = newAttachChildOps.find(
|
|
2045
|
+
(op) => op.parentId === this._id
|
|
2046
|
+
);
|
|
2047
|
+
if (createCrdtOp) {
|
|
2048
|
+
this._propToLastUpdate.set(key, nn(createCrdtOp.opId));
|
|
2049
|
+
}
|
|
2050
|
+
ops.push(...newAttachChildOps);
|
|
2051
|
+
} else {
|
|
2052
|
+
updatedProps[key] = newValue;
|
|
2053
|
+
this._propToLastUpdate.set(key, opId);
|
|
2054
|
+
}
|
|
2055
|
+
this._map.set(key, newValue);
|
|
2056
|
+
this.invalidate();
|
|
2057
|
+
updateDelta[key] = { type: "update" };
|
|
2058
|
+
}
|
|
2059
|
+
if (Object.keys(reverseUpdateOp.data).length !== 0) {
|
|
2060
|
+
reverseOps.unshift(reverseUpdateOp);
|
|
2061
|
+
}
|
|
2062
|
+
if (Object.keys(updatedProps).length !== 0) {
|
|
2063
|
+
ops.unshift({
|
|
2064
|
+
opId,
|
|
2065
|
+
id: this._id,
|
|
2066
|
+
type: 3 /* UPDATE_OBJECT */,
|
|
2067
|
+
data: updatedProps
|
|
2068
|
+
});
|
|
2069
|
+
}
|
|
2070
|
+
const storageUpdates = /* @__PURE__ */ new Map();
|
|
2071
|
+
storageUpdates.set(this._id, {
|
|
2072
|
+
node: this,
|
|
2073
|
+
type: "LiveObject",
|
|
2074
|
+
updates: updateDelta
|
|
2075
|
+
});
|
|
2076
|
+
this._pool.dispatch(ops, reverseOps, storageUpdates);
|
|
2077
|
+
}
|
|
2078
|
+
toImmutable() {
|
|
2079
|
+
return super.toImmutable();
|
|
2080
|
+
}
|
|
2081
|
+
_toImmutable() {
|
|
2082
|
+
const result = {};
|
|
2083
|
+
for (const [key, val] of this._map) {
|
|
2084
|
+
result[key] = isLiveStructure(val) ? val.toImmutable() : val;
|
|
2085
|
+
}
|
|
2086
|
+
return process.env.NODE_ENV === "production" ? result : Object.freeze(result);
|
|
2087
|
+
}
|
|
2088
|
+
};
|
|
2089
|
+
|
|
2090
|
+
// src/crdts/liveblocks-helpers.ts
|
|
2091
|
+
function creationOpToLiveNode(op) {
|
|
2092
|
+
return lsonToLiveNode(creationOpToLson(op));
|
|
2093
|
+
}
|
|
2094
|
+
function creationOpToLson(op) {
|
|
2095
|
+
switch (op.type) {
|
|
2096
|
+
case 8 /* CREATE_REGISTER */:
|
|
2097
|
+
return op.data;
|
|
2098
|
+
case 4 /* CREATE_OBJECT */:
|
|
2099
|
+
return new LiveObject(op.data);
|
|
2100
|
+
case 7 /* CREATE_MAP */:
|
|
2101
|
+
return new LiveMap();
|
|
2102
|
+
case 2 /* CREATE_LIST */:
|
|
2103
|
+
return new LiveList();
|
|
2104
|
+
default:
|
|
2105
|
+
return assertNever(op, "Unknown creation Op");
|
|
2106
|
+
}
|
|
2107
|
+
}
|
|
2108
|
+
function isSameNodeOrChildOf(node, parent) {
|
|
2109
|
+
if (node === parent) {
|
|
2110
|
+
return true;
|
|
2111
|
+
}
|
|
2112
|
+
if (node.parent.type === "HasParent") {
|
|
2113
|
+
return isSameNodeOrChildOf(node.parent.node, parent);
|
|
2114
|
+
}
|
|
2115
|
+
return false;
|
|
2116
|
+
}
|
|
2117
|
+
function deserialize([id, crdt], parentToChildren, pool) {
|
|
2118
|
+
switch (crdt.type) {
|
|
2119
|
+
case 0 /* OBJECT */: {
|
|
2120
|
+
return LiveObject._deserialize([id, crdt], parentToChildren, pool);
|
|
2121
|
+
}
|
|
2122
|
+
case 1 /* LIST */: {
|
|
2123
|
+
return LiveList._deserialize([id, crdt], parentToChildren, pool);
|
|
2124
|
+
}
|
|
2125
|
+
case 2 /* MAP */: {
|
|
2126
|
+
return LiveMap._deserialize([id, crdt], parentToChildren, pool);
|
|
2127
|
+
}
|
|
2128
|
+
case 3 /* REGISTER */: {
|
|
2129
|
+
return LiveRegister._deserialize([id, crdt], parentToChildren, pool);
|
|
2130
|
+
}
|
|
2131
|
+
default: {
|
|
2132
|
+
throw new Error("Unexpected CRDT type");
|
|
2133
|
+
}
|
|
2134
|
+
}
|
|
2135
|
+
}
|
|
2136
|
+
function deserializeToLson([id, crdt], parentToChildren, pool) {
|
|
2137
|
+
switch (crdt.type) {
|
|
2138
|
+
case 0 /* OBJECT */: {
|
|
2139
|
+
return LiveObject._deserialize([id, crdt], parentToChildren, pool);
|
|
2140
|
+
}
|
|
2141
|
+
case 1 /* LIST */: {
|
|
2142
|
+
return LiveList._deserialize([id, crdt], parentToChildren, pool);
|
|
2143
|
+
}
|
|
2144
|
+
case 2 /* MAP */: {
|
|
2145
|
+
return LiveMap._deserialize([id, crdt], parentToChildren, pool);
|
|
2146
|
+
}
|
|
2147
|
+
case 3 /* REGISTER */: {
|
|
2148
|
+
return crdt.data;
|
|
2149
|
+
}
|
|
2150
|
+
default: {
|
|
2151
|
+
throw new Error("Unexpected CRDT type");
|
|
2152
|
+
}
|
|
2153
|
+
}
|
|
2154
|
+
}
|
|
2155
|
+
function isLiveStructure(value) {
|
|
2156
|
+
return isLiveList(value) || isLiveMap(value) || isLiveObject(value);
|
|
2157
|
+
}
|
|
2158
|
+
function isLiveNode(value) {
|
|
2159
|
+
return isLiveStructure(value) || isLiveRegister(value);
|
|
2160
|
+
}
|
|
2161
|
+
function isLiveList(value) {
|
|
2162
|
+
return value instanceof LiveList;
|
|
2163
|
+
}
|
|
2164
|
+
function isLiveMap(value) {
|
|
2165
|
+
return value instanceof LiveMap;
|
|
2166
|
+
}
|
|
2167
|
+
function isLiveObject(value) {
|
|
2168
|
+
return value instanceof LiveObject;
|
|
2169
|
+
}
|
|
2170
|
+
function isLiveRegister(value) {
|
|
2171
|
+
return value instanceof LiveRegister;
|
|
2172
|
+
}
|
|
2173
|
+
function liveNodeToLson(obj) {
|
|
2174
|
+
if (obj instanceof LiveRegister) {
|
|
2175
|
+
return obj.data;
|
|
2176
|
+
} else if (obj instanceof LiveList || obj instanceof LiveMap || obj instanceof LiveObject) {
|
|
2177
|
+
return obj;
|
|
2178
|
+
} else {
|
|
2179
|
+
return assertNever(obj, "Unknown AbstractCrdt");
|
|
2180
|
+
}
|
|
2181
|
+
}
|
|
2182
|
+
function lsonToLiveNode(value) {
|
|
2183
|
+
if (value instanceof LiveObject || value instanceof LiveMap || value instanceof LiveList) {
|
|
2184
|
+
return value;
|
|
2185
|
+
} else {
|
|
2186
|
+
return new LiveRegister(value);
|
|
2187
|
+
}
|
|
2188
|
+
}
|
|
2189
|
+
function getTreesDiffOperations(currentItems, newItems) {
|
|
2190
|
+
const ops = [];
|
|
2191
|
+
currentItems.forEach((_, id) => {
|
|
2192
|
+
if (!newItems.get(id)) {
|
|
2193
|
+
ops.push({
|
|
2194
|
+
type: 5 /* DELETE_CRDT */,
|
|
2195
|
+
id
|
|
2196
|
+
});
|
|
2197
|
+
}
|
|
2198
|
+
});
|
|
2199
|
+
newItems.forEach((crdt, id) => {
|
|
2200
|
+
const currentCrdt = currentItems.get(id);
|
|
2201
|
+
if (currentCrdt) {
|
|
2202
|
+
if (crdt.type === 0 /* OBJECT */) {
|
|
2203
|
+
if (currentCrdt.type !== 0 /* OBJECT */ || JSON.stringify(crdt.data) !== JSON.stringify(currentCrdt.data)) {
|
|
2204
|
+
ops.push({
|
|
2205
|
+
type: 3 /* UPDATE_OBJECT */,
|
|
2206
|
+
id,
|
|
2207
|
+
data: crdt.data
|
|
2208
|
+
});
|
|
2209
|
+
}
|
|
2324
2210
|
}
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
} else {
|
|
2332
|
-
reverseUpdateOp.data[key] = oldValue;
|
|
2211
|
+
if (crdt.parentKey !== currentCrdt.parentKey) {
|
|
2212
|
+
ops.push({
|
|
2213
|
+
type: 1 /* SET_PARENT_KEY */,
|
|
2214
|
+
id,
|
|
2215
|
+
parentKey: nn(crdt.parentKey, "Parent key must not be missing")
|
|
2216
|
+
});
|
|
2333
2217
|
}
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2218
|
+
} else {
|
|
2219
|
+
switch (crdt.type) {
|
|
2220
|
+
case 3 /* REGISTER */:
|
|
2221
|
+
ops.push({
|
|
2222
|
+
type: 8 /* CREATE_REGISTER */,
|
|
2223
|
+
id,
|
|
2224
|
+
parentId: crdt.parentId,
|
|
2225
|
+
parentKey: crdt.parentKey,
|
|
2226
|
+
data: crdt.data
|
|
2227
|
+
});
|
|
2228
|
+
break;
|
|
2229
|
+
case 1 /* LIST */:
|
|
2230
|
+
ops.push({
|
|
2231
|
+
type: 2 /* CREATE_LIST */,
|
|
2232
|
+
id,
|
|
2233
|
+
parentId: crdt.parentId,
|
|
2234
|
+
parentKey: crdt.parentKey
|
|
2235
|
+
});
|
|
2236
|
+
break;
|
|
2237
|
+
case 0 /* OBJECT */:
|
|
2238
|
+
ops.push(
|
|
2239
|
+
crdt.parentId ? {
|
|
2240
|
+
type: 4 /* CREATE_OBJECT */,
|
|
2241
|
+
id,
|
|
2242
|
+
parentId: crdt.parentId,
|
|
2243
|
+
parentKey: crdt.parentKey,
|
|
2244
|
+
data: crdt.data
|
|
2245
|
+
} : { type: 4 /* CREATE_OBJECT */, id, data: crdt.data }
|
|
2246
|
+
);
|
|
2247
|
+
break;
|
|
2248
|
+
case 2 /* MAP */:
|
|
2249
|
+
ops.push({
|
|
2250
|
+
type: 7 /* CREATE_MAP */,
|
|
2251
|
+
id,
|
|
2252
|
+
parentId: crdt.parentId,
|
|
2253
|
+
parentKey: crdt.parentKey
|
|
2254
|
+
});
|
|
2255
|
+
break;
|
|
2348
2256
|
}
|
|
2349
|
-
this._map.set(key, newValue);
|
|
2350
|
-
this.invalidate();
|
|
2351
|
-
updateDelta[key] = { type: "update" };
|
|
2352
|
-
}
|
|
2353
|
-
if (Object.keys(reverseUpdateOp.data).length !== 0) {
|
|
2354
|
-
reverseOps.unshift(reverseUpdateOp);
|
|
2355
|
-
}
|
|
2356
|
-
if (Object.keys(updatedProps).length !== 0) {
|
|
2357
|
-
ops.unshift({
|
|
2358
|
-
opId,
|
|
2359
|
-
id: this._id,
|
|
2360
|
-
type: 3 /* UPDATE_OBJECT */,
|
|
2361
|
-
data: updatedProps
|
|
2362
|
-
});
|
|
2363
2257
|
}
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2258
|
+
});
|
|
2259
|
+
return ops;
|
|
2260
|
+
}
|
|
2261
|
+
function mergeObjectStorageUpdates(first, second) {
|
|
2262
|
+
const updates = first.updates;
|
|
2263
|
+
for (const [key, value] of entries(second.updates)) {
|
|
2264
|
+
updates[key] = value;
|
|
2371
2265
|
}
|
|
2372
|
-
|
|
2373
|
-
|
|
2266
|
+
return __spreadProps(__spreadValues({}, second), {
|
|
2267
|
+
updates
|
|
2268
|
+
});
|
|
2269
|
+
}
|
|
2270
|
+
function mergeMapStorageUpdates(first, second) {
|
|
2271
|
+
const updates = first.updates;
|
|
2272
|
+
for (const [key, value] of entries(second.updates)) {
|
|
2273
|
+
updates[key] = value;
|
|
2374
2274
|
}
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2275
|
+
return __spreadProps(__spreadValues({}, second), {
|
|
2276
|
+
updates
|
|
2277
|
+
});
|
|
2278
|
+
}
|
|
2279
|
+
function mergeListStorageUpdates(first, second) {
|
|
2280
|
+
const updates = first.updates;
|
|
2281
|
+
return __spreadProps(__spreadValues({}, second), {
|
|
2282
|
+
updates: updates.concat(second.updates)
|
|
2283
|
+
});
|
|
2284
|
+
}
|
|
2285
|
+
function mergeStorageUpdates(first, second) {
|
|
2286
|
+
if (!first) {
|
|
2287
|
+
return second;
|
|
2288
|
+
}
|
|
2289
|
+
if (first.type === "LiveObject" && second.type === "LiveObject") {
|
|
2290
|
+
return mergeObjectStorageUpdates(first, second);
|
|
2291
|
+
} else if (first.type === "LiveMap" && second.type === "LiveMap") {
|
|
2292
|
+
return mergeMapStorageUpdates(first, second);
|
|
2293
|
+
} else if (first.type === "LiveList" && second.type === "LiveList") {
|
|
2294
|
+
return mergeListStorageUpdates(first, second);
|
|
2295
|
+
} else {
|
|
2296
|
+
}
|
|
2297
|
+
return second;
|
|
2298
|
+
}
|
|
2299
|
+
function isPlain(value) {
|
|
2300
|
+
const type = typeof value;
|
|
2301
|
+
return value === void 0 || value === null || type === "string" || type === "boolean" || type === "number" || Array.isArray(value) || isPlainObject(value);
|
|
2302
|
+
}
|
|
2303
|
+
function findNonSerializableValue(value, path = "") {
|
|
2304
|
+
if (!isPlain) {
|
|
2305
|
+
return {
|
|
2306
|
+
path: path || "root",
|
|
2307
|
+
value
|
|
2308
|
+
};
|
|
2309
|
+
}
|
|
2310
|
+
if (typeof value !== "object" || value === null) {
|
|
2311
|
+
return false;
|
|
2312
|
+
}
|
|
2313
|
+
for (const [key, nestedValue] of Object.entries(value)) {
|
|
2314
|
+
const nestedPath = path ? path + "." + key : key;
|
|
2315
|
+
if (!isPlain(nestedValue)) {
|
|
2316
|
+
return {
|
|
2317
|
+
path: nestedPath,
|
|
2318
|
+
value: nestedValue
|
|
2319
|
+
};
|
|
2320
|
+
}
|
|
2321
|
+
if (typeof nestedValue === "object") {
|
|
2322
|
+
const nonSerializableNestedValue = findNonSerializableValue(
|
|
2323
|
+
nestedValue,
|
|
2324
|
+
nestedPath
|
|
2325
|
+
);
|
|
2326
|
+
if (nonSerializableNestedValue) {
|
|
2327
|
+
return nonSerializableNestedValue;
|
|
2328
|
+
}
|
|
2379
2329
|
}
|
|
2380
|
-
return process.env.NODE_ENV === "production" ? result : Object.freeze(result);
|
|
2381
2330
|
}
|
|
2382
|
-
|
|
2331
|
+
return false;
|
|
2332
|
+
}
|
|
2383
2333
|
|
|
2384
2334
|
// src/lib/EventSource.ts
|
|
2385
2335
|
function makeEventSource() {
|
|
@@ -2425,6 +2375,58 @@ function isJsonObject(data) {
|
|
|
2425
2375
|
return !isJsonScalar(data) && !isJsonArray(data);
|
|
2426
2376
|
}
|
|
2427
2377
|
|
|
2378
|
+
// src/protocol/AuthToken.ts
|
|
2379
|
+
function hasJwtMeta(data) {
|
|
2380
|
+
if (!isPlainObject(data)) {
|
|
2381
|
+
return false;
|
|
2382
|
+
}
|
|
2383
|
+
const { iat, exp } = data;
|
|
2384
|
+
return typeof iat === "number" && typeof exp === "number";
|
|
2385
|
+
}
|
|
2386
|
+
function isTokenExpired(token) {
|
|
2387
|
+
const now = Date.now() / 1e3;
|
|
2388
|
+
return now > token.exp - 300 || now < token.iat + 300;
|
|
2389
|
+
}
|
|
2390
|
+
function isStringList(value) {
|
|
2391
|
+
return Array.isArray(value) && value.every((i) => typeof i === "string");
|
|
2392
|
+
}
|
|
2393
|
+
function isAppOnlyAuthToken(data) {
|
|
2394
|
+
return typeof data.appId === "string" && data.roomId === void 0 && isStringList(data.scopes);
|
|
2395
|
+
}
|
|
2396
|
+
function isRoomAuthToken(data) {
|
|
2397
|
+
return typeof data.appId === "string" && typeof data.roomId === "string" && typeof data.actor === "number" && (data.id === void 0 || typeof data.id === "string") && isStringList(data.scopes) && (data.maxConnectionsPerRoom === void 0 || typeof data.maxConnectionsPerRoom === "number");
|
|
2398
|
+
}
|
|
2399
|
+
function isAuthToken(data) {
|
|
2400
|
+
return isAppOnlyAuthToken(data) || isRoomAuthToken(data);
|
|
2401
|
+
}
|
|
2402
|
+
function parseJwtToken(token) {
|
|
2403
|
+
const tokenParts = token.split(".");
|
|
2404
|
+
if (tokenParts.length !== 3) {
|
|
2405
|
+
throw new Error("Authentication error: invalid JWT token");
|
|
2406
|
+
}
|
|
2407
|
+
const data = tryParseJson(b64decode(tokenParts[1]));
|
|
2408
|
+
if (data && hasJwtMeta(data)) {
|
|
2409
|
+
return data;
|
|
2410
|
+
} else {
|
|
2411
|
+
throw new Error("Authentication error: missing JWT metadata");
|
|
2412
|
+
}
|
|
2413
|
+
}
|
|
2414
|
+
function parseRoomAuthToken(tokenString) {
|
|
2415
|
+
const data = parseJwtToken(tokenString);
|
|
2416
|
+
if (data && isRoomAuthToken(data)) {
|
|
2417
|
+
const _a = data, {
|
|
2418
|
+
maxConnections: _legacyField
|
|
2419
|
+
} = _a, token = __objRest(_a, [
|
|
2420
|
+
"maxConnections"
|
|
2421
|
+
]);
|
|
2422
|
+
return token;
|
|
2423
|
+
} else {
|
|
2424
|
+
throw new Error(
|
|
2425
|
+
"Authentication error: we expected a room token but did not get one. Hint: if you are using a callback, ensure the room is passed when creating the token. For more information: https://liveblocks.io/docs/api-reference/liveblocks-client#createClientCallback"
|
|
2426
|
+
);
|
|
2427
|
+
}
|
|
2428
|
+
}
|
|
2429
|
+
|
|
2428
2430
|
// src/protocol/ClientMsg.ts
|
|
2429
2431
|
var ClientMsgCode = /* @__PURE__ */ ((ClientMsgCode2) => {
|
|
2430
2432
|
ClientMsgCode2[ClientMsgCode2["UPDATE_PRESENCE"] = 100] = "UPDATE_PRESENCE";
|
|
@@ -2605,7 +2607,7 @@ var OthersRef = class extends ImmutableRef {
|
|
|
2605
2607
|
var ValueRef = class extends ImmutableRef {
|
|
2606
2608
|
constructor(initialValue) {
|
|
2607
2609
|
super();
|
|
2608
|
-
this._value = freeze(
|
|
2610
|
+
this._value = freeze(initialValue);
|
|
2609
2611
|
}
|
|
2610
2612
|
_toImmutable() {
|
|
2611
2613
|
return this._value;
|
|
@@ -2616,8 +2618,10 @@ var ValueRef = class extends ImmutableRef {
|
|
|
2616
2618
|
}
|
|
2617
2619
|
};
|
|
2618
2620
|
var DerivedRef = class extends ImmutableRef {
|
|
2619
|
-
constructor(
|
|
2621
|
+
constructor(...args) {
|
|
2620
2622
|
super();
|
|
2623
|
+
const transformFn = args.pop();
|
|
2624
|
+
const otherRefs = args;
|
|
2621
2625
|
this._refs = otherRefs;
|
|
2622
2626
|
this._refs.forEach((ref) => {
|
|
2623
2627
|
ref.didInvalidate.subscribe(() => this.invalidate());
|
|
@@ -2625,7 +2629,9 @@ var DerivedRef = class extends ImmutableRef {
|
|
|
2625
2629
|
this._transform = transformFn;
|
|
2626
2630
|
}
|
|
2627
2631
|
_toImmutable() {
|
|
2628
|
-
return this._transform(
|
|
2632
|
+
return this._transform(
|
|
2633
|
+
...this._refs.map((ref) => ref.current)
|
|
2634
|
+
);
|
|
2629
2635
|
}
|
|
2630
2636
|
};
|
|
2631
2637
|
|
|
@@ -2756,7 +2762,8 @@ function makeStateMachine(state, config, mockedEffects) {
|
|
|
2756
2762
|
}
|
|
2757
2763
|
};
|
|
2758
2764
|
const self = new DerivedRef(
|
|
2759
|
-
|
|
2765
|
+
state.connection,
|
|
2766
|
+
state.me,
|
|
2760
2767
|
(conn, me) => isConnectionSelfAware(conn) ? {
|
|
2761
2768
|
connectionId: conn.id,
|
|
2762
2769
|
id: conn.userId,
|
|
@@ -3269,7 +3276,9 @@ function makeStateMachine(state, config, mockedEffects) {
|
|
|
3269
3276
|
const offlineOps = new Map(state.offlineOperations);
|
|
3270
3277
|
createOrUpdateRootFromMessage(message, doNotBatchUpdates);
|
|
3271
3278
|
applyAndSendOfflineOps(offlineOps, doNotBatchUpdates);
|
|
3272
|
-
_getInitialStateResolver
|
|
3279
|
+
if (_getInitialStateResolver !== null) {
|
|
3280
|
+
_getInitialStateResolver();
|
|
3281
|
+
}
|
|
3273
3282
|
eventHub.storageDidLoad.notify();
|
|
3274
3283
|
break;
|
|
3275
3284
|
}
|
|
@@ -3797,7 +3806,7 @@ function prepareCreateWebSocket(liveblocksServer, WebSocketPolyfill) {
|
|
|
3797
3806
|
const ws = WebSocketPolyfill || WebSocket;
|
|
3798
3807
|
return (token) => {
|
|
3799
3808
|
return new ws(
|
|
3800
|
-
`${liveblocksServer}/?token=${token}&version=${true ? "0.19.
|
|
3809
|
+
`${liveblocksServer}/?token=${token}&version=${true ? "0.19.1-test1" : "dev"}`
|
|
3801
3810
|
);
|
|
3802
3811
|
};
|
|
3803
3812
|
}
|
|
@@ -3808,10 +3817,14 @@ function prepareAuthEndpoint(authentication, fetchPolyfill) {
|
|
|
3808
3817
|
"To use Liveblocks client in a non-dom environment with a publicApiKey, you need to provide a fetch polyfill."
|
|
3809
3818
|
);
|
|
3810
3819
|
}
|
|
3811
|
-
return (room) => fetchAuthEndpoint(
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
|
|
3820
|
+
return (room) => fetchAuthEndpoint(
|
|
3821
|
+
fetchPolyfill || fetch,
|
|
3822
|
+
authentication.url,
|
|
3823
|
+
{
|
|
3824
|
+
room,
|
|
3825
|
+
publicApiKey: authentication.publicApiKey
|
|
3826
|
+
}
|
|
3827
|
+
);
|
|
3815
3828
|
}
|
|
3816
3829
|
if (authentication.type === "private") {
|
|
3817
3830
|
if (typeof window === "undefined" && fetchPolyfill === void 0) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@liveblocks/core",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.1-test1",
|
|
4
4
|
"description": "Shared code and foundational internals for Liveblocks",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -19,13 +19,16 @@
|
|
|
19
19
|
"url": "https://github.com/liveblocks/liveblocks/issues"
|
|
20
20
|
},
|
|
21
21
|
"scripts": {
|
|
22
|
-
"dev": "tsup --watch
|
|
23
|
-
"build": "tsup
|
|
22
|
+
"dev": "tsup --watch",
|
|
23
|
+
"build": "tsup",
|
|
24
24
|
"format": "eslint --fix src/ && prettier --write src/",
|
|
25
25
|
"lint": "eslint src/",
|
|
26
|
-
"test": "jest --silent --verbose",
|
|
27
|
-
"test:watch": "jest --silent --verbose --watch",
|
|
28
|
-
"test
|
|
26
|
+
"test": "jest --silent --verbose --color=always",
|
|
27
|
+
"test:watch": "jest --silent --verbose --color=always --watch",
|
|
28
|
+
"test:e2e": "jest --silent --verbose --color=always --config=./jest.config.e2e.js",
|
|
29
|
+
"test:deps": "depcruise src --exclude __tests__ --config",
|
|
30
|
+
"showdeps": "depcruise src --include-only '^src' --exclude='__tests__' --config --output-type dot | dot -T svg > /tmp/dependency-graph.svg && open /tmp/dependency-graph.svg",
|
|
31
|
+
"showdeps:high-level": "depcruise src --include-only '^src' --exclude='(^src/index.ts|shallow.ts|__tests__)' --collapse='^src/(refs|lib|compat|types|crdts|protocol)' --config --output-type dot | dot -T svg > /tmp/dependency-graph.svg && open /tmp/dependency-graph.svg"
|
|
29
32
|
},
|
|
30
33
|
"license": "Apache-2.0",
|
|
31
34
|
"devDependencies": {
|
package/dist/index.mjs
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import mod from "./index.js";
|
|
2
|
-
|
|
3
|
-
export default mod;
|
|
4
|
-
export const ClientMsgCode = mod.ClientMsgCode;
|
|
5
|
-
export const CrdtType = mod.CrdtType;
|
|
6
|
-
export const LiveList = mod.LiveList;
|
|
7
|
-
export const LiveMap = mod.LiveMap;
|
|
8
|
-
export const LiveObject = mod.LiveObject;
|
|
9
|
-
export const OpCode = mod.OpCode;
|
|
10
|
-
export const ServerMsgCode = mod.ServerMsgCode;
|
|
11
|
-
export const WebsocketCloseCodes = mod.WebsocketCloseCodes;
|
|
12
|
-
export const asArrayWithLegacyMethods = mod.asArrayWithLegacyMethods;
|
|
13
|
-
export const assertNever = mod.assertNever;
|
|
14
|
-
export const b64decode = mod.b64decode;
|
|
15
|
-
export const comparePosition = mod.comparePosition;
|
|
16
|
-
export const createClient = mod.createClient;
|
|
17
|
-
export const deprecate = mod.deprecate;
|
|
18
|
-
export const deprecateIf = mod.deprecateIf;
|
|
19
|
-
export const errorIf = mod.errorIf;
|
|
20
|
-
export const freeze = mod.freeze;
|
|
21
|
-
export const isAppOnlyAuthToken = mod.isAppOnlyAuthToken;
|
|
22
|
-
export const isAuthToken = mod.isAuthToken;
|
|
23
|
-
export const isChildCrdt = mod.isChildCrdt;
|
|
24
|
-
export const isJsonArray = mod.isJsonArray;
|
|
25
|
-
export const isJsonObject = mod.isJsonObject;
|
|
26
|
-
export const isJsonScalar = mod.isJsonScalar;
|
|
27
|
-
export const isPlainObject = mod.isPlainObject;
|
|
28
|
-
export const isRoomAuthToken = mod.isRoomAuthToken;
|
|
29
|
-
export const isRootCrdt = mod.isRootCrdt;
|
|
30
|
-
export const legacy_patchImmutableObject = mod.legacy_patchImmutableObject;
|
|
31
|
-
export const lsonToJson = mod.lsonToJson;
|
|
32
|
-
export const makePosition = mod.makePosition;
|
|
33
|
-
export const nn = mod.nn;
|
|
34
|
-
export const patchLiveObjectKey = mod.patchLiveObjectKey;
|
|
35
|
-
export const shallow = mod.shallow;
|
|
36
|
-
export const throwUsageError = mod.throwUsageError;
|
|
37
|
-
export const tryParseJson = mod.tryParseJson;
|