@liveblocks/core 1.1.0-fsm4 → 1.1.0-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 +49 -28
- package/dist/index.js +172 -182
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -636,6 +636,44 @@ declare enum WebsocketCloseCodes {
|
|
|
636
636
|
CLOSE_WITHOUT_RETRY = 4999
|
|
637
637
|
}
|
|
638
638
|
|
|
639
|
+
/**
|
|
640
|
+
* Arbitrary record that will be used as the authentication "token". It's the
|
|
641
|
+
* value that is returned by calling the authentication delegate, and will get
|
|
642
|
+
* passed to the connection factory delegate. This value will be remembered by
|
|
643
|
+
* the connection manager, but its value will not be interpreted, so it can be
|
|
644
|
+
* any object value.
|
|
645
|
+
*/
|
|
646
|
+
declare type BaseAuthResult = Record<string, unknown>;
|
|
647
|
+
declare type Delegates<T extends BaseAuthResult> = {
|
|
648
|
+
authenticate: () => Promise<T>;
|
|
649
|
+
createSocket: (token: T) => IWebSocketInstance;
|
|
650
|
+
};
|
|
651
|
+
|
|
652
|
+
declare type AppOnlyAuthToken = {
|
|
653
|
+
appId: string;
|
|
654
|
+
roomId?: never;
|
|
655
|
+
scopes: string[];
|
|
656
|
+
};
|
|
657
|
+
declare type RoomAuthToken = {
|
|
658
|
+
appId: string;
|
|
659
|
+
roomId: string;
|
|
660
|
+
scopes: string[];
|
|
661
|
+
actor: number;
|
|
662
|
+
maxConnectionsPerRoom?: number;
|
|
663
|
+
info?: Json;
|
|
664
|
+
groupIds?: string[];
|
|
665
|
+
} & ({
|
|
666
|
+
id: string;
|
|
667
|
+
anonymousId?: never;
|
|
668
|
+
} | {
|
|
669
|
+
id?: never;
|
|
670
|
+
anonymousId: string;
|
|
671
|
+
});
|
|
672
|
+
declare type AuthToken = AppOnlyAuthToken | RoomAuthToken;
|
|
673
|
+
declare function isAppOnlyAuthToken(data: JsonObject): data is AppOnlyAuthToken;
|
|
674
|
+
declare function isRoomAuthToken(data: JsonObject): data is RoomAuthToken;
|
|
675
|
+
declare function isAuthToken(data: JsonObject): data is AuthToken;
|
|
676
|
+
|
|
639
677
|
declare type ReadonlyArrayWithLegacyMethods<T> = readonly T[] & {
|
|
640
678
|
/**
|
|
641
679
|
* @deprecated Prefer the normal .length property on arrays.
|
|
@@ -1133,11 +1171,13 @@ declare type ClientOptions = {
|
|
|
1133
1171
|
polyfills?: Polyfills;
|
|
1134
1172
|
unstable_fallbackToHTTP?: boolean;
|
|
1135
1173
|
/**
|
|
1136
|
-
*
|
|
1174
|
+
* @deprecated Use `polyfills: { fetch: ... }` instead.
|
|
1175
|
+
* This option will be removed in a future release.
|
|
1137
1176
|
*/
|
|
1138
1177
|
fetchPolyfill?: Polyfills["fetch"];
|
|
1139
1178
|
/**
|
|
1140
|
-
*
|
|
1179
|
+
* @deprecated Use `polyfills: { WebSocket: ... }` instead.
|
|
1180
|
+
* This option will be removed in a future release.
|
|
1141
1181
|
*/
|
|
1142
1182
|
WebSocketPolyfill?: Polyfills["WebSocket"];
|
|
1143
1183
|
} & ({
|
|
@@ -1269,6 +1309,12 @@ declare function tryParseJson(rawMessage: string): Json | undefined;
|
|
|
1269
1309
|
* Decode base64 string.
|
|
1270
1310
|
*/
|
|
1271
1311
|
declare function b64decode(b64value: string): string;
|
|
1312
|
+
/**
|
|
1313
|
+
* Returns whatever the given promise returns, but will be rejected with
|
|
1314
|
+
* a "Timed out" error if the given promise does not return or reject within
|
|
1315
|
+
* the given timeout period (in milliseconds).
|
|
1316
|
+
*/
|
|
1317
|
+
declare function withTimeout<T>(promise: Promise<T>, millis: number, errmsg?: string): Promise<T>;
|
|
1272
1318
|
|
|
1273
1319
|
/**
|
|
1274
1320
|
* Positions, aka the Pos type, are efficient encodings of "positions" in
|
|
@@ -1346,31 +1392,6 @@ declare function asPos(str: string): Pos;
|
|
|
1346
1392
|
*/
|
|
1347
1393
|
declare function shallow(a: unknown, b: unknown): boolean;
|
|
1348
1394
|
|
|
1349
|
-
declare type AppOnlyAuthToken = {
|
|
1350
|
-
appId: string;
|
|
1351
|
-
roomId?: never;
|
|
1352
|
-
scopes: string[];
|
|
1353
|
-
};
|
|
1354
|
-
declare type RoomAuthToken = {
|
|
1355
|
-
appId: string;
|
|
1356
|
-
roomId: string;
|
|
1357
|
-
scopes: string[];
|
|
1358
|
-
actor: number;
|
|
1359
|
-
maxConnectionsPerRoom?: number;
|
|
1360
|
-
info?: Json;
|
|
1361
|
-
groupIds?: string[];
|
|
1362
|
-
} & ({
|
|
1363
|
-
id: string;
|
|
1364
|
-
anonymousId?: never;
|
|
1365
|
-
} | {
|
|
1366
|
-
id?: never;
|
|
1367
|
-
anonymousId: string;
|
|
1368
|
-
});
|
|
1369
|
-
declare type AuthToken = AppOnlyAuthToken | RoomAuthToken;
|
|
1370
|
-
declare function isAppOnlyAuthToken(data: JsonObject): data is AppOnlyAuthToken;
|
|
1371
|
-
declare function isRoomAuthToken(data: JsonObject): data is RoomAuthToken;
|
|
1372
|
-
declare function isAuthToken(data: JsonObject): data is AuthToken;
|
|
1373
|
-
|
|
1374
1395
|
declare enum ClientMsgCode {
|
|
1375
1396
|
UPDATE_PRESENCE = 100,
|
|
1376
1397
|
BROADCAST_EVENT = 103,
|
|
@@ -1803,4 +1824,4 @@ declare type EnsureJson<T> = [
|
|
|
1803
1824
|
[K in keyof T]: EnsureJson<T[K]>;
|
|
1804
1825
|
};
|
|
1805
1826
|
|
|
1806
|
-
export { AckOp, AppOnlyAuthToken, AuthToken, BaseUserMeta, BroadcastEventClientMsg, BroadcastOptions, BroadcastedEventServerMsg, Client, ClientMsg, ClientMsgCode, ConnectionStatus, CrdtType, CreateChildOp, CreateListOp, CreateMapOp, CreateObjectOp, CreateOp, CreateRegisterOp, CreateRootObjectOp, DeleteCrdtOp, DeleteObjectKeyOp, DevToolsTreeNode as DevTools, protocol as DevToolsMsg, EnsureJson, FetchStorageClientMsg, History, IWebSocket, IWebSocketCloseEvent, IWebSocketEvent, IWebSocketInstance, IWebSocketMessageEvent, IdTuple, Immutable, InitialDocumentStateServerMsg, Json, JsonArray, JsonObject, JsonScalar, LiveList, LiveListUpdate, LiveMap, LiveMapUpdate, LiveNode, LiveObject, LiveObjectUpdate, LiveStructure, Lson, LsonObject, NodeMap, Op, OpCode, Others, ParentToChildNodeMap, PlainLson, PlainLsonFields, PlainLsonList, PlainLsonMap, PlainLsonObject, RejectedStorageOpServerMsg, Resolve, Room, RoomAuthToken, RoomInitializers, RoomStateServerMsg, SerializedChild, SerializedCrdt, SerializedList, SerializedMap, SerializedObject, SerializedRegister, SerializedRootObject, ServerMsg, ServerMsgCode, SetParentKeyOp, StorageStatus, StorageUpdate, ToImmutable, ToJson, UpdateObjectOp, UpdatePresenceClientMsg, UpdatePresenceServerMsg, UpdateStorageClientMsg, UpdateStorageServerMsg, User, UserJoinServerMsg, UserLeftServerMsg, WebsocketCloseCodes, asArrayWithLegacyMethods, asPos, assert, assertNever, b64decode, createClient, deprecate, deprecateIf, errorIf, freeze, isAppOnlyAuthToken, isAuthToken, isChildCrdt, isJsonArray, isJsonObject, isJsonScalar, isPlainObject, isRoomAuthToken, isRootCrdt, legacy_patchImmutableObject, lsonToJson, makePosition, nn, patchLiveObjectKey, shallow, throwUsageError, toPlainLson, tryParseJson };
|
|
1827
|
+
export { AckOp, AppOnlyAuthToken, AuthToken, BaseAuthResult, BaseUserMeta, BroadcastEventClientMsg, BroadcastOptions, BroadcastedEventServerMsg, Client, ClientMsg, ClientMsgCode, ConnectionStatus, CrdtType, CreateChildOp, CreateListOp, CreateMapOp, CreateObjectOp, CreateOp, CreateRegisterOp, CreateRootObjectOp, Delegates, DeleteCrdtOp, DeleteObjectKeyOp, DevToolsTreeNode as DevTools, protocol as DevToolsMsg, EnsureJson, FetchStorageClientMsg, History, IWebSocket, IWebSocketCloseEvent, IWebSocketEvent, IWebSocketInstance, IWebSocketMessageEvent, IdTuple, Immutable, InitialDocumentStateServerMsg, Json, JsonArray, JsonObject, JsonScalar, LiveList, LiveListUpdate, LiveMap, LiveMapUpdate, LiveNode, LiveObject, LiveObjectUpdate, LiveStructure, Lson, LsonObject, NodeMap, Op, OpCode, Others, ParentToChildNodeMap, PlainLson, PlainLsonFields, PlainLsonList, PlainLsonMap, PlainLsonObject, RejectedStorageOpServerMsg, Resolve, Room, RoomAuthToken, RoomInitializers, RoomStateServerMsg, SerializedChild, SerializedCrdt, SerializedList, SerializedMap, SerializedObject, SerializedRegister, SerializedRootObject, ServerMsg, ServerMsgCode, SetParentKeyOp, StorageStatus, StorageUpdate, ToImmutable, ToJson, UpdateObjectOp, UpdatePresenceClientMsg, UpdatePresenceServerMsg, UpdateStorageClientMsg, UpdateStorageServerMsg, User, UserJoinServerMsg, UserLeftServerMsg, WebsocketCloseCodes, asArrayWithLegacyMethods, asPos, assert, assertNever, b64decode, createClient, deprecate, deprecateIf, errorIf, freeze, isAppOnlyAuthToken, isAuthToken, isChildCrdt, isJsonArray, isJsonObject, isJsonScalar, isPlainObject, isRoomAuthToken, isRootCrdt, legacy_patchImmutableObject, lsonToJson, makePosition, nn, patchLiveObjectKey, shallow, throwUsageError, toPlainLson, tryParseJson, withTimeout };
|
package/dist/index.js
CHANGED
|
@@ -157,7 +157,7 @@ var onMessageFromPanel = eventSource.observable;
|
|
|
157
157
|
// src/devtools/index.ts
|
|
158
158
|
var VERSION = true ? (
|
|
159
159
|
/* istanbul ignore next */
|
|
160
|
-
"1.1.0-
|
|
160
|
+
"1.1.0-test1"
|
|
161
161
|
) : "dev";
|
|
162
162
|
var _devtoolsSetupHasRun = false;
|
|
163
163
|
function setupDevTools(getAllRooms) {
|
|
@@ -386,17 +386,6 @@ function nn(value, errmsg = "Expected value to be non-nullable") {
|
|
|
386
386
|
}
|
|
387
387
|
|
|
388
388
|
// src/lib/fsm.ts
|
|
389
|
-
function withTimeout(promise, millis, errmsg = "Timed out") {
|
|
390
|
-
return __async(this, null, function* () {
|
|
391
|
-
let timerID;
|
|
392
|
-
const timer$ = new Promise((_, reject) => {
|
|
393
|
-
timerID = setTimeout(() => {
|
|
394
|
-
reject(new Error(errmsg));
|
|
395
|
-
}, millis);
|
|
396
|
-
});
|
|
397
|
-
return Promise.race([promise, timer$]).finally(() => clearTimeout(timerID));
|
|
398
|
-
});
|
|
399
|
-
}
|
|
400
389
|
function distance(state1, state2) {
|
|
401
390
|
if (state1 === state2) {
|
|
402
391
|
return [0, 0];
|
|
@@ -772,6 +761,67 @@ var FSM = class {
|
|
|
772
761
|
}
|
|
773
762
|
};
|
|
774
763
|
|
|
764
|
+
// src/lib/utils.ts
|
|
765
|
+
function isPlainObject(blob) {
|
|
766
|
+
return blob !== null && typeof blob === "object" && Object.prototype.toString.call(blob) === "[object Object]";
|
|
767
|
+
}
|
|
768
|
+
function fromEntries(iterable) {
|
|
769
|
+
const obj = {};
|
|
770
|
+
for (const [key, val] of iterable) {
|
|
771
|
+
obj[key] = val;
|
|
772
|
+
}
|
|
773
|
+
return obj;
|
|
774
|
+
}
|
|
775
|
+
function entries(obj) {
|
|
776
|
+
return Object.entries(obj);
|
|
777
|
+
}
|
|
778
|
+
function tryParseJson(rawMessage) {
|
|
779
|
+
try {
|
|
780
|
+
return JSON.parse(rawMessage);
|
|
781
|
+
} catch (e) {
|
|
782
|
+
return void 0;
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
function b64decode(b64value) {
|
|
786
|
+
try {
|
|
787
|
+
const formattedValue = b64value.replace(/-/g, "+").replace(/_/g, "/");
|
|
788
|
+
const decodedValue = decodeURIComponent(
|
|
789
|
+
atob(formattedValue).split("").map(function(c) {
|
|
790
|
+
return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
|
|
791
|
+
}).join("")
|
|
792
|
+
);
|
|
793
|
+
return decodedValue;
|
|
794
|
+
} catch (err) {
|
|
795
|
+
return atob(b64value);
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
function compact(items) {
|
|
799
|
+
return items.filter(
|
|
800
|
+
(item) => item !== null && item !== void 0
|
|
801
|
+
);
|
|
802
|
+
}
|
|
803
|
+
function compactObject(obj) {
|
|
804
|
+
const newObj = __spreadValues({}, obj);
|
|
805
|
+
Object.keys(obj).forEach((k) => {
|
|
806
|
+
const key = k;
|
|
807
|
+
if (newObj[key] === void 0) {
|
|
808
|
+
delete newObj[key];
|
|
809
|
+
}
|
|
810
|
+
});
|
|
811
|
+
return newObj;
|
|
812
|
+
}
|
|
813
|
+
function withTimeout(promise, millis, errmsg = "Timed out") {
|
|
814
|
+
return __async(this, null, function* () {
|
|
815
|
+
let timerID;
|
|
816
|
+
const timer$ = new Promise((_, reject) => {
|
|
817
|
+
timerID = setTimeout(() => {
|
|
818
|
+
reject(new Error(errmsg));
|
|
819
|
+
}, millis);
|
|
820
|
+
});
|
|
821
|
+
return Promise.race([promise, timer$]).finally(() => clearTimeout(timerID));
|
|
822
|
+
});
|
|
823
|
+
}
|
|
824
|
+
|
|
775
825
|
// src/connection.ts
|
|
776
826
|
function toPublicConnectionStatus(state) {
|
|
777
827
|
switch (state) {
|
|
@@ -800,7 +850,10 @@ var HEARTBEAT_INTERVAL = 3e4;
|
|
|
800
850
|
var PONG_TIMEOUT = 2e3;
|
|
801
851
|
var AUTH_TIMEOUT = 1e4;
|
|
802
852
|
var SOCKET_CONNECT_TIMEOUT = 1e4;
|
|
803
|
-
var
|
|
853
|
+
var StopRetrying = class extends Error {
|
|
854
|
+
constructor(reason) {
|
|
855
|
+
super(reason);
|
|
856
|
+
}
|
|
804
857
|
};
|
|
805
858
|
var LiveblocksError = class extends Error {
|
|
806
859
|
constructor(message, code) {
|
|
@@ -843,21 +896,15 @@ function enableTracing(machine) {
|
|
|
843
896
|
);
|
|
844
897
|
}
|
|
845
898
|
const unsubs = [
|
|
846
|
-
machine.events.didReceiveEvent.subscribe((e) => {
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
// machine.events.willExitState.subscribe((s) => {
|
|
856
|
-
// log("Exiting state", s);
|
|
857
|
-
// }),
|
|
858
|
-
// machine.events.didEnterState.subscribe((s) => {
|
|
859
|
-
// log("Entering state", s);
|
|
860
|
-
// }),
|
|
899
|
+
machine.events.didReceiveEvent.subscribe((e) => log2(`Event ${e.type}`)),
|
|
900
|
+
machine.events.willTransition.subscribe(
|
|
901
|
+
({ from, to }) => log2("Transitioning", from, "\u2192", to)
|
|
902
|
+
),
|
|
903
|
+
machine.events.didIgnoreEvent.subscribe(
|
|
904
|
+
(e) => log2("Ignored event", e.type, e, "(current state won't handle it)")
|
|
905
|
+
)
|
|
906
|
+
// machine.events.willExitState.subscribe((s) => log("Exiting state", s)),
|
|
907
|
+
// machine.events.didEnterState.subscribe((s) => log("Entering state", s)),
|
|
861
908
|
];
|
|
862
909
|
return () => {
|
|
863
910
|
for (const unsub of unsubs) {
|
|
@@ -888,7 +935,7 @@ function defineConnectivityEvents(machine) {
|
|
|
888
935
|
};
|
|
889
936
|
}
|
|
890
937
|
var assign = (patch) => (ctx) => ctx.patch(patch);
|
|
891
|
-
function createConnectionStateMachine(delegates) {
|
|
938
|
+
function createConnectionStateMachine(delegates, enableDebugLogging) {
|
|
892
939
|
const onMessage = makeEventSource();
|
|
893
940
|
onMessage.pause();
|
|
894
941
|
const onLiveblocksError = makeEventSource();
|
|
@@ -933,21 +980,23 @@ function createConnectionStateMachine(delegates) {
|
|
|
933
980
|
})
|
|
934
981
|
}),
|
|
935
982
|
// Auth failed
|
|
936
|
-
(failedEvent) =>
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
983
|
+
(failedEvent) => {
|
|
984
|
+
if (failedEvent.reason instanceof StopRetrying) {
|
|
985
|
+
return {
|
|
986
|
+
target: "@idle.failed",
|
|
987
|
+
effect: log(2 /* ERROR */, failedEvent.reason.message)
|
|
988
|
+
};
|
|
989
|
+
}
|
|
990
|
+
return {
|
|
991
|
+
target: "@auth.backoff",
|
|
992
|
+
effect: [
|
|
993
|
+
increaseBackoffDelay,
|
|
994
|
+
log(
|
|
995
|
+
2 /* ERROR */,
|
|
996
|
+
`Authentication failed: ${failedEvent.reason instanceof Error ? failedEvent.reason.message : String(failedEvent.reason)}`
|
|
997
|
+
)
|
|
998
|
+
]
|
|
999
|
+
};
|
|
951
1000
|
}
|
|
952
1001
|
);
|
|
953
1002
|
const onSocketError = (event) => machine.send({ type: "EXPLICIT_SOCKET_ERROR", event });
|
|
@@ -1042,6 +1091,12 @@ function createConnectionStateMachine(delegates) {
|
|
|
1042
1091
|
// If the WebSocket connection cannot be established
|
|
1043
1092
|
(failure) => {
|
|
1044
1093
|
const err = failure.reason;
|
|
1094
|
+
if (err instanceof StopRetrying) {
|
|
1095
|
+
return {
|
|
1096
|
+
target: "@idle.failed",
|
|
1097
|
+
effect: log(2 /* ERROR */, err.message)
|
|
1098
|
+
};
|
|
1099
|
+
}
|
|
1045
1100
|
return {
|
|
1046
1101
|
target: "@auth.backoff",
|
|
1047
1102
|
effect: [
|
|
@@ -1096,7 +1151,7 @@ function createConnectionStateMachine(delegates) {
|
|
|
1096
1151
|
// not. When still OPEN, don't transition.
|
|
1097
1152
|
EXPLICIT_SOCKET_ERROR: (_, context) => {
|
|
1098
1153
|
var _a;
|
|
1099
|
-
if (((_a = context.socket) == null ? void 0 : _a.readyState) ===
|
|
1154
|
+
if (((_a = context.socket) == null ? void 0 : _a.readyState) === 1) {
|
|
1100
1155
|
return null;
|
|
1101
1156
|
}
|
|
1102
1157
|
return {
|
|
@@ -1167,7 +1222,9 @@ function createConnectionStateMachine(delegates) {
|
|
|
1167
1222
|
const cleanups = [];
|
|
1168
1223
|
const { statusDidChange, didConnect, didDisconnect, unsubscribe } = defineConnectivityEvents(machine);
|
|
1169
1224
|
cleanups.push(unsubscribe);
|
|
1170
|
-
|
|
1225
|
+
if (enableDebugLogging) {
|
|
1226
|
+
cleanups.push(enableTracing(machine));
|
|
1227
|
+
}
|
|
1171
1228
|
machine.start();
|
|
1172
1229
|
return {
|
|
1173
1230
|
machine,
|
|
@@ -1183,8 +1240,11 @@ function createConnectionStateMachine(delegates) {
|
|
|
1183
1240
|
};
|
|
1184
1241
|
}
|
|
1185
1242
|
var ManagedSocket = class {
|
|
1186
|
-
constructor(delegates) {
|
|
1187
|
-
const { machine, events, cleanups } = createConnectionStateMachine(
|
|
1243
|
+
constructor(delegates, enableDebugLogging = false) {
|
|
1244
|
+
const { machine, events, cleanups } = createConnectionStateMachine(
|
|
1245
|
+
delegates,
|
|
1246
|
+
enableDebugLogging
|
|
1247
|
+
);
|
|
1188
1248
|
this.machine = machine;
|
|
1189
1249
|
this.events = events;
|
|
1190
1250
|
this.cleanups = cleanups;
|
|
@@ -1248,7 +1308,7 @@ var ManagedSocket = class {
|
|
|
1248
1308
|
const socket = (_a = this.machine.context) == null ? void 0 : _a.socket;
|
|
1249
1309
|
if (socket === null) {
|
|
1250
1310
|
warn("Cannot send: not connected yet", data);
|
|
1251
|
-
} else if (socket.readyState !==
|
|
1311
|
+
} else if (socket.readyState !== 1) {
|
|
1252
1312
|
warn("Cannot send: WebSocket no longer open", data);
|
|
1253
1313
|
} else {
|
|
1254
1314
|
socket.send(data);
|
|
@@ -1574,56 +1634,6 @@ var AbstractCrdt = class {
|
|
|
1574
1634
|
}
|
|
1575
1635
|
};
|
|
1576
1636
|
|
|
1577
|
-
// src/lib/utils.ts
|
|
1578
|
-
function isPlainObject(blob) {
|
|
1579
|
-
return blob !== null && typeof blob === "object" && Object.prototype.toString.call(blob) === "[object Object]";
|
|
1580
|
-
}
|
|
1581
|
-
function fromEntries(iterable) {
|
|
1582
|
-
const obj = {};
|
|
1583
|
-
for (const [key, val] of iterable) {
|
|
1584
|
-
obj[key] = val;
|
|
1585
|
-
}
|
|
1586
|
-
return obj;
|
|
1587
|
-
}
|
|
1588
|
-
function entries(obj) {
|
|
1589
|
-
return Object.entries(obj);
|
|
1590
|
-
}
|
|
1591
|
-
function tryParseJson(rawMessage) {
|
|
1592
|
-
try {
|
|
1593
|
-
return JSON.parse(rawMessage);
|
|
1594
|
-
} catch (e) {
|
|
1595
|
-
return void 0;
|
|
1596
|
-
}
|
|
1597
|
-
}
|
|
1598
|
-
function b64decode(b64value) {
|
|
1599
|
-
try {
|
|
1600
|
-
const formattedValue = b64value.replace(/-/g, "+").replace(/_/g, "/");
|
|
1601
|
-
const decodedValue = decodeURIComponent(
|
|
1602
|
-
atob(formattedValue).split("").map(function(c) {
|
|
1603
|
-
return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
|
|
1604
|
-
}).join("")
|
|
1605
|
-
);
|
|
1606
|
-
return decodedValue;
|
|
1607
|
-
} catch (err) {
|
|
1608
|
-
return atob(b64value);
|
|
1609
|
-
}
|
|
1610
|
-
}
|
|
1611
|
-
function compact(items) {
|
|
1612
|
-
return items.filter(
|
|
1613
|
-
(item) => item !== null && item !== void 0
|
|
1614
|
-
);
|
|
1615
|
-
}
|
|
1616
|
-
function compactObject(obj) {
|
|
1617
|
-
const newObj = __spreadValues({}, obj);
|
|
1618
|
-
Object.keys(obj).forEach((k) => {
|
|
1619
|
-
const key = k;
|
|
1620
|
-
if (newObj[key] === void 0) {
|
|
1621
|
-
delete newObj[key];
|
|
1622
|
-
}
|
|
1623
|
-
});
|
|
1624
|
-
return newObj;
|
|
1625
|
-
}
|
|
1626
|
-
|
|
1627
1637
|
// src/protocol/SerializedCrdt.ts
|
|
1628
1638
|
var CrdtType = /* @__PURE__ */ ((CrdtType2) => {
|
|
1629
1639
|
CrdtType2[CrdtType2["OBJECT"] = 0] = "OBJECT";
|
|
@@ -4174,11 +4184,11 @@ function userToTreeNode(key, user) {
|
|
|
4174
4184
|
payload: user
|
|
4175
4185
|
};
|
|
4176
4186
|
}
|
|
4177
|
-
function createRoom(options, config
|
|
4178
|
-
var _a, _b, _c;
|
|
4187
|
+
function createRoom(options, config) {
|
|
4188
|
+
var _a, _b, _c, _d;
|
|
4179
4189
|
const initialPresence = typeof options.initialPresence === "function" ? options.initialPresence(config.roomId) : options.initialPresence;
|
|
4180
4190
|
const initialStorage = typeof options.initialStorage === "function" ? options.initialStorage(config.roomId) : options.initialStorage;
|
|
4181
|
-
const delegates =
|
|
4191
|
+
const delegates = (_c = config.delegates) != null ? _c : {
|
|
4182
4192
|
authenticate: makeAuthDelegateForRoom(
|
|
4183
4193
|
config.roomId,
|
|
4184
4194
|
config.authentication,
|
|
@@ -4189,7 +4199,10 @@ function createRoom(options, config, mockedDelegates) {
|
|
|
4189
4199
|
(_b = config.polyfills) == null ? void 0 : _b.WebSocket
|
|
4190
4200
|
)
|
|
4191
4201
|
};
|
|
4192
|
-
const managedSocket = new ManagedSocket(
|
|
4202
|
+
const managedSocket = new ManagedSocket(
|
|
4203
|
+
delegates,
|
|
4204
|
+
config.enableDebugLogging
|
|
4205
|
+
);
|
|
4193
4206
|
const context = {
|
|
4194
4207
|
lastConnectionId: null,
|
|
4195
4208
|
buffer: {
|
|
@@ -4224,11 +4237,9 @@ function createRoom(options, config, mockedDelegates) {
|
|
|
4224
4237
|
opStackTraces: process.env.NODE_ENV !== "production" ? /* @__PURE__ */ new Map() : void 0
|
|
4225
4238
|
};
|
|
4226
4239
|
const doNotBatchUpdates = (cb) => cb();
|
|
4227
|
-
const batchUpdates = (
|
|
4240
|
+
const batchUpdates = (_d = config.unstable_batchedUpdates) != null ? _d : doNotBatchUpdates;
|
|
4228
4241
|
function onStatusDidChange(newStatus) {
|
|
4229
|
-
if (newStatus
|
|
4230
|
-
context.connection.set({ status: newStatus });
|
|
4231
|
-
} else {
|
|
4242
|
+
if (newStatus === "open" || newStatus === "connecting") {
|
|
4232
4243
|
context.connection.set({
|
|
4233
4244
|
status: newStatus,
|
|
4234
4245
|
id: managedSocket.token.parsed.actor,
|
|
@@ -4236,6 +4247,8 @@ function createRoom(options, config, mockedDelegates) {
|
|
|
4236
4247
|
userId: managedSocket.token.parsed.id,
|
|
4237
4248
|
isReadOnly: isStorageReadOnly(managedSocket.token.parsed.scopes)
|
|
4238
4249
|
});
|
|
4250
|
+
} else {
|
|
4251
|
+
context.connection.set({ status: newStatus });
|
|
4239
4252
|
}
|
|
4240
4253
|
batchUpdates(() => {
|
|
4241
4254
|
eventHub.connection.notify(newStatus);
|
|
@@ -4345,31 +4358,29 @@ function createRoom(options, config, mockedDelegates) {
|
|
|
4345
4358
|
storageDidLoad: makeEventSource(),
|
|
4346
4359
|
storageStatus: makeEventSource()
|
|
4347
4360
|
};
|
|
4348
|
-
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
if (
|
|
4355
|
-
|
|
4356
|
-
return managedSocket.reconnect();
|
|
4357
|
-
}
|
|
4358
|
-
void httpSend(
|
|
4359
|
-
message,
|
|
4360
|
-
managedSocket.token.raw,
|
|
4361
|
-
config.httpSendEndpoint,
|
|
4362
|
-
(_a2 = config.polyfills) == null ? void 0 : _a2.fetch
|
|
4363
|
-
);
|
|
4364
|
-
warn(
|
|
4365
|
-
"Message was too large for websockets and sent over HTTP instead"
|
|
4366
|
-
);
|
|
4367
|
-
return;
|
|
4361
|
+
function sendMessages(messageOrMessages) {
|
|
4362
|
+
var _a2;
|
|
4363
|
+
const message = JSON.stringify(messageOrMessages);
|
|
4364
|
+
if (config.unstable_fallbackToHTTP) {
|
|
4365
|
+
const size = new TextEncoder().encode(message).length;
|
|
4366
|
+
if (size > MAX_MESSAGE_SIZE && managedSocket.token.raw && config.httpSendEndpoint) {
|
|
4367
|
+
if (isTokenExpired(managedSocket.token.parsed)) {
|
|
4368
|
+
return managedSocket.reconnect();
|
|
4368
4369
|
}
|
|
4370
|
+
void httpSend(
|
|
4371
|
+
message,
|
|
4372
|
+
managedSocket.token.raw,
|
|
4373
|
+
config.httpSendEndpoint,
|
|
4374
|
+
(_a2 = config.polyfills) == null ? void 0 : _a2.fetch
|
|
4375
|
+
);
|
|
4376
|
+
warn(
|
|
4377
|
+
"Message was too large for websockets and sent over HTTP instead"
|
|
4378
|
+
);
|
|
4379
|
+
return;
|
|
4369
4380
|
}
|
|
4370
|
-
managedSocket.send(message);
|
|
4371
4381
|
}
|
|
4372
|
-
|
|
4382
|
+
managedSocket.send(message);
|
|
4383
|
+
}
|
|
4373
4384
|
const self = new DerivedRef(
|
|
4374
4385
|
context.connection,
|
|
4375
4386
|
context.me,
|
|
@@ -4720,7 +4731,7 @@ function createRoom(options, config, mockedDelegates) {
|
|
|
4720
4731
|
ops: result.ops
|
|
4721
4732
|
});
|
|
4722
4733
|
notify(result.updates, batchedUpdatesWrapper);
|
|
4723
|
-
|
|
4734
|
+
sendMessages(messages);
|
|
4724
4735
|
}
|
|
4725
4736
|
function handleServerMessage(event) {
|
|
4726
4737
|
if (typeof event.data !== "string") {
|
|
@@ -4842,7 +4853,7 @@ ${Array.from(traces).join("\n\n")}`
|
|
|
4842
4853
|
if (messagesToFlush.length === 0) {
|
|
4843
4854
|
return;
|
|
4844
4855
|
}
|
|
4845
|
-
|
|
4856
|
+
sendMessages(messagesToFlush);
|
|
4846
4857
|
context.buffer = {
|
|
4847
4858
|
flushTimerID: void 0,
|
|
4848
4859
|
lastFlushedAt: now,
|
|
@@ -5078,20 +5089,9 @@ ${Array.from(traces).join("\n\n")}`
|
|
|
5078
5089
|
getOthers_forDevTools: () => others_forDevTools.current,
|
|
5079
5090
|
// prettier-ignore
|
|
5080
5091
|
send: {
|
|
5081
|
-
simulateAuthSuccess() {
|
|
5082
|
-
throw new Error("\u{1F64F} Rewrite this test to no longer depend on authSuccess, please! \u{1F64F}");
|
|
5083
|
-
},
|
|
5084
5092
|
// These exist only for our E2E testing app
|
|
5085
5093
|
explicitClose: (event) => managedSocket._privateSendMachineEvent({ type: "EXPLICIT_SOCKET_CLOSE", event }),
|
|
5086
|
-
implicitClose: () => managedSocket._privateSendMachineEvent({ type: "PONG_TIMEOUT" })
|
|
5087
|
-
/**
|
|
5088
|
-
* This one looks differently from the rest, because receiving messages
|
|
5089
|
-
* is handled orthorgonally from all other possible events above,
|
|
5090
|
-
* because it does not matter what the connectivity state of the
|
|
5091
|
-
* machine is, so there won't be an explicit state machine transition
|
|
5092
|
-
* needed for this event.
|
|
5093
|
-
*/
|
|
5094
|
-
incomingMessage: handleServerMessage
|
|
5094
|
+
implicitClose: () => managedSocket._privateSendMachineEvent({ type: "PONG_TIMEOUT" })
|
|
5095
5095
|
}
|
|
5096
5096
|
},
|
|
5097
5097
|
id: config.roomId,
|
|
@@ -5099,7 +5099,6 @@ ${Array.from(traces).join("\n\n")}`
|
|
|
5099
5099
|
connect: () => managedSocket.connect(),
|
|
5100
5100
|
reconnect: () => managedSocket.reconnect(),
|
|
5101
5101
|
disconnect: () => managedSocket.disconnect(),
|
|
5102
|
-
// XXX Do we really need disconnect() now that we have destroy()? Seems still useful to reset the machine, but also... YAGNI?
|
|
5103
5102
|
destroy: () => managedSocket.destroy(),
|
|
5104
5103
|
// Presence
|
|
5105
5104
|
updatePresence,
|
|
@@ -5209,9 +5208,9 @@ function isRoomEventName(value) {
|
|
|
5209
5208
|
}
|
|
5210
5209
|
function makeCreateSocketDelegateForRoom(liveblocksServer, WebSocketPolyfill) {
|
|
5211
5210
|
return (richToken) => {
|
|
5212
|
-
const ws = WebSocketPolyfill
|
|
5213
|
-
if (
|
|
5214
|
-
throw new
|
|
5211
|
+
const ws = WebSocketPolyfill != null ? WebSocketPolyfill : typeof WebSocket === "undefined" ? void 0 : WebSocket;
|
|
5212
|
+
if (ws === void 0) {
|
|
5213
|
+
throw new StopRetrying(
|
|
5215
5214
|
"To use Liveblocks client in a non-dom environment, you need to provide a WebSocket polyfill."
|
|
5216
5215
|
);
|
|
5217
5216
|
}
|
|
@@ -5222,7 +5221,7 @@ function makeCreateSocketDelegateForRoom(liveblocksServer, WebSocketPolyfill) {
|
|
|
5222
5221
|
// @ts-ignore (__PACKAGE_VERSION__ will be injected by the build script)
|
|
5223
5222
|
true ? (
|
|
5224
5223
|
/* istanbul ignore next */
|
|
5225
|
-
"1.1.0-
|
|
5224
|
+
"1.1.0-test1"
|
|
5226
5225
|
) : "dev"}`
|
|
5227
5226
|
);
|
|
5228
5227
|
};
|
|
@@ -5242,48 +5241,43 @@ function httpSend(message, token, endpoint, fetchPolyfill) {
|
|
|
5242
5241
|
});
|
|
5243
5242
|
}
|
|
5244
5243
|
function makeAuthDelegateForRoom(roomId, authentication, fetchPolyfill) {
|
|
5244
|
+
const fetcher = fetchPolyfill != null ? fetchPolyfill : typeof window === "undefined" ? void 0 : window.fetch;
|
|
5245
5245
|
if (authentication.type === "public") {
|
|
5246
5246
|
return () => __async(this, null, function* () {
|
|
5247
|
-
if (
|
|
5248
|
-
throw new
|
|
5247
|
+
if (fetcher === void 0) {
|
|
5248
|
+
throw new StopRetrying(
|
|
5249
5249
|
"To use Liveblocks client in a non-dom environment with a publicApiKey, you need to provide a fetch polyfill."
|
|
5250
5250
|
);
|
|
5251
5251
|
}
|
|
5252
|
-
return fetchAuthEndpoint(
|
|
5253
|
-
|
|
5254
|
-
|
|
5255
|
-
|
|
5256
|
-
{
|
|
5257
|
-
room: roomId,
|
|
5258
|
-
publicApiKey: authentication.publicApiKey
|
|
5259
|
-
}
|
|
5260
|
-
).then(({ token }) => parseRoomAuthToken(token));
|
|
5252
|
+
return fetchAuthEndpoint(fetcher, authentication.url, {
|
|
5253
|
+
room: roomId,
|
|
5254
|
+
publicApiKey: authentication.publicApiKey
|
|
5255
|
+
}).then(({ token }) => parseRoomAuthToken(token));
|
|
5261
5256
|
});
|
|
5262
|
-
}
|
|
5263
|
-
if (authentication.type === "private") {
|
|
5257
|
+
} else if (authentication.type === "private") {
|
|
5264
5258
|
return () => __async(this, null, function* () {
|
|
5265
|
-
if (
|
|
5266
|
-
throw new
|
|
5259
|
+
if (fetcher === void 0) {
|
|
5260
|
+
throw new StopRetrying(
|
|
5267
5261
|
"To use Liveblocks client in a non-dom environment with a url as auth endpoint, you need to provide a fetch polyfill."
|
|
5268
5262
|
);
|
|
5269
5263
|
}
|
|
5270
|
-
return fetchAuthEndpoint(
|
|
5264
|
+
return fetchAuthEndpoint(fetcher, authentication.url, {
|
|
5271
5265
|
room: roomId
|
|
5272
5266
|
}).then(({ token }) => parseRoomAuthToken(token));
|
|
5273
5267
|
});
|
|
5274
|
-
}
|
|
5275
|
-
if (authentication.type === "custom") {
|
|
5268
|
+
} else if (authentication.type === "custom") {
|
|
5276
5269
|
return () => __async(this, null, function* () {
|
|
5277
5270
|
const response = yield authentication.callback(roomId);
|
|
5278
5271
|
if (!response || !response.token) {
|
|
5279
5272
|
throw new Error(
|
|
5280
|
-
'
|
|
5273
|
+
'We expect the authentication callback to return a token, but it does not. Hint: the return value should look like: { token: "..." }'
|
|
5281
5274
|
);
|
|
5282
5275
|
}
|
|
5283
5276
|
return parseRoomAuthToken(response.token);
|
|
5284
5277
|
});
|
|
5278
|
+
} else {
|
|
5279
|
+
throw new Error("Internal error. Unexpected authentication type");
|
|
5285
5280
|
}
|
|
5286
|
-
throw new Error("Internal error. Unexpected authentication type");
|
|
5287
5281
|
}
|
|
5288
5282
|
function fetchAuthEndpoint(fetch2, endpoint, body) {
|
|
5289
5283
|
return __async(this, null, function* () {
|
|
@@ -5297,26 +5291,25 @@ function fetchAuthEndpoint(fetch2, endpoint, body) {
|
|
|
5297
5291
|
body: JSON.stringify(body)
|
|
5298
5292
|
});
|
|
5299
5293
|
if (!res.ok) {
|
|
5294
|
+
const reason = `${(yield res.text()).trim() || "reason not provided in auth response"} (${res.status} returned by POST ${endpoint})`;
|
|
5300
5295
|
if (res.status === 401 || res.status === 403) {
|
|
5301
|
-
throw new
|
|
5296
|
+
throw new StopRetrying(`Unauthorized: ${reason}`);
|
|
5302
5297
|
} else {
|
|
5303
|
-
throw new
|
|
5304
|
-
`Expected a status 200 but got ${res.status} when doing a POST request on "${endpoint}"`
|
|
5305
|
-
);
|
|
5298
|
+
throw new Error(`Failed to authenticate: ${reason}`);
|
|
5306
5299
|
}
|
|
5307
5300
|
}
|
|
5308
5301
|
let data;
|
|
5309
5302
|
try {
|
|
5310
5303
|
data = yield res.json();
|
|
5311
5304
|
} catch (er) {
|
|
5312
|
-
throw new
|
|
5305
|
+
throw new Error(
|
|
5313
5306
|
`Expected a JSON response when doing a POST request on "${endpoint}". ${String(
|
|
5314
5307
|
er
|
|
5315
5308
|
)}`
|
|
5316
5309
|
);
|
|
5317
5310
|
}
|
|
5318
5311
|
if (!isPlainObject(data) || typeof data.token !== "string") {
|
|
5319
|
-
throw new
|
|
5312
|
+
throw new Error(
|
|
5320
5313
|
`Expected a JSON response of the form \`{ token: "..." }\` when doing a POST request on "${endpoint}", but got ${JSON.stringify(
|
|
5321
5314
|
data
|
|
5322
5315
|
)}`
|
|
@@ -5326,11 +5319,6 @@ function fetchAuthEndpoint(fetch2, endpoint, body) {
|
|
|
5326
5319
|
return { token };
|
|
5327
5320
|
});
|
|
5328
5321
|
}
|
|
5329
|
-
var AuthenticationError = class extends Error {
|
|
5330
|
-
constructor(message) {
|
|
5331
|
-
super(message);
|
|
5332
|
-
}
|
|
5333
|
-
};
|
|
5334
5322
|
|
|
5335
5323
|
// src/client.ts
|
|
5336
5324
|
var MIN_THROTTLE = 16;
|
|
@@ -5367,6 +5355,8 @@ function createClient(options) {
|
|
|
5367
5355
|
roomId,
|
|
5368
5356
|
throttleDelay,
|
|
5369
5357
|
polyfills: clientOptions.polyfills,
|
|
5358
|
+
delegates: clientOptions.mockedDelegates,
|
|
5359
|
+
enableDebugLogging: clientOptions.enableDebugLogging,
|
|
5370
5360
|
unstable_batchedUpdates: options2 == null ? void 0 : options2.unstable_batchedUpdates,
|
|
5371
5361
|
liveblocksServer: getServerFromClientOptions(clientOptions),
|
|
5372
5362
|
authentication: prepareAuthentication(clientOptions, roomId),
|
|
@@ -5375,8 +5365,7 @@ function createClient(options) {
|
|
|
5375
5365
|
roomId
|
|
5376
5366
|
),
|
|
5377
5367
|
unstable_fallbackToHTTP: !!clientOptions.unstable_fallbackToHTTP
|
|
5378
|
-
}
|
|
5379
|
-
void 0
|
|
5368
|
+
}
|
|
5380
5369
|
);
|
|
5381
5370
|
rooms.set(roomId, newRoom);
|
|
5382
5371
|
setupDevTools(() => Array.from(rooms.keys()));
|
|
@@ -5869,4 +5858,5 @@ var WebsocketCloseCodes = /* @__PURE__ */ ((WebsocketCloseCodes2) => {
|
|
|
5869
5858
|
|
|
5870
5859
|
|
|
5871
5860
|
|
|
5872
|
-
|
|
5861
|
+
|
|
5862
|
+
exports.ClientMsgCode = ClientMsgCode; exports.CrdtType = CrdtType; exports.LiveList = LiveList; exports.LiveMap = LiveMap; exports.LiveObject = LiveObject; exports.OpCode = OpCode; exports.ServerMsgCode = ServerMsgCode; exports.WebsocketCloseCodes = WebsocketCloseCodes; exports.asArrayWithLegacyMethods = asArrayWithLegacyMethods; exports.asPos = asPos; exports.assert = assert; exports.assertNever = assertNever; exports.b64decode = b64decode; exports.createClient = createClient; exports.deprecate = deprecate; exports.deprecateIf = deprecateIf; exports.errorIf = errorIf; exports.freeze = freeze; exports.isAppOnlyAuthToken = isAppOnlyAuthToken; exports.isAuthToken = isAuthToken; exports.isChildCrdt = isChildCrdt; exports.isJsonArray = isJsonArray; exports.isJsonObject = isJsonObject; exports.isJsonScalar = isJsonScalar; exports.isPlainObject = isPlainObject; exports.isRoomAuthToken = isRoomAuthToken; exports.isRootCrdt = isRootCrdt; exports.legacy_patchImmutableObject = legacy_patchImmutableObject; exports.lsonToJson = lsonToJson; exports.makePosition = makePosition; exports.nn = nn; exports.patchLiveObjectKey = patchLiveObjectKey; exports.shallow = shallow; exports.throwUsageError = throwUsageError; exports.tryParseJson = tryParseJson; exports.withTimeout = withTimeout;
|