@liveblocks/core 0.18.3-test2 → 0.18.4
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 +14 -0
- package/dist/index.js +55 -10
- package/package.json +19 -7
package/dist/index.d.ts
CHANGED
|
@@ -367,6 +367,10 @@ declare type BaseUserMeta = {
|
|
|
367
367
|
* Additional user information that has been set in the authentication endpoint.
|
|
368
368
|
*/
|
|
369
369
|
info?: Json;
|
|
370
|
+
/**
|
|
371
|
+
* Permissions that the user has in the room.
|
|
372
|
+
*/
|
|
373
|
+
scopes: string[];
|
|
370
374
|
};
|
|
371
375
|
|
|
372
376
|
declare enum OpCode {
|
|
@@ -639,6 +643,10 @@ declare type UserJoinServerMsg<TUserMeta extends BaseUserMeta> = {
|
|
|
639
643
|
* endpoint.
|
|
640
644
|
*/
|
|
641
645
|
info: TUserMeta["info"];
|
|
646
|
+
/**
|
|
647
|
+
* Permissions that the user has in the Room.
|
|
648
|
+
*/
|
|
649
|
+
scopes: string[];
|
|
642
650
|
};
|
|
643
651
|
/**
|
|
644
652
|
* Sent by the WebSocket server and broadcasted to all clients to announce that
|
|
@@ -858,6 +866,10 @@ declare type User<TPresence extends JsonObject, TUserMeta extends BaseUserMeta>
|
|
|
858
866
|
* The user presence.
|
|
859
867
|
*/
|
|
860
868
|
readonly presence: TPresence;
|
|
869
|
+
/**
|
|
870
|
+
* False if the user can modify the room storage, true otherwise.
|
|
871
|
+
*/
|
|
872
|
+
readonly isReadOnly: boolean;
|
|
861
873
|
};
|
|
862
874
|
declare type AuthEndpointCallback = (room: string) => Promise<{
|
|
863
875
|
token: string;
|
|
@@ -899,11 +911,13 @@ declare type Connection = {
|
|
|
899
911
|
id: number;
|
|
900
912
|
userId?: string;
|
|
901
913
|
userInfo?: Json;
|
|
914
|
+
isReadOnly: boolean;
|
|
902
915
|
} | {
|
|
903
916
|
state: "open";
|
|
904
917
|
id: number;
|
|
905
918
|
userId?: string;
|
|
906
919
|
userInfo?: Json;
|
|
920
|
+
isReadOnly: boolean;
|
|
907
921
|
} | {
|
|
908
922
|
state: "unavailable";
|
|
909
923
|
} | {
|
package/dist/index.js
CHANGED
|
@@ -997,9 +997,13 @@ var LiveList = class extends AbstractCrdt {
|
|
|
997
997
|
return this._items.length;
|
|
998
998
|
}
|
|
999
999
|
push(element) {
|
|
1000
|
+
var _a;
|
|
1001
|
+
(_a = this._pool) == null ? void 0 : _a.assertStorageIsWritable();
|
|
1000
1002
|
return this.insert(element, this.length);
|
|
1001
1003
|
}
|
|
1002
1004
|
insert(element, index) {
|
|
1005
|
+
var _a;
|
|
1006
|
+
(_a = this._pool) == null ? void 0 : _a.assertStorageIsWritable();
|
|
1003
1007
|
if (index < 0 || index > this._items.length) {
|
|
1004
1008
|
throw new Error(
|
|
1005
1009
|
`Cannot insert list item at index "${index}". index should be between 0 and ${this._items.length}`
|
|
@@ -1024,6 +1028,8 @@ var LiveList = class extends AbstractCrdt {
|
|
|
1024
1028
|
}
|
|
1025
1029
|
}
|
|
1026
1030
|
move(index, targetIndex) {
|
|
1031
|
+
var _a;
|
|
1032
|
+
(_a = this._pool) == null ? void 0 : _a.assertStorageIsWritable();
|
|
1027
1033
|
if (targetIndex < 0) {
|
|
1028
1034
|
throw new Error("targetIndex cannot be less than 0");
|
|
1029
1035
|
}
|
|
@@ -1077,6 +1083,8 @@ var LiveList = class extends AbstractCrdt {
|
|
|
1077
1083
|
}
|
|
1078
1084
|
}
|
|
1079
1085
|
delete(index) {
|
|
1086
|
+
var _a;
|
|
1087
|
+
(_a = this._pool) == null ? void 0 : _a.assertStorageIsWritable();
|
|
1080
1088
|
if (index < 0 || index >= this._items.length) {
|
|
1081
1089
|
throw new Error(
|
|
1082
1090
|
`Cannot delete list item at index "${index}". index should be between 0 and ${this._items.length - 1}`
|
|
@@ -1109,6 +1117,8 @@ var LiveList = class extends AbstractCrdt {
|
|
|
1109
1117
|
}
|
|
1110
1118
|
}
|
|
1111
1119
|
clear() {
|
|
1120
|
+
var _a;
|
|
1121
|
+
(_a = this._pool) == null ? void 0 : _a.assertStorageIsWritable();
|
|
1112
1122
|
if (this._pool) {
|
|
1113
1123
|
const ops = [];
|
|
1114
1124
|
const reverseOps = [];
|
|
@@ -1142,6 +1152,8 @@ var LiveList = class extends AbstractCrdt {
|
|
|
1142
1152
|
}
|
|
1143
1153
|
}
|
|
1144
1154
|
set(index, item) {
|
|
1155
|
+
var _a;
|
|
1156
|
+
(_a = this._pool) == null ? void 0 : _a.assertStorageIsWritable();
|
|
1145
1157
|
if (index < 0 || index >= this._items.length) {
|
|
1146
1158
|
throw new Error(
|
|
1147
1159
|
`Cannot set list item at index "${index}". index should be between 0 and ${this._items.length - 1}`
|
|
@@ -1446,6 +1458,8 @@ var LiveMap = class extends AbstractCrdt {
|
|
|
1446
1458
|
return liveNodeToLson(value);
|
|
1447
1459
|
}
|
|
1448
1460
|
set(key, value) {
|
|
1461
|
+
var _a;
|
|
1462
|
+
(_a = this._pool) == null ? void 0 : _a.assertStorageIsWritable();
|
|
1449
1463
|
const oldValue = this._map.get(key);
|
|
1450
1464
|
if (oldValue) {
|
|
1451
1465
|
oldValue._detach();
|
|
@@ -1479,6 +1493,8 @@ var LiveMap = class extends AbstractCrdt {
|
|
|
1479
1493
|
return this._map.has(key);
|
|
1480
1494
|
}
|
|
1481
1495
|
delete(key) {
|
|
1496
|
+
var _a;
|
|
1497
|
+
(_a = this._pool) == null ? void 0 : _a.assertStorageIsWritable();
|
|
1482
1498
|
const item = this._map.get(key);
|
|
1483
1499
|
if (item === void 0) {
|
|
1484
1500
|
return false;
|
|
@@ -1849,12 +1865,16 @@ var LiveObject = class extends AbstractCrdt {
|
|
|
1849
1865
|
return fromEntries(this._map);
|
|
1850
1866
|
}
|
|
1851
1867
|
set(key, value) {
|
|
1868
|
+
var _a;
|
|
1869
|
+
(_a = this._pool) == null ? void 0 : _a.assertStorageIsWritable();
|
|
1852
1870
|
this.update({ [key]: value });
|
|
1853
1871
|
}
|
|
1854
1872
|
get(key) {
|
|
1855
1873
|
return this._map.get(key);
|
|
1856
1874
|
}
|
|
1857
1875
|
delete(key) {
|
|
1876
|
+
var _a;
|
|
1877
|
+
(_a = this._pool) == null ? void 0 : _a.assertStorageIsWritable();
|
|
1858
1878
|
const keyAsString = key;
|
|
1859
1879
|
const oldValue = this._map.get(keyAsString);
|
|
1860
1880
|
if (oldValue === void 0) {
|
|
@@ -1903,6 +1923,8 @@ var LiveObject = class extends AbstractCrdt {
|
|
|
1903
1923
|
);
|
|
1904
1924
|
}
|
|
1905
1925
|
update(patch) {
|
|
1926
|
+
var _a;
|
|
1927
|
+
(_a = this._pool) == null ? void 0 : _a.assertStorageIsWritable();
|
|
1906
1928
|
if (this._pool === void 0 || this._id === void 0) {
|
|
1907
1929
|
for (const key in patch) {
|
|
1908
1930
|
const newValue = patch[key];
|
|
@@ -2545,11 +2567,12 @@ var OthersRef = class extends ImmutableRef {
|
|
|
2545
2567
|
}
|
|
2546
2568
|
this.invalidate();
|
|
2547
2569
|
}
|
|
2548
|
-
setConnection(connectionId, metaUserId, metaUserInfo) {
|
|
2570
|
+
setConnection(connectionId, metaUserId, metaUserInfo, metaIsReadonly) {
|
|
2549
2571
|
this._connections[connectionId] = freeze({
|
|
2550
2572
|
connectionId,
|
|
2551
2573
|
id: metaUserId,
|
|
2552
|
-
info: metaUserInfo
|
|
2574
|
+
info: metaUserInfo,
|
|
2575
|
+
isReadOnly: metaIsReadonly
|
|
2553
2576
|
});
|
|
2554
2577
|
if (this._presences[connectionId] !== void 0) {
|
|
2555
2578
|
this._invalidateUser(connectionId);
|
|
@@ -2666,6 +2689,13 @@ function makeStateMachine(state, config, mockedEffects) {
|
|
|
2666
2689
|
notify({ storageUpdates }, doNotBatchUpdates);
|
|
2667
2690
|
});
|
|
2668
2691
|
}
|
|
2692
|
+
},
|
|
2693
|
+
assertStorageIsWritable: () => {
|
|
2694
|
+
if (isConnectionSelfAware(state.connection.current) && state.connection.current.isReadOnly) {
|
|
2695
|
+
throw new Error(
|
|
2696
|
+
"Cannot write to storage with a read only user, please ensure the user has write permissions"
|
|
2697
|
+
);
|
|
2698
|
+
}
|
|
2669
2699
|
}
|
|
2670
2700
|
};
|
|
2671
2701
|
const eventHub = {
|
|
@@ -2727,7 +2757,8 @@ function makeStateMachine(state, config, mockedEffects) {
|
|
|
2727
2757
|
connectionId: conn.id,
|
|
2728
2758
|
id: conn.userId,
|
|
2729
2759
|
info: conn.userInfo,
|
|
2730
|
-
presence: me
|
|
2760
|
+
presence: me,
|
|
2761
|
+
isReadOnly: conn.isReadOnly
|
|
2731
2762
|
} : null
|
|
2732
2763
|
);
|
|
2733
2764
|
function createOrUpdateRootFromMessage(message, batchedUpdatesWrapper) {
|
|
@@ -3060,6 +3091,9 @@ function makeStateMachine(state, config, mockedEffects) {
|
|
|
3060
3091
|
});
|
|
3061
3092
|
}
|
|
3062
3093
|
}
|
|
3094
|
+
function isReadOnly(scopes) {
|
|
3095
|
+
return scopes.includes("room:read" /* Read */) && scopes.includes("room:presence:write" /* PresenceWrite */) && !scopes.includes("room:write" /* Write */);
|
|
3096
|
+
}
|
|
3063
3097
|
function authenticationSuccess(token, socket) {
|
|
3064
3098
|
socket.addEventListener("message", onMessage);
|
|
3065
3099
|
socket.addEventListener("open", onOpen);
|
|
@@ -3070,7 +3104,8 @@ function makeStateMachine(state, config, mockedEffects) {
|
|
|
3070
3104
|
state: "connecting",
|
|
3071
3105
|
id: token.actor,
|
|
3072
3106
|
userInfo: token.info,
|
|
3073
|
-
userId: token.id
|
|
3107
|
+
userId: token.id,
|
|
3108
|
+
isReadOnly: isReadOnly(token.scopes)
|
|
3074
3109
|
},
|
|
3075
3110
|
batchUpdates
|
|
3076
3111
|
);
|
|
@@ -3126,7 +3161,12 @@ function makeStateMachine(state, config, mockedEffects) {
|
|
|
3126
3161
|
for (const key in message.users) {
|
|
3127
3162
|
const user = message.users[key];
|
|
3128
3163
|
const connectionId = Number(key);
|
|
3129
|
-
state.others.setConnection(
|
|
3164
|
+
state.others.setConnection(
|
|
3165
|
+
connectionId,
|
|
3166
|
+
user.id,
|
|
3167
|
+
user.info,
|
|
3168
|
+
isReadOnly(user.scopes)
|
|
3169
|
+
);
|
|
3130
3170
|
}
|
|
3131
3171
|
return { type: "reset" };
|
|
3132
3172
|
}
|
|
@@ -3142,7 +3182,12 @@ function makeStateMachine(state, config, mockedEffects) {
|
|
|
3142
3182
|
});
|
|
3143
3183
|
}
|
|
3144
3184
|
function onUserJoinedMessage(message) {
|
|
3145
|
-
state.others.setConnection(
|
|
3185
|
+
state.others.setConnection(
|
|
3186
|
+
message.actor,
|
|
3187
|
+
message.id,
|
|
3188
|
+
message.info,
|
|
3189
|
+
isReadOnly(message.scopes)
|
|
3190
|
+
);
|
|
3146
3191
|
state.buffer.messages.push({
|
|
3147
3192
|
type: 100 /* UPDATE_PRESENCE */,
|
|
3148
3193
|
data: state.me.current,
|
|
@@ -3556,7 +3601,7 @@ function makeStateMachine(state, config, mockedEffects) {
|
|
|
3556
3601
|
if (state.activeBatch) {
|
|
3557
3602
|
return callback();
|
|
3558
3603
|
}
|
|
3559
|
-
let
|
|
3604
|
+
let returnValue = void 0;
|
|
3560
3605
|
batchUpdates(() => {
|
|
3561
3606
|
state.activeBatch = {
|
|
3562
3607
|
ops: [],
|
|
@@ -3568,7 +3613,7 @@ function makeStateMachine(state, config, mockedEffects) {
|
|
|
3568
3613
|
reverseOps: []
|
|
3569
3614
|
};
|
|
3570
3615
|
try {
|
|
3571
|
-
|
|
3616
|
+
returnValue = callback();
|
|
3572
3617
|
} finally {
|
|
3573
3618
|
const currentBatch = state.activeBatch;
|
|
3574
3619
|
state.activeBatch = null;
|
|
@@ -3585,7 +3630,7 @@ function makeStateMachine(state, config, mockedEffects) {
|
|
|
3585
3630
|
tryFlushing();
|
|
3586
3631
|
}
|
|
3587
3632
|
});
|
|
3588
|
-
return
|
|
3633
|
+
return returnValue;
|
|
3589
3634
|
}
|
|
3590
3635
|
function pauseHistory() {
|
|
3591
3636
|
state.pausedHistory = [];
|
|
@@ -3748,7 +3793,7 @@ function prepareCreateWebSocket(liveblocksServer, WebSocketPolyfill) {
|
|
|
3748
3793
|
const ws = WebSocketPolyfill || WebSocket;
|
|
3749
3794
|
return (token) => {
|
|
3750
3795
|
return new ws(
|
|
3751
|
-
`${liveblocksServer}/?token=${token}&version=${true ? "0.18.
|
|
3796
|
+
`${liveblocksServer}/?token=${token}&version=${true ? "0.18.4" : "dev"}`
|
|
3752
3797
|
);
|
|
3753
3798
|
};
|
|
3754
3799
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@liveblocks/core",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.4",
|
|
4
4
|
"description": "Shared code and foundational internals for Liveblocks",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -19,23 +19,35 @@
|
|
|
19
19
|
"url": "https://github.com/liveblocks/liveblocks/issues"
|
|
20
20
|
},
|
|
21
21
|
"scripts": {
|
|
22
|
-
"dev": "tsup --watch --onSuccess ../../scripts/build.sh",
|
|
23
22
|
"build": "tsup && ../../scripts/build.sh",
|
|
24
23
|
"format": "eslint --fix src/ && prettier --write src/",
|
|
25
24
|
"lint": "eslint src/",
|
|
26
|
-
"test": "jest --silent --verbose",
|
|
27
|
-
"test
|
|
25
|
+
"test": "jest --watch --silent --verbose --config=./jest.config.js",
|
|
26
|
+
"test-ci": "jest --silent --verbose",
|
|
28
27
|
"test-e2e": "jest --silent --verbose --config=./jest.config.e2e.js"
|
|
29
28
|
},
|
|
30
29
|
"license": "Apache-2.0",
|
|
31
30
|
"devDependencies": {
|
|
32
|
-
"@
|
|
33
|
-
"@
|
|
31
|
+
"@types/jest": "^29.1.2",
|
|
32
|
+
"@types/node-fetch": "^2.6.1",
|
|
34
33
|
"@types/ws": "^8.5.3",
|
|
34
|
+
"@typescript-eslint/eslint-plugin": "^5.26.0",
|
|
35
|
+
"@typescript-eslint/parser": "^5.26.0",
|
|
35
36
|
"dotenv": "^16.0.3",
|
|
37
|
+
"eslint": "^8.12.0",
|
|
38
|
+
"eslint-plugin-import": "^2.26.0",
|
|
36
39
|
"eslint-plugin-rulesdir": "^0.2.1",
|
|
40
|
+
"eslint-plugin-simple-import-sort": "^7.0.0",
|
|
37
41
|
"fast-check": "^3.0.1",
|
|
38
|
-
"
|
|
42
|
+
"jest": "^29.1.2",
|
|
43
|
+
"jest-environment-jsdom": "^29.1.2",
|
|
44
|
+
"msw": "^0.39.1",
|
|
45
|
+
"node-fetch": "2.6.7",
|
|
46
|
+
"prettier": "^2.7.1",
|
|
47
|
+
"ts-jest": "^29.0.3",
|
|
48
|
+
"tsup": "^6.2.2",
|
|
49
|
+
"typescript": "^4.7.2",
|
|
50
|
+
"whatwg-fetch": "^3.6.2",
|
|
39
51
|
"ws": "^8.5.0"
|
|
40
52
|
},
|
|
41
53
|
"repository": {
|