@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.
Files changed (3) hide show
  1. package/dist/index.d.ts +49 -28
  2. package/dist/index.js +172 -182
  3. 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
- * Backward-compatible way to set `polyfills.fetch`.
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
- * Backward-compatible way to set `polyfills.WebSocket`.
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-fsm4"
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 UnauthorizedError = class extends Error {
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
- log2(`Event ${e.type}`);
848
- }),
849
- machine.events.willTransition.subscribe(({ from, to }) => {
850
- log2("Transitioning", from, "\u2192", to);
851
- }),
852
- machine.events.didIgnoreEvent.subscribe((e) => {
853
- log2("Ignored event", e.type, e, "(current state won't handle it)");
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) => failedEvent.reason instanceof UnauthorizedError ? {
937
- target: "@idle.failed",
938
- effect: log(
939
- 2 /* ERROR */,
940
- `Unauthorized: ${failedEvent.reason.message}`
941
- )
942
- } : {
943
- target: "@auth.backoff",
944
- effect: [
945
- increaseBackoffDelay,
946
- log(
947
- 0 /* INFO */,
948
- `Authentication failed: ${String(failedEvent.reason)}`
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) === WebSocket.OPEN) {
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
- cleanups.push(enableTracing(machine));
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(delegates);
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 !== WebSocket.OPEN) {
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, mockedDelegates) {
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 = mockedDelegates != null ? mockedDelegates : {
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(delegates);
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 = (_c = config.unstable_batchedUpdates) != null ? _c : doNotBatchUpdates;
4240
+ const batchUpdates = (_d = config.unstable_batchedUpdates) != null ? _d : doNotBatchUpdates;
4228
4241
  function onStatusDidChange(newStatus) {
4229
- if (newStatus !== "open" && newStatus !== "connecting") {
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
- const effects = config.mockedEffects || {
4349
- send(messageOrMessages) {
4350
- var _a2;
4351
- const message = JSON.stringify(messageOrMessages);
4352
- if (config.unstable_fallbackToHTTP) {
4353
- const size = new TextEncoder().encode(message).length;
4354
- if (size > MAX_MESSAGE_SIZE && managedSocket.token.raw && config.httpSendEndpoint) {
4355
- if (isTokenExpired(managedSocket.token.parsed)) {
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
- effects.send(messages);
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
- effects.send(messagesToFlush);
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 || WebSocket;
5213
- if (typeof WebSocket === "undefined" && WebSocketPolyfill === void 0) {
5214
- throw new Error(
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-fsm4"
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 (typeof window === "undefined" && fetchPolyfill === void 0) {
5248
- throw new Error(
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
- fetchPolyfill || /* istanbul ignore next */
5254
- fetch,
5255
- authentication.url,
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 (typeof window === "undefined" && fetchPolyfill === void 0) {
5266
- throw new Error(
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(fetchPolyfill || fetch, authentication.url, {
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
- 'Authentication error. We expect the authentication callback to return a token, but it does not. Hint: the return value should look like: { token: "..." }'
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 UnauthorizedError(yield res.text());
5296
+ throw new StopRetrying(`Unauthorized: ${reason}`);
5302
5297
  } else {
5303
- throw new AuthenticationError(
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 AuthenticationError(
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 AuthenticationError(
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
- 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;
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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liveblocks/core",
3
- "version": "1.1.0-fsm4",
3
+ "version": "1.1.0-test1",
4
4
  "description": "Shared code and foundational internals for Liveblocks",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",