@liveblocks/core 1.10.0-beta2 → 1.10.0-beta3

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.js CHANGED
@@ -6,7 +6,7 @@ var __export = (target, all) => {
6
6
 
7
7
  // src/version.ts
8
8
  var PKG_NAME = "@liveblocks/core";
9
- var PKG_VERSION = "1.10.0-beta2";
9
+ var PKG_VERSION = "1.10.0-beta3";
10
10
  var PKG_FORMAT = "cjs";
11
11
 
12
12
  // src/dupe-detection.ts
@@ -1325,7 +1325,7 @@ function createAuthManager(authOptions) {
1325
1325
  }
1326
1326
  return false;
1327
1327
  }
1328
- function getCachedToken(roomOptions) {
1328
+ function getCachedToken(requestOptions) {
1329
1329
  const now = Math.ceil(Date.now() / 1e3);
1330
1330
  for (let i = tokens.length - 1; i >= 0; i--) {
1331
1331
  const token = tokens[i];
@@ -1338,11 +1338,12 @@ function createAuthManager(authOptions) {
1338
1338
  if (token.parsed.k === "id" /* ID_TOKEN */) {
1339
1339
  return token;
1340
1340
  } else if (token.parsed.k === "acc" /* ACCESS_TOKEN */) {
1341
- if (!roomOptions) {
1342
- return token;
1343
- }
1344
1341
  for (const [resource, scopes] of Object.entries(token.parsed.perms)) {
1345
- if (resource.includes("*") && roomOptions.roomId.startsWith(resource.replace("*", "")) || roomOptions.roomId === resource && hasCorrespondingScopes(roomOptions.requestedScope, scopes)) {
1342
+ if (!requestOptions.roomId) {
1343
+ if (resource.includes("*") && hasCorrespondingScopes(requestOptions.requestedScope, scopes)) {
1344
+ return token;
1345
+ }
1346
+ } else if (resource.includes("*") && requestOptions.roomId.startsWith(resource.replace("*", "")) || requestOptions.roomId === resource && hasCorrespondingScopes(requestOptions.requestedScope, scopes)) {
1346
1347
  return token;
1347
1348
  }
1348
1349
  }
@@ -1350,7 +1351,7 @@ function createAuthManager(authOptions) {
1350
1351
  }
1351
1352
  return void 0;
1352
1353
  }
1353
- async function makeAuthRequest(roomId) {
1354
+ async function makeAuthRequest(options) {
1354
1355
  const fetcher = _nullishCoalesce(_optionalChain([authOptions, 'access', _36 => _36.polyfills, 'optionalAccess', _37 => _37.fetch]), () => ( (typeof window === "undefined" ? void 0 : window.fetch)));
1355
1356
  if (authentication.type === "private") {
1356
1357
  if (fetcher === void 0) {
@@ -1359,9 +1360,10 @@ function createAuthManager(authOptions) {
1359
1360
  );
1360
1361
  }
1361
1362
  const response = await fetchAuthEndpoint(fetcher, authentication.url, {
1362
- room: roomId
1363
+ room: options.roomId
1363
1364
  });
1364
1365
  const parsed = parseAuthToken(response.token);
1366
+ verifyTokenPermissions(parsed, options);
1365
1367
  if (seenTokens.has(parsed.raw)) {
1366
1368
  throw new StopRetrying(
1367
1369
  "The same Liveblocks auth token was issued from the backend before. Caching Liveblocks tokens is not supported."
@@ -1370,10 +1372,12 @@ function createAuthManager(authOptions) {
1370
1372
  return parsed;
1371
1373
  }
1372
1374
  if (authentication.type === "custom") {
1373
- const response = await authentication.callback(roomId);
1375
+ const response = await authentication.callback(options.roomId);
1374
1376
  if (response && typeof response === "object") {
1375
1377
  if (typeof response.token === "string") {
1376
- return parseAuthToken(response.token);
1378
+ const parsed = parseAuthToken(response.token);
1379
+ verifyTokenPermissions(parsed, options);
1380
+ return parsed;
1377
1381
  } else if (typeof response.error === "string") {
1378
1382
  const reason = `Authentication failed: ${"reason" in response && typeof response.reason === "string" ? response.reason : "Forbidden"}`;
1379
1383
  if (response.error === "forbidden") {
@@ -1391,25 +1395,39 @@ function createAuthManager(authOptions) {
1391
1395
  "Unexpected authentication type. Must be private or custom."
1392
1396
  );
1393
1397
  }
1394
- async function getAuthValue(roomOptions) {
1398
+ function verifyTokenPermissions(parsedToken, options) {
1399
+ if (!options.roomId && parsedToken.parsed.k === "acc" /* ACCESS_TOKEN */) {
1400
+ for (const [resource, scopes] of Object.entries(
1401
+ parsedToken.parsed.perms
1402
+ )) {
1403
+ if (resource.includes("*") && hasCorrespondingScopes(options.requestedScope, scopes)) {
1404
+ return;
1405
+ }
1406
+ }
1407
+ throw new StopRetrying(
1408
+ "The issued Access Token doesn't grant enough permissions. Please follow the instructions at https://liveblocks.io/docs/errors/liveblocks-client/access-tokens-not-enough-permissions"
1409
+ );
1410
+ }
1411
+ }
1412
+ async function getAuthValue(requestOptions) {
1395
1413
  if (authentication.type === "public") {
1396
1414
  return { type: "public", publicApiKey: authentication.publicApiKey };
1397
1415
  }
1398
- const cachedToken = getCachedToken(roomOptions);
1416
+ const cachedToken = getCachedToken(requestOptions);
1399
1417
  if (cachedToken !== void 0) {
1400
1418
  return { type: "secret", token: cachedToken };
1401
1419
  }
1402
1420
  let currentPromise;
1403
- if (roomOptions) {
1404
- currentPromise = requestPromises.get(roomOptions.roomId);
1421
+ if (requestOptions.roomId) {
1422
+ currentPromise = requestPromises.get(requestOptions.roomId);
1405
1423
  if (currentPromise === void 0) {
1406
- currentPromise = makeAuthRequest(roomOptions.roomId);
1407
- requestPromises.set(roomOptions.roomId, currentPromise);
1424
+ currentPromise = makeAuthRequest(requestOptions);
1425
+ requestPromises.set(requestOptions.roomId, currentPromise);
1408
1426
  }
1409
1427
  } else {
1410
1428
  currentPromise = requestPromises.get("liveblocks-user-token");
1411
1429
  if (currentPromise === void 0) {
1412
- currentPromise = makeAuthRequest();
1430
+ currentPromise = makeAuthRequest(requestOptions);
1413
1431
  requestPromises.set("liveblocks-user-token", currentPromise);
1414
1432
  }
1415
1433
  }
@@ -1424,8 +1442,8 @@ function createAuthManager(authOptions) {
1424
1442
  }
1425
1443
  return { type: "secret", token };
1426
1444
  } finally {
1427
- if (roomOptions) {
1428
- requestPromises.delete(roomOptions.roomId);
1445
+ if (requestOptions.roomId) {
1446
+ requestPromises.delete(requestOptions.roomId);
1429
1447
  } else {
1430
1448
  requestPromises.delete("liveblocks-user-token");
1431
1449
  }
@@ -1996,6 +2014,38 @@ function convertToInboxNotificationData(data) {
1996
2014
  readAt
1997
2015
  };
1998
2016
  }
2017
+ function convertToThreadDeleteInfo(data) {
2018
+ const deletedAt = new Date(data.deletedAt);
2019
+ return {
2020
+ ...data,
2021
+ deletedAt
2022
+ };
2023
+ }
2024
+ function convertToInboxNotificationDeleteInfo(data) {
2025
+ const deletedAt = new Date(data.deletedAt);
2026
+ return {
2027
+ ...data,
2028
+ deletedAt
2029
+ };
2030
+ }
2031
+
2032
+ // src/lib/url.ts
2033
+ function toURLSearchParams(params) {
2034
+ const result = new URLSearchParams();
2035
+ for (const [key, value] of Object.entries(params)) {
2036
+ if (value !== void 0 && value !== null) {
2037
+ result.set(key, value.toString());
2038
+ }
2039
+ }
2040
+ return result;
2041
+ }
2042
+ function urljoin(baseUrl, path, params) {
2043
+ const url = new URL(path, baseUrl);
2044
+ if (params !== void 0) {
2045
+ url.search = (params instanceof URLSearchParams ? params : toURLSearchParams(params)).toString();
2046
+ }
2047
+ return url.toString();
2048
+ }
1999
2049
 
2000
2050
  // src/notifications.ts
2001
2051
  var MARK_INBOX_NOTIFICATIONS_AS_READ_BATCH_DELAY = 50;
@@ -2005,13 +2055,15 @@ function createInboxNotificationsApi({
2005
2055
  currentUserIdStore,
2006
2056
  fetcher
2007
2057
  }) {
2008
- async function fetchJson(endpoint, options) {
2009
- const authValue = await authManager.getAuthValue();
2058
+ async function fetchJson(endpoint, options, params) {
2059
+ const authValue = await authManager.getAuthValue({
2060
+ requestedScope: "comments:read"
2061
+ });
2010
2062
  if (authValue.type === "secret" && authValue.token.parsed.k === "acc" /* ACCESS_TOKEN */) {
2011
2063
  const userId = authValue.token.parsed.uid;
2012
2064
  currentUserIdStore.set(() => userId);
2013
2065
  }
2014
- const url = new URL(`/v2/c${endpoint}`, baseUrl);
2066
+ const url = urljoin(baseUrl, `/v2/c${endpoint}`, params);
2015
2067
  const response = await fetcher(url.toString(), {
2016
2068
  ...options,
2017
2069
  headers: {
@@ -2047,13 +2099,24 @@ function createInboxNotificationsApi({
2047
2099
  return body;
2048
2100
  }
2049
2101
  async function getInboxNotifications(options) {
2050
- const queryParams = toURLSearchParams({ limit: _optionalChain([options, 'optionalAccess', _48 => _48.limit]) });
2051
- const json = await fetchJson(`/inbox-notifications?${queryParams.toString()}`);
2102
+ const json = await fetchJson("/inbox-notifications", void 0, {
2103
+ limit: _optionalChain([options, 'optionalAccess', _48 => _48.limit]),
2104
+ since: _optionalChain([options, 'optionalAccess', _49 => _49.since, 'optionalAccess', _50 => _50.toISOString, 'call', _51 => _51()])
2105
+ });
2052
2106
  return {
2053
2107
  threads: json.threads.map((thread) => convertToThreadData(thread)),
2054
2108
  inboxNotifications: json.inboxNotifications.map(
2055
2109
  (notification) => convertToInboxNotificationData(notification)
2056
- )
2110
+ ),
2111
+ deletedThreads: json.deletedThreads.map(
2112
+ (info) => convertToThreadDeleteInfo(info)
2113
+ ),
2114
+ deletedInboxNotifications: json.deletedInboxNotifications.map(
2115
+ (info) => convertToInboxNotificationDeleteInfo(info)
2116
+ ),
2117
+ meta: {
2118
+ requestedAt: new Date(json.meta.requestedAt)
2119
+ }
2057
2120
  };
2058
2121
  }
2059
2122
  async function getUnreadInboxNotificationsCount() {
@@ -2096,15 +2159,6 @@ function createInboxNotificationsApi({
2096
2159
  markInboxNotificationAsRead
2097
2160
  };
2098
2161
  }
2099
- function toURLSearchParams(params) {
2100
- const result = new URLSearchParams();
2101
- for (const [key, value] of Object.entries(params)) {
2102
- if (value !== void 0 && value !== null) {
2103
- result.set(key, value.toString());
2104
- }
2105
- }
2106
- return result;
2107
- }
2108
2162
 
2109
2163
  // src/lib/position.ts
2110
2164
  var MIN_CODE = 32;
@@ -2479,7 +2533,7 @@ var LiveRegister = class _LiveRegister extends AbstractCrdt {
2479
2533
  return [
2480
2534
  {
2481
2535
  type: 8 /* CREATE_REGISTER */,
2482
- opId: _optionalChain([pool, 'optionalAccess', _49 => _49.generateOpId, 'call', _50 => _50()]),
2536
+ opId: _optionalChain([pool, 'optionalAccess', _52 => _52.generateOpId, 'call', _53 => _53()]),
2483
2537
  id: this._id,
2484
2538
  parentId,
2485
2539
  parentKey,
@@ -2581,7 +2635,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
2581
2635
  const ops = [];
2582
2636
  const op = {
2583
2637
  id: this._id,
2584
- opId: _optionalChain([pool, 'optionalAccess', _51 => _51.generateOpId, 'call', _52 => _52()]),
2638
+ opId: _optionalChain([pool, 'optionalAccess', _54 => _54.generateOpId, 'call', _55 => _55()]),
2585
2639
  type: 2 /* CREATE_LIST */,
2586
2640
  parentId,
2587
2641
  parentKey
@@ -2858,7 +2912,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
2858
2912
  _applyInsertUndoRedo(op) {
2859
2913
  const { id, parentKey: key } = op;
2860
2914
  const child = creationOpToLiveNode(op);
2861
- if (_optionalChain([this, 'access', _53 => _53._pool, 'optionalAccess', _54 => _54.getNode, 'call', _55 => _55(id)]) !== void 0) {
2915
+ if (_optionalChain([this, 'access', _56 => _56._pool, 'optionalAccess', _57 => _57.getNode, 'call', _58 => _58(id)]) !== void 0) {
2862
2916
  return { modified: false };
2863
2917
  }
2864
2918
  child._attach(id, nn(this._pool));
@@ -2866,8 +2920,8 @@ var LiveList = class _LiveList extends AbstractCrdt {
2866
2920
  const existingItemIndex = this._indexOfPosition(key);
2867
2921
  let newKey = key;
2868
2922
  if (existingItemIndex !== -1) {
2869
- const before2 = _optionalChain([this, 'access', _56 => _56._items, 'access', _57 => _57[existingItemIndex], 'optionalAccess', _58 => _58._parentPos]);
2870
- const after2 = _optionalChain([this, 'access', _59 => _59._items, 'access', _60 => _60[existingItemIndex + 1], 'optionalAccess', _61 => _61._parentPos]);
2923
+ const before2 = _optionalChain([this, 'access', _59 => _59._items, 'access', _60 => _60[existingItemIndex], 'optionalAccess', _61 => _61._parentPos]);
2924
+ const after2 = _optionalChain([this, 'access', _62 => _62._items, 'access', _63 => _63[existingItemIndex + 1], 'optionalAccess', _64 => _64._parentPos]);
2871
2925
  newKey = makePosition(before2, after2);
2872
2926
  child._setParentLink(this, newKey);
2873
2927
  }
@@ -2882,7 +2936,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
2882
2936
  _applySetUndoRedo(op) {
2883
2937
  const { id, parentKey: key } = op;
2884
2938
  const child = creationOpToLiveNode(op);
2885
- if (_optionalChain([this, 'access', _62 => _62._pool, 'optionalAccess', _63 => _63.getNode, 'call', _64 => _64(id)]) !== void 0) {
2939
+ if (_optionalChain([this, 'access', _65 => _65._pool, 'optionalAccess', _66 => _66.getNode, 'call', _67 => _67(id)]) !== void 0) {
2886
2940
  return { modified: false };
2887
2941
  }
2888
2942
  this._unacknowledgedSets.set(key, nn(op.opId));
@@ -3004,7 +3058,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
3004
3058
  } else {
3005
3059
  this._items[existingItemIndex]._setParentLink(
3006
3060
  this,
3007
- makePosition(newKey, _optionalChain([this, 'access', _65 => _65._items, 'access', _66 => _66[existingItemIndex + 1], 'optionalAccess', _67 => _67._parentPos]))
3061
+ makePosition(newKey, _optionalChain([this, 'access', _68 => _68._items, 'access', _69 => _69[existingItemIndex + 1], 'optionalAccess', _70 => _70._parentPos]))
3008
3062
  );
3009
3063
  const previousIndex = this._items.indexOf(child);
3010
3064
  child._setParentLink(this, newKey);
@@ -3030,7 +3084,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
3030
3084
  if (existingItemIndex !== -1) {
3031
3085
  this._items[existingItemIndex]._setParentLink(
3032
3086
  this,
3033
- makePosition(newKey, _optionalChain([this, 'access', _68 => _68._items, 'access', _69 => _69[existingItemIndex + 1], 'optionalAccess', _70 => _70._parentPos]))
3087
+ makePosition(newKey, _optionalChain([this, 'access', _71 => _71._items, 'access', _72 => _72[existingItemIndex + 1], 'optionalAccess', _73 => _73._parentPos]))
3034
3088
  );
3035
3089
  }
3036
3090
  child._setParentLink(this, newKey);
@@ -3049,7 +3103,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
3049
3103
  if (existingItemIndex !== -1) {
3050
3104
  this._items[existingItemIndex]._setParentLink(
3051
3105
  this,
3052
- makePosition(newKey, _optionalChain([this, 'access', _71 => _71._items, 'access', _72 => _72[existingItemIndex + 1], 'optionalAccess', _73 => _73._parentPos]))
3106
+ makePosition(newKey, _optionalChain([this, 'access', _74 => _74._items, 'access', _75 => _75[existingItemIndex + 1], 'optionalAccess', _76 => _76._parentPos]))
3053
3107
  );
3054
3108
  }
3055
3109
  child._setParentLink(this, newKey);
@@ -3077,7 +3131,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
3077
3131
  if (existingItemIndex !== -1) {
3078
3132
  this._items[existingItemIndex]._setParentLink(
3079
3133
  this,
3080
- makePosition(newKey, _optionalChain([this, 'access', _74 => _74._items, 'access', _75 => _75[existingItemIndex + 1], 'optionalAccess', _76 => _76._parentPos]))
3134
+ makePosition(newKey, _optionalChain([this, 'access', _77 => _77._items, 'access', _78 => _78[existingItemIndex + 1], 'optionalAccess', _79 => _79._parentPos]))
3081
3135
  );
3082
3136
  }
3083
3137
  child._setParentLink(this, newKey);
@@ -3135,7 +3189,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
3135
3189
  * @param element The element to add to the end of the LiveList.
3136
3190
  */
3137
3191
  push(element) {
3138
- _optionalChain([this, 'access', _77 => _77._pool, 'optionalAccess', _78 => _78.assertStorageIsWritable, 'call', _79 => _79()]);
3192
+ _optionalChain([this, 'access', _80 => _80._pool, 'optionalAccess', _81 => _81.assertStorageIsWritable, 'call', _82 => _82()]);
3139
3193
  return this.insert(element, this.length);
3140
3194
  }
3141
3195
  /**
@@ -3144,7 +3198,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
3144
3198
  * @param index The index at which you want to insert the element.
3145
3199
  */
3146
3200
  insert(element, index) {
3147
- _optionalChain([this, 'access', _80 => _80._pool, 'optionalAccess', _81 => _81.assertStorageIsWritable, 'call', _82 => _82()]);
3201
+ _optionalChain([this, 'access', _83 => _83._pool, 'optionalAccess', _84 => _84.assertStorageIsWritable, 'call', _85 => _85()]);
3148
3202
  if (index < 0 || index > this._items.length) {
3149
3203
  throw new Error(
3150
3204
  `Cannot insert list item at index "${index}". index should be between 0 and ${this._items.length}`
@@ -3174,7 +3228,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
3174
3228
  * @param targetIndex The index where the element should be after moving.
3175
3229
  */
3176
3230
  move(index, targetIndex) {
3177
- _optionalChain([this, 'access', _83 => _83._pool, 'optionalAccess', _84 => _84.assertStorageIsWritable, 'call', _85 => _85()]);
3231
+ _optionalChain([this, 'access', _86 => _86._pool, 'optionalAccess', _87 => _87.assertStorageIsWritable, 'call', _88 => _88()]);
3178
3232
  if (targetIndex < 0) {
3179
3233
  throw new Error("targetIndex cannot be less than 0");
3180
3234
  }
@@ -3232,7 +3286,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
3232
3286
  * @param index The index of the element to delete
3233
3287
  */
3234
3288
  delete(index) {
3235
- _optionalChain([this, 'access', _86 => _86._pool, 'optionalAccess', _87 => _87.assertStorageIsWritable, 'call', _88 => _88()]);
3289
+ _optionalChain([this, 'access', _89 => _89._pool, 'optionalAccess', _90 => _90.assertStorageIsWritable, 'call', _91 => _91()]);
3236
3290
  if (index < 0 || index >= this._items.length) {
3237
3291
  throw new Error(
3238
3292
  `Cannot delete list item at index "${index}". index should be between 0 and ${this._items.length - 1}`
@@ -3265,7 +3319,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
3265
3319
  }
3266
3320
  }
3267
3321
  clear() {
3268
- _optionalChain([this, 'access', _89 => _89._pool, 'optionalAccess', _90 => _90.assertStorageIsWritable, 'call', _91 => _91()]);
3322
+ _optionalChain([this, 'access', _92 => _92._pool, 'optionalAccess', _93 => _93.assertStorageIsWritable, 'call', _94 => _94()]);
3269
3323
  if (this._pool) {
3270
3324
  const ops = [];
3271
3325
  const reverseOps = [];
@@ -3299,7 +3353,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
3299
3353
  }
3300
3354
  }
3301
3355
  set(index, item) {
3302
- _optionalChain([this, 'access', _92 => _92._pool, 'optionalAccess', _93 => _93.assertStorageIsWritable, 'call', _94 => _94()]);
3356
+ _optionalChain([this, 'access', _95 => _95._pool, 'optionalAccess', _96 => _96.assertStorageIsWritable, 'call', _97 => _97()]);
3303
3357
  if (index < 0 || index >= this._items.length) {
3304
3358
  throw new Error(
3305
3359
  `Cannot set list item at index "${index}". index should be between 0 and ${this._items.length - 1}`
@@ -3447,7 +3501,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
3447
3501
  _shiftItemPosition(index, key) {
3448
3502
  const shiftedPosition = makePosition(
3449
3503
  key,
3450
- this._items.length > index + 1 ? _optionalChain([this, 'access', _95 => _95._items, 'access', _96 => _96[index + 1], 'optionalAccess', _97 => _97._parentPos]) : void 0
3504
+ this._items.length > index + 1 ? _optionalChain([this, 'access', _98 => _98._items, 'access', _99 => _99[index + 1], 'optionalAccess', _100 => _100._parentPos]) : void 0
3451
3505
  );
3452
3506
  this._items[index]._setParentLink(this, shiftedPosition);
3453
3507
  }
@@ -3576,7 +3630,7 @@ var LiveMap = class _LiveMap extends AbstractCrdt {
3576
3630
  const ops = [];
3577
3631
  const op = {
3578
3632
  id: this._id,
3579
- opId: _optionalChain([pool, 'optionalAccess', _98 => _98.generateOpId, 'call', _99 => _99()]),
3633
+ opId: _optionalChain([pool, 'optionalAccess', _101 => _101.generateOpId, 'call', _102 => _102()]),
3580
3634
  type: 7 /* CREATE_MAP */,
3581
3635
  parentId,
3582
3636
  parentKey
@@ -3723,7 +3777,7 @@ var LiveMap = class _LiveMap extends AbstractCrdt {
3723
3777
  * @param value The value of the element to add. Should be serializable to JSON.
3724
3778
  */
3725
3779
  set(key, value) {
3726
- _optionalChain([this, 'access', _100 => _100._pool, 'optionalAccess', _101 => _101.assertStorageIsWritable, 'call', _102 => _102()]);
3780
+ _optionalChain([this, 'access', _103 => _103._pool, 'optionalAccess', _104 => _104.assertStorageIsWritable, 'call', _105 => _105()]);
3727
3781
  const oldValue = this._map.get(key);
3728
3782
  if (oldValue) {
3729
3783
  oldValue._detach();
@@ -3769,7 +3823,7 @@ var LiveMap = class _LiveMap extends AbstractCrdt {
3769
3823
  * @returns true if an element existed and has been removed, or false if the element does not exist.
3770
3824
  */
3771
3825
  delete(key) {
3772
- _optionalChain([this, 'access', _103 => _103._pool, 'optionalAccess', _104 => _104.assertStorageIsWritable, 'call', _105 => _105()]);
3826
+ _optionalChain([this, 'access', _106 => _106._pool, 'optionalAccess', _107 => _107.assertStorageIsWritable, 'call', _108 => _108()]);
3773
3827
  const item = this._map.get(key);
3774
3828
  if (item === void 0) {
3775
3829
  return false;
@@ -3948,7 +4002,7 @@ var LiveObject = class _LiveObject extends AbstractCrdt {
3948
4002
  if (this._id === void 0) {
3949
4003
  throw new Error("Cannot serialize item is not attached");
3950
4004
  }
3951
- const opId = _optionalChain([pool, 'optionalAccess', _106 => _106.generateOpId, 'call', _107 => _107()]);
4005
+ const opId = _optionalChain([pool, 'optionalAccess', _109 => _109.generateOpId, 'call', _110 => _110()]);
3952
4006
  const ops = [];
3953
4007
  const op = {
3954
4008
  type: 4 /* CREATE_OBJECT */,
@@ -4226,7 +4280,7 @@ var LiveObject = class _LiveObject extends AbstractCrdt {
4226
4280
  * @param value The value of the property to add
4227
4281
  */
4228
4282
  set(key, value) {
4229
- _optionalChain([this, 'access', _108 => _108._pool, 'optionalAccess', _109 => _109.assertStorageIsWritable, 'call', _110 => _110()]);
4283
+ _optionalChain([this, 'access', _111 => _111._pool, 'optionalAccess', _112 => _112.assertStorageIsWritable, 'call', _113 => _113()]);
4230
4284
  this.update({ [key]: value });
4231
4285
  }
4232
4286
  /**
@@ -4241,7 +4295,7 @@ var LiveObject = class _LiveObject extends AbstractCrdt {
4241
4295
  * @param key The key of the property to delete
4242
4296
  */
4243
4297
  delete(key) {
4244
- _optionalChain([this, 'access', _111 => _111._pool, 'optionalAccess', _112 => _112.assertStorageIsWritable, 'call', _113 => _113()]);
4298
+ _optionalChain([this, 'access', _114 => _114._pool, 'optionalAccess', _115 => _115.assertStorageIsWritable, 'call', _116 => _116()]);
4245
4299
  const keyAsString = key;
4246
4300
  const oldValue = this._map.get(keyAsString);
4247
4301
  if (oldValue === void 0) {
@@ -4294,7 +4348,7 @@ var LiveObject = class _LiveObject extends AbstractCrdt {
4294
4348
  * @param patch The object used to overrides properties
4295
4349
  */
4296
4350
  update(patch) {
4297
- _optionalChain([this, 'access', _114 => _114._pool, 'optionalAccess', _115 => _115.assertStorageIsWritable, 'call', _116 => _116()]);
4351
+ _optionalChain([this, 'access', _117 => _117._pool, 'optionalAccess', _118 => _118.assertStorageIsWritable, 'call', _119 => _119()]);
4298
4352
  if (this._pool === void 0 || this._id === void 0) {
4299
4353
  for (const key in patch) {
4300
4354
  const newValue = patch[key];
@@ -4938,15 +4992,15 @@ function installBackgroundTabSpy() {
4938
4992
  const doc = typeof document !== "undefined" ? document : void 0;
4939
4993
  const inBackgroundSince = { current: null };
4940
4994
  function onVisibilityChange() {
4941
- if (_optionalChain([doc, 'optionalAccess', _117 => _117.visibilityState]) === "hidden") {
4995
+ if (_optionalChain([doc, 'optionalAccess', _120 => _120.visibilityState]) === "hidden") {
4942
4996
  inBackgroundSince.current = _nullishCoalesce(inBackgroundSince.current, () => ( Date.now()));
4943
4997
  } else {
4944
4998
  inBackgroundSince.current = null;
4945
4999
  }
4946
5000
  }
4947
- _optionalChain([doc, 'optionalAccess', _118 => _118.addEventListener, 'call', _119 => _119("visibilitychange", onVisibilityChange)]);
5001
+ _optionalChain([doc, 'optionalAccess', _121 => _121.addEventListener, 'call', _122 => _122("visibilitychange", onVisibilityChange)]);
4948
5002
  const unsub = () => {
4949
- _optionalChain([doc, 'optionalAccess', _120 => _120.removeEventListener, 'call', _121 => _121("visibilitychange", onVisibilityChange)]);
5003
+ _optionalChain([doc, 'optionalAccess', _123 => _123.removeEventListener, 'call', _124 => _124("visibilitychange", onVisibilityChange)]);
4950
5004
  };
4951
5005
  return [inBackgroundSince, unsub];
4952
5006
  }
@@ -4959,12 +5013,12 @@ var CommentsApiError = class extends Error {
4959
5013
  }
4960
5014
  };
4961
5015
  function createCommentsApi(roomId, getAuthValue, fetchClientApi) {
4962
- async function fetchCommentsApi(endpoint, options) {
5016
+ async function fetchCommentsApi(endpoint, params, options) {
4963
5017
  const authValue = await getAuthValue();
4964
- return fetchClientApi(roomId, endpoint, authValue, options);
5018
+ return fetchClientApi(roomId, endpoint, authValue, options, params);
4965
5019
  }
4966
- async function fetchJson(endpoint, options) {
4967
- const response = await fetchCommentsApi(endpoint, options);
5020
+ async function fetchJson(endpoint, options, params) {
5021
+ const response = await fetchCommentsApi(endpoint, params, options);
4968
5022
  if (!response.ok) {
4969
5023
  if (response.status >= 400 && response.status < 600) {
4970
5024
  let error3;
@@ -4990,25 +5044,48 @@ function createCommentsApi(roomId, getAuthValue, fetchClientApi) {
4990
5044
  return body;
4991
5045
  }
4992
5046
  async function getThreads(options) {
4993
- const response = await fetchCommentsApi("/threads/search", {
4994
- body: JSON.stringify({
4995
- ..._optionalChain([options, 'optionalAccess', _122 => _122.query, 'optionalAccess', _123 => _123.metadata]) && { metadata: options.query.metadata }
4996
- }),
4997
- headers: {
4998
- "Content-Type": "application/json"
5047
+ const response = await fetchCommentsApi(
5048
+ "/threads/search",
5049
+ {
5050
+ since: _optionalChain([options, 'optionalAccess', _125 => _125.since, 'optionalAccess', _126 => _126.toISOString, 'call', _127 => _127()])
4999
5051
  },
5000
- method: "POST"
5001
- });
5052
+ {
5053
+ body: JSON.stringify({
5054
+ ..._optionalChain([options, 'optionalAccess', _128 => _128.query, 'optionalAccess', _129 => _129.metadata]) && { metadata: options.query.metadata }
5055
+ }),
5056
+ headers: {
5057
+ "Content-Type": "application/json"
5058
+ },
5059
+ method: "POST"
5060
+ }
5061
+ );
5002
5062
  if (response.ok) {
5003
5063
  const json = await response.json();
5004
5064
  return {
5005
5065
  threads: json.data.map((thread) => convertToThreadData(thread)),
5006
5066
  inboxNotifications: json.inboxNotifications.map(
5007
5067
  (notification) => convertToInboxNotificationData(notification)
5008
- )
5068
+ ),
5069
+ deletedThreads: json.deletedThreads.map(
5070
+ (info) => convertToThreadDeleteInfo(info)
5071
+ ),
5072
+ deletedInboxNotifications: json.deletedInboxNotifications.map(
5073
+ (info) => convertToInboxNotificationDeleteInfo(info)
5074
+ ),
5075
+ meta: {
5076
+ requestedAt: new Date(json.meta.requestedAt)
5077
+ }
5009
5078
  };
5010
5079
  } else if (response.status === 404) {
5011
- return { threads: [], inboxNotifications: [] };
5080
+ return {
5081
+ threads: [],
5082
+ inboxNotifications: [],
5083
+ deletedThreads: [],
5084
+ deletedInboxNotifications: [],
5085
+ meta: {
5086
+ requestedAt: /* @__PURE__ */ new Date()
5087
+ }
5088
+ };
5012
5089
  } else {
5013
5090
  throw new Error("There was an error while getting threads.");
5014
5091
  }
@@ -5215,6 +5292,9 @@ function createRoom(options, config) {
5215
5292
  opClock: 0,
5216
5293
  nodes: /* @__PURE__ */ new Map(),
5217
5294
  root: void 0,
5295
+ comments: {
5296
+ lastRequestedAt: null
5297
+ },
5218
5298
  undoStack: [],
5219
5299
  redoStack: [],
5220
5300
  pausedHistory: null,
@@ -5353,7 +5433,7 @@ function createRoom(options, config) {
5353
5433
  }
5354
5434
  },
5355
5435
  assertStorageIsWritable: () => {
5356
- const scopes = _optionalChain([context, 'access', _124 => _124.dynamicSessionInfo, 'access', _125 => _125.current, 'optionalAccess', _126 => _126.scopes]);
5436
+ const scopes = _optionalChain([context, 'access', _130 => _130.dynamicSessionInfo, 'access', _131 => _131.current, 'optionalAccess', _132 => _132.scopes]);
5357
5437
  if (scopes === void 0) {
5358
5438
  return;
5359
5439
  }
@@ -5383,17 +5463,18 @@ function createRoom(options, config) {
5383
5463
  ydoc: makeEventSource(),
5384
5464
  comments: makeEventSource()
5385
5465
  };
5386
- async function fetchClientApi(roomId, endpoint, authValue, options2) {
5387
- const url = new URL(
5466
+ async function fetchClientApi(roomId, endpoint, authValue, options2, params) {
5467
+ const url = urljoin(
5468
+ config.baseUrl,
5388
5469
  `/v2/c/rooms/${encodeURIComponent(roomId)}${endpoint}`,
5389
- config.baseUrl
5470
+ params
5390
5471
  );
5391
- const fetcher = _optionalChain([config, 'access', _127 => _127.polyfills, 'optionalAccess', _128 => _128.fetch]) || /* istanbul ignore next */
5472
+ const fetcher = _optionalChain([config, 'access', _133 => _133.polyfills, 'optionalAccess', _134 => _134.fetch]) || /* istanbul ignore next */
5392
5473
  fetch;
5393
- return await fetcher(url.toString(), {
5474
+ return await fetcher(url, {
5394
5475
  ...options2,
5395
5476
  headers: {
5396
- ..._optionalChain([options2, 'optionalAccess', _129 => _129.headers]),
5477
+ ..._optionalChain([options2, 'optionalAccess', _135 => _135.headers]),
5397
5478
  Authorization: `Bearer ${getAuthBearerHeaderFromAuthValue(authValue)}`
5398
5479
  }
5399
5480
  });
@@ -5420,7 +5501,7 @@ function createRoom(options, config) {
5420
5501
  }
5421
5502
  function sendMessages(messages) {
5422
5503
  const serializedPayload = JSON.stringify(messages);
5423
- const nonce = _optionalChain([context, 'access', _130 => _130.dynamicSessionInfo, 'access', _131 => _131.current, 'optionalAccess', _132 => _132.nonce]);
5504
+ const nonce = _optionalChain([context, 'access', _136 => _136.dynamicSessionInfo, 'access', _137 => _137.current, 'optionalAccess', _138 => _138.nonce]);
5424
5505
  if (config.unstable_fallbackToHTTP && nonce) {
5425
5506
  const size = new TextEncoder().encode(serializedPayload).length;
5426
5507
  if (size > MAX_SOCKET_MESSAGE_SIZE) {
@@ -5682,7 +5763,7 @@ function createRoom(options, config) {
5682
5763
  }
5683
5764
  context.myPresence.patch(patch);
5684
5765
  if (context.activeBatch) {
5685
- if (_optionalChain([options2, 'optionalAccess', _133 => _133.addToHistory])) {
5766
+ if (_optionalChain([options2, 'optionalAccess', _139 => _139.addToHistory])) {
5686
5767
  context.activeBatch.reverseOps.unshift({
5687
5768
  type: "presence",
5688
5769
  data: oldValues
@@ -5692,7 +5773,7 @@ function createRoom(options, config) {
5692
5773
  } else {
5693
5774
  flushNowOrSoon();
5694
5775
  batchUpdates(() => {
5695
- if (_optionalChain([options2, 'optionalAccess', _134 => _134.addToHistory])) {
5776
+ if (_optionalChain([options2, 'optionalAccess', _140 => _140.addToHistory])) {
5696
5777
  addToUndoStack(
5697
5778
  [{ type: "presence", data: oldValues }],
5698
5779
  doNotBatchUpdates
@@ -5890,7 +5971,7 @@ function createRoom(options, config) {
5890
5971
  if (process.env.NODE_ENV !== "production") {
5891
5972
  const traces = /* @__PURE__ */ new Set();
5892
5973
  for (const opId of message.opIds) {
5893
- const trace = _optionalChain([context, 'access', _135 => _135.opStackTraces, 'optionalAccess', _136 => _136.get, 'call', _137 => _137(opId)]);
5974
+ const trace = _optionalChain([context, 'access', _141 => _141.opStackTraces, 'optionalAccess', _142 => _142.get, 'call', _143 => _143(opId)]);
5894
5975
  if (trace) {
5895
5976
  traces.add(trace);
5896
5977
  }
@@ -6019,7 +6100,7 @@ ${Array.from(traces).join("\n\n")}`
6019
6100
  const unacknowledgedOps = new Map(context.unacknowledgedOps);
6020
6101
  createOrUpdateRootFromMessage(message, doNotBatchUpdates);
6021
6102
  applyAndSendOps(unacknowledgedOps, doNotBatchUpdates);
6022
- _optionalChain([_resolveStoragePromise, 'optionalCall', _138 => _138()]);
6103
+ _optionalChain([_resolveStoragePromise, 'optionalCall', _144 => _144()]);
6023
6104
  notifyStorageStatus();
6024
6105
  eventHub.storageDidLoad.notify();
6025
6106
  }
@@ -6265,7 +6346,7 @@ ${Array.from(traces).join("\n\n")}`
6265
6346
  /* NOTE: Exposing internals here only to allow testing implementation details in unit tests */
6266
6347
  [kInternal]: {
6267
6348
  get presenceBuffer() {
6268
- return deepClone(_nullishCoalesce(_optionalChain([context, 'access', _139 => _139.buffer, 'access', _140 => _140.presenceUpdates, 'optionalAccess', _141 => _141.data]), () => ( null)));
6349
+ return deepClone(_nullishCoalesce(_optionalChain([context, 'access', _145 => _145.buffer, 'access', _146 => _146.presenceUpdates, 'optionalAccess', _147 => _147.data]), () => ( null)));
6269
6350
  },
6270
6351
  // prettier-ignore
6271
6352
  get undoStack() {
@@ -6284,6 +6365,14 @@ ${Array.from(traces).join("\n\n")}`
6284
6365
  // These exist only for our E2E testing app
6285
6366
  explicitClose: (event) => managedSocket._privateSendMachineEvent({ type: "EXPLICIT_SOCKET_CLOSE", event }),
6286
6367
  rawSend: (data) => managedSocket.send(data)
6368
+ },
6369
+ comments: {
6370
+ get lastRequestedAt() {
6371
+ return context.comments.lastRequestedAt;
6372
+ },
6373
+ set lastRequestedAt(value) {
6374
+ context.comments.lastRequestedAt = value;
6375
+ }
6287
6376
  }
6288
6377
  },
6289
6378
  id: config.roomId,
@@ -6411,7 +6500,7 @@ function makeClassicSubscribeFn(events) {
6411
6500
  }
6412
6501
  if (isLiveNode(first)) {
6413
6502
  const node = first;
6414
- if (_optionalChain([options, 'optionalAccess', _142 => _142.isDeep])) {
6503
+ if (_optionalChain([options, 'optionalAccess', _148 => _148.isDeep])) {
6415
6504
  const storageCallback = second;
6416
6505
  return subscribeToLiveStructureDeeply(node, storageCallback);
6417
6506
  } else {
@@ -6466,28 +6555,6 @@ function createClientStore() {
6466
6555
  inboxNotifications: {},
6467
6556
  notificationSettings: {}
6468
6557
  });
6469
- function mergeThreads(existingThreads, newThreads) {
6470
- const updatedThreads = { ...existingThreads };
6471
- Object.entries(newThreads).forEach(([id, thread]) => {
6472
- const existingThread = updatedThreads[id];
6473
- if (existingThread) {
6474
- const result = compareThreads(existingThread, thread);
6475
- if (result === 1)
6476
- return;
6477
- }
6478
- updatedThreads[id] = thread;
6479
- });
6480
- return updatedThreads;
6481
- }
6482
- function mergeNotifications(existingInboxNotifications, newInboxNotifications) {
6483
- const inboxNotifications = Object.values({
6484
- ...existingInboxNotifications,
6485
- ...newInboxNotifications
6486
- });
6487
- return Object.fromEntries(
6488
- inboxNotifications.map((notification) => [notification.id, notification])
6489
- );
6490
- }
6491
6558
  return {
6492
6559
  ...store,
6493
6560
  deleteThread(threadId) {
@@ -6516,21 +6583,19 @@ function createClientStore() {
6516
6583
  };
6517
6584
  });
6518
6585
  },
6519
- updateThreadsAndNotifications(threads, inboxNotifications, queryKey) {
6586
+ updateThreadsAndNotifications(threads, inboxNotifications, deletedThreads, deletedInboxNotifications, queryKey) {
6520
6587
  store.set((state) => ({
6521
6588
  ...state,
6522
- threads: mergeThreads(
6523
- state.threads,
6524
- Object.fromEntries(threads.map((thread) => [thread.id, thread]))
6525
- ),
6526
- inboxNotifications: mergeNotifications(
6589
+ threads: applyThreadUpdates(state.threads, {
6590
+ newThreads: threads,
6591
+ deletedThreads
6592
+ }),
6593
+ inboxNotifications: applyNotificationsUpdates(
6527
6594
  state.inboxNotifications,
6528
- Object.fromEntries(
6529
- inboxNotifications.map((notification) => [
6530
- notification.id,
6531
- notification
6532
- ])
6533
- )
6595
+ {
6596
+ newInboxNotifications: inboxNotifications,
6597
+ deletedNotifications: deletedInboxNotifications
6598
+ }
6534
6599
  ),
6535
6600
  queries: queryKey !== void 0 ? {
6536
6601
  ...state.queries,
@@ -6540,6 +6605,21 @@ function createClientStore() {
6540
6605
  } : state.queries
6541
6606
  }));
6542
6607
  },
6608
+ updateRoomInboxNotificationSettings(roomId, settings, queryKey) {
6609
+ store.set((state) => ({
6610
+ ...state,
6611
+ notificationSettings: {
6612
+ ...state.notificationSettings,
6613
+ [roomId]: settings
6614
+ },
6615
+ queries: {
6616
+ ...state.queries,
6617
+ [queryKey]: {
6618
+ isLoading: false
6619
+ }
6620
+ }
6621
+ }));
6622
+ },
6543
6623
  pushOptimisticUpdate(optimisticUpdate) {
6544
6624
  store.set((state) => ({
6545
6625
  ...state,
@@ -6777,6 +6857,59 @@ function applyOptimisticUpdates(state) {
6777
6857
  }
6778
6858
  return result;
6779
6859
  }
6860
+ function applyThreadUpdates(existingThreads, updates) {
6861
+ const updatedThreads = { ...existingThreads };
6862
+ updates.newThreads.forEach((thread) => {
6863
+ const existingThread = updatedThreads[thread.id];
6864
+ if (existingThread) {
6865
+ const result = compareThreads(existingThread, thread);
6866
+ if (result === 1)
6867
+ return;
6868
+ }
6869
+ updatedThreads[thread.id] = thread;
6870
+ });
6871
+ updates.deletedThreads.forEach(({ id, deletedAt }) => {
6872
+ const existingThread = updatedThreads[id];
6873
+ if (existingThread === void 0)
6874
+ return;
6875
+ existingThread.deletedAt = deletedAt;
6876
+ existingThread.updatedAt = deletedAt;
6877
+ existingThread.comments = [];
6878
+ });
6879
+ return updatedThreads;
6880
+ }
6881
+ function applyNotificationsUpdates(existingInboxNotifications, updates) {
6882
+ const updatedInboxNotifications = { ...existingInboxNotifications };
6883
+ updates.newInboxNotifications.forEach((notification) => {
6884
+ const existingNotification = updatedInboxNotifications[notification.id];
6885
+ if (existingNotification) {
6886
+ const result = compareInboxNotifications(
6887
+ existingNotification,
6888
+ notification
6889
+ );
6890
+ if (result === 1)
6891
+ return;
6892
+ }
6893
+ updatedInboxNotifications[notification.id] = notification;
6894
+ });
6895
+ updates.deletedNotifications.forEach(
6896
+ ({ id }) => delete updatedInboxNotifications[id]
6897
+ );
6898
+ return updatedInboxNotifications;
6899
+ }
6900
+ function compareInboxNotifications(inboxNotificationA, inboxNotificationB) {
6901
+ if (inboxNotificationA.notifiedAt > inboxNotificationB.notifiedAt) {
6902
+ return 1;
6903
+ } else if (inboxNotificationA.notifiedAt < inboxNotificationB.notifiedAt) {
6904
+ return -1;
6905
+ }
6906
+ if (inboxNotificationA.readAt && inboxNotificationB.readAt) {
6907
+ return inboxNotificationA.readAt > inboxNotificationB.readAt ? 1 : inboxNotificationA.readAt < inboxNotificationB.readAt ? -1 : 0;
6908
+ } else if (inboxNotificationA.readAt || inboxNotificationB.readAt) {
6909
+ return inboxNotificationA.readAt ? 1 : -1;
6910
+ }
6911
+ return 0;
6912
+ }
6780
6913
 
6781
6914
  // src/client.ts
6782
6915
  var MIN_THROTTLE = 16;
@@ -6866,12 +6999,12 @@ function createClient(options) {
6866
6999
  createSocket: makeCreateSocketDelegateForRoom(
6867
7000
  roomId,
6868
7001
  baseUrl,
6869
- _optionalChain([clientOptions, 'access', _143 => _143.polyfills, 'optionalAccess', _144 => _144.WebSocket])
7002
+ _optionalChain([clientOptions, 'access', _149 => _149.polyfills, 'optionalAccess', _150 => _150.WebSocket])
6870
7003
  ),
6871
7004
  authenticate: makeAuthDelegateForRoom(roomId, authManager)
6872
7005
  })),
6873
7006
  enableDebugLogging: clientOptions.enableDebugLogging,
6874
- unstable_batchedUpdates: _optionalChain([options2, 'optionalAccess', _145 => _145.unstable_batchedUpdates]),
7007
+ unstable_batchedUpdates: _optionalChain([options2, 'optionalAccess', _151 => _151.unstable_batchedUpdates]),
6875
7008
  baseUrl,
6876
7009
  unstable_fallbackToHTTP: !!clientOptions.unstable_fallbackToHTTP,
6877
7010
  unstable_streamData: !!clientOptions.unstable_streamData
@@ -6887,7 +7020,7 @@ function createClient(options) {
6887
7020
  const shouldConnect = _nullishCoalesce(_nullishCoalesce(options2.autoConnect, () => ( options2.shouldInitiallyConnect)), () => ( true));
6888
7021
  if (shouldConnect) {
6889
7022
  if (typeof atob === "undefined") {
6890
- if (_optionalChain([clientOptions, 'access', _146 => _146.polyfills, 'optionalAccess', _147 => _147.atob]) === void 0) {
7023
+ if (_optionalChain([clientOptions, 'access', _152 => _152.polyfills, 'optionalAccess', _153 => _153.atob]) === void 0) {
6891
7024
  throw new Error(
6892
7025
  "You need to polyfill atob to use the client in your environment. Please follow the instructions at https://liveblocks.io/docs/errors/liveblocks-client/atob-polyfill"
6893
7026
  );
@@ -6903,11 +7036,11 @@ function createClient(options) {
6903
7036
  return room;
6904
7037
  }
6905
7038
  function getRoom(roomId) {
6906
- const room = _optionalChain([roomsById, 'access', _148 => _148.get, 'call', _149 => _149(roomId), 'optionalAccess', _150 => _150.room]);
7039
+ const room = _optionalChain([roomsById, 'access', _154 => _154.get, 'call', _155 => _155(roomId), 'optionalAccess', _156 => _156.room]);
6907
7040
  return room ? room : null;
6908
7041
  }
6909
7042
  function forceLeave(roomId) {
6910
- const unsubs = _nullishCoalesce(_optionalChain([roomsById, 'access', _151 => _151.get, 'call', _152 => _152(roomId), 'optionalAccess', _153 => _153.unsubs]), () => ( /* @__PURE__ */ new Set()));
7043
+ const unsubs = _nullishCoalesce(_optionalChain([roomsById, 'access', _157 => _157.get, 'call', _158 => _158(roomId), 'optionalAccess', _159 => _159.unsubs]), () => ( /* @__PURE__ */ new Set()));
6911
7044
  for (const unsub of unsubs) {
6912
7045
  unsub();
6913
7046
  }
@@ -6928,7 +7061,7 @@ function createClient(options) {
6928
7061
  markInboxNotificationAsRead
6929
7062
  } = createInboxNotificationsApi({
6930
7063
  baseUrl,
6931
- fetcher: _optionalChain([clientOptions, 'access', _154 => _154.polyfills, 'optionalAccess', _155 => _155.fetch]) || /* istanbul ignore next */
7064
+ fetcher: _optionalChain([clientOptions, 'access', _160 => _160.polyfills, 'optionalAccess', _161 => _161.fetch]) || /* istanbul ignore next */
6932
7065
  fetch,
6933
7066
  authManager,
6934
7067
  currentUserIdStore
@@ -6942,7 +7075,7 @@ function createClient(options) {
6942
7075
  const usersStore = createBatchStore(
6943
7076
  async (batchedUserIds) => {
6944
7077
  const userIds = batchedUserIds.flat();
6945
- const users = await _optionalChain([resolveUsers, 'optionalCall', _156 => _156({ userIds })]);
7078
+ const users = await _optionalChain([resolveUsers, 'optionalCall', _162 => _162({ userIds })]);
6946
7079
  warnIfNoResolveUsers();
6947
7080
  return _nullishCoalesce(users, () => ( userIds.map(() => void 0)));
6948
7081
  },
@@ -6956,7 +7089,7 @@ function createClient(options) {
6956
7089
  const roomsInfoStore = createBatchStore(
6957
7090
  async (batchedRoomIds) => {
6958
7091
  const roomIds = batchedRoomIds.flat();
6959
- const roomsInfo = await _optionalChain([resolveRoomsInfo, 'optionalCall', _157 => _157({ roomIds })]);
7092
+ const roomsInfo = await _optionalChain([resolveRoomsInfo, 'optionalCall', _163 => _163({ roomIds })]);
6960
7093
  warnIfNoResolveRoomsInfo();
6961
7094
  return _nullishCoalesce(roomsInfo, () => ( roomIds.map(() => void 0)));
6962
7095
  },
@@ -6982,7 +7115,10 @@ function createClient(options) {
6982
7115
  resolveMentionSuggestions: clientOptions.resolveMentionSuggestions,
6983
7116
  cacheStore,
6984
7117
  usersStore,
6985
- roomsInfoStore
7118
+ roomsInfoStore,
7119
+ getRoomIds() {
7120
+ return Array.from(roomsById.keys());
7121
+ }
6986
7122
  }
6987
7123
  },
6988
7124
  kInternal,
@@ -7069,7 +7205,7 @@ var commentBodyElementsTypes = {
7069
7205
  mention: "inline"
7070
7206
  };
7071
7207
  function traverseCommentBody(body, elementOrVisitor, possiblyVisitor) {
7072
- if (!body || !_optionalChain([body, 'optionalAccess', _158 => _158.content])) {
7208
+ if (!body || !_optionalChain([body, 'optionalAccess', _164 => _164.content])) {
7073
7209
  return;
7074
7210
  }
7075
7211
  const element = typeof elementOrVisitor === "string" ? elementOrVisitor : void 0;
@@ -7079,13 +7215,13 @@ function traverseCommentBody(body, elementOrVisitor, possiblyVisitor) {
7079
7215
  for (const block of body.content) {
7080
7216
  if (type === "all" || type === "block") {
7081
7217
  if (guard(block)) {
7082
- _optionalChain([visitor, 'optionalCall', _159 => _159(block)]);
7218
+ _optionalChain([visitor, 'optionalCall', _165 => _165(block)]);
7083
7219
  }
7084
7220
  }
7085
7221
  if (type === "all" || type === "inline") {
7086
7222
  for (const inline of block.children) {
7087
7223
  if (guard(inline)) {
7088
- _optionalChain([visitor, 'optionalCall', _160 => _160(inline)]);
7224
+ _optionalChain([visitor, 'optionalCall', _166 => _166(inline)]);
7089
7225
  }
7090
7226
  }
7091
7227
  }
@@ -7110,7 +7246,7 @@ async function resolveUsersInCommentBody(body, resolveUsers) {
7110
7246
  userIds
7111
7247
  });
7112
7248
  for (const [index, userId] of userIds.entries()) {
7113
- const user = _optionalChain([users, 'optionalAccess', _161 => _161[index]]);
7249
+ const user = _optionalChain([users, 'optionalAccess', _167 => _167[index]]);
7114
7250
  if (user) {
7115
7251
  resolvedUsers.set(userId, user);
7116
7252
  }
@@ -7233,7 +7369,7 @@ var stringifyCommentBodyPlainElements = {
7233
7369
  text: ({ element }) => element.text,
7234
7370
  link: ({ element }) => element.url,
7235
7371
  mention: ({ element, user }) => {
7236
- return `@${_nullishCoalesce(_optionalChain([user, 'optionalAccess', _162 => _162.name]), () => ( element.id))}`;
7372
+ return `@${_nullishCoalesce(_optionalChain([user, 'optionalAccess', _168 => _168.name]), () => ( element.id))}`;
7237
7373
  }
7238
7374
  };
7239
7375
  var stringifyCommentBodyHtmlElements = {
@@ -7263,7 +7399,7 @@ var stringifyCommentBodyHtmlElements = {
7263
7399
  return html`<a href="${href}" target="_blank" rel="noopener noreferrer">${element.url}</a>`;
7264
7400
  },
7265
7401
  mention: ({ element, user }) => {
7266
- return html`<span data-mention>@${_nullishCoalesce(_optionalChain([user, 'optionalAccess', _163 => _163.name]), () => ( element.id))}</span>`;
7402
+ return html`<span data-mention>@${_nullishCoalesce(_optionalChain([user, 'optionalAccess', _169 => _169.name]), () => ( element.id))}</span>`;
7267
7403
  }
7268
7404
  };
7269
7405
  var stringifyCommentBodyMarkdownElements = {
@@ -7293,19 +7429,19 @@ var stringifyCommentBodyMarkdownElements = {
7293
7429
  return markdown`[${element.url}](${href})`;
7294
7430
  },
7295
7431
  mention: ({ element, user }) => {
7296
- return markdown`@${_nullishCoalesce(_optionalChain([user, 'optionalAccess', _164 => _164.name]), () => ( element.id))}`;
7432
+ return markdown`@${_nullishCoalesce(_optionalChain([user, 'optionalAccess', _170 => _170.name]), () => ( element.id))}`;
7297
7433
  }
7298
7434
  };
7299
7435
  async function stringifyCommentBody(body, options) {
7300
- const format = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _165 => _165.format]), () => ( "plain"));
7301
- const separator = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _166 => _166.separator]), () => ( (format === "markdown" ? "\n\n" : "\n")));
7436
+ const format = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _171 => _171.format]), () => ( "plain"));
7437
+ const separator = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _172 => _172.separator]), () => ( (format === "markdown" ? "\n\n" : "\n")));
7302
7438
  const elements = {
7303
7439
  ...format === "html" ? stringifyCommentBodyHtmlElements : format === "markdown" ? stringifyCommentBodyMarkdownElements : stringifyCommentBodyPlainElements,
7304
- ..._optionalChain([options, 'optionalAccess', _167 => _167.elements])
7440
+ ..._optionalChain([options, 'optionalAccess', _173 => _173.elements])
7305
7441
  };
7306
7442
  const resolvedUsers = await resolveUsersInCommentBody(
7307
7443
  body,
7308
- _optionalChain([options, 'optionalAccess', _168 => _168.resolveUsers])
7444
+ _optionalChain([options, 'optionalAccess', _174 => _174.resolveUsers])
7309
7445
  );
7310
7446
  const blocks = body.content.flatMap((block, blockIndex) => {
7311
7447
  switch (block.type) {
@@ -7580,12 +7716,12 @@ function legacy_patchImmutableNode(state, path, update) {
7580
7716
  }
7581
7717
  const newState = Object.assign({}, state);
7582
7718
  for (const key in update.updates) {
7583
- if (_optionalChain([update, 'access', _169 => _169.updates, 'access', _170 => _170[key], 'optionalAccess', _171 => _171.type]) === "update") {
7719
+ if (_optionalChain([update, 'access', _175 => _175.updates, 'access', _176 => _176[key], 'optionalAccess', _177 => _177.type]) === "update") {
7584
7720
  const val = update.node.get(key);
7585
7721
  if (val !== void 0) {
7586
7722
  newState[key] = lsonToJson(val);
7587
7723
  }
7588
- } else if (_optionalChain([update, 'access', _172 => _172.updates, 'access', _173 => _173[key], 'optionalAccess', _174 => _174.type]) === "delete") {
7724
+ } else if (_optionalChain([update, 'access', _178 => _178.updates, 'access', _179 => _179[key], 'optionalAccess', _180 => _180.type]) === "delete") {
7589
7725
  delete newState[key];
7590
7726
  }
7591
7727
  }
@@ -7646,12 +7782,12 @@ function legacy_patchImmutableNode(state, path, update) {
7646
7782
  }
7647
7783
  const newState = Object.assign({}, state);
7648
7784
  for (const key in update.updates) {
7649
- if (_optionalChain([update, 'access', _175 => _175.updates, 'access', _176 => _176[key], 'optionalAccess', _177 => _177.type]) === "update") {
7785
+ if (_optionalChain([update, 'access', _181 => _181.updates, 'access', _182 => _182[key], 'optionalAccess', _183 => _183.type]) === "update") {
7650
7786
  const value = update.node.get(key);
7651
7787
  if (value !== void 0) {
7652
7788
  newState[key] = lsonToJson(value);
7653
7789
  }
7654
- } else if (_optionalChain([update, 'access', _178 => _178.updates, 'access', _179 => _179[key], 'optionalAccess', _180 => _180.type]) === "delete") {
7790
+ } else if (_optionalChain([update, 'access', _184 => _184.updates, 'access', _185 => _185[key], 'optionalAccess', _186 => _186.type]) === "delete") {
7655
7791
  delete newState[key];
7656
7792
  }
7657
7793
  }