@liveblocks/core 3.20.0-rc1 → 3.20.0

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.cjs 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 = "3.20.0-rc1";
9
+ var PKG_VERSION = "3.20.0";
10
10
  var PKG_FORMAT = "cjs";
11
11
 
12
12
  // src/dupe-detection.ts
@@ -1570,7 +1570,6 @@ function isUrl(string) {
1570
1570
  function createApiClient({
1571
1571
  baseUrl,
1572
1572
  authManager,
1573
- currentUserId,
1574
1573
  fetchPolyfill
1575
1574
  }) {
1576
1575
  const httpClient = new HttpClient(baseUrl, fetchPolyfill);
@@ -1578,8 +1577,9 @@ function createApiClient({
1578
1577
  const result = await httpClient.get(
1579
1578
  url`/v2/c/rooms/${options.roomId}/threads/delta`,
1580
1579
  await authManager.getAuthValue({
1581
- requestedScope: "comments:read",
1582
- roomId: options.roomId
1580
+ roomId: options.roomId,
1581
+ resource: "comments",
1582
+ access: "read"
1583
1583
  }),
1584
1584
  {
1585
1585
  since: options.since.toISOString()
@@ -1617,8 +1617,9 @@ function createApiClient({
1617
1617
  const result = await httpClient.get(
1618
1618
  url`/v2/c/rooms/${options.roomId}/threads`,
1619
1619
  await authManager.getAuthValue({
1620
- requestedScope: "comments:read",
1621
- roomId: options.roomId
1620
+ roomId: options.roomId,
1621
+ resource: "comments",
1622
+ access: "read"
1622
1623
  }),
1623
1624
  {
1624
1625
  cursor: options.cursor,
@@ -1662,8 +1663,9 @@ function createApiClient({
1662
1663
  const result = await httpClient.get(
1663
1664
  url`/v2/c/rooms/${options.roomId}/threads/comments/search`,
1664
1665
  await authManager.getAuthValue({
1665
- requestedScope: "comments:read",
1666
- roomId: options.roomId
1666
+ roomId: options.roomId,
1667
+ resource: "comments",
1668
+ access: "read"
1667
1669
  }),
1668
1670
  {
1669
1671
  text: options.query.text,
@@ -1684,8 +1686,9 @@ function createApiClient({
1684
1686
  const thread = await httpClient.post(
1685
1687
  url`/v2/c/rooms/${options.roomId}/threads`,
1686
1688
  await authManager.getAuthValue({
1687
- requestedScope: "comments:read",
1688
- roomId: options.roomId
1689
+ roomId: options.roomId,
1690
+ resource: "comments",
1691
+ access: "write"
1689
1692
  }),
1690
1693
  {
1691
1694
  id: threadId,
@@ -1704,8 +1707,9 @@ function createApiClient({
1704
1707
  await httpClient.delete(
1705
1708
  url`/v2/c/rooms/${options.roomId}/threads/${options.threadId}`,
1706
1709
  await authManager.getAuthValue({
1707
- requestedScope: "comments:read",
1708
- roomId: options.roomId
1710
+ roomId: options.roomId,
1711
+ resource: "comments",
1712
+ access: "write"
1709
1713
  })
1710
1714
  );
1711
1715
  }
@@ -1713,8 +1717,9 @@ function createApiClient({
1713
1717
  const response = await httpClient.rawGet(
1714
1718
  url`/v2/c/rooms/${options.roomId}/thread-with-notification/${options.threadId}`,
1715
1719
  await authManager.getAuthValue({
1716
- requestedScope: "comments:read",
1717
- roomId: options.roomId
1720
+ roomId: options.roomId,
1721
+ resource: "comments",
1722
+ access: "read"
1718
1723
  })
1719
1724
  );
1720
1725
  if (response.ok) {
@@ -1740,8 +1745,9 @@ function createApiClient({
1740
1745
  return await httpClient.post(
1741
1746
  url`/v2/c/rooms/${options.roomId}/threads/${options.threadId}/metadata`,
1742
1747
  await authManager.getAuthValue({
1743
- requestedScope: "comments:read",
1744
- roomId: options.roomId
1748
+ roomId: options.roomId,
1749
+ resource: "comments",
1750
+ access: "write"
1745
1751
  }),
1746
1752
  options.metadata
1747
1753
  );
@@ -1750,8 +1756,9 @@ function createApiClient({
1750
1756
  return await httpClient.post(
1751
1757
  url`/v2/c/rooms/${options.roomId}/threads/${options.threadId}/comments/${options.commentId}/metadata`,
1752
1758
  await authManager.getAuthValue({
1753
- requestedScope: "comments:read",
1754
- roomId: options.roomId
1759
+ roomId: options.roomId,
1760
+ resource: "comments",
1761
+ access: "write"
1755
1762
  }),
1756
1763
  options.metadata
1757
1764
  );
@@ -1761,8 +1768,9 @@ function createApiClient({
1761
1768
  const comment = await httpClient.post(
1762
1769
  url`/v2/c/rooms/${options.roomId}/threads/${options.threadId}/comments`,
1763
1770
  await authManager.getAuthValue({
1764
- requestedScope: "comments:read",
1765
- roomId: options.roomId
1771
+ roomId: options.roomId,
1772
+ resource: "comments",
1773
+ access: "write"
1766
1774
  }),
1767
1775
  {
1768
1776
  id: commentId,
@@ -1777,8 +1785,9 @@ function createApiClient({
1777
1785
  const comment = await httpClient.post(
1778
1786
  url`/v2/c/rooms/${options.roomId}/threads/${options.threadId}/comments/${options.commentId}`,
1779
1787
  await authManager.getAuthValue({
1780
- requestedScope: "comments:read",
1781
- roomId: options.roomId
1788
+ roomId: options.roomId,
1789
+ resource: "comments",
1790
+ access: "write"
1782
1791
  }),
1783
1792
  {
1784
1793
  body: options.body,
@@ -1792,8 +1801,9 @@ function createApiClient({
1792
1801
  await httpClient.delete(
1793
1802
  url`/v2/c/rooms/${options.roomId}/threads/${options.threadId}/comments/${options.commentId}`,
1794
1803
  await authManager.getAuthValue({
1795
- requestedScope: "comments:read",
1796
- roomId: options.roomId
1804
+ roomId: options.roomId,
1805
+ resource: "comments",
1806
+ access: "write"
1797
1807
  })
1798
1808
  );
1799
1809
  }
@@ -1801,8 +1811,9 @@ function createApiClient({
1801
1811
  const reaction = await httpClient.post(
1802
1812
  url`/v2/c/rooms/${options.roomId}/threads/${options.threadId}/comments/${options.commentId}/reactions`,
1803
1813
  await authManager.getAuthValue({
1804
- requestedScope: "comments:read",
1805
- roomId: options.roomId
1814
+ roomId: options.roomId,
1815
+ resource: "comments",
1816
+ access: "write"
1806
1817
  }),
1807
1818
  { emoji: options.emoji }
1808
1819
  );
@@ -1812,8 +1823,9 @@ function createApiClient({
1812
1823
  await httpClient.delete(
1813
1824
  url`/v2/c/rooms/${options.roomId}/threads/${options.threadId}/comments/${options.commentId}/reactions/${options.emoji}`,
1814
1825
  await authManager.getAuthValue({
1815
- requestedScope: "comments:read",
1816
- roomId: options.roomId
1826
+ roomId: options.roomId,
1827
+ resource: "comments",
1828
+ access: "write"
1817
1829
  })
1818
1830
  );
1819
1831
  }
@@ -1821,8 +1833,9 @@ function createApiClient({
1821
1833
  await httpClient.post(
1822
1834
  url`/v2/c/rooms/${options.roomId}/threads/${options.threadId}/mark-as-resolved`,
1823
1835
  await authManager.getAuthValue({
1824
- requestedScope: "comments:read",
1825
- roomId: options.roomId
1836
+ roomId: options.roomId,
1837
+ resource: "comments",
1838
+ access: "write"
1826
1839
  })
1827
1840
  );
1828
1841
  }
@@ -1830,8 +1843,9 @@ function createApiClient({
1830
1843
  await httpClient.post(
1831
1844
  url`/v2/c/rooms/${options.roomId}/threads/${options.threadId}/mark-as-unresolved`,
1832
1845
  await authManager.getAuthValue({
1833
- requestedScope: "comments:read",
1834
- roomId: options.roomId
1846
+ roomId: options.roomId,
1847
+ resource: "comments",
1848
+ access: "write"
1835
1849
  })
1836
1850
  );
1837
1851
  }
@@ -1839,8 +1853,9 @@ function createApiClient({
1839
1853
  const subscription = await httpClient.post(
1840
1854
  url`/v2/c/rooms/${options.roomId}/threads/${options.threadId}/subscribe`,
1841
1855
  await authManager.getAuthValue({
1842
- requestedScope: "comments:read",
1843
- roomId: options.roomId
1856
+ roomId: options.roomId,
1857
+ resource: "comments",
1858
+ access: "read"
1844
1859
  })
1845
1860
  );
1846
1861
  return convertToSubscriptionData(subscription);
@@ -1849,8 +1864,9 @@ function createApiClient({
1849
1864
  await httpClient.post(
1850
1865
  url`/v2/c/rooms/${options.roomId}/threads/${options.threadId}/unsubscribe`,
1851
1866
  await authManager.getAuthValue({
1852
- requestedScope: "comments:read",
1853
- roomId: options.roomId
1867
+ roomId: options.roomId,
1868
+ resource: "comments",
1869
+ access: "read"
1854
1870
  })
1855
1871
  );
1856
1872
  }
@@ -1906,8 +1922,9 @@ function createApiClient({
1906
1922
  async () => httpClient.putBlob(
1907
1923
  url`/v2/c/rooms/${roomId}/attachments/${attachment.id}/upload/${encodeURIComponent(attachment.name)}`,
1908
1924
  await authManager.getAuthValue({
1909
- requestedScope: "comments:read",
1910
- roomId
1925
+ roomId,
1926
+ resource: "comments",
1927
+ access: "write"
1911
1928
  }),
1912
1929
  attachment.file,
1913
1930
  { fileSize: attachment.size },
@@ -1924,8 +1941,9 @@ function createApiClient({
1924
1941
  async () => httpClient.post(
1925
1942
  url`/v2/c/rooms/${roomId}/attachments/${attachment.id}/multipart/${encodeURIComponent(attachment.name)}`,
1926
1943
  await authManager.getAuthValue({
1927
- requestedScope: "comments:read",
1928
- roomId
1944
+ roomId,
1945
+ resource: "comments",
1946
+ access: "write"
1929
1947
  }),
1930
1948
  void 0,
1931
1949
  { signal: abortSignal },
@@ -1950,8 +1968,9 @@ function createApiClient({
1950
1968
  async () => httpClient.putBlob(
1951
1969
  url`/v2/c/rooms/${roomId}/attachments/${attachment.id}/multipart/${createMultiPartUpload.uploadId}/${String(partNumber)}`,
1952
1970
  await authManager.getAuthValue({
1953
- requestedScope: "comments:read",
1954
- roomId
1971
+ roomId,
1972
+ resource: "comments",
1973
+ access: "write"
1955
1974
  }),
1956
1975
  part,
1957
1976
  void 0,
@@ -1974,8 +1993,9 @@ function createApiClient({
1974
1993
  return httpClient.post(
1975
1994
  url`/v2/c/rooms/${roomId}/attachments/${attachment.id}/multipart/${uploadId}/complete`,
1976
1995
  await authManager.getAuthValue({
1977
- requestedScope: "comments:read",
1978
- roomId
1996
+ roomId,
1997
+ resource: "comments",
1998
+ access: "write"
1979
1999
  }),
1980
2000
  { parts: sortedUploadedParts },
1981
2001
  { signal: abortSignal }
@@ -1986,8 +2006,9 @@ function createApiClient({
1986
2006
  await httpClient.rawDelete(
1987
2007
  url`/v2/c/rooms/${roomId}/attachments/${attachment.id}/multipart/${uploadId}`,
1988
2008
  await authManager.getAuthValue({
1989
- requestedScope: "comments:read",
1990
- roomId
2009
+ roomId,
2010
+ resource: "comments",
2011
+ access: "write"
1991
2012
  })
1992
2013
  );
1993
2014
  } catch (e8) {
@@ -2004,8 +2025,9 @@ function createApiClient({
2004
2025
  const { urls } = await httpClient.post(
2005
2026
  url`/v2/c/rooms/${roomId}/attachments/presigned-urls`,
2006
2027
  await authManager.getAuthValue({
2007
- requestedScope: "comments:read",
2008
- roomId
2028
+ roomId,
2029
+ resource: "comments",
2030
+ access: "read"
2009
2031
  }),
2010
2032
  { attachmentIds }
2011
2033
  );
@@ -2024,109 +2046,13 @@ function createApiClient({
2024
2046
  const batch2 = getOrCreateAttachmentUrlsStore(options.roomId).batch;
2025
2047
  return batch2.get(options.attachmentId);
2026
2048
  }
2027
- async function uploadChatAttachment(options) {
2028
- const { chatId, attachment, signal } = options;
2029
- const userId = currentUserId.get();
2030
- if (userId === void 0) {
2031
- throw new Error("Attachment upload requires an authenticated user.");
2032
- }
2033
- const ATTACHMENT_PART_SIZE = 5 * 1024 * 1024;
2034
- if (options.attachment.file.size <= ATTACHMENT_PART_SIZE) {
2035
- await httpClient.putBlob(
2036
- url`/v2/c/chats/${chatId}/attachments/${attachment.id}/upload/${encodeURIComponent(attachment.file.name)}`,
2037
- await authManager.getAuthValue({ requestedScope: "comments:read" }),
2038
- attachment.file,
2039
- { fileSize: attachment.file.size },
2040
- { signal }
2041
- );
2042
- } else {
2043
- const multipartUpload = await httpClient.post(
2044
- url`/v2/c/chats/${chatId}/attachments/${attachment.id}/multipart/${encodeURIComponent(attachment.file.name)}`,
2045
- await authManager.getAuthValue({ requestedScope: "comments:read" }),
2046
- void 0,
2047
- { signal },
2048
- { fileSize: attachment.file.size }
2049
- );
2050
- try {
2051
- const uploadedParts = [];
2052
- const parts = [];
2053
- let start = 0;
2054
- while (start < attachment.file.size) {
2055
- const end = Math.min(
2056
- start + ATTACHMENT_PART_SIZE,
2057
- attachment.file.size
2058
- );
2059
- parts.push({
2060
- number: parts.length + 1,
2061
- part: attachment.file.slice(start, end)
2062
- });
2063
- start = end;
2064
- }
2065
- uploadedParts.push(
2066
- ...await Promise.all(
2067
- parts.map(async ({ number, part }) => {
2068
- return await httpClient.putBlob(
2069
- url`/v2/c/chats/${chatId}/attachments/${attachment.id}/multipart/${multipartUpload.uploadId}/${String(number)}`,
2070
- await authManager.getAuthValue({
2071
- requestedScope: "comments:read"
2072
- }),
2073
- part,
2074
- void 0,
2075
- { signal }
2076
- );
2077
- })
2078
- )
2079
- );
2080
- await httpClient.post(
2081
- url`/v2/c/chats/${chatId}/attachments/${attachment.id}/multipart/${multipartUpload.uploadId}/complete`,
2082
- await authManager.getAuthValue({ requestedScope: "comments:read" }),
2083
- { parts: uploadedParts.sort((a, b) => a.number - b.number) },
2084
- { signal }
2085
- );
2086
- } catch (err) {
2087
- try {
2088
- await httpClient.delete(
2089
- url`/v2/c/chats/${chatId}/attachments/${attachment.id}/multipart/${multipartUpload.uploadId}`,
2090
- await authManager.getAuthValue({ requestedScope: "comments:read" })
2091
- );
2092
- } catch (e9) {
2093
- }
2094
- throw err;
2095
- }
2096
- }
2097
- }
2098
- const attachmentUrlsBatchStoresByChat = new DefaultMap((chatId) => {
2099
- const batch2 = new Batch(
2100
- async (batchedAttachmentIds) => {
2101
- const attachmentIds = batchedAttachmentIds.flat();
2102
- const { urls } = await httpClient.post(
2103
- url`/v2/c/chats/${chatId}/attachments/presigned-urls`,
2104
- await authManager.getAuthValue({
2105
- requestedScope: "comments:read"
2106
- }),
2107
- { attachmentIds }
2108
- );
2109
- return urls.map(
2110
- (url2) => _nullishCoalesce(url2, () => ( new Error("There was an error while getting this attachment's URL")))
2111
- );
2112
- },
2113
- { delay: 50 }
2114
- );
2115
- return createBatchStore(batch2);
2116
- });
2117
- function getOrCreateChatAttachmentUrlsStore(chatId) {
2118
- return attachmentUrlsBatchStoresByChat.getOrCreate(chatId);
2119
- }
2120
- function getChatAttachmentUrl(options) {
2121
- const batch2 = getOrCreateChatAttachmentUrlsStore(options.chatId).batch;
2122
- return batch2.get(options.attachmentId);
2123
- }
2124
2049
  async function getSubscriptionSettings(options) {
2125
2050
  return httpClient.get(
2126
2051
  url`/v2/c/rooms/${options.roomId}/subscription-settings`,
2127
2052
  await authManager.getAuthValue({
2128
- requestedScope: "comments:read",
2129
- roomId: options.roomId
2053
+ roomId: options.roomId,
2054
+ resource: "comments",
2055
+ access: "read"
2130
2056
  }),
2131
2057
  void 0,
2132
2058
  {
@@ -2138,8 +2064,9 @@ function createApiClient({
2138
2064
  return httpClient.post(
2139
2065
  url`/v2/c/rooms/${options.roomId}/subscription-settings`,
2140
2066
  await authManager.getAuthValue({
2141
- requestedScope: "comments:read",
2142
- roomId: options.roomId
2067
+ roomId: options.roomId,
2068
+ resource: "comments",
2069
+ access: "read"
2143
2070
  }),
2144
2071
  options.settings
2145
2072
  );
@@ -2151,8 +2078,9 @@ function createApiClient({
2151
2078
  await httpClient.post(
2152
2079
  url`/v2/c/rooms/${roomId}/inbox-notifications/read`,
2153
2080
  await authManager.getAuthValue({
2154
- requestedScope: "comments:read",
2155
- roomId
2081
+ roomId,
2082
+ resource: "comments",
2083
+ access: "read"
2156
2084
  }),
2157
2085
  { inboxNotificationIds }
2158
2086
  );
@@ -2172,8 +2100,9 @@ function createApiClient({
2172
2100
  await httpClient.rawPost(
2173
2101
  url`/v2/c/rooms/${options.roomId}/text-mentions`,
2174
2102
  await authManager.getAuthValue({
2175
- requestedScope: "comments:read",
2176
- roomId: options.roomId
2103
+ roomId: options.roomId,
2104
+ resource: "storage",
2105
+ access: "write"
2177
2106
  }),
2178
2107
  {
2179
2108
  userId: options.mention.kind === "user" ? options.mention.id : void 0,
@@ -2187,8 +2116,9 @@ function createApiClient({
2187
2116
  await httpClient.rawDelete(
2188
2117
  url`/v2/c/rooms/${options.roomId}/text-mentions/${options.mentionId}`,
2189
2118
  await authManager.getAuthValue({
2190
- requestedScope: "comments:read",
2191
- roomId: options.roomId
2119
+ roomId: options.roomId,
2120
+ resource: "storage",
2121
+ access: "write"
2192
2122
  })
2193
2123
  );
2194
2124
  }
@@ -2196,8 +2126,9 @@ function createApiClient({
2196
2126
  return httpClient.rawGet(
2197
2127
  url`/v2/c/rooms/${options.roomId}/y-version/${options.versionId}`,
2198
2128
  await authManager.getAuthValue({
2199
- requestedScope: "comments:read",
2200
- roomId: options.roomId
2129
+ roomId: options.roomId,
2130
+ resource: "storage",
2131
+ access: "read"
2201
2132
  })
2202
2133
  );
2203
2134
  }
@@ -2205,8 +2136,9 @@ function createApiClient({
2205
2136
  await httpClient.rawPost(
2206
2137
  url`/v2/c/rooms/${options.roomId}/version`,
2207
2138
  await authManager.getAuthValue({
2208
- requestedScope: "comments:read",
2209
- roomId: options.roomId
2139
+ roomId: options.roomId,
2140
+ resource: "storage",
2141
+ access: "write"
2210
2142
  })
2211
2143
  );
2212
2144
  }
@@ -2214,8 +2146,9 @@ function createApiClient({
2214
2146
  await httpClient.rawPost(
2215
2147
  url`/v2/c/rooms/${options.roomId}/text-metadata`,
2216
2148
  await authManager.getAuthValue({
2217
- requestedScope: "comments:read",
2218
- roomId: options.roomId
2149
+ roomId: options.roomId,
2150
+ resource: "storage",
2151
+ access: "read"
2219
2152
  }),
2220
2153
  {
2221
2154
  type: options.type,
@@ -2227,8 +2160,9 @@ function createApiClient({
2227
2160
  const result = await httpClient.post(
2228
2161
  url`/v2/c/rooms/${options.roomId}/ai/contextual-prompt`,
2229
2162
  await authManager.getAuthValue({
2230
- requestedScope: "room:read",
2231
- roomId: options.roomId
2163
+ roomId: options.roomId,
2164
+ resource: "storage",
2165
+ access: "read"
2232
2166
  }),
2233
2167
  {
2234
2168
  prompt: options.prompt,
@@ -2250,8 +2184,9 @@ function createApiClient({
2250
2184
  const result = await httpClient.get(
2251
2185
  url`/v2/c/rooms/${options.roomId}/versions`,
2252
2186
  await authManager.getAuthValue({
2253
- requestedScope: "comments:read",
2254
- roomId: options.roomId
2187
+ roomId: options.roomId,
2188
+ resource: "storage",
2189
+ access: "read"
2255
2190
  })
2256
2191
  );
2257
2192
  return {
@@ -2268,8 +2203,9 @@ function createApiClient({
2268
2203
  const result = await httpClient.get(
2269
2204
  url`/v2/c/rooms/${options.roomId}/versions/delta`,
2270
2205
  await authManager.getAuthValue({
2271
- requestedScope: "comments:read",
2272
- roomId: options.roomId
2206
+ roomId: options.roomId,
2207
+ resource: "storage",
2208
+ access: "read"
2273
2209
  }),
2274
2210
  { since: options.since.toISOString() },
2275
2211
  { signal: options.signal }
@@ -2288,8 +2224,9 @@ function createApiClient({
2288
2224
  const result = await httpClient.rawGet(
2289
2225
  url`/v2/c/rooms/${options.roomId}/storage`,
2290
2226
  await authManager.getAuthValue({
2291
- requestedScope: "room:read",
2292
- roomId: options.roomId
2227
+ roomId: options.roomId,
2228
+ resource: "storage",
2229
+ access: "read"
2293
2230
  })
2294
2231
  );
2295
2232
  return await result.json();
@@ -2302,7 +2239,7 @@ function createApiClient({
2302
2239
  }
2303
2240
  const json = await httpClient.get(
2304
2241
  url`/v2/c/inbox-notifications`,
2305
- await authManager.getAuthValue({ requestedScope: "comments:read" }),
2242
+ await authManager.getAuthValue({ resource: "personal", access: "write" }),
2306
2243
  {
2307
2244
  cursor: _optionalChain([options, 'optionalAccess', _22 => _22.cursor]),
2308
2245
  limit: PAGE_SIZE,
@@ -2328,7 +2265,7 @@ function createApiClient({
2328
2265
  }
2329
2266
  const json = await httpClient.get(
2330
2267
  url`/v2/c/inbox-notifications/delta`,
2331
- await authManager.getAuthValue({ requestedScope: "comments:read" }),
2268
+ await authManager.getAuthValue({ resource: "personal", access: "write" }),
2332
2269
  { since: options.since.toISOString(), query },
2333
2270
  { signal: options.signal }
2334
2271
  );
@@ -2357,7 +2294,7 @@ function createApiClient({
2357
2294
  }
2358
2295
  const { count } = await httpClient.get(
2359
2296
  url`/v2/c/inbox-notifications/count`,
2360
- await authManager.getAuthValue({ requestedScope: "comments:read" }),
2297
+ await authManager.getAuthValue({ resource: "personal", access: "write" }),
2361
2298
  { query },
2362
2299
  { signal: _optionalChain([options, 'optionalAccess', _25 => _25.signal]) }
2363
2300
  );
@@ -2366,7 +2303,7 @@ function createApiClient({
2366
2303
  async function markAllInboxNotificationsAsRead() {
2367
2304
  await httpClient.post(
2368
2305
  url`/v2/c/inbox-notifications/read`,
2369
- await authManager.getAuthValue({ requestedScope: "comments:read" }),
2306
+ await authManager.getAuthValue({ resource: "personal", access: "write" }),
2370
2307
  {
2371
2308
  inboxNotificationIds: "all"
2372
2309
  }
@@ -2375,7 +2312,7 @@ function createApiClient({
2375
2312
  async function markInboxNotificationsAsRead(inboxNotificationIds) {
2376
2313
  await httpClient.post(
2377
2314
  url`/v2/c/inbox-notifications/read`,
2378
- await authManager.getAuthValue({ requestedScope: "comments:read" }),
2315
+ await authManager.getAuthValue({ resource: "personal", access: "write" }),
2379
2316
  {
2380
2317
  inboxNotificationIds
2381
2318
  }
@@ -2395,19 +2332,19 @@ function createApiClient({
2395
2332
  async function deleteAllInboxNotifications() {
2396
2333
  await httpClient.delete(
2397
2334
  url`/v2/c/inbox-notifications`,
2398
- await authManager.getAuthValue({ requestedScope: "comments:read" })
2335
+ await authManager.getAuthValue({ resource: "personal", access: "write" })
2399
2336
  );
2400
2337
  }
2401
2338
  async function deleteInboxNotification(inboxNotificationId) {
2402
2339
  await httpClient.delete(
2403
2340
  url`/v2/c/inbox-notifications/${inboxNotificationId}`,
2404
- await authManager.getAuthValue({ requestedScope: "comments:read" })
2341
+ await authManager.getAuthValue({ resource: "personal", access: "write" })
2405
2342
  );
2406
2343
  }
2407
2344
  async function getNotificationSettings(options) {
2408
2345
  return httpClient.get(
2409
2346
  url`/v2/c/notification-settings`,
2410
- await authManager.getAuthValue({ requestedScope: "comments:read" }),
2347
+ await authManager.getAuthValue({ resource: "personal", access: "write" }),
2411
2348
  void 0,
2412
2349
  { signal: _optionalChain([options, 'optionalAccess', _26 => _26.signal]) }
2413
2350
  );
@@ -2415,7 +2352,7 @@ function createApiClient({
2415
2352
  async function updateNotificationSettings(settings) {
2416
2353
  return httpClient.post(
2417
2354
  url`/v2/c/notification-settings`,
2418
- await authManager.getAuthValue({ requestedScope: "comments:read" }),
2355
+ await authManager.getAuthValue({ resource: "personal", access: "write" }),
2419
2356
  settings
2420
2357
  );
2421
2358
  }
@@ -2427,7 +2364,7 @@ function createApiClient({
2427
2364
  const PAGE_SIZE = 50;
2428
2365
  const json = await httpClient.get(
2429
2366
  url`/v2/c/threads`,
2430
- await authManager.getAuthValue({ requestedScope: "comments:read" }),
2367
+ await authManager.getAuthValue({ resource: "personal", access: "write" }),
2431
2368
  {
2432
2369
  cursor: _optionalChain([options, 'optionalAccess', _28 => _28.cursor]),
2433
2370
  query,
@@ -2448,7 +2385,7 @@ function createApiClient({
2448
2385
  async function getUserThreadsSince_experimental(options) {
2449
2386
  const json = await httpClient.get(
2450
2387
  url`/v2/c/threads/delta`,
2451
- await authManager.getAuthValue({ requestedScope: "comments:read" }),
2388
+ await authManager.getAuthValue({ resource: "personal", access: "write" }),
2452
2389
  { since: options.since.toISOString() },
2453
2390
  { signal: options.signal }
2454
2391
  );
@@ -2477,7 +2414,8 @@ function createApiClient({
2477
2414
  const { groups: plainGroups } = await httpClient.post(
2478
2415
  url`/v2/c/groups/find`,
2479
2416
  await authManager.getAuthValue({
2480
- requestedScope: "comments:read"
2417
+ resource: "personal",
2418
+ access: "write"
2481
2419
  }),
2482
2420
  { groupIds }
2483
2421
  );
@@ -2496,7 +2434,7 @@ function createApiClient({
2496
2434
  async function getUrlMetadata(_url) {
2497
2435
  const { metadata } = await httpClient.get(
2498
2436
  url`/v2/c/urls/metadata`,
2499
- await authManager.getAuthValue({ requestedScope: "comments:read" }),
2437
+ await authManager.getAuthValue({ resource: "personal", access: "write" }),
2500
2438
  { url: _url }
2501
2439
  );
2502
2440
  return metadata;
@@ -2536,10 +2474,6 @@ function createApiClient({
2536
2474
  getAttachmentUrl,
2537
2475
  uploadAttachment,
2538
2476
  getOrCreateAttachmentUrlsStore,
2539
- // User attachments
2540
- uploadChatAttachment,
2541
- getOrCreateChatAttachmentUrlsStore,
2542
- getChatAttachmentUrl,
2543
2477
  // Room storage
2544
2478
  streamStorage,
2545
2479
  // Notifications
@@ -2645,7 +2579,7 @@ var HttpClient = class {
2645
2579
  let body;
2646
2580
  try {
2647
2581
  body = await response.json();
2648
- } catch (e10) {
2582
+ } catch (e9) {
2649
2583
  body = {};
2650
2584
  }
2651
2585
  return body;
@@ -3845,7 +3779,7 @@ var ManagedSocket = class {
3845
3779
  getStatus() {
3846
3780
  try {
3847
3781
  return toNewConnectionStatus(this.#machine);
3848
- } catch (e11) {
3782
+ } catch (e10) {
3849
3783
  return "initial";
3850
3784
  }
3851
3785
  }
@@ -5233,22 +5167,327 @@ function createReceivingToolInvocation(invocationId, name, partialArgsText = "")
5233
5167
  };
5234
5168
  }
5235
5169
 
5236
- // src/protocol/AuthToken.ts
5237
- var Permission = /* @__PURE__ */ ((Permission2) => {
5238
- Permission2["Read"] = "room:read";
5239
- Permission2["Write"] = "room:write";
5240
- Permission2["PresenceWrite"] = "room:presence:write";
5241
- Permission2["CommentsWrite"] = "comments:write";
5242
- Permission2["CommentsRead"] = "comments:read";
5243
- Permission2["FeedsWrite"] = "feeds:write";
5244
- return Permission2;
5245
- })(Permission || {});
5246
- function canWriteStorage(scopes) {
5247
- return scopes.includes("room:write" /* Write */);
5248
- }
5249
- function canComment(scopes) {
5250
- return scopes.includes("comments:write" /* CommentsWrite */) || scopes.includes("room:write" /* Write */);
5170
+ // src/permissions.ts
5171
+ var Permission = {
5172
+ /**
5173
+ * Default permission for a room.
5174
+ */
5175
+ Read: "*:read",
5176
+ Write: "*:write",
5177
+ /**
5178
+ * Legacy aliases for default room permissions.
5179
+ */
5180
+ RoomWrite: "room:write",
5181
+ RoomRead: "room:read",
5182
+ /**
5183
+ * Storage
5184
+ */
5185
+ StorageRead: "storage:read",
5186
+ StorageWrite: "storage:write",
5187
+ StorageNone: "storage:none",
5188
+ /**
5189
+ * Comments
5190
+ */
5191
+ CommentsWrite: "comments:write",
5192
+ CommentsRead: "comments:read",
5193
+ CommentsNone: "comments:none",
5194
+ /**
5195
+ * Feeds
5196
+ */
5197
+ FeedsRead: "feeds:read",
5198
+ FeedsWrite: "feeds:write",
5199
+ FeedsNone: "feeds:none",
5200
+ /**
5201
+ * Legacy
5202
+ */
5203
+ LegacyRoomPresenceWrite: "room:presence:write"
5204
+ };
5205
+ var ACCESS_LEVELS = ["none", "read", "write"];
5206
+ var basePermissionScopes = /* @__PURE__ */ new Set([
5207
+ Permission.Read,
5208
+ Permission.Write,
5209
+ Permission.RoomRead,
5210
+ Permission.RoomWrite
5211
+ ]);
5212
+ var ACCESS_LEVEL_RANKS = {
5213
+ none: 0,
5214
+ read: 1,
5215
+ write: 2
5216
+ };
5217
+ var PERMISSIONS_BY_RESOURCE = {
5218
+ room: {
5219
+ read: [Permission.Read, Permission.RoomRead],
5220
+ write: [Permission.Write, Permission.RoomWrite]
5221
+ },
5222
+ personal: {
5223
+ write: []
5224
+ },
5225
+ storage: {
5226
+ write: [Permission.StorageWrite],
5227
+ read: [Permission.StorageRead],
5228
+ none: [Permission.StorageNone]
5229
+ },
5230
+ comments: {
5231
+ write: [Permission.CommentsWrite],
5232
+ read: [Permission.CommentsRead],
5233
+ none: [Permission.CommentsNone]
5234
+ },
5235
+ feeds: {
5236
+ write: [Permission.FeedsWrite],
5237
+ read: [Permission.FeedsRead],
5238
+ none: [Permission.FeedsNone]
5239
+ }
5240
+ };
5241
+ var NO_PERMISSION_MATRIX = {
5242
+ room: "none",
5243
+ storage: "none",
5244
+ comments: "none",
5245
+ feeds: "none",
5246
+ personal: "none"
5247
+ };
5248
+ var BASE_PERMISSION_RESOURCE = "room";
5249
+ var ROOM_PERMISSION_RESOURCES = [
5250
+ "storage",
5251
+ "comments",
5252
+ "feeds"
5253
+ ];
5254
+ var VALID_PERMISSIONS = new Set(Object.values(Permission));
5255
+ function isPermission(permission) {
5256
+ return VALID_PERMISSIONS.has(permission);
5257
+ }
5258
+ function resolveResourceAccess(scopes, resource) {
5259
+ const permissions = PERMISSIONS_BY_RESOURCE[resource];
5260
+ let resourceAccess;
5261
+ for (const access of ACCESS_LEVELS) {
5262
+ const scopedPermissions = permissions[access];
5263
+ if (scopedPermissions !== void 0 && scopedPermissions.some((permission) => scopes.includes(permission))) {
5264
+ resourceAccess = access;
5265
+ }
5266
+ }
5267
+ return resourceAccess;
5268
+ }
5269
+ function permissionMatrixFromResolvedScopes(resolved) {
5270
+ if (!resolved.hasDefaultPermission) {
5271
+ return { ...NO_PERMISSION_MATRIX };
5272
+ }
5273
+ const matrix = {
5274
+ ...NO_PERMISSION_MATRIX,
5275
+ [BASE_PERMISSION_RESOURCE]: resolved.baseAccess,
5276
+ personal: "write"
5277
+ };
5278
+ for (const resource of ROOM_PERMISSION_RESOURCES) {
5279
+ matrix[resource] = _nullishCoalesce(resolved.matrix[resource], () => ( resolved.baseAccess));
5280
+ }
5281
+ return matrix;
5282
+ }
5283
+ function permissionMatrixFromScopes(scopes) {
5284
+ return permissionMatrixFromResolvedScopes(resolvePermissionScopes(scopes));
5285
+ }
5286
+ function resolvePermissionScopes(scopes) {
5287
+ const hasDefaultPermission = scopes.includes(Permission.Write) || scopes.includes(Permission.Read) || scopes.includes(Permission.RoomWrite) || scopes.includes(Permission.RoomRead);
5288
+ const baseAccess = scopes.includes(Permission.Write) || scopes.includes(Permission.RoomWrite) ? "write" : scopes.includes(Permission.Read) || scopes.includes(Permission.RoomRead) ? "read" : "none";
5289
+ const matrix = {};
5290
+ for (const resource of ROOM_PERMISSION_RESOURCES) {
5291
+ const access = resolveResourceAccess(scopes, resource);
5292
+ if (access !== void 0) {
5293
+ matrix[resource] = access;
5294
+ }
5295
+ }
5296
+ return { hasDefaultPermission, baseAccess, matrix };
5297
+ }
5298
+ function hasPermissionAccess(matrix, resource, requiredAccess) {
5299
+ const access = _nullishCoalesce(matrix[resource], () => ( "none"));
5300
+ return ACCESS_LEVEL_RANKS[access] >= ACCESS_LEVEL_RANKS[requiredAccess];
5301
+ }
5302
+ function resolveRoomPermissionMatrix(permissions, roomId) {
5303
+ const matchedPermissions = permissions.filter(
5304
+ (entry) => roomPatternMatches(entry.pattern, roomId)
5305
+ );
5306
+ if (matchedPermissions.length === 0) {
5307
+ return void 0;
5308
+ }
5309
+ let hasDefaultPermission = false;
5310
+ let baseAccess = "none";
5311
+ const explicitMatrix = {};
5312
+ const explicitSpecificity = {};
5313
+ for (const entry of matchedPermissions) {
5314
+ const resolved = resolvePermissionScopes(entry.scopes);
5315
+ const specificity = roomPatternSpecificity(entry.pattern);
5316
+ if (resolved.hasDefaultPermission) {
5317
+ hasDefaultPermission = true;
5318
+ baseAccess = strongestAccess(baseAccess, resolved.baseAccess);
5319
+ }
5320
+ for (const resource of ROOM_PERMISSION_RESOURCES) {
5321
+ const access = resolved.matrix[resource];
5322
+ if (access !== void 0) {
5323
+ const currentSpecificity = _nullishCoalesce(explicitSpecificity[resource], () => ( -1));
5324
+ if (specificity > currentSpecificity) {
5325
+ explicitMatrix[resource] = access;
5326
+ explicitSpecificity[resource] = specificity;
5327
+ } else if (specificity === currentSpecificity) {
5328
+ explicitMatrix[resource] = strongestAccess(
5329
+ _nullishCoalesce(explicitMatrix[resource], () => ( "none")),
5330
+ access
5331
+ );
5332
+ }
5333
+ }
5334
+ }
5335
+ }
5336
+ return permissionMatrixFromResolvedScopes({
5337
+ hasDefaultPermission,
5338
+ baseAccess,
5339
+ matrix: explicitMatrix
5340
+ });
5251
5341
  }
5342
+ function normalizeRoomPermissions(permissions) {
5343
+ if (!Array.isArray(permissions)) {
5344
+ throw new Error("Permission list must be an array");
5345
+ }
5346
+ const result = [];
5347
+ for (const permission of permissions) {
5348
+ if (!isPermission(permission)) {
5349
+ throw new Error(`Not a valid permission: ${permission}`);
5350
+ }
5351
+ result.push(permission);
5352
+ }
5353
+ return result;
5354
+ }
5355
+ function normalizeRoomAccesses(accesses) {
5356
+ if (accesses === void 0) {
5357
+ return void 0;
5358
+ }
5359
+ return Object.fromEntries(
5360
+ Object.entries(accesses).map(([id, permissions]) => [
5361
+ id,
5362
+ normalizeRoomPermissions(permissions)
5363
+ ])
5364
+ );
5365
+ }
5366
+ function normalizeUpdateRoomAccesses(accesses) {
5367
+ if (accesses === void 0) {
5368
+ return void 0;
5369
+ }
5370
+ return Object.fromEntries(
5371
+ Object.entries(accesses).map(([id, permissions]) => [
5372
+ id,
5373
+ permissions === null ? null : normalizeRoomPermissions(permissions)
5374
+ ])
5375
+ );
5376
+ }
5377
+ function permissionMatrixToScopes(matrix) {
5378
+ const scopes = [];
5379
+ const baseAccess = matrix.room;
5380
+ if (baseAccess !== "none") {
5381
+ scopes.push(permissionForAccessLevel(BASE_PERMISSION_RESOURCE, baseAccess));
5382
+ }
5383
+ for (const resource of ROOM_PERMISSION_RESOURCES) {
5384
+ const access = matrix[resource];
5385
+ if (access !== baseAccess) {
5386
+ scopes.push(permissionForAccessLevel(resource, access));
5387
+ }
5388
+ }
5389
+ return scopes;
5390
+ }
5391
+ function mergeRoomPermissionScopes({
5392
+ defaultAccesses,
5393
+ groupsAccesses,
5394
+ userAccesses
5395
+ }) {
5396
+ const sources = [
5397
+ resolvePermissionScopes(defaultAccesses),
5398
+ mergeResolvedScopesByHighestAccess(
5399
+ groupsAccesses.map(resolvePermissionScopes)
5400
+ ),
5401
+ resolvePermissionScopes(userAccesses)
5402
+ ];
5403
+ const merged = {
5404
+ hasDefaultPermission: false,
5405
+ baseAccess: "none",
5406
+ matrix: {}
5407
+ };
5408
+ for (const source of sources) {
5409
+ if (source.hasDefaultPermission) {
5410
+ merged.hasDefaultPermission = true;
5411
+ merged.baseAccess = source.baseAccess;
5412
+ }
5413
+ for (const resource of ROOM_PERMISSION_RESOURCES) {
5414
+ const access = source.matrix[resource];
5415
+ if (access !== void 0) {
5416
+ merged.matrix[resource] = access;
5417
+ }
5418
+ }
5419
+ }
5420
+ return permissionMatrixToScopes(permissionMatrixFromResolvedScopes(merged));
5421
+ }
5422
+ function mergeResolvedScopesByHighestAccess(sources) {
5423
+ const merged = {
5424
+ hasDefaultPermission: false,
5425
+ baseAccess: "none",
5426
+ matrix: {}
5427
+ };
5428
+ for (const source of sources) {
5429
+ if (source.hasDefaultPermission) {
5430
+ merged.hasDefaultPermission = true;
5431
+ merged.baseAccess = strongestAccess(merged.baseAccess, source.baseAccess);
5432
+ }
5433
+ for (const resource of ROOM_PERMISSION_RESOURCES) {
5434
+ const access = source.matrix[resource];
5435
+ if (access !== void 0) {
5436
+ merged.matrix[resource] = strongestAccess(
5437
+ _nullishCoalesce(merged.matrix[resource], () => ( "none")),
5438
+ access
5439
+ );
5440
+ }
5441
+ }
5442
+ }
5443
+ return merged;
5444
+ }
5445
+ function permissionForAccessLevel(resource, access, field = resource) {
5446
+ const levels = PERMISSIONS_BY_RESOURCE[resource];
5447
+ const permissions = levels[access];
5448
+ if (permissions === void 0 || permissions.length === 0) {
5449
+ throw new Error(
5450
+ `Invalid permission level for ${field}: ${_nullishCoalesce(JSON.stringify(access), () => ( String(access)))}`
5451
+ );
5452
+ }
5453
+ return permissions[0];
5454
+ }
5455
+ function strongestAccess(left, right) {
5456
+ return ACCESS_LEVEL_RANKS[right] > ACCESS_LEVEL_RANKS[left] ? right : left;
5457
+ }
5458
+ function roomPatternMatches(pattern, roomId) {
5459
+ if (pattern.includes("*")) {
5460
+ return roomId.startsWith(pattern.replace("*", ""));
5461
+ }
5462
+ return pattern === roomId;
5463
+ }
5464
+ function roomPatternSpecificity(pattern) {
5465
+ return pattern.replace("*", "").length;
5466
+ }
5467
+ function validatePermissionsSet(scopes) {
5468
+ const unknownScopes = scopes.filter((scope) => !VALID_PERMISSIONS.has(scope));
5469
+ if (unknownScopes.length > 0) {
5470
+ return `Unknown permission scope(s): ${unknownScopes.join(", ")}`;
5471
+ }
5472
+ const baseScopes = scopes.filter((scope) => basePermissionScopes.has(scope));
5473
+ if (baseScopes.length !== 1) {
5474
+ return `Permissions must include exactly one of ${Permission.Read}, ${Permission.Write} (or the legacy aliases ${Permission.RoomRead}, ${Permission.RoomWrite}), got ${baseScopes.length === 0 ? "none" : baseScopes.join(", ")}`;
5475
+ }
5476
+ const seenFeatures = /* @__PURE__ */ new Set();
5477
+ for (const scope of scopes) {
5478
+ if (basePermissionScopes.has(scope) || scope === Permission.LegacyRoomPresenceWrite) {
5479
+ continue;
5480
+ }
5481
+ const feature = scope.slice(0, scope.indexOf(":"));
5482
+ if (seenFeatures.has(feature)) {
5483
+ return `Permissions can include at most one scope per feature, got multiple "${feature}" scopes`;
5484
+ }
5485
+ seenFeatures.add(feature);
5486
+ }
5487
+ return true;
5488
+ }
5489
+
5490
+ // src/protocol/AuthToken.ts
5252
5491
  function isValidAuthTokenPayload(data) {
5253
5492
  return isPlainObject(data) && (data.k === "acc" /* ACCESS_TOKEN */ || data.k === "id" /* ID_TOKEN */);
5254
5493
  }
@@ -5287,47 +5526,22 @@ function createAuthManager(authOptions, onAuthenticate) {
5287
5526
  const authentication = prepareAuthentication(authOptions);
5288
5527
  const seenTokens = /* @__PURE__ */ new Set();
5289
5528
  const tokens = [];
5290
- const expiryTimes = [];
5291
5529
  const requestPromises = /* @__PURE__ */ new Map();
5292
5530
  function reset() {
5293
5531
  seenTokens.clear();
5294
5532
  tokens.length = 0;
5295
- expiryTimes.length = 0;
5296
5533
  requestPromises.clear();
5297
5534
  }
5298
- function hasCorrespondingScopes(requestedScope, scopes) {
5299
- if (requestedScope === "comments:read") {
5300
- return scopes.includes("comments:read" /* CommentsRead */) || scopes.includes("comments:write" /* CommentsWrite */) || scopes.includes("room:read" /* Read */) || scopes.includes("room:write" /* Write */);
5301
- } else if (requestedScope === "room:read") {
5302
- return scopes.includes("room:read" /* Read */) || scopes.includes("room:write" /* Write */);
5303
- }
5304
- return false;
5305
- }
5306
5535
  function getCachedToken(requestOptions) {
5307
5536
  const now2 = Math.ceil(Date.now() / 1e3);
5308
5537
  for (let i = tokens.length - 1; i >= 0; i--) {
5309
- const token = tokens[i];
5310
- const expiresAt = expiryTimes[i];
5311
- if (expiresAt <= now2) {
5538
+ const cachedToken = tokens[i];
5539
+ if (cachedToken.expiresAt <= now2) {
5312
5540
  tokens.splice(i, 1);
5313
- expiryTimes.splice(i, 1);
5314
5541
  continue;
5315
5542
  }
5316
- if (token.parsed.k === "id" /* ID_TOKEN */) {
5317
- return token;
5318
- } else if (token.parsed.k === "acc" /* ACCESS_TOKEN */) {
5319
- if (!requestOptions.roomId && Object.entries(token.parsed.perms).length === 0) {
5320
- return token;
5321
- }
5322
- for (const [resource, scopes] of Object.entries(token.parsed.perms)) {
5323
- if (!requestOptions.roomId) {
5324
- if (resource.includes("*") && hasCorrespondingScopes(requestOptions.requestedScope, scopes)) {
5325
- return token;
5326
- }
5327
- } else if (resource.includes("*") && requestOptions.roomId.startsWith(resource.replace("*", "")) || requestOptions.roomId === resource && hasCorrespondingScopes(requestOptions.requestedScope, scopes)) {
5328
- return token;
5329
- }
5330
- }
5543
+ if (cachedTokenSatisfiesRequest(cachedToken, requestOptions)) {
5544
+ return cachedToken.token;
5331
5545
  }
5332
5546
  }
5333
5547
  return void 0;
@@ -5345,11 +5559,15 @@ function createAuthManager(authOptions, onAuthenticate) {
5345
5559
  });
5346
5560
  const parsed = parseAuthToken(response.token);
5347
5561
  if (seenTokens.has(parsed.raw)) {
5562
+ const cachedToken = getCachedToken(options);
5563
+ if (_optionalChain([cachedToken, 'optionalAccess', _109 => _109.raw]) === parsed.raw) {
5564
+ return cachedToken;
5565
+ }
5348
5566
  throw new StopRetrying(
5349
5567
  "The same Liveblocks auth token was issued from the backend before. Caching Liveblocks tokens is not supported."
5350
5568
  );
5351
5569
  }
5352
- _optionalChain([onAuthenticate, 'optionalCall', _109 => _109(parsed.parsed)]);
5570
+ _optionalChain([onAuthenticate, 'optionalCall', _110 => _110(parsed.parsed)]);
5353
5571
  return parsed;
5354
5572
  }
5355
5573
  if (authentication.type === "custom") {
@@ -5357,7 +5575,7 @@ function createAuthManager(authOptions, onAuthenticate) {
5357
5575
  if (response && typeof response === "object") {
5358
5576
  if (typeof response.token === "string") {
5359
5577
  const parsed = parseAuthToken(response.token);
5360
- _optionalChain([onAuthenticate, 'optionalCall', _110 => _110(parsed.parsed)]);
5578
+ _optionalChain([onAuthenticate, 'optionalCall', _111 => _111(parsed.parsed)]);
5361
5579
  return parsed;
5362
5580
  } else if (typeof response.error === "string") {
5363
5581
  const reason = `Authentication failed: ${"reason" in response && typeof response.reason === "string" ? response.reason : "Forbidden"}`;
@@ -5385,11 +5603,12 @@ function createAuthManager(authOptions, onAuthenticate) {
5385
5603
  return { type: "secret", token: cachedToken };
5386
5604
  }
5387
5605
  let currentPromise;
5388
- if (requestOptions.roomId) {
5389
- currentPromise = requestPromises.get(requestOptions.roomId);
5606
+ const requestKey = getAuthRequestKey(requestOptions);
5607
+ if (requestKey !== void 0) {
5608
+ currentPromise = requestPromises.get(requestKey);
5390
5609
  if (currentPromise === void 0) {
5391
5610
  currentPromise = makeAuthRequest(requestOptions);
5392
- requestPromises.set(requestOptions.roomId, currentPromise);
5611
+ requestPromises.set(requestKey, currentPromise);
5393
5612
  }
5394
5613
  } else {
5395
5614
  currentPromise = requestPromises.get("liveblocks-user-token");
@@ -5403,12 +5622,12 @@ function createAuthManager(authOptions, onAuthenticate) {
5403
5622
  const BUFFER = 30;
5404
5623
  const expiresAt = Math.floor(Date.now() / 1e3) + (token.parsed.exp - token.parsed.iat) - BUFFER;
5405
5624
  seenTokens.add(token.raw);
5406
- tokens.push(token);
5407
- expiryTimes.push(expiresAt);
5625
+ const cachedToken2 = makeCachedToken(token, expiresAt);
5626
+ tokens.push(cachedToken2);
5408
5627
  return { type: "secret", token };
5409
5628
  } finally {
5410
- if (requestOptions.roomId) {
5411
- requestPromises.delete(requestOptions.roomId);
5629
+ if (requestKey !== void 0) {
5630
+ requestPromises.delete(requestKey);
5412
5631
  } else {
5413
5632
  requestPromises.delete("liveblocks-user-token");
5414
5633
  }
@@ -5419,6 +5638,43 @@ function createAuthManager(authOptions, onAuthenticate) {
5419
5638
  getAuthValue
5420
5639
  };
5421
5640
  }
5641
+ function getAuthRequestKey(request) {
5642
+ if (request.roomId === void 0) {
5643
+ return void 0;
5644
+ }
5645
+ return `${request.roomId}:${request.resource}:${request.access}`;
5646
+ }
5647
+ function makeCachedToken(token, expiresAt) {
5648
+ if (token.parsed.k === "acc" /* ACCESS_TOKEN */) {
5649
+ return {
5650
+ token,
5651
+ expiresAt,
5652
+ permissions: Object.entries(token.parsed.perms).map(
5653
+ ([pattern, scopes]) => ({
5654
+ pattern,
5655
+ scopes: normalizeRoomPermissions(scopes)
5656
+ })
5657
+ )
5658
+ };
5659
+ }
5660
+ return { token, expiresAt };
5661
+ }
5662
+ function cachedTokenSatisfiesRequest(cachedToken, request) {
5663
+ if (cachedToken.token.parsed.k === "id" /* ID_TOKEN */) {
5664
+ return true;
5665
+ }
5666
+ if (request.resource === "personal") {
5667
+ return true;
5668
+ }
5669
+ if (request.roomId === void 0) {
5670
+ return false;
5671
+ }
5672
+ const matrix = resolveRoomPermissionMatrix(
5673
+ _nullishCoalesce(cachedToken.permissions, () => ( [])),
5674
+ request.roomId
5675
+ );
5676
+ return matrix !== void 0 && hasPermissionAccess(matrix, request.resource, request.access);
5677
+ }
5422
5678
  function prepareAuthentication(authOptions) {
5423
5679
  const { publicApiKey, authEndpoint } = authOptions;
5424
5680
  if (authEndpoint !== void 0 && publicApiKey !== void 0) {
@@ -5784,6 +6040,9 @@ var UnacknowledgedOps = class {
5784
6040
  #createOpsByPosition = /* @__PURE__ */ new Map();
5785
6041
  // parentId -> (opId -> Create op)
5786
6042
  #createOpsByParent = /* @__PURE__ */ new Map();
6043
+ // opIds of pending ops that were in flight when a connection died, so the
6044
+ // server may already have processed them. See isPossiblyStored().
6045
+ #possiblyStoredOpIds = /* @__PURE__ */ new Set();
5787
6046
  #posKey(parentId, parentKey) {
5788
6047
  return `${parentId}
5789
6048
  ${parentKey}`;
@@ -5823,15 +6082,16 @@ ${parentKey}`;
5823
6082
  return;
5824
6083
  }
5825
6084
  this.#byOpId.delete(opId);
6085
+ this.#possiblyStoredOpIds.delete(opId);
5826
6086
  if (isCreateOp(op)) {
5827
6087
  const posKey = this.#posKey(op.parentId, op.parentKey);
5828
6088
  const atPosition = this.#createOpsByPosition.get(posKey);
5829
- _optionalChain([atPosition, 'optionalAccess', _111 => _111.delete, 'call', _112 => _112(opId)]);
6089
+ _optionalChain([atPosition, 'optionalAccess', _112 => _112.delete, 'call', _113 => _113(opId)]);
5830
6090
  if (atPosition !== void 0 && atPosition.size === 0) {
5831
6091
  this.#createOpsByPosition.delete(posKey);
5832
6092
  }
5833
6093
  const inParent = this.#createOpsByParent.get(op.parentId);
5834
- _optionalChain([inParent, 'optionalAccess', _113 => _113.delete, 'call', _114 => _114(opId)]);
6094
+ _optionalChain([inParent, 'optionalAccess', _114 => _114.delete, 'call', _115 => _115(opId)]);
5835
6095
  if (inParent !== void 0 && inParent.size === 0) {
5836
6096
  this.#createOpsByParent.delete(op.parentId);
5837
6097
  }
@@ -5843,19 +6103,32 @@ ${parentKey}`;
5843
6103
  * Empty if none.
5844
6104
  */
5845
6105
  getByParentIdAndKey(parentId, parentKey) {
5846
- return _nullishCoalesce(_optionalChain([this, 'access', _115 => _115.#createOpsByPosition, 'access', _116 => _116.get, 'call', _117 => _117(this.#posKey(parentId, parentKey)), 'optionalAccess', _118 => _118.values, 'call', _119 => _119()]), () => ( []));
6106
+ return _nullishCoalesce(_optionalChain([this, 'access', _116 => _116.#createOpsByPosition, 'access', _117 => _117.get, 'call', _118 => _118(this.#posKey(parentId, parentKey)), 'optionalAccess', _119 => _119.values, 'call', _120 => _120()]), () => ( []));
5847
6107
  }
5848
6108
  /**
5849
6109
  * The still-unacknowledged Create ops with the given `parentId` (across all
5850
6110
  * positions), in dispatch order. O(1) lookup. Empty if none.
5851
6111
  */
5852
6112
  getByParentId(parentId) {
5853
- return _nullishCoalesce(_optionalChain([this, 'access', _120 => _120.#createOpsByParent, 'access', _121 => _121.get, 'call', _122 => _122(parentId), 'optionalAccess', _123 => _123.values, 'call', _124 => _124()]), () => ( []));
6113
+ return _nullishCoalesce(_optionalChain([this, 'access', _121 => _121.#createOpsByParent, 'access', _122 => _122.get, 'call', _123 => _123(parentId), 'optionalAccess', _124 => _124.values, 'call', _125 => _125()]), () => ( []));
5854
6114
  }
5855
6115
  /** All still-unacknowledged ops, in dispatch order. */
5856
6116
  values() {
5857
6117
  return this.#byOpId.values();
5858
6118
  }
6119
+ isPossiblyStored(opId) {
6120
+ return this.#possiblyStoredOpIds.has(opId);
6121
+ }
6122
+ /**
6123
+ * Mark every currently pending op as possibly stored on the server. Called
6124
+ * when the connection dies: all of these ops were in flight, and their
6125
+ * (possibly lost) acks would have been the only way to know their fate.
6126
+ */
6127
+ markAllAsPossiblyStored() {
6128
+ for (const opId of this.#byOpId.keys()) {
6129
+ this.#possiblyStoredOpIds.add(opId);
6130
+ }
6131
+ }
5859
6132
  };
5860
6133
 
5861
6134
  // src/crdts/AbstractCrdt.ts
@@ -5878,7 +6151,7 @@ function createManagedPool(roomId, options) {
5878
6151
  generateId: () => `${getCurrentConnectionId()}:${clock++}`,
5879
6152
  generateOpId: () => `${getCurrentConnectionId()}:${opClock++}`,
5880
6153
  dispatch(ops, reverse, storageUpdates) {
5881
- _optionalChain([onDispatch, 'optionalCall', _125 => _125(ops, reverse, storageUpdates)]);
6154
+ _optionalChain([onDispatch, 'optionalCall', _126 => _126(ops, reverse, storageUpdates)]);
5882
6155
  },
5883
6156
  assertStorageIsWritable: () => {
5884
6157
  if (!isStorageWritable()) {
@@ -6452,7 +6725,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
6452
6725
  }
6453
6726
  return result.modified.updates[0];
6454
6727
  }
6455
- #applyRemoteInsert(op, fromSnapshot) {
6728
+ #applyRemoteInsert(op) {
6456
6729
  if (this._pool === void 0) {
6457
6730
  throw new Error("Can't attach child if managed pool is not present");
6458
6731
  }
@@ -6462,7 +6735,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
6462
6735
  this.#shiftItemPosition(existingItemIndex, key);
6463
6736
  }
6464
6737
  const { newItem, newIndex } = this.#createAttachItemAndSort(op, key);
6465
- const bumpDeltas = fromSnapshot ? [] : this.#bumpUnackedPushesAbove(key);
6738
+ const bumpDeltas = this.#bumpUnackedPushesAbove(key);
6466
6739
  return {
6467
6740
  modified: makeUpdate(this, [
6468
6741
  insertDelta(newIndex, newItem),
@@ -6477,6 +6750,13 @@ var LiveList = class _LiveList extends AbstractCrdt {
6477
6750
  * the single source of truth, so an item drops out the instant its op is
6478
6751
  * acked, with no per-instance membership to leak. Yielded in push order.
6479
6752
  *
6753
+ * Excludes ops that may already be stored on the server (they were in
6754
+ * flight when a connection died, so their fate is unknown): the bump
6755
+ * prediction assumes the server has not processed the op yet, which is only
6756
+ * guaranteed for ops sent on the current connection. For these excluded
6757
+ * ops, the server's (re-)ack states the authoritative position; predicting
6758
+ * locally could produce a wrong position that no ack would correct.
6759
+ *
6480
6760
  * Restricted to items currently in `#items`: a pushed node whose op is still
6481
6761
  * pending may have been pulled out of the list (e.g. implicitly deleted by a
6482
6762
  * remote set, or removed by an undo) while still living in the pool, and such
@@ -6490,6 +6770,9 @@ var LiveList = class _LiveList extends AbstractCrdt {
6490
6770
  if (op.intent !== "push") {
6491
6771
  continue;
6492
6772
  }
6773
+ if (this._pool.unacknowledgedOps.isPossiblyStored(op.opId)) {
6774
+ continue;
6775
+ }
6493
6776
  const node = this._pool.getNode(op.id);
6494
6777
  if (node !== void 0 && this.#items.includes(node)) {
6495
6778
  yield node;
@@ -6592,7 +6875,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
6592
6875
  #applyInsertUndoRedo(op) {
6593
6876
  const { id, parentKey: key } = op;
6594
6877
  const child = creationOpToLiveNode(op);
6595
- if (_optionalChain([this, 'access', _126 => _126._pool, 'optionalAccess', _127 => _127.getNode, 'call', _128 => _128(id)]) !== void 0) {
6878
+ if (_optionalChain([this, 'access', _127 => _127._pool, 'optionalAccess', _128 => _128.getNode, 'call', _129 => _129(id)]) !== void 0) {
6596
6879
  return { modified: false };
6597
6880
  }
6598
6881
  child._attach(id, nn(this._pool));
@@ -6600,8 +6883,8 @@ var LiveList = class _LiveList extends AbstractCrdt {
6600
6883
  const existingItemIndex = this._indexOfPosition(key);
6601
6884
  let newKey = key;
6602
6885
  if (existingItemIndex !== -1) {
6603
- const before2 = _optionalChain([this, 'access', _129 => _129.#items, 'access', _130 => _130.at, 'call', _131 => _131(existingItemIndex), 'optionalAccess', _132 => _132._parentPos]);
6604
- const after2 = _optionalChain([this, 'access', _133 => _133.#items, 'access', _134 => _134.at, 'call', _135 => _135(existingItemIndex + 1), 'optionalAccess', _136 => _136._parentPos]);
6886
+ const before2 = _optionalChain([this, 'access', _130 => _130.#items, 'access', _131 => _131.at, 'call', _132 => _132(existingItemIndex), 'optionalAccess', _133 => _133._parentPos]);
6887
+ const after2 = _optionalChain([this, 'access', _134 => _134.#items, 'access', _135 => _135.at, 'call', _136 => _136(existingItemIndex + 1), 'optionalAccess', _137 => _137._parentPos]);
6605
6888
  newKey = makePosition(before2, after2);
6606
6889
  child._setParentLink(this, newKey);
6607
6890
  }
@@ -6615,7 +6898,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
6615
6898
  #applySetUndoRedo(op) {
6616
6899
  const { id, parentKey: key } = op;
6617
6900
  const child = creationOpToLiveNode(op);
6618
- if (_optionalChain([this, 'access', _137 => _137._pool, 'optionalAccess', _138 => _138.getNode, 'call', _139 => _139(id)]) !== void 0) {
6901
+ if (_optionalChain([this, 'access', _138 => _138._pool, 'optionalAccess', _139 => _139.getNode, 'call', _140 => _140(id)]) !== void 0) {
6619
6902
  return { modified: false };
6620
6903
  }
6621
6904
  const indexOfItemWithSameKey = this._indexOfPosition(key);
@@ -6654,7 +6937,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
6654
6937
  }
6655
6938
  }
6656
6939
  /** @internal */
6657
- _attachChild(op, source, fromSnapshot = false) {
6940
+ _attachChild(op, source) {
6658
6941
  if (this._pool === void 0) {
6659
6942
  throw new Error("Can't attach child if managed pool is not present");
6660
6943
  }
@@ -6669,7 +6952,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
6669
6952
  }
6670
6953
  } else {
6671
6954
  if (source === 1 /* THEIRS */) {
6672
- result = this.#applyRemoteInsert(op, fromSnapshot);
6955
+ result = this.#applyRemoteInsert(op);
6673
6956
  } else if (source === 2 /* OURS */) {
6674
6957
  result = this.#applyInsertAck(op);
6675
6958
  } else {
@@ -6736,7 +7019,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
6736
7019
  } else {
6737
7020
  this.#updateItemPositionAt(
6738
7021
  existingItemIndex,
6739
- makePosition(newKey, _optionalChain([this, 'access', _140 => _140.#items, 'access', _141 => _141.at, 'call', _142 => _142(existingItemIndex + 1), 'optionalAccess', _143 => _143._parentPos]))
7022
+ makePosition(newKey, _optionalChain([this, 'access', _141 => _141.#items, 'access', _142 => _142.at, 'call', _143 => _143(existingItemIndex + 1), 'optionalAccess', _144 => _144._parentPos]))
6740
7023
  );
6741
7024
  const previousIndex = this.#items.findIndex((item) => item === child);
6742
7025
  this.#updateItemPosition(child, newKey);
@@ -6763,7 +7046,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
6763
7046
  this,
6764
7047
  makePosition(
6765
7048
  newKey,
6766
- _optionalChain([this, 'access', _144 => _144.#items, 'access', _145 => _145.at, 'call', _146 => _146(existingItemIndex + 1), 'optionalAccess', _147 => _147._parentPos])
7049
+ _optionalChain([this, 'access', _145 => _145.#items, 'access', _146 => _146.at, 'call', _147 => _147(existingItemIndex + 1), 'optionalAccess', _148 => _148._parentPos])
6767
7050
  )
6768
7051
  );
6769
7052
  this.#items.reposition(existingItem);
@@ -6787,7 +7070,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
6787
7070
  existingItemIndex,
6788
7071
  makePosition(
6789
7072
  newKey,
6790
- _optionalChain([this, 'access', _148 => _148.#items, 'access', _149 => _149.at, 'call', _150 => _150(existingItemIndex + 1), 'optionalAccess', _151 => _151._parentPos])
7073
+ _optionalChain([this, 'access', _149 => _149.#items, 'access', _150 => _150.at, 'call', _151 => _151(existingItemIndex + 1), 'optionalAccess', _152 => _152._parentPos])
6791
7074
  )
6792
7075
  );
6793
7076
  }
@@ -6815,7 +7098,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
6815
7098
  if (existingItemIndex !== -1) {
6816
7099
  actualNewKey = makePosition(
6817
7100
  newKey,
6818
- _optionalChain([this, 'access', _152 => _152.#items, 'access', _153 => _153.at, 'call', _154 => _154(existingItemIndex + 1), 'optionalAccess', _155 => _155._parentPos])
7101
+ _optionalChain([this, 'access', _153 => _153.#items, 'access', _154 => _154.at, 'call', _155 => _155(existingItemIndex + 1), 'optionalAccess', _156 => _156._parentPos])
6819
7102
  );
6820
7103
  }
6821
7104
  this.#updateItemPosition(child, actualNewKey);
@@ -6889,14 +7172,14 @@ var LiveList = class _LiveList extends AbstractCrdt {
6889
7172
  * instead of resolving its position against the client's stale view.
6890
7173
  */
6891
7174
  #injectAt(element, index, intent) {
6892
- _optionalChain([this, 'access', _156 => _156._pool, 'optionalAccess', _157 => _157.assertStorageIsWritable, 'call', _158 => _158()]);
7175
+ _optionalChain([this, 'access', _157 => _157._pool, 'optionalAccess', _158 => _158.assertStorageIsWritable, 'call', _159 => _159()]);
6893
7176
  if (index < 0 || index > this.#items.length) {
6894
7177
  throw new Error(
6895
7178
  `Cannot insert list item at index "${index}". index should be between 0 and ${this.#items.length}`
6896
7179
  );
6897
7180
  }
6898
- const before2 = _optionalChain([this, 'access', _159 => _159.#items, 'access', _160 => _160.at, 'call', _161 => _161(index - 1), 'optionalAccess', _162 => _162._parentPos]);
6899
- const after2 = _optionalChain([this, 'access', _163 => _163.#items, 'access', _164 => _164.at, 'call', _165 => _165(index), 'optionalAccess', _166 => _166._parentPos]);
7181
+ const before2 = _optionalChain([this, 'access', _160 => _160.#items, 'access', _161 => _161.at, 'call', _162 => _162(index - 1), 'optionalAccess', _163 => _163._parentPos]);
7182
+ const after2 = _optionalChain([this, 'access', _164 => _164.#items, 'access', _165 => _165.at, 'call', _166 => _166(index), 'optionalAccess', _167 => _167._parentPos]);
6900
7183
  const position = makePosition(before2, after2);
6901
7184
  const value = lsonToLiveNode(element);
6902
7185
  value._setParentLink(this, position);
@@ -6920,7 +7203,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
6920
7203
  * @param targetIndex The index where the element should be after moving.
6921
7204
  */
6922
7205
  move(index, targetIndex) {
6923
- _optionalChain([this, 'access', _167 => _167._pool, 'optionalAccess', _168 => _168.assertStorageIsWritable, 'call', _169 => _169()]);
7206
+ _optionalChain([this, 'access', _168 => _168._pool, 'optionalAccess', _169 => _169.assertStorageIsWritable, 'call', _170 => _170()]);
6924
7207
  if (targetIndex < 0) {
6925
7208
  throw new Error("targetIndex cannot be less than 0");
6926
7209
  }
@@ -6938,11 +7221,11 @@ var LiveList = class _LiveList extends AbstractCrdt {
6938
7221
  let beforePosition = null;
6939
7222
  let afterPosition = null;
6940
7223
  if (index < targetIndex) {
6941
- afterPosition = targetIndex === this.#items.length - 1 ? void 0 : _optionalChain([this, 'access', _170 => _170.#items, 'access', _171 => _171.at, 'call', _172 => _172(targetIndex + 1), 'optionalAccess', _173 => _173._parentPos]);
7224
+ afterPosition = targetIndex === this.#items.length - 1 ? void 0 : _optionalChain([this, 'access', _171 => _171.#items, 'access', _172 => _172.at, 'call', _173 => _173(targetIndex + 1), 'optionalAccess', _174 => _174._parentPos]);
6942
7225
  beforePosition = this.#items.at(targetIndex)._parentPos;
6943
7226
  } else {
6944
7227
  afterPosition = this.#items.at(targetIndex)._parentPos;
6945
- beforePosition = targetIndex === 0 ? void 0 : _optionalChain([this, 'access', _174 => _174.#items, 'access', _175 => _175.at, 'call', _176 => _176(targetIndex - 1), 'optionalAccess', _177 => _177._parentPos]);
7228
+ beforePosition = targetIndex === 0 ? void 0 : _optionalChain([this, 'access', _175 => _175.#items, 'access', _176 => _176.at, 'call', _177 => _177(targetIndex - 1), 'optionalAccess', _178 => _178._parentPos]);
6946
7229
  }
6947
7230
  const position = makePosition(beforePosition, afterPosition);
6948
7231
  const item = this.#items.at(index);
@@ -6977,7 +7260,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
6977
7260
  * @param index The index of the element to delete
6978
7261
  */
6979
7262
  delete(index) {
6980
- _optionalChain([this, 'access', _178 => _178._pool, 'optionalAccess', _179 => _179.assertStorageIsWritable, 'call', _180 => _180()]);
7263
+ _optionalChain([this, 'access', _179 => _179._pool, 'optionalAccess', _180 => _180.assertStorageIsWritable, 'call', _181 => _181()]);
6981
7264
  if (index < 0 || index >= this.#items.length) {
6982
7265
  throw new Error(
6983
7266
  `Cannot delete list item at index "${index}". index should be between 0 and ${this.#items.length - 1}`
@@ -7010,7 +7293,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
7010
7293
  }
7011
7294
  }
7012
7295
  clear() {
7013
- _optionalChain([this, 'access', _181 => _181._pool, 'optionalAccess', _182 => _182.assertStorageIsWritable, 'call', _183 => _183()]);
7296
+ _optionalChain([this, 'access', _182 => _182._pool, 'optionalAccess', _183 => _183.assertStorageIsWritable, 'call', _184 => _184()]);
7014
7297
  if (this._pool) {
7015
7298
  const ops = [];
7016
7299
  const reverseOps = [];
@@ -7044,7 +7327,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
7044
7327
  }
7045
7328
  }
7046
7329
  set(index, item) {
7047
- _optionalChain([this, 'access', _184 => _184._pool, 'optionalAccess', _185 => _185.assertStorageIsWritable, 'call', _186 => _186()]);
7330
+ _optionalChain([this, 'access', _185 => _185._pool, 'optionalAccess', _186 => _186.assertStorageIsWritable, 'call', _187 => _187()]);
7048
7331
  if (index < 0 || index >= this.#items.length) {
7049
7332
  throw new Error(
7050
7333
  `Cannot set list item at index "${index}". index should be between 0 and ${this.#items.length - 1}`
@@ -7203,7 +7486,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
7203
7486
  #shiftItemPosition(index, key) {
7204
7487
  const shiftedPosition = makePosition(
7205
7488
  key,
7206
- this.#items.length > index + 1 ? _optionalChain([this, 'access', _187 => _187.#items, 'access', _188 => _188.at, 'call', _189 => _189(index + 1), 'optionalAccess', _190 => _190._parentPos]) : void 0
7489
+ this.#items.length > index + 1 ? _optionalChain([this, 'access', _188 => _188.#items, 'access', _189 => _189.at, 'call', _190 => _190(index + 1), 'optionalAccess', _191 => _191._parentPos]) : void 0
7207
7490
  );
7208
7491
  this.#updateItemPositionAt(index, shiftedPosition);
7209
7492
  }
@@ -7452,7 +7735,7 @@ var LiveMap = class _LiveMap extends AbstractCrdt {
7452
7735
  * @param value The value of the element to add. Should be serializable to JSON.
7453
7736
  */
7454
7737
  set(key, value) {
7455
- _optionalChain([this, 'access', _191 => _191._pool, 'optionalAccess', _192 => _192.assertStorageIsWritable, 'call', _193 => _193()]);
7738
+ _optionalChain([this, 'access', _192 => _192._pool, 'optionalAccess', _193 => _193.assertStorageIsWritable, 'call', _194 => _194()]);
7456
7739
  const oldValue = this.#map.get(key);
7457
7740
  if (oldValue) {
7458
7741
  oldValue._detach();
@@ -7498,7 +7781,7 @@ var LiveMap = class _LiveMap extends AbstractCrdt {
7498
7781
  * @returns true if an element existed and has been removed, or false if the element does not exist.
7499
7782
  */
7500
7783
  delete(key) {
7501
- _optionalChain([this, 'access', _194 => _194._pool, 'optionalAccess', _195 => _195.assertStorageIsWritable, 'call', _196 => _196()]);
7784
+ _optionalChain([this, 'access', _195 => _195._pool, 'optionalAccess', _196 => _196.assertStorageIsWritable, 'call', _197 => _197()]);
7502
7785
  const item = this.#map.get(key);
7503
7786
  if (item === void 0) {
7504
7787
  return false;
@@ -7928,6 +8211,7 @@ var LiveObject = (_class2 = class _LiveObject extends AbstractCrdt {
7928
8211
  const id = nn(this._id);
7929
8212
  const parentKey = nn(child._parentKey);
7930
8213
  const reverse = child._toOps(id, parentKey);
8214
+ const deletedItem = liveNodeToLson(child);
7931
8215
  for (const [key, value] of this.#synced) {
7932
8216
  if (value === child) {
7933
8217
  this.#synced.delete(key);
@@ -7939,7 +8223,7 @@ var LiveObject = (_class2 = class _LiveObject extends AbstractCrdt {
7939
8223
  node: this,
7940
8224
  type: "LiveObject",
7941
8225
  updates: {
7942
- [parentKey]: { type: "delete" }
8226
+ [parentKey]: { type: "delete", deletedItem }
7943
8227
  }
7944
8228
  };
7945
8229
  return { modified: storageUpdate, reverse };
@@ -8109,20 +8393,20 @@ var LiveObject = (_class2 = class _LiveObject extends AbstractCrdt {
8109
8393
  * Caveat: this method will not add changes to the undo/redo stack.
8110
8394
  */
8111
8395
  setLocal(key, value) {
8112
- _optionalChain([this, 'access', _197 => _197._pool, 'optionalAccess', _198 => _198.assertStorageIsWritable, 'call', _199 => _199()]);
8396
+ _optionalChain([this, 'access', _198 => _198._pool, 'optionalAccess', _199 => _199.assertStorageIsWritable, 'call', _200 => _200()]);
8113
8397
  const deleteResult = this.#prepareDelete(key);
8114
8398
  this.#local.set(key, value);
8115
8399
  this.invalidate();
8116
8400
  if (this._pool !== void 0 && this._id !== void 0) {
8117
- const ops = _nullishCoalesce(_optionalChain([deleteResult, 'optionalAccess', _200 => _200[0]]), () => ( []));
8118
- const reverse = _nullishCoalesce(_optionalChain([deleteResult, 'optionalAccess', _201 => _201[1]]), () => ( []));
8119
- const storageUpdates = _nullishCoalesce(_optionalChain([deleteResult, 'optionalAccess', _202 => _202[2]]), () => ( /* @__PURE__ */ new Map()));
8401
+ const ops = _nullishCoalesce(_optionalChain([deleteResult, 'optionalAccess', _201 => _201[0]]), () => ( []));
8402
+ const reverse = _nullishCoalesce(_optionalChain([deleteResult, 'optionalAccess', _202 => _202[1]]), () => ( []));
8403
+ const storageUpdates = _nullishCoalesce(_optionalChain([deleteResult, 'optionalAccess', _203 => _203[2]]), () => ( /* @__PURE__ */ new Map()));
8120
8404
  const existing = storageUpdates.get(this._id);
8121
8405
  storageUpdates.set(this._id, {
8122
8406
  node: this,
8123
8407
  type: "LiveObject",
8124
8408
  updates: {
8125
- ..._optionalChain([existing, 'optionalAccess', _203 => _203.updates]),
8409
+ ..._optionalChain([existing, 'optionalAccess', _204 => _204.updates]),
8126
8410
  [key]: { type: "update" }
8127
8411
  }
8128
8412
  });
@@ -8142,7 +8426,7 @@ var LiveObject = (_class2 = class _LiveObject extends AbstractCrdt {
8142
8426
  * #synced or pool/id are unavailable. Does NOT dispatch.
8143
8427
  */
8144
8428
  #prepareDelete(key) {
8145
- _optionalChain([this, 'access', _204 => _204._pool, 'optionalAccess', _205 => _205.assertStorageIsWritable, 'call', _206 => _206()]);
8429
+ _optionalChain([this, 'access', _205 => _205._pool, 'optionalAccess', _206 => _206.assertStorageIsWritable, 'call', _207 => _207()]);
8146
8430
  const k = key;
8147
8431
  if (this.#local.has(k) && !this.#synced.has(k)) {
8148
8432
  const oldValue2 = this.#local.get(k);
@@ -8218,7 +8502,7 @@ var LiveObject = (_class2 = class _LiveObject extends AbstractCrdt {
8218
8502
  const result = this.#prepareDelete(key);
8219
8503
  if (result) {
8220
8504
  const [ops, reverse, storageUpdates] = result;
8221
- _optionalChain([this, 'access', _207 => _207._pool, 'optionalAccess', _208 => _208.dispatch, 'call', _209 => _209(ops, reverse, storageUpdates)]);
8505
+ _optionalChain([this, 'access', _208 => _208._pool, 'optionalAccess', _209 => _209.dispatch, 'call', _210 => _210(ops, reverse, storageUpdates)]);
8222
8506
  }
8223
8507
  }
8224
8508
  /**
@@ -8226,7 +8510,7 @@ var LiveObject = (_class2 = class _LiveObject extends AbstractCrdt {
8226
8510
  * @param patch The object used to overrides properties
8227
8511
  */
8228
8512
  update(patch) {
8229
- _optionalChain([this, 'access', _210 => _210._pool, 'optionalAccess', _211 => _211.assertStorageIsWritable, 'call', _212 => _212()]);
8513
+ _optionalChain([this, 'access', _211 => _211._pool, 'optionalAccess', _212 => _212.assertStorageIsWritable, 'call', _213 => _213()]);
8230
8514
  if (_LiveObject.detectLargeObjects) {
8231
8515
  const data = {};
8232
8516
  for (const [key, value] of this.#synced) {
@@ -8541,23 +8825,68 @@ function dumpPool(pool) {
8541
8825
  (r) => ` ${r.id} parent=${r.parentId} key=${r.key || "\u2014"} ${r.value}`
8542
8826
  ).join("\n");
8543
8827
  }
8544
- function getTreesDiffOperations(currentItems, newItems) {
8828
+ function isJsonEq(a, b) {
8829
+ if (a === b) {
8830
+ return true;
8831
+ }
8832
+ if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) {
8833
+ return false;
8834
+ }
8835
+ if (Array.isArray(a) || Array.isArray(b)) {
8836
+ if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) {
8837
+ return false;
8838
+ }
8839
+ for (let i = 0; i < a.length; i++) {
8840
+ if (!isJsonEq(a[i], b[i])) {
8841
+ return false;
8842
+ }
8843
+ }
8844
+ return true;
8845
+ }
8846
+ const aKeys = Object.keys(a);
8847
+ if (aKeys.length !== Object.keys(b).length) {
8848
+ return false;
8849
+ }
8850
+ for (const key of aKeys) {
8851
+ if (!isJsonEq(a[key], b[key])) {
8852
+ return false;
8853
+ }
8854
+ }
8855
+ return true;
8856
+ }
8857
+ function diffNodeMap(prev, next) {
8545
8858
  const ops = [];
8546
- currentItems.forEach((_, id) => {
8547
- if (!newItems.get(id)) {
8859
+ prev.forEach((_, id) => {
8860
+ if (!next.get(id)) {
8548
8861
  ops.push({ type: OpCode.DELETE_CRDT, id });
8549
8862
  }
8550
8863
  });
8551
- newItems.forEach((crdt, id) => {
8552
- const currentCrdt = currentItems.get(id);
8864
+ next.forEach((crdt, id) => {
8865
+ const currentCrdt = prev.get(id);
8553
8866
  if (currentCrdt) {
8554
8867
  if (crdt.type === CrdtType.OBJECT) {
8555
- if (currentCrdt.type !== CrdtType.OBJECT || stringifyOrLog(crdt.data) !== stringifyOrLog(currentCrdt.data)) {
8556
- ops.push({
8557
- type: OpCode.UPDATE_OBJECT,
8558
- id,
8559
- data: crdt.data
8560
- });
8868
+ if (currentCrdt.type !== CrdtType.OBJECT) {
8869
+ ops.push({ type: OpCode.UPDATE_OBJECT, id, data: crdt.data });
8870
+ } else {
8871
+ const changed = /* @__PURE__ */ new Map();
8872
+ for (const key of Object.keys(crdt.data)) {
8873
+ const value = crdt.data[key];
8874
+ if (value !== void 0 && !isJsonEq(value, currentCrdt.data[key])) {
8875
+ changed.set(key, value);
8876
+ }
8877
+ }
8878
+ if (changed.size > 0) {
8879
+ ops.push({
8880
+ type: OpCode.UPDATE_OBJECT,
8881
+ id,
8882
+ data: Object.fromEntries(changed)
8883
+ });
8884
+ }
8885
+ for (const key of Object.keys(currentCrdt.data)) {
8886
+ if (!(key in crdt.data)) {
8887
+ ops.push({ type: OpCode.DELETE_OBJECT_KEY, id, key });
8888
+ }
8889
+ }
8561
8890
  }
8562
8891
  }
8563
8892
  if (crdt.parentKey !== currentCrdt.parentKey) {
@@ -8668,7 +8997,7 @@ function sendToPanel(message, options) {
8668
8997
  ...message,
8669
8998
  source: "liveblocks-devtools-client"
8670
8999
  };
8671
- if (!(_optionalChain([options, 'optionalAccess', _213 => _213.force]) || _bridgeActive)) {
9000
+ if (!(_optionalChain([options, 'optionalAccess', _214 => _214.force]) || _bridgeActive)) {
8672
9001
  return;
8673
9002
  }
8674
9003
  window.postMessage(fullMsg, "*");
@@ -8676,7 +9005,7 @@ function sendToPanel(message, options) {
8676
9005
  var eventSource = makeEventSource();
8677
9006
  if (process.env.NODE_ENV !== "production" && typeof window !== "undefined") {
8678
9007
  window.addEventListener("message", (event) => {
8679
- if (event.source === window && _optionalChain([event, 'access', _214 => _214.data, 'optionalAccess', _215 => _215.source]) === "liveblocks-devtools-panel") {
9008
+ if (event.source === window && _optionalChain([event, 'access', _215 => _215.data, 'optionalAccess', _216 => _216.source]) === "liveblocks-devtools-panel") {
8680
9009
  eventSource.notify(event.data);
8681
9010
  } else {
8682
9011
  }
@@ -8780,7 +9109,7 @@ function partialSyncConnection(room) {
8780
9109
  });
8781
9110
  }
8782
9111
  function partialSyncStorage(room) {
8783
- const root = room.getStorageSnapshot();
9112
+ const root = room.getStorageOrNull();
8784
9113
  if (root) {
8785
9114
  sendToPanel({
8786
9115
  msg: "room::sync::partial",
@@ -8810,7 +9139,7 @@ function partialSyncOthers(room) {
8810
9139
  }
8811
9140
  }
8812
9141
  function fullSync(room) {
8813
- const root = room.getStorageSnapshot();
9142
+ const root = room.getStorageOrNull();
8814
9143
  const me = room[kInternal].getSelf_forDevTools();
8815
9144
  const others = room[kInternal].getOthers_forDevTools();
8816
9145
  room.fetchYDoc("");
@@ -8818,7 +9147,7 @@ function fullSync(room) {
8818
9147
  msg: "room::sync::full",
8819
9148
  roomId: room.id,
8820
9149
  status: room.getStatus(),
8821
- storage: _nullishCoalesce(_optionalChain([root, 'optionalAccess', _216 => _216.toTreeNode, 'call', _217 => _217("root"), 'access', _218 => _218.payload]), () => ( null)),
9150
+ storage: _nullishCoalesce(_optionalChain([root, 'optionalAccess', _217 => _217.toTreeNode, 'call', _218 => _218("root"), 'access', _219 => _219.payload]), () => ( null)),
8822
9151
  me,
8823
9152
  others
8824
9153
  });
@@ -9235,15 +9564,15 @@ var ClientMsgCode = Object.freeze({
9235
9564
 
9236
9565
  // src/refs/ManagedOthers.ts
9237
9566
  function makeUser(conn, presence) {
9238
- const { connectionId, id, info } = conn;
9239
- const canWrite = canWriteStorage(conn.scopes);
9567
+ const { connectionId, id, info, access } = conn;
9568
+ const { canWrite, canComment } = access;
9240
9569
  return freeze(
9241
9570
  compactObject({
9242
9571
  connectionId,
9243
9572
  id,
9244
9573
  info,
9245
9574
  canWrite,
9246
- canComment: canComment(conn.scopes),
9575
+ canComment,
9247
9576
  isReadOnly: !canWrite,
9248
9577
  // Deprecated, kept for backward-compatibility
9249
9578
  presence
@@ -9314,7 +9643,7 @@ var ManagedOthers = class {
9314
9643
  * Records a known connection. This records the connection ID and the
9315
9644
  * associated metadata.
9316
9645
  */
9317
- setConnection(connectionId, metaUserId, metaUserInfo, scopes) {
9646
+ setConnection(connectionId, metaUserId, metaUserInfo, access) {
9318
9647
  this.#internal.mutate((state) => {
9319
9648
  state.connections.set(
9320
9649
  connectionId,
@@ -9322,7 +9651,7 @@ var ManagedOthers = class {
9322
9651
  connectionId,
9323
9652
  id: metaUserId,
9324
9653
  info: metaUserInfo,
9325
- scopes
9654
+ access
9326
9655
  })
9327
9656
  );
9328
9657
  if (!state.presences.has(connectionId)) {
@@ -9475,6 +9804,14 @@ function defaultMessageFromContext(context) {
9475
9804
 
9476
9805
  // src/room.ts
9477
9806
  var FEEDS_TIMEOUT = 5e3;
9807
+ function connectionAccessFromScopes(scopes) {
9808
+ const roomPermissions = normalizeRoomPermissions(scopes);
9809
+ const matrix = permissionMatrixFromScopes(roomPermissions);
9810
+ return {
9811
+ canWrite: hasPermissionAccess(matrix, "storage", "write"),
9812
+ canComment: hasPermissionAccess(matrix, "comments", "write")
9813
+ };
9814
+ }
9478
9815
  function makeIdFactory(connectionId) {
9479
9816
  let count = 0;
9480
9817
  return () => `${connectionId}:${count++}`;
@@ -9497,15 +9834,15 @@ function installBackgroundTabSpy() {
9497
9834
  const doc = typeof document !== "undefined" ? document : void 0;
9498
9835
  const inBackgroundSince = { current: null };
9499
9836
  function onVisibilityChange() {
9500
- if (_optionalChain([doc, 'optionalAccess', _219 => _219.visibilityState]) === "hidden") {
9837
+ if (_optionalChain([doc, 'optionalAccess', _220 => _220.visibilityState]) === "hidden") {
9501
9838
  inBackgroundSince.current = _nullishCoalesce(inBackgroundSince.current, () => ( Date.now()));
9502
9839
  } else {
9503
9840
  inBackgroundSince.current = null;
9504
9841
  }
9505
9842
  }
9506
- _optionalChain([doc, 'optionalAccess', _220 => _220.addEventListener, 'call', _221 => _221("visibilitychange", onVisibilityChange)]);
9843
+ _optionalChain([doc, 'optionalAccess', _221 => _221.addEventListener, 'call', _222 => _222("visibilitychange", onVisibilityChange)]);
9507
9844
  const unsub = () => {
9508
- _optionalChain([doc, 'optionalAccess', _222 => _222.removeEventListener, 'call', _223 => _223("visibilitychange", onVisibilityChange)]);
9845
+ _optionalChain([doc, 'optionalAccess', _223 => _223.removeEventListener, 'call', _224 => _224("visibilitychange", onVisibilityChange)]);
9509
9846
  };
9510
9847
  return [inBackgroundSince, unsub];
9511
9848
  }
@@ -9647,12 +9984,13 @@ function createRoom(options, config) {
9647
9984
  )
9648
9985
  };
9649
9986
  if (_getStorage$ !== null) {
9650
- refreshStorage({ flush: false });
9987
+ refreshStorage();
9651
9988
  }
9652
9989
  flushNowOrSoon();
9653
9990
  }
9654
9991
  function onDidDisconnect() {
9655
9992
  clearTimeout(context.buffer.flushTimerID);
9993
+ context.unacknowledgedOps.markAllAsPossiblyStored();
9656
9994
  }
9657
9995
  managedSocket.events.onMessage.subscribe(handleServerMessage);
9658
9996
  managedSocket.events.statusDidChange.subscribe(onStatusDidChange);
@@ -9698,8 +10036,8 @@ function createRoom(options, config) {
9698
10036
  }
9699
10037
  }
9700
10038
  function isStorageWritable() {
9701
- const scopes = _optionalChain([context, 'access', _224 => _224.dynamicSessionInfoSig, 'access', _225 => _225.get, 'call', _226 => _226(), 'optionalAccess', _227 => _227.scopes]);
9702
- return scopes !== void 0 ? canWriteStorage(scopes) : true;
10039
+ const permissionMatrix = _optionalChain([context, 'access', _225 => _225.dynamicSessionInfoSig, 'access', _226 => _226.get, 'call', _227 => _227(), 'optionalAccess', _228 => _228.permissionMatrix]);
10040
+ return permissionMatrix !== void 0 ? hasPermissionAccess(permissionMatrix, "storage", "write") : true;
9703
10041
  }
9704
10042
  const eventHub = {
9705
10043
  status: makeEventSource(),
@@ -9760,14 +10098,22 @@ function createRoom(options, config) {
9760
10098
  if (staticSession === null || dynamicSession === null) {
9761
10099
  return null;
9762
10100
  } else {
9763
- const canWrite = canWriteStorage(dynamicSession.scopes);
10101
+ const canWrite = hasPermissionAccess(
10102
+ dynamicSession.permissionMatrix,
10103
+ "storage",
10104
+ "write"
10105
+ );
9764
10106
  return {
9765
10107
  connectionId: dynamicSession.actor,
9766
10108
  id: staticSession.userId,
9767
10109
  info: staticSession.userInfo,
9768
10110
  presence: myPresence,
9769
10111
  canWrite,
9770
- canComment: canComment(dynamicSession.scopes)
10112
+ canComment: hasPermissionAccess(
10113
+ dynamicSession.permissionMatrix,
10114
+ "comments",
10115
+ "write"
10116
+ )
9771
10117
  };
9772
10118
  }
9773
10119
  }
@@ -9793,12 +10139,8 @@ function createRoom(options, config) {
9793
10139
  for (const [id, crdt] of context.pool.nodes) {
9794
10140
  currentItems.set(id, crdt._serialize());
9795
10141
  }
9796
- const ops = getTreesDiffOperations(currentItems, nodes);
9797
- const result = applyRemoteOps(
9798
- ops,
9799
- /* fromSnapshot */
9800
- true
9801
- );
10142
+ const ops = diffNodeMap(currentItems, nodes);
10143
+ const result = applyRemoteOps(ops);
9802
10144
  notify(result.updates);
9803
10145
  } else {
9804
10146
  context.root = LiveObject._fromItems(
@@ -9806,7 +10148,7 @@ function createRoom(options, config) {
9806
10148
  context.pool
9807
10149
  );
9808
10150
  }
9809
- const canWrite = _nullishCoalesce(_optionalChain([self, 'access', _228 => _228.get, 'call', _229 => _229(), 'optionalAccess', _230 => _230.canWrite]), () => ( true));
10151
+ const canWrite = _nullishCoalesce(_optionalChain([self, 'access', _229 => _229.get, 'call', _230 => _230(), 'optionalAccess', _231 => _231.canWrite]), () => ( true));
9810
10152
  const root = context.root;
9811
10153
  disableHistory(() => {
9812
10154
  for (const key in context.initialStorage) {
@@ -9880,16 +10222,15 @@ function createRoom(options, config) {
9880
10222
  );
9881
10223
  return { opsToEmit: opsWithOpIds, reverse, updates };
9882
10224
  }
9883
- function applyRemoteOps(ops, fromSnapshot = false) {
10225
+ function applyRemoteOps(ops) {
9884
10226
  return applyOps(
9885
10227
  [],
9886
10228
  ops,
9887
10229
  /* isLocal */
9888
- false,
9889
- fromSnapshot
10230
+ false
9890
10231
  );
9891
10232
  }
9892
- function applyOps(pframes, ops, isLocal, fromSnapshot = false) {
10233
+ function applyOps(pframes, ops, isLocal) {
9893
10234
  const output = {
9894
10235
  reverse: new Deque(),
9895
10236
  storageUpdates: /* @__PURE__ */ new Map(),
@@ -9925,7 +10266,7 @@ function createRoom(options, config) {
9925
10266
  } else {
9926
10267
  source = 1 /* THEIRS */;
9927
10268
  }
9928
- const applyOpResult = applyOp(op, source, fromSnapshot);
10269
+ const applyOpResult = applyOp(op, source);
9929
10270
  if (applyOpResult.modified) {
9930
10271
  const nodeId = applyOpResult.modified.node._id;
9931
10272
  if (!(nodeId && createdNodeIds.has(nodeId))) {
@@ -9951,7 +10292,7 @@ function createRoom(options, config) {
9951
10292
  }
9952
10293
  };
9953
10294
  }
9954
- function applyOp(op, source, fromSnapshot = false) {
10295
+ function applyOp(op, source) {
9955
10296
  if (isIgnoredOp(op)) {
9956
10297
  return { modified: false };
9957
10298
  }
@@ -9990,7 +10331,7 @@ function createRoom(options, config) {
9990
10331
  if (parentNode === void 0) {
9991
10332
  return { modified: false };
9992
10333
  }
9993
- return parentNode._attachChild(op, source, fromSnapshot);
10334
+ return parentNode._attachChild(op, source);
9994
10335
  }
9995
10336
  }
9996
10337
  }
@@ -10012,7 +10353,7 @@ function createRoom(options, config) {
10012
10353
  }
10013
10354
  context.myPresence.patch(patch);
10014
10355
  if (context.activeBatch) {
10015
- if (_optionalChain([options2, 'optionalAccess', _231 => _231.addToHistory])) {
10356
+ if (_optionalChain([options2, 'optionalAccess', _232 => _232.addToHistory])) {
10016
10357
  context.activeBatch.reverseOps.pushLeft({
10017
10358
  type: "presence",
10018
10359
  data: oldValues
@@ -10021,7 +10362,7 @@ function createRoom(options, config) {
10021
10362
  context.activeBatch.updates.presence = true;
10022
10363
  } else {
10023
10364
  flushNowOrSoon();
10024
- if (_optionalChain([options2, 'optionalAccess', _232 => _232.addToHistory])) {
10365
+ if (_optionalChain([options2, 'optionalAccess', _233 => _233.addToHistory])) {
10025
10366
  addToUndoStack([{ type: "presence", data: oldValues }]);
10026
10367
  }
10027
10368
  notify({ presence: true });
@@ -10061,7 +10402,9 @@ function createRoom(options, config) {
10061
10402
  context.dynamicSessionInfoSig.set({
10062
10403
  actor: message.actor,
10063
10404
  nonce: message.nonce,
10064
- scopes: message.scopes,
10405
+ permissionMatrix: permissionMatrixFromScopes(
10406
+ normalizeRoomPermissions(message.scopes)
10407
+ ),
10065
10408
  meta: message.meta
10066
10409
  });
10067
10410
  context.idFactory = makeIdFactory(message.actor);
@@ -10082,7 +10425,7 @@ function createRoom(options, config) {
10082
10425
  connectionId,
10083
10426
  user.id,
10084
10427
  user.info,
10085
- user.scopes
10428
+ connectionAccessFromScopes(user.scopes)
10086
10429
  );
10087
10430
  }
10088
10431
  return { type: "reset" };
@@ -10102,7 +10445,7 @@ function createRoom(options, config) {
10102
10445
  message.actor,
10103
10446
  message.id,
10104
10447
  message.info,
10105
- message.scopes
10448
+ connectionAccessFromScopes(message.scopes)
10106
10449
  );
10107
10450
  context.buffer.messages.push({
10108
10451
  type: ClientMsgCode.UPDATE_PRESENCE,
@@ -10198,11 +10541,11 @@ function createRoom(options, config) {
10198
10541
  break;
10199
10542
  }
10200
10543
  case ServerMsgCode.STORAGE_CHUNK:
10201
- _optionalChain([stopwatch, 'optionalAccess', _233 => _233.lap, 'call', _234 => _234()]);
10544
+ _optionalChain([stopwatch, 'optionalAccess', _234 => _234.lap, 'call', _235 => _235()]);
10202
10545
  nodeMapBuffer.append(compactNodesToNodeStream(message.nodes));
10203
10546
  break;
10204
10547
  case ServerMsgCode.STORAGE_STREAM_END: {
10205
- const timing = _optionalChain([stopwatch, 'optionalAccess', _235 => _235.stop, 'call', _236 => _236()]);
10548
+ const timing = _optionalChain([stopwatch, 'optionalAccess', _236 => _236.stop, 'call', _237 => _237()]);
10206
10549
  if (timing) {
10207
10550
  const ms = (v) => `${v.toFixed(1)}ms`;
10208
10551
  const rest = timing.laps.slice(1);
@@ -10337,11 +10680,11 @@ function createRoom(options, config) {
10337
10680
  } else if (pendingFeedsRequests.has(requestId)) {
10338
10681
  const pending = pendingFeedsRequests.get(requestId);
10339
10682
  pendingFeedsRequests.delete(requestId);
10340
- _optionalChain([pending, 'optionalAccess', _237 => _237.reject, 'call', _238 => _238(err)]);
10683
+ _optionalChain([pending, 'optionalAccess', _238 => _238.reject, 'call', _239 => _239(err)]);
10341
10684
  } else if (pendingFeedMessagesRequests.has(requestId)) {
10342
10685
  const pending = pendingFeedMessagesRequests.get(requestId);
10343
10686
  pendingFeedMessagesRequests.delete(requestId);
10344
- _optionalChain([pending, 'optionalAccess', _239 => _239.reject, 'call', _240 => _240(err)]);
10687
+ _optionalChain([pending, 'optionalAccess', _240 => _240.reject, 'call', _241 => _241(err)]);
10345
10688
  }
10346
10689
  eventHub.feeds.notify(message);
10347
10690
  break;
@@ -10495,10 +10838,10 @@ function createRoom(options, config) {
10495
10838
  timeoutId,
10496
10839
  kind,
10497
10840
  feedId,
10498
- messageId: _optionalChain([options2, 'optionalAccess', _241 => _241.messageId]),
10499
- expectedClientMessageId: _optionalChain([options2, 'optionalAccess', _242 => _242.expectedClientMessageId])
10841
+ messageId: _optionalChain([options2, 'optionalAccess', _242 => _242.messageId]),
10842
+ expectedClientMessageId: _optionalChain([options2, 'optionalAccess', _243 => _243.expectedClientMessageId])
10500
10843
  });
10501
- if (kind === "add-message" && _optionalChain([options2, 'optionalAccess', _243 => _243.expectedClientMessageId]) === void 0) {
10844
+ if (kind === "add-message" && _optionalChain([options2, 'optionalAccess', _244 => _244.expectedClientMessageId]) === void 0) {
10502
10845
  const q = _nullishCoalesce(pendingAddMessageFifoByFeed.get(feedId), () => ( []));
10503
10846
  q.push(requestId);
10504
10847
  pendingAddMessageFifoByFeed.set(feedId, q);
@@ -10549,10 +10892,10 @@ function createRoom(options, config) {
10549
10892
  }
10550
10893
  if (!matched) {
10551
10894
  const q = pendingAddMessageFifoByFeed.get(message.feedId);
10552
- const headId = _optionalChain([q, 'optionalAccess', _244 => _244[0]]);
10895
+ const headId = _optionalChain([q, 'optionalAccess', _245 => _245[0]]);
10553
10896
  if (headId !== void 0) {
10554
10897
  const pending = pendingFeedMutations.get(headId);
10555
- if (_optionalChain([pending, 'optionalAccess', _245 => _245.kind]) === "add-message" && pending.expectedClientMessageId === void 0) {
10898
+ if (_optionalChain([pending, 'optionalAccess', _246 => _246.kind]) === "add-message" && pending.expectedClientMessageId === void 0) {
10556
10899
  settleFeedMutation(headId, "ok");
10557
10900
  }
10558
10901
  }
@@ -10588,33 +10931,22 @@ function createRoom(options, config) {
10588
10931
  const unacknowledgedOps2 = [...context.unacknowledgedOps.values()];
10589
10932
  createOrUpdateRootFromMessage(nodes);
10590
10933
  applyAndSendOfflineOps(unacknowledgedOps2);
10591
- _optionalChain([_resolveStoragePromise, 'optionalCall', _246 => _246()]);
10934
+ _optionalChain([_resolveStoragePromise, 'optionalCall', _247 => _247()]);
10592
10935
  notifyStorageStatus();
10593
10936
  eventHub.storageDidLoad.notify();
10594
10937
  }
10595
- async function streamStorage() {
10596
- if (!managedSocket.authValue) return;
10597
- const nodes = new Map(
10598
- await httpClient.streamStorage({ roomId })
10599
- );
10600
- processInitialStorage(nodes);
10601
- }
10602
- function refreshStorage(options2) {
10938
+ function refreshStorage() {
10603
10939
  const messages = context.buffer.messages;
10604
- if (config.unstable_streamData) {
10605
- void streamStorage();
10606
- } else if (!messages.some((msg) => msg.type === ClientMsgCode.FETCH_STORAGE)) {
10940
+ if (!messages.some((msg) => msg.type === ClientMsgCode.FETCH_STORAGE)) {
10607
10941
  messages.push({ type: ClientMsgCode.FETCH_STORAGE });
10608
10942
  nodeMapBuffer.take();
10609
- _optionalChain([stopwatch, 'optionalAccess', _247 => _247.start, 'call', _248 => _248()]);
10610
- }
10611
- if (options2.flush) {
10612
- flushNowOrSoon();
10943
+ _optionalChain([stopwatch, 'optionalAccess', _248 => _248.start, 'call', _249 => _249()]);
10613
10944
  }
10614
10945
  }
10615
10946
  function startLoadingStorage() {
10616
10947
  if (_getStorage$ === null) {
10617
- refreshStorage({ flush: true });
10948
+ refreshStorage();
10949
+ flushNowOrSoon();
10618
10950
  _getStorage$ = new Promise((resolve) => {
10619
10951
  _resolveStoragePromise = resolve;
10620
10952
  });
@@ -10622,7 +10954,7 @@ function createRoom(options, config) {
10622
10954
  }
10623
10955
  return _getStorage$;
10624
10956
  }
10625
- function getStorageSnapshot() {
10957
+ function getStorageOrNull() {
10626
10958
  const root = context.root;
10627
10959
  if (root !== void 0) {
10628
10960
  return root;
@@ -10662,10 +10994,10 @@ function createRoom(options, config) {
10662
10994
  const message = {
10663
10995
  type: ClientMsgCode.FETCH_FEEDS,
10664
10996
  requestId,
10665
- cursor: _optionalChain([options2, 'optionalAccess', _249 => _249.cursor]),
10666
- since: _optionalChain([options2, 'optionalAccess', _250 => _250.since]),
10667
- limit: _optionalChain([options2, 'optionalAccess', _251 => _251.limit]),
10668
- metadata: _optionalChain([options2, 'optionalAccess', _252 => _252.metadata])
10997
+ cursor: _optionalChain([options2, 'optionalAccess', _250 => _250.cursor]),
10998
+ since: _optionalChain([options2, 'optionalAccess', _251 => _251.since]),
10999
+ limit: _optionalChain([options2, 'optionalAccess', _252 => _252.limit]),
11000
+ metadata: _optionalChain([options2, 'optionalAccess', _253 => _253.metadata])
10669
11001
  };
10670
11002
  context.buffer.messages.push(message);
10671
11003
  flushNowOrSoon();
@@ -10685,9 +11017,9 @@ function createRoom(options, config) {
10685
11017
  type: ClientMsgCode.FETCH_FEED_MESSAGES,
10686
11018
  requestId,
10687
11019
  feedId,
10688
- cursor: _optionalChain([options2, 'optionalAccess', _253 => _253.cursor]),
10689
- since: _optionalChain([options2, 'optionalAccess', _254 => _254.since]),
10690
- limit: _optionalChain([options2, 'optionalAccess', _255 => _255.limit])
11020
+ cursor: _optionalChain([options2, 'optionalAccess', _254 => _254.cursor]),
11021
+ since: _optionalChain([options2, 'optionalAccess', _255 => _255.since]),
11022
+ limit: _optionalChain([options2, 'optionalAccess', _256 => _256.limit])
10691
11023
  };
10692
11024
  context.buffer.messages.push(message);
10693
11025
  flushNowOrSoon();
@@ -10706,8 +11038,8 @@ function createRoom(options, config) {
10706
11038
  type: ClientMsgCode.ADD_FEED,
10707
11039
  requestId,
10708
11040
  feedId,
10709
- metadata: _optionalChain([options2, 'optionalAccess', _256 => _256.metadata]),
10710
- createdAt: _optionalChain([options2, 'optionalAccess', _257 => _257.createdAt])
11041
+ metadata: _optionalChain([options2, 'optionalAccess', _257 => _257.metadata]),
11042
+ createdAt: _optionalChain([options2, 'optionalAccess', _258 => _258.createdAt])
10711
11043
  };
10712
11044
  context.buffer.messages.push(message);
10713
11045
  flushNowOrSoon();
@@ -10741,15 +11073,15 @@ function createRoom(options, config) {
10741
11073
  function addFeedMessage(feedId, data, options2) {
10742
11074
  const requestId = nanoid();
10743
11075
  const promise = registerFeedMutation(requestId, "add-message", feedId, {
10744
- expectedClientMessageId: _optionalChain([options2, 'optionalAccess', _258 => _258.id])
11076
+ expectedClientMessageId: _optionalChain([options2, 'optionalAccess', _259 => _259.id])
10745
11077
  });
10746
11078
  const message = {
10747
11079
  type: ClientMsgCode.ADD_FEED_MESSAGE,
10748
11080
  requestId,
10749
11081
  feedId,
10750
11082
  data,
10751
- id: _optionalChain([options2, 'optionalAccess', _259 => _259.id]),
10752
- createdAt: _optionalChain([options2, 'optionalAccess', _260 => _260.createdAt])
11083
+ id: _optionalChain([options2, 'optionalAccess', _260 => _260.id]),
11084
+ createdAt: _optionalChain([options2, 'optionalAccess', _261 => _261.createdAt])
10753
11085
  };
10754
11086
  context.buffer.messages.push(message);
10755
11087
  flushNowOrSoon();
@@ -10766,7 +11098,7 @@ function createRoom(options, config) {
10766
11098
  feedId,
10767
11099
  messageId,
10768
11100
  data,
10769
- updatedAt: _optionalChain([options2, 'optionalAccess', _261 => _261.updatedAt])
11101
+ updatedAt: _optionalChain([options2, 'optionalAccess', _262 => _262.updatedAt])
10770
11102
  };
10771
11103
  context.buffer.messages.push(message);
10772
11104
  flushNowOrSoon();
@@ -10936,7 +11268,7 @@ function createRoom(options, config) {
10936
11268
  }
10937
11269
  }
10938
11270
  function isStorageReady() {
10939
- return getStorageSnapshot() !== null;
11271
+ return getStorageOrNull() !== null;
10940
11272
  }
10941
11273
  async function waitUntilStorageReady() {
10942
11274
  while (!isStorageReady()) {
@@ -10973,8 +11305,8 @@ function createRoom(options, config) {
10973
11305
  async function getThreads(options2) {
10974
11306
  return httpClient.getThreads({
10975
11307
  roomId,
10976
- query: _optionalChain([options2, 'optionalAccess', _262 => _262.query]),
10977
- cursor: _optionalChain([options2, 'optionalAccess', _263 => _263.cursor])
11308
+ query: _optionalChain([options2, 'optionalAccess', _263 => _263.query]),
11309
+ cursor: _optionalChain([options2, 'optionalAccess', _264 => _264.cursor])
10978
11310
  });
10979
11311
  }
10980
11312
  async function getThread(threadId) {
@@ -11096,7 +11428,7 @@ function createRoom(options, config) {
11096
11428
  function getSubscriptionSettings(options2) {
11097
11429
  return httpClient.getSubscriptionSettings({
11098
11430
  roomId,
11099
- signal: _optionalChain([options2, 'optionalAccess', _264 => _264.signal])
11431
+ signal: _optionalChain([options2, 'optionalAccess', _265 => _265.signal])
11100
11432
  });
11101
11433
  }
11102
11434
  function updateSubscriptionSettings(settings) {
@@ -11118,7 +11450,7 @@ function createRoom(options, config) {
11118
11450
  {
11119
11451
  [kInternal]: {
11120
11452
  get presenceBuffer() {
11121
- return deepClone(_nullishCoalesce(_optionalChain([context, 'access', _265 => _265.buffer, 'access', _266 => _266.presenceUpdates, 'optionalAccess', _267 => _267.data]), () => ( null)));
11453
+ return deepClone(_nullishCoalesce(_optionalChain([context, 'access', _266 => _266.buffer, 'access', _267 => _267.presenceUpdates, 'optionalAccess', _268 => _268.data]), () => ( null)));
11122
11454
  },
11123
11455
  // prettier-ignore
11124
11456
  get undoStack() {
@@ -11133,9 +11465,9 @@ function createRoom(options, config) {
11133
11465
  return context.yjsProvider;
11134
11466
  },
11135
11467
  setYjsProvider(newProvider) {
11136
- _optionalChain([context, 'access', _268 => _268.yjsProvider, 'optionalAccess', _269 => _269.off, 'call', _270 => _270("status", yjsStatusDidChange)]);
11468
+ _optionalChain([context, 'access', _269 => _269.yjsProvider, 'optionalAccess', _270 => _270.off, 'call', _271 => _271("status", yjsStatusDidChange)]);
11137
11469
  context.yjsProvider = newProvider;
11138
- _optionalChain([newProvider, 'optionalAccess', _271 => _271.on, 'call', _272 => _272("status", yjsStatusDidChange)]);
11470
+ _optionalChain([newProvider, 'optionalAccess', _272 => _272.on, 'call', _273 => _273("status", yjsStatusDidChange)]);
11139
11471
  context.yjsProviderDidChange.notify();
11140
11472
  },
11141
11473
  yjsProviderDidChange: context.yjsProviderDidChange.observable,
@@ -11179,7 +11511,9 @@ function createRoom(options, config) {
11179
11511
  _dump: () => {
11180
11512
  const n = context.pool.nodes.size;
11181
11513
  return `Room "${roomId}" (${n} node${n === 1 ? "" : "s"}):
11182
- ${dumpPool(context.pool)}`;
11514
+ ${dumpPool(
11515
+ context.pool
11516
+ )}`;
11183
11517
  },
11184
11518
  destroy: () => {
11185
11519
  pendingFeedsRequests.forEach(
@@ -11193,7 +11527,7 @@ ${dumpPool(context.pool)}`;
11193
11527
  source.dispose();
11194
11528
  }
11195
11529
  eventHub.roomWillDestroy.notify();
11196
- _optionalChain([context, 'access', _273 => _273.yjsProvider, 'optionalAccess', _274 => _274.off, 'call', _275 => _275("status", yjsStatusDidChange)]);
11530
+ _optionalChain([context, 'access', _274 => _274.yjsProvider, 'optionalAccess', _275 => _275.off, 'call', _276 => _276("status", yjsStatusDidChange)]);
11197
11531
  syncSourceForStorage.destroy();
11198
11532
  syncSourceForYjs.destroy();
11199
11533
  uninstallBgTabSpy();
@@ -11226,7 +11560,9 @@ ${dumpPool(context.pool)}`;
11226
11560
  updateFeedMessage,
11227
11561
  deleteFeedMessage,
11228
11562
  getStorage,
11229
- getStorageSnapshot,
11563
+ getStorageOrNull,
11564
+ getStorageSnapshot: getStorageOrNull,
11565
+ // Deprecated alias, will be removed in the future
11230
11566
  getStorageStatus,
11231
11567
  isPresenceReady,
11232
11568
  isStorageReady,
@@ -11353,7 +11689,7 @@ function makeClassicSubscribeFn(roomId, events, errorEvents) {
11353
11689
  }
11354
11690
  if (isLiveNode(first)) {
11355
11691
  const node = first;
11356
- if (_optionalChain([options, 'optionalAccess', _276 => _276.isDeep])) {
11692
+ if (_optionalChain([options, 'optionalAccess', _277 => _277.isDeep])) {
11357
11693
  const storageCallback = second;
11358
11694
  return subscribeToLiveStructureDeeply(node, storageCallback);
11359
11695
  } else {
@@ -11372,7 +11708,11 @@ function isRoomEventName(value) {
11372
11708
  }
11373
11709
  function makeAuthDelegateForRoom(roomId, authManager) {
11374
11710
  return async () => {
11375
- return authManager.getAuthValue({ requestedScope: "room:read", roomId });
11711
+ return authManager.getAuthValue({
11712
+ roomId,
11713
+ resource: "room",
11714
+ access: "read"
11715
+ });
11376
11716
  };
11377
11717
  }
11378
11718
  function makeCreateSocketDelegateForRoom(roomId, baseUrl, WebSocketPolyfill) {
@@ -11421,7 +11761,7 @@ function getBaseUrl(baseUrl) {
11421
11761
  function isLocalhost(url2) {
11422
11762
  try {
11423
11763
  return new URL(url2).hostname === "localhost";
11424
- } catch (e12) {
11764
+ } catch (e11) {
11425
11765
  return false;
11426
11766
  }
11427
11767
  }
@@ -11439,12 +11779,11 @@ function createClient(options) {
11439
11779
  const authManager = createAuthManager(options, (token) => {
11440
11780
  currentUserId.set(() => token.uid);
11441
11781
  });
11442
- const fetchPolyfill = _optionalChain([clientOptions, 'access', _277 => _277.polyfills, 'optionalAccess', _278 => _278.fetch]) || /* istanbul ignore next */
11443
- _optionalChain([globalThis, 'access', _279 => _279.fetch, 'optionalAccess', _280 => _280.bind, 'call', _281 => _281(globalThis)]);
11782
+ const fetchPolyfill = _optionalChain([clientOptions, 'access', _278 => _278.polyfills, 'optionalAccess', _279 => _279.fetch]) || /* istanbul ignore next */
11783
+ _optionalChain([globalThis, 'access', _280 => _280.fetch, 'optionalAccess', _281 => _281.bind, 'call', _282 => _282(globalThis)]);
11444
11784
  const httpClient = createApiClient({
11445
11785
  baseUrl,
11446
11786
  fetchPolyfill,
11447
- currentUserId,
11448
11787
  authManager
11449
11788
  });
11450
11789
  const roomsById = /* @__PURE__ */ new Map();
@@ -11458,11 +11797,12 @@ function createClient(options) {
11458
11797
  delegates: {
11459
11798
  createSocket: makeCreateSocketDelegateForAi(
11460
11799
  baseUrl,
11461
- _optionalChain([clientOptions, 'access', _282 => _282.polyfills, 'optionalAccess', _283 => _283.WebSocket])
11800
+ _optionalChain([clientOptions, 'access', _283 => _283.polyfills, 'optionalAccess', _284 => _284.WebSocket])
11462
11801
  ),
11463
11802
  authenticate: async () => {
11464
11803
  const resp = await authManager.getAuthValue({
11465
- requestedScope: "room:read"
11804
+ resource: "personal",
11805
+ access: "write"
11466
11806
  });
11467
11807
  if (resp.type === "public") {
11468
11808
  throw new StopRetrying(
@@ -11528,14 +11868,13 @@ function createClient(options) {
11528
11868
  createSocket: makeCreateSocketDelegateForRoom(
11529
11869
  roomId,
11530
11870
  baseUrl,
11531
- _optionalChain([clientOptions, 'access', _284 => _284.polyfills, 'optionalAccess', _285 => _285.WebSocket])
11871
+ _optionalChain([clientOptions, 'access', _285 => _285.polyfills, 'optionalAccess', _286 => _286.WebSocket])
11532
11872
  ),
11533
11873
  authenticate: makeAuthDelegateForRoom(roomId, authManager)
11534
11874
  })),
11535
11875
  enableDebugLogging: clientOptions.enableDebugLogging,
11536
11876
  baseUrl,
11537
11877
  errorEventSource: liveblocksErrorSource,
11538
- unstable_streamData: !!clientOptions.unstable_streamData,
11539
11878
  roomHttpClient: httpClient,
11540
11879
  createSyncSource,
11541
11880
  badgeLocation: _nullishCoalesce(clientOptions.badgeLocation, () => ( "bottom-right"))
@@ -11551,7 +11890,7 @@ function createClient(options) {
11551
11890
  const shouldConnect = _nullishCoalesce(options2.autoConnect, () => ( true));
11552
11891
  if (shouldConnect) {
11553
11892
  if (typeof atob === "undefined") {
11554
- if (_optionalChain([clientOptions, 'access', _286 => _286.polyfills, 'optionalAccess', _287 => _287.atob]) === void 0) {
11893
+ if (_optionalChain([clientOptions, 'access', _287 => _287.polyfills, 'optionalAccess', _288 => _288.atob]) === void 0) {
11555
11894
  throw new Error(
11556
11895
  "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"
11557
11896
  );
@@ -11563,7 +11902,7 @@ function createClient(options) {
11563
11902
  return leaseRoom(newRoomDetails);
11564
11903
  }
11565
11904
  function getRoom(roomId) {
11566
- const room = _optionalChain([roomsById, 'access', _288 => _288.get, 'call', _289 => _289(roomId), 'optionalAccess', _290 => _290.room]);
11905
+ const room = _optionalChain([roomsById, 'access', _289 => _289.get, 'call', _290 => _290(roomId), 'optionalAccess', _291 => _291.room]);
11567
11906
  return room ? room : null;
11568
11907
  }
11569
11908
  function logout() {
@@ -11579,7 +11918,7 @@ function createClient(options) {
11579
11918
  const batchedResolveUsers = new Batch(
11580
11919
  async (batchedUserIds) => {
11581
11920
  const userIds = batchedUserIds.flat();
11582
- const users = await _optionalChain([resolveUsers, 'optionalCall', _291 => _291({ userIds })]);
11921
+ const users = await _optionalChain([resolveUsers, 'optionalCall', _292 => _292({ userIds })]);
11583
11922
  warnOnceIf(
11584
11923
  !resolveUsers,
11585
11924
  "Set the resolveUsers option in createClient to specify user info."
@@ -11596,7 +11935,7 @@ function createClient(options) {
11596
11935
  const batchedResolveRoomsInfo = new Batch(
11597
11936
  async (batchedRoomIds) => {
11598
11937
  const roomIds = batchedRoomIds.flat();
11599
- const roomsInfo = await _optionalChain([resolveRoomsInfo, 'optionalCall', _292 => _292({ roomIds })]);
11938
+ const roomsInfo = await _optionalChain([resolveRoomsInfo, 'optionalCall', _293 => _293({ roomIds })]);
11600
11939
  warnOnceIf(
11601
11940
  !resolveRoomsInfo,
11602
11941
  "Set the resolveRoomsInfo option in createClient to specify room info."
@@ -11613,7 +11952,7 @@ function createClient(options) {
11613
11952
  const batchedResolveGroupsInfo = new Batch(
11614
11953
  async (batchedGroupIds) => {
11615
11954
  const groupIds = batchedGroupIds.flat();
11616
- const groupsInfo = await _optionalChain([resolveGroupsInfo, 'optionalCall', _293 => _293({ groupIds })]);
11955
+ const groupsInfo = await _optionalChain([resolveGroupsInfo, 'optionalCall', _294 => _294({ groupIds })]);
11617
11956
  warnOnceIf(
11618
11957
  !resolveGroupsInfo,
11619
11958
  "Set the resolveGroupsInfo option in createClient to specify group info."
@@ -11672,7 +12011,7 @@ function createClient(options) {
11672
12011
  }
11673
12012
  };
11674
12013
  const win = typeof window !== "undefined" ? window : void 0;
11675
- _optionalChain([win, 'optionalAccess', _294 => _294.addEventListener, 'call', _295 => _295("beforeunload", maybePreventClose)]);
12014
+ _optionalChain([win, 'optionalAccess', _295 => _295.addEventListener, 'call', _296 => _296("beforeunload", maybePreventClose)]);
11676
12015
  }
11677
12016
  async function getNotificationSettings(options2) {
11678
12017
  const plainSettings = await httpClient.getNotificationSettings(options2);
@@ -11800,7 +12139,7 @@ var commentBodyElementsTypes = {
11800
12139
  mention: "inline"
11801
12140
  };
11802
12141
  function traverseCommentBody(body, elementOrVisitor, possiblyVisitor) {
11803
- if (!body || !_optionalChain([body, 'optionalAccess', _296 => _296.content])) {
12142
+ if (!body || !_optionalChain([body, 'optionalAccess', _297 => _297.content])) {
11804
12143
  return;
11805
12144
  }
11806
12145
  const element = typeof elementOrVisitor === "string" ? elementOrVisitor : void 0;
@@ -11810,13 +12149,13 @@ function traverseCommentBody(body, elementOrVisitor, possiblyVisitor) {
11810
12149
  for (const block of body.content) {
11811
12150
  if (type === "all" || type === "block") {
11812
12151
  if (guard(block)) {
11813
- _optionalChain([visitor, 'optionalCall', _297 => _297(block)]);
12152
+ _optionalChain([visitor, 'optionalCall', _298 => _298(block)]);
11814
12153
  }
11815
12154
  }
11816
12155
  if (type === "all" || type === "inline") {
11817
12156
  for (const inline of block.children) {
11818
12157
  if (guard(inline)) {
11819
- _optionalChain([visitor, 'optionalCall', _298 => _298(inline)]);
12158
+ _optionalChain([visitor, 'optionalCall', _299 => _299(inline)]);
11820
12159
  }
11821
12160
  }
11822
12161
  }
@@ -11986,7 +12325,7 @@ var stringifyCommentBodyPlainElements = {
11986
12325
  text: ({ element }) => element.text,
11987
12326
  link: ({ element }) => _nullishCoalesce(element.text, () => ( element.url)),
11988
12327
  mention: ({ element, user, group }) => {
11989
- return `@${_nullishCoalesce(_nullishCoalesce(_optionalChain([user, 'optionalAccess', _299 => _299.name]), () => ( _optionalChain([group, 'optionalAccess', _300 => _300.name]))), () => ( element.id))}`;
12328
+ return `@${_nullishCoalesce(_nullishCoalesce(_optionalChain([user, 'optionalAccess', _300 => _300.name]), () => ( _optionalChain([group, 'optionalAccess', _301 => _301.name]))), () => ( element.id))}`;
11990
12329
  }
11991
12330
  };
11992
12331
  var stringifyCommentBodyHtmlElements = {
@@ -12016,7 +12355,7 @@ var stringifyCommentBodyHtmlElements = {
12016
12355
  return html`<a href="${href}" target="_blank" rel="noopener noreferrer">${element.text ? html`${element.text}` : element.url}</a>`;
12017
12356
  },
12018
12357
  mention: ({ element, user, group }) => {
12019
- return html`<span data-mention>@${_optionalChain([user, 'optionalAccess', _301 => _301.name]) ? html`${_optionalChain([user, 'optionalAccess', _302 => _302.name])}` : _optionalChain([group, 'optionalAccess', _303 => _303.name]) ? html`${_optionalChain([group, 'optionalAccess', _304 => _304.name])}` : element.id}</span>`;
12358
+ return html`<span data-mention>@${_optionalChain([user, 'optionalAccess', _302 => _302.name]) ? html`${_optionalChain([user, 'optionalAccess', _303 => _303.name])}` : _optionalChain([group, 'optionalAccess', _304 => _304.name]) ? html`${_optionalChain([group, 'optionalAccess', _305 => _305.name])}` : element.id}</span>`;
12020
12359
  }
12021
12360
  };
12022
12361
  var stringifyCommentBodyMarkdownElements = {
@@ -12046,20 +12385,20 @@ var stringifyCommentBodyMarkdownElements = {
12046
12385
  return markdown`[${_nullishCoalesce(element.text, () => ( element.url))}](${href})`;
12047
12386
  },
12048
12387
  mention: ({ element, user, group }) => {
12049
- return markdown`@${_nullishCoalesce(_nullishCoalesce(_optionalChain([user, 'optionalAccess', _305 => _305.name]), () => ( _optionalChain([group, 'optionalAccess', _306 => _306.name]))), () => ( element.id))}`;
12388
+ return markdown`@${_nullishCoalesce(_nullishCoalesce(_optionalChain([user, 'optionalAccess', _306 => _306.name]), () => ( _optionalChain([group, 'optionalAccess', _307 => _307.name]))), () => ( element.id))}`;
12050
12389
  }
12051
12390
  };
12052
12391
  async function stringifyCommentBody(body, options) {
12053
- const format = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _307 => _307.format]), () => ( "plain"));
12054
- const separator = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _308 => _308.separator]), () => ( (format === "markdown" ? "\n\n" : "\n")));
12392
+ const format = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _308 => _308.format]), () => ( "plain"));
12393
+ const separator = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _309 => _309.separator]), () => ( (format === "markdown" ? "\n\n" : "\n")));
12055
12394
  const elements = {
12056
12395
  ...format === "html" ? stringifyCommentBodyHtmlElements : format === "markdown" ? stringifyCommentBodyMarkdownElements : stringifyCommentBodyPlainElements,
12057
- ..._optionalChain([options, 'optionalAccess', _309 => _309.elements])
12396
+ ..._optionalChain([options, 'optionalAccess', _310 => _310.elements])
12058
12397
  };
12059
12398
  const { users: resolvedUsers, groups: resolvedGroupsInfo } = await resolveMentionsInCommentBody(
12060
12399
  body,
12061
- _optionalChain([options, 'optionalAccess', _310 => _310.resolveUsers]),
12062
- _optionalChain([options, 'optionalAccess', _311 => _311.resolveGroupsInfo])
12400
+ _optionalChain([options, 'optionalAccess', _311 => _311.resolveUsers]),
12401
+ _optionalChain([options, 'optionalAccess', _312 => _312.resolveGroupsInfo])
12063
12402
  );
12064
12403
  const blocks = body.content.flatMap((block, blockIndex) => {
12065
12404
  switch (block.type) {
@@ -12194,9 +12533,9 @@ function makePoller(callback, intervalMs, options) {
12194
12533
  const startTime = performance.now();
12195
12534
  const doc = typeof document !== "undefined" ? document : void 0;
12196
12535
  const win = typeof window !== "undefined" ? window : void 0;
12197
- const maxStaleTimeMs = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _312 => _312.maxStaleTimeMs]), () => ( Number.POSITIVE_INFINITY));
12536
+ const maxStaleTimeMs = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _313 => _313.maxStaleTimeMs]), () => ( Number.POSITIVE_INFINITY));
12198
12537
  const context = {
12199
- inForeground: _optionalChain([doc, 'optionalAccess', _313 => _313.visibilityState]) !== "hidden",
12538
+ inForeground: _optionalChain([doc, 'optionalAccess', _314 => _314.visibilityState]) !== "hidden",
12200
12539
  lastSuccessfulPollAt: startTime,
12201
12540
  count: 0,
12202
12541
  backoff: 0
@@ -12277,11 +12616,11 @@ function makePoller(callback, intervalMs, options) {
12277
12616
  pollNowIfStale();
12278
12617
  }
12279
12618
  function onVisibilityChange() {
12280
- setInForeground(_optionalChain([doc, 'optionalAccess', _314 => _314.visibilityState]) !== "hidden");
12619
+ setInForeground(_optionalChain([doc, 'optionalAccess', _315 => _315.visibilityState]) !== "hidden");
12281
12620
  }
12282
- _optionalChain([doc, 'optionalAccess', _315 => _315.addEventListener, 'call', _316 => _316("visibilitychange", onVisibilityChange)]);
12283
- _optionalChain([win, 'optionalAccess', _317 => _317.addEventListener, 'call', _318 => _318("online", onVisibilityChange)]);
12284
- _optionalChain([win, 'optionalAccess', _319 => _319.addEventListener, 'call', _320 => _320("focus", pollNowIfStale)]);
12621
+ _optionalChain([doc, 'optionalAccess', _316 => _316.addEventListener, 'call', _317 => _317("visibilitychange", onVisibilityChange)]);
12622
+ _optionalChain([win, 'optionalAccess', _318 => _318.addEventListener, 'call', _319 => _319("online", onVisibilityChange)]);
12623
+ _optionalChain([win, 'optionalAccess', _320 => _320.addEventListener, 'call', _321 => _321("focus", pollNowIfStale)]);
12285
12624
  fsm.start();
12286
12625
  return {
12287
12626
  inc,
@@ -12418,5 +12757,13 @@ detectDupes(PKG_NAME, PKG_VERSION, PKG_FORMAT);
12418
12757
 
12419
12758
 
12420
12759
 
12421
- exports.ClientMsgCode = ClientMsgCode; exports.CrdtType = CrdtType; exports.DefaultMap = DefaultMap; exports.Deque = Deque; exports.DerivedSignal = DerivedSignal; exports.FeedRequestErrorCode = FeedRequestErrorCode; exports.HttpError = HttpError; exports.LiveList = LiveList; exports.LiveMap = LiveMap; exports.LiveObject = LiveObject; exports.LiveblocksError = LiveblocksError; exports.MENTION_CHARACTER = MENTION_CHARACTER; exports.MutableSignal = MutableSignal; exports.OpCode = OpCode; exports.Permission = Permission; exports.Promise_withResolvers = Promise_withResolvers; exports.ServerMsgCode = ServerMsgCode; exports.Signal = Signal; exports.SortedList = SortedList; exports.TextEditorType = TextEditorType; exports.WebsocketCloseCodes = WebsocketCloseCodes; exports.asPos = asPos; exports.assert = assert; exports.assertNever = assertNever; exports.autoRetry = autoRetry; exports.b64decode = b64decode; exports.batch = batch; exports.checkBounds = checkBounds; exports.chunk = chunk; exports.cloneLson = cloneLson; exports.compactNodesToNodeStream = compactNodesToNodeStream; exports.compactObject = compactObject; exports.console = fancy_console_exports; exports.convertToCommentData = convertToCommentData; exports.convertToCommentUserReaction = convertToCommentUserReaction; exports.convertToGroupData = convertToGroupData; exports.convertToInboxNotificationData = convertToInboxNotificationData; exports.convertToSubscriptionData = convertToSubscriptionData; exports.convertToThreadData = convertToThreadData; exports.convertToUserSubscriptionData = convertToUserSubscriptionData; exports.createClient = createClient; exports.createCommentAttachmentId = createCommentAttachmentId; exports.createCommentId = createCommentId; exports.createInboxNotificationId = createInboxNotificationId; exports.createManagedPool = createManagedPool; exports.createNotificationSettings = createNotificationSettings; exports.createThreadId = createThreadId; exports.defineAiTool = defineAiTool; exports.deprecate = deprecate; exports.deprecateIf = deprecateIf; exports.detectDupes = detectDupes; exports.entries = entries; exports.errorIf = errorIf; exports.findLastIndex = findLastIndex; exports.freeze = freeze; exports.generateUrl = generateUrl; exports.getMentionsFromCommentBody = getMentionsFromCommentBody; exports.getSubscriptionKey = getSubscriptionKey; exports.html = html; exports.htmlSafe = htmlSafe; exports.isCommentBodyLink = isCommentBodyLink; exports.isCommentBodyMention = isCommentBodyMention; exports.isCommentBodyText = isCommentBodyText; exports.isJsonArray = isJsonArray; exports.isJsonObject = isJsonObject; exports.isJsonScalar = isJsonScalar; exports.isListStorageNode = isListStorageNode; exports.isLiveNode = isLiveNode; exports.isMapStorageNode = isMapStorageNode; exports.isNotificationChannelEnabled = isNotificationChannelEnabled; exports.isNumberOperator = isNumberOperator; exports.isObjectStorageNode = isObjectStorageNode; exports.isPlainObject = isPlainObject; exports.isRegisterStorageNode = isRegisterStorageNode; exports.isRootStorageNode = isRootStorageNode; exports.isStartsWithOperator = isStartsWithOperator; exports.isUrl = isUrl; exports.kInternal = kInternal; exports.keys = keys; exports.makeAbortController = makeAbortController; exports.makeEventSource = makeEventSource; exports.makePoller = makePoller; exports.makePosition = makePosition; exports.mapValues = mapValues; exports.memoizeOnSuccess = memoizeOnSuccess; exports.nanoid = nanoid; exports.nn = nn; exports.nodeStreamToCompactNodes = nodeStreamToCompactNodes; exports.objectToQuery = objectToQuery; exports.patchNotificationSettings = patchNotificationSettings; exports.raise = raise; exports.resolveMentionsInCommentBody = resolveMentionsInCommentBody; exports.sanitizeUrl = sanitizeUrl; exports.shallow = shallow; exports.shallow2 = shallow2; exports.stableStringify = stableStringify; exports.stringifyCommentBody = stringifyCommentBody; exports.throwUsageError = throwUsageError; exports.toPlainLson = toPlainLson; exports.tryParseJson = tryParseJson; exports.url = url; exports.urljoin = urljoin; exports.wait = wait; exports.warnOnce = warnOnce; exports.warnOnceIf = warnOnceIf; exports.withTimeout = withTimeout;
12760
+
12761
+
12762
+
12763
+
12764
+
12765
+
12766
+
12767
+
12768
+ exports.ClientMsgCode = ClientMsgCode; exports.CrdtType = CrdtType; exports.DefaultMap = DefaultMap; exports.Deque = Deque; exports.DerivedSignal = DerivedSignal; exports.FeedRequestErrorCode = FeedRequestErrorCode; exports.HttpError = HttpError; exports.LiveList = LiveList; exports.LiveMap = LiveMap; exports.LiveObject = LiveObject; exports.LiveblocksError = LiveblocksError; exports.MENTION_CHARACTER = MENTION_CHARACTER; exports.MutableSignal = MutableSignal; exports.OpCode = OpCode; exports.Permission = Permission; exports.Promise_withResolvers = Promise_withResolvers; exports.ServerMsgCode = ServerMsgCode; exports.Signal = Signal; exports.SortedList = SortedList; exports.TextEditorType = TextEditorType; exports.WebsocketCloseCodes = WebsocketCloseCodes; exports.asPos = asPos; exports.assert = assert; exports.assertNever = assertNever; exports.autoRetry = autoRetry; exports.b64decode = b64decode; exports.batch = batch; exports.checkBounds = checkBounds; exports.chunk = chunk; exports.cloneLson = cloneLson; exports.compactNodesToNodeStream = compactNodesToNodeStream; exports.compactObject = compactObject; exports.console = fancy_console_exports; exports.convertToCommentData = convertToCommentData; exports.convertToCommentUserReaction = convertToCommentUserReaction; exports.convertToGroupData = convertToGroupData; exports.convertToInboxNotificationData = convertToInboxNotificationData; exports.convertToSubscriptionData = convertToSubscriptionData; exports.convertToThreadData = convertToThreadData; exports.convertToUserSubscriptionData = convertToUserSubscriptionData; exports.createClient = createClient; exports.createCommentAttachmentId = createCommentAttachmentId; exports.createCommentId = createCommentId; exports.createInboxNotificationId = createInboxNotificationId; exports.createManagedPool = createManagedPool; exports.createNotificationSettings = createNotificationSettings; exports.createThreadId = createThreadId; exports.deepLiveify = deepLiveify; exports.defineAiTool = defineAiTool; exports.deprecate = deprecate; exports.deprecateIf = deprecateIf; exports.detectDupes = detectDupes; exports.entries = entries; exports.errorIf = errorIf; exports.findLastIndex = findLastIndex; exports.freeze = freeze; exports.generateUrl = generateUrl; exports.getMentionsFromCommentBody = getMentionsFromCommentBody; exports.getSubscriptionKey = getSubscriptionKey; exports.hasPermissionAccess = hasPermissionAccess; exports.html = html; exports.htmlSafe = htmlSafe; exports.isCommentBodyLink = isCommentBodyLink; exports.isCommentBodyMention = isCommentBodyMention; exports.isCommentBodyText = isCommentBodyText; exports.isJsonArray = isJsonArray; exports.isJsonObject = isJsonObject; exports.isJsonScalar = isJsonScalar; exports.isListStorageNode = isListStorageNode; exports.isLiveNode = isLiveNode; exports.isMapStorageNode = isMapStorageNode; exports.isNotificationChannelEnabled = isNotificationChannelEnabled; exports.isNumberOperator = isNumberOperator; exports.isObjectStorageNode = isObjectStorageNode; exports.isPlainObject = isPlainObject; exports.isRegisterStorageNode = isRegisterStorageNode; exports.isRootStorageNode = isRootStorageNode; exports.isStartsWithOperator = isStartsWithOperator; exports.isUrl = isUrl; exports.kInternal = kInternal; exports.keys = keys; exports.makeAbortController = makeAbortController; exports.makeEventSource = makeEventSource; exports.makePoller = makePoller; exports.makePosition = makePosition; exports.mapValues = mapValues; exports.memoizeOnSuccess = memoizeOnSuccess; exports.mergeRoomPermissionScopes = mergeRoomPermissionScopes; exports.nanoid = nanoid; exports.nn = nn; exports.nodeStreamToCompactNodes = nodeStreamToCompactNodes; exports.normalizeRoomAccesses = normalizeRoomAccesses; exports.normalizeRoomPermissions = normalizeRoomPermissions; exports.normalizeUpdateRoomAccesses = normalizeUpdateRoomAccesses; exports.objectToQuery = objectToQuery; exports.patchNotificationSettings = patchNotificationSettings; exports.permissionMatrixFromScopes = permissionMatrixFromScopes; exports.raise = raise; exports.resolveMentionsInCommentBody = resolveMentionsInCommentBody; exports.sanitizeUrl = sanitizeUrl; exports.shallow = shallow; exports.shallow2 = shallow2; exports.stableStringify = stableStringify; exports.stringifyCommentBody = stringifyCommentBody; exports.throwUsageError = throwUsageError; exports.toPlainLson = toPlainLson; exports.tryParseJson = tryParseJson; exports.url = url; exports.urljoin = urljoin; exports.validatePermissionsSet = validatePermissionsSet; exports.wait = wait; exports.warnOnce = warnOnce; exports.warnOnceIf = warnOnceIf; exports.withTimeout = withTimeout;
12422
12769
  //# sourceMappingURL=index.cjs.map