@liveblocks/core 3.21.0-exp2 → 3.21.0-private1

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.21.0-exp2";
9
+ var PKG_VERSION = "3.21.0-private1";
10
10
  var PKG_FORMAT = "cjs";
11
11
 
12
12
  // src/dupe-detection.ts
@@ -1567,6 +1567,15 @@ function isUrl(string) {
1567
1567
  }
1568
1568
 
1569
1569
  // src/api-client.ts
1570
+ function commentsResourceForVisibility(visibility) {
1571
+ if (visibility === "private") {
1572
+ return "comments:private";
1573
+ }
1574
+ if (visibility === "public") {
1575
+ return "comments:public";
1576
+ }
1577
+ return "comments";
1578
+ }
1570
1579
  function createApiClient({
1571
1580
  baseUrl,
1572
1581
  authManager,
@@ -1618,7 +1627,7 @@ function createApiClient({
1618
1627
  url`/v2/c/rooms/${options.roomId}/threads`,
1619
1628
  await authManager.getAuthValue({
1620
1629
  roomId: options.roomId,
1621
- resource: "comments",
1630
+ resource: commentsResourceForVisibility(_optionalChain([options, 'access', _15 => _15.query, 'optionalAccess', _16 => _16.visibility])),
1622
1631
  access: "read"
1623
1632
  }),
1624
1633
  {
@@ -1676,7 +1685,7 @@ function createApiClient({
1676
1685
  hasMentions: options.query.hasMentions
1677
1686
  })
1678
1687
  },
1679
- { signal: _optionalChain([requestOptions, 'optionalAccess', _15 => _15.signal]) }
1688
+ { signal: _optionalChain([requestOptions, 'optionalAccess', _17 => _17.signal]) }
1680
1689
  );
1681
1690
  return result;
1682
1691
  }
@@ -1687,11 +1696,12 @@ function createApiClient({
1687
1696
  url`/v2/c/rooms/${options.roomId}/threads`,
1688
1697
  await authManager.getAuthValue({
1689
1698
  roomId: options.roomId,
1690
- resource: "comments",
1699
+ resource: commentsResourceForVisibility(_nullishCoalesce(options.visibility, () => ( "public"))),
1691
1700
  access: "write"
1692
1701
  }),
1693
1702
  {
1694
1703
  id: threadId,
1704
+ visibility: options.visibility,
1695
1705
  comment: {
1696
1706
  id: commentId,
1697
1707
  body: options.body,
@@ -1878,11 +1888,11 @@ function createApiClient({
1878
1888
  `Upload of attachment ${options.attachment.id} was aborted.`,
1879
1889
  "AbortError"
1880
1890
  ) : void 0;
1881
- if (_optionalChain([abortSignal, 'optionalAccess', _16 => _16.aborted])) {
1891
+ if (_optionalChain([abortSignal, 'optionalAccess', _18 => _18.aborted])) {
1882
1892
  throw abortError;
1883
1893
  }
1884
1894
  const handleRetryError = (err) => {
1885
- if (_optionalChain([abortSignal, 'optionalAccess', _17 => _17.aborted])) {
1895
+ if (_optionalChain([abortSignal, 'optionalAccess', _19 => _19.aborted])) {
1886
1896
  throw abortError;
1887
1897
  }
1888
1898
  if (err instanceof HttpError && err.status === 413) {
@@ -1956,7 +1966,7 @@ function createApiClient({
1956
1966
  try {
1957
1967
  uploadId = createMultiPartUpload.uploadId;
1958
1968
  const parts = splitFileIntoParts(attachment.file);
1959
- if (_optionalChain([abortSignal, 'optionalAccess', _18 => _18.aborted])) {
1969
+ if (_optionalChain([abortSignal, 'optionalAccess', _20 => _20.aborted])) {
1960
1970
  throw abortError;
1961
1971
  }
1962
1972
  const batches = chunk(parts, 5);
@@ -1984,7 +1994,7 @@ function createApiClient({
1984
1994
  }
1985
1995
  uploadedParts.push(...await Promise.all(uploadedPartsPromises));
1986
1996
  }
1987
- if (_optionalChain([abortSignal, 'optionalAccess', _19 => _19.aborted])) {
1997
+ if (_optionalChain([abortSignal, 'optionalAccess', _21 => _21.aborted])) {
1988
1998
  throw abortError;
1989
1999
  }
1990
2000
  const sortedUploadedParts = uploadedParts.sort(
@@ -2001,7 +2011,7 @@ function createApiClient({
2001
2011
  { signal: abortSignal }
2002
2012
  );
2003
2013
  } catch (error3) {
2004
- if (uploadId && _optionalChain([error3, 'optionalAccess', _20 => _20.name]) && (error3.name === "AbortError" || error3.name === "TimeoutError")) {
2014
+ if (uploadId && _optionalChain([error3, 'optionalAccess', _22 => _22.name]) && (error3.name === "AbortError" || error3.name === "TimeoutError")) {
2005
2015
  try {
2006
2016
  await httpClient.rawDelete(
2007
2017
  url`/v2/c/rooms/${roomId}/attachments/${attachment.id}/multipart/${uploadId}`,
@@ -2234,14 +2244,14 @@ function createApiClient({
2234
2244
  async function getInboxNotifications(options) {
2235
2245
  const PAGE_SIZE = 50;
2236
2246
  let query;
2237
- if (_optionalChain([options, 'optionalAccess', _21 => _21.query])) {
2247
+ if (_optionalChain([options, 'optionalAccess', _23 => _23.query])) {
2238
2248
  query = objectToQuery(options.query);
2239
2249
  }
2240
2250
  const json = await httpClient.get(
2241
2251
  url`/v2/c/inbox-notifications`,
2242
2252
  await authManager.getAuthValue({ resource: "personal", access: "write" }),
2243
2253
  {
2244
- cursor: _optionalChain([options, 'optionalAccess', _22 => _22.cursor]),
2254
+ cursor: _optionalChain([options, 'optionalAccess', _24 => _24.cursor]),
2245
2255
  limit: PAGE_SIZE,
2246
2256
  query
2247
2257
  }
@@ -2260,7 +2270,7 @@ function createApiClient({
2260
2270
  }
2261
2271
  async function getInboxNotificationsSince(options) {
2262
2272
  let query;
2263
- if (_optionalChain([options, 'optionalAccess', _23 => _23.query])) {
2273
+ if (_optionalChain([options, 'optionalAccess', _25 => _25.query])) {
2264
2274
  query = objectToQuery(options.query);
2265
2275
  }
2266
2276
  const json = await httpClient.get(
@@ -2289,14 +2299,14 @@ function createApiClient({
2289
2299
  }
2290
2300
  async function getUnreadInboxNotificationsCount(options) {
2291
2301
  let query;
2292
- if (_optionalChain([options, 'optionalAccess', _24 => _24.query])) {
2302
+ if (_optionalChain([options, 'optionalAccess', _26 => _26.query])) {
2293
2303
  query = objectToQuery(options.query);
2294
2304
  }
2295
2305
  const { count } = await httpClient.get(
2296
2306
  url`/v2/c/inbox-notifications/count`,
2297
2307
  await authManager.getAuthValue({ resource: "personal", access: "write" }),
2298
2308
  { query },
2299
- { signal: _optionalChain([options, 'optionalAccess', _25 => _25.signal]) }
2309
+ { signal: _optionalChain([options, 'optionalAccess', _27 => _27.signal]) }
2300
2310
  );
2301
2311
  return count;
2302
2312
  }
@@ -2346,7 +2356,7 @@ function createApiClient({
2346
2356
  url`/v2/c/notification-settings`,
2347
2357
  await authManager.getAuthValue({ resource: "personal", access: "write" }),
2348
2358
  void 0,
2349
- { signal: _optionalChain([options, 'optionalAccess', _26 => _26.signal]) }
2359
+ { signal: _optionalChain([options, 'optionalAccess', _28 => _28.signal]) }
2350
2360
  );
2351
2361
  }
2352
2362
  async function updateNotificationSettings(settings) {
@@ -2358,7 +2368,7 @@ function createApiClient({
2358
2368
  }
2359
2369
  async function getUserThreads_experimental(options) {
2360
2370
  let query;
2361
- if (_optionalChain([options, 'optionalAccess', _27 => _27.query])) {
2371
+ if (_optionalChain([options, 'optionalAccess', _29 => _29.query])) {
2362
2372
  query = objectToQuery(options.query);
2363
2373
  }
2364
2374
  const PAGE_SIZE = 50;
@@ -2366,7 +2376,7 @@ function createApiClient({
2366
2376
  url`/v2/c/threads`,
2367
2377
  await authManager.getAuthValue({ resource: "personal", access: "write" }),
2368
2378
  {
2369
- cursor: _optionalChain([options, 'optionalAccess', _28 => _28.cursor]),
2379
+ cursor: _optionalChain([options, 'optionalAccess', _30 => _30.cursor]),
2370
2380
  query,
2371
2381
  limit: PAGE_SIZE
2372
2382
  }
@@ -2539,7 +2549,7 @@ var HttpClient = class {
2539
2549
  // These headers are default, but can be overriden by custom headers
2540
2550
  "Content-Type": "application/json; charset=utf-8",
2541
2551
  // Possible header overrides
2542
- ..._optionalChain([options, 'optionalAccess', _29 => _29.headers]),
2552
+ ..._optionalChain([options, 'optionalAccess', _31 => _31.headers]),
2543
2553
  // Cannot be overriden by custom headers
2544
2554
  Authorization: `Bearer ${getBearerTokenFromAuthValue(authValue)}`,
2545
2555
  "X-LB-Client": PKG_VERSION || "dev"
@@ -2547,7 +2557,7 @@ var HttpClient = class {
2547
2557
  });
2548
2558
  const xwarn = response.headers.get("X-LB-Warn");
2549
2559
  if (xwarn) {
2550
- const method = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _30 => _30.method, 'optionalAccess', _31 => _31.toUpperCase, 'call', _32 => _32()]), () => ( "GET"));
2560
+ const method = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _32 => _32.method, 'optionalAccess', _33 => _33.toUpperCase, 'call', _34 => _34()]), () => ( "GET"));
2551
2561
  const msg = `${xwarn} (${method} ${endpoint})`;
2552
2562
  if (response.ok) {
2553
2563
  warn(msg);
@@ -3029,7 +3039,7 @@ var FSM = class {
3029
3039
  });
3030
3040
  }
3031
3041
  #getTargetFn(eventName) {
3032
- return _optionalChain([this, 'access', _33 => _33.#allowedTransitions, 'access', _34 => _34.get, 'call', _35 => _35(this.currentState), 'optionalAccess', _36 => _36.get, 'call', _37 => _37(eventName)]);
3042
+ return _optionalChain([this, 'access', _35 => _35.#allowedTransitions, 'access', _36 => _36.get, 'call', _37 => _37(this.currentState), 'optionalAccess', _38 => _38.get, 'call', _39 => _39(eventName)]);
3033
3043
  }
3034
3044
  /**
3035
3045
  * Exits the current state, and executes any necessary cleanup functions.
@@ -3048,7 +3058,7 @@ var FSM = class {
3048
3058
  this.#currentContext.allowPatching((patchableContext) => {
3049
3059
  levels = _nullishCoalesce(levels, () => ( this.#cleanupStack.length));
3050
3060
  for (let i = 0; i < levels; i++) {
3051
- _optionalChain([this, 'access', _38 => _38.#cleanupStack, 'access', _39 => _39.pop, 'call', _40 => _40(), 'optionalCall', _41 => _41(patchableContext)]);
3061
+ _optionalChain([this, 'access', _40 => _40.#cleanupStack, 'access', _41 => _41.pop, 'call', _42 => _42(), 'optionalCall', _43 => _43(patchableContext)]);
3052
3062
  const entryTime = this.#entryTimesStack.pop();
3053
3063
  if (entryTime !== void 0 && // ...but avoid computing state names if nobody is listening
3054
3064
  this.#eventHub.didExitState.count() > 0) {
@@ -3076,7 +3086,7 @@ var FSM = class {
3076
3086
  this.#currentContext.allowPatching((patchableContext) => {
3077
3087
  for (const pattern of enterPatterns) {
3078
3088
  const enterFn = this.#enterFns.get(pattern);
3079
- const cleanupFn = _optionalChain([enterFn, 'optionalCall', _42 => _42(patchableContext)]);
3089
+ const cleanupFn = _optionalChain([enterFn, 'optionalCall', _44 => _44(patchableContext)]);
3080
3090
  if (typeof cleanupFn === "function") {
3081
3091
  this.#cleanupStack.push(cleanupFn);
3082
3092
  } else {
@@ -3503,7 +3513,7 @@ function createConnectionStateMachine(delegates, options) {
3503
3513
  }
3504
3514
  function waitForActorId(event) {
3505
3515
  const serverMsg = tryParseJson(event.data);
3506
- if (_optionalChain([serverMsg, 'optionalAccess', _43 => _43.type]) === ServerMsgCode.ROOM_STATE) {
3516
+ if (_optionalChain([serverMsg, 'optionalAccess', _45 => _45.type]) === ServerMsgCode.ROOM_STATE) {
3507
3517
  if (options.enableDebugLogging && socketOpenAt !== null) {
3508
3518
  const elapsed = performance.now() - socketOpenAt;
3509
3519
  warn(
@@ -3631,12 +3641,12 @@ function createConnectionStateMachine(delegates, options) {
3631
3641
  const sendHeartbeat = {
3632
3642
  target: "@ok.awaiting-pong",
3633
3643
  effect: (ctx) => {
3634
- _optionalChain([ctx, 'access', _44 => _44.socket, 'optionalAccess', _45 => _45.send, 'call', _46 => _46("ping")]);
3644
+ _optionalChain([ctx, 'access', _46 => _46.socket, 'optionalAccess', _47 => _47.send, 'call', _48 => _48("ping")]);
3635
3645
  }
3636
3646
  };
3637
3647
  const maybeHeartbeat = () => {
3638
3648
  const doc = typeof document !== "undefined" ? document : void 0;
3639
- const canZombie = _optionalChain([doc, 'optionalAccess', _47 => _47.visibilityState]) === "hidden" && delegates.canZombie();
3649
+ const canZombie = _optionalChain([doc, 'optionalAccess', _49 => _49.visibilityState]) === "hidden" && delegates.canZombie();
3640
3650
  return canZombie ? "@idle.zombie" : sendHeartbeat;
3641
3651
  };
3642
3652
  machine.addTimedTransition("@ok.connected", HEARTBEAT_INTERVAL, maybeHeartbeat).addTransitions("@ok.connected", {
@@ -3676,7 +3686,7 @@ function createConnectionStateMachine(delegates, options) {
3676
3686
  // socket, or not. So always check to see if the socket is still OPEN or
3677
3687
  // not. When still OPEN, don't transition.
3678
3688
  EXPLICIT_SOCKET_ERROR: (_, context) => {
3679
- if (_optionalChain([context, 'access', _48 => _48.socket, 'optionalAccess', _49 => _49.readyState]) === 1) {
3689
+ if (_optionalChain([context, 'access', _50 => _50.socket, 'optionalAccess', _51 => _51.readyState]) === 1) {
3680
3690
  return IGNORE;
3681
3691
  }
3682
3692
  return {
@@ -3728,17 +3738,17 @@ function createConnectionStateMachine(delegates, options) {
3728
3738
  machine.send({ type: "NAVIGATOR_ONLINE" });
3729
3739
  }
3730
3740
  function onVisibilityChange() {
3731
- if (_optionalChain([doc, 'optionalAccess', _50 => _50.visibilityState]) === "visible") {
3741
+ if (_optionalChain([doc, 'optionalAccess', _52 => _52.visibilityState]) === "visible") {
3732
3742
  machine.send({ type: "WINDOW_GOT_FOCUS" });
3733
3743
  }
3734
3744
  }
3735
- _optionalChain([win, 'optionalAccess', _51 => _51.addEventListener, 'call', _52 => _52("online", onNetworkBackOnline)]);
3736
- _optionalChain([win, 'optionalAccess', _53 => _53.addEventListener, 'call', _54 => _54("offline", onNetworkOffline)]);
3737
- _optionalChain([root, 'optionalAccess', _55 => _55.addEventListener, 'call', _56 => _56("visibilitychange", onVisibilityChange)]);
3745
+ _optionalChain([win, 'optionalAccess', _53 => _53.addEventListener, 'call', _54 => _54("online", onNetworkBackOnline)]);
3746
+ _optionalChain([win, 'optionalAccess', _55 => _55.addEventListener, 'call', _56 => _56("offline", onNetworkOffline)]);
3747
+ _optionalChain([root, 'optionalAccess', _57 => _57.addEventListener, 'call', _58 => _58("visibilitychange", onVisibilityChange)]);
3738
3748
  return () => {
3739
- _optionalChain([root, 'optionalAccess', _57 => _57.removeEventListener, 'call', _58 => _58("visibilitychange", onVisibilityChange)]);
3740
- _optionalChain([win, 'optionalAccess', _59 => _59.removeEventListener, 'call', _60 => _60("online", onNetworkBackOnline)]);
3741
- _optionalChain([win, 'optionalAccess', _61 => _61.removeEventListener, 'call', _62 => _62("offline", onNetworkOffline)]);
3749
+ _optionalChain([root, 'optionalAccess', _59 => _59.removeEventListener, 'call', _60 => _60("visibilitychange", onVisibilityChange)]);
3750
+ _optionalChain([win, 'optionalAccess', _61 => _61.removeEventListener, 'call', _62 => _62("online", onNetworkBackOnline)]);
3751
+ _optionalChain([win, 'optionalAccess', _63 => _63.removeEventListener, 'call', _64 => _64("offline", onNetworkOffline)]);
3742
3752
  teardownSocket(ctx.socket);
3743
3753
  };
3744
3754
  });
@@ -3827,7 +3837,7 @@ var ManagedSocket = class {
3827
3837
  * message if this is somehow impossible.
3828
3838
  */
3829
3839
  send(data) {
3830
- const socket = _optionalChain([this, 'access', _63 => _63.#machine, 'access', _64 => _64.context, 'optionalAccess', _65 => _65.socket]);
3840
+ const socket = _optionalChain([this, 'access', _65 => _65.#machine, 'access', _66 => _66.context, 'optionalAccess', _67 => _67.socket]);
3831
3841
  if (socket === null) {
3832
3842
  warn("Cannot send: not connected yet", data);
3833
3843
  } else if (socket.readyState !== 1) {
@@ -3847,7 +3857,6 @@ var ManagedSocket = class {
3847
3857
 
3848
3858
  // src/internal.ts
3849
3859
  var kInternal = /* @__PURE__ */ Symbol();
3850
- var kStorageUpdateSource = /* @__PURE__ */ Symbol();
3851
3860
 
3852
3861
  // src/lib/IncrementalJsonParser.ts
3853
3862
  var EMPTY_OBJECT = Object.freeze({});
@@ -4290,7 +4299,7 @@ function createStore_forKnowledge() {
4290
4299
  }
4291
4300
  function getKnowledgeForChat(chatId) {
4292
4301
  const globalKnowledge = knowledgeByChatId.getOrCreate(kWILDCARD).get();
4293
- const scopedKnowledge = _nullishCoalesce(_optionalChain([knowledgeByChatId, 'access', _66 => _66.get, 'call', _67 => _67(chatId), 'optionalAccess', _68 => _68.get, 'call', _69 => _69()]), () => ( []));
4302
+ const scopedKnowledge = _nullishCoalesce(_optionalChain([knowledgeByChatId, 'access', _68 => _68.get, 'call', _69 => _69(chatId), 'optionalAccess', _70 => _70.get, 'call', _71 => _71()]), () => ( []));
4294
4303
  return [...globalKnowledge, ...scopedKnowledge];
4295
4304
  }
4296
4305
  return {
@@ -4315,7 +4324,7 @@ function createStore_forTools() {
4315
4324
  return DerivedSignal.from(() => {
4316
4325
  return (
4317
4326
  // A tool that's registered and scoped to a specific chat ID...
4318
- _nullishCoalesce(_optionalChain([(chatId !== void 0 ? toolsByChatId\u03A3.getOrCreate(chatId).getOrCreate(name) : void 0), 'optionalAccess', _70 => _70.get, 'call', _71 => _71()]), () => ( // ...or a globally registered tool
4327
+ _nullishCoalesce(_optionalChain([(chatId !== void 0 ? toolsByChatId\u03A3.getOrCreate(chatId).getOrCreate(name) : void 0), 'optionalAccess', _72 => _72.get, 'call', _73 => _73()]), () => ( // ...or a globally registered tool
4319
4328
  toolsByChatId\u03A3.getOrCreate(kWILDCARD).getOrCreate(name).get()))
4320
4329
  );
4321
4330
  });
@@ -4345,8 +4354,8 @@ function createStore_forTools() {
4345
4354
  const globalTools\u03A3 = toolsByChatId\u03A3.get(kWILDCARD);
4346
4355
  const scopedTools\u03A3 = toolsByChatId\u03A3.get(chatId);
4347
4356
  return Array.from([
4348
- ..._nullishCoalesce(_optionalChain([globalTools\u03A3, 'optionalAccess', _72 => _72.entries, 'call', _73 => _73()]), () => ( [])),
4349
- ..._nullishCoalesce(_optionalChain([scopedTools\u03A3, 'optionalAccess', _74 => _74.entries, 'call', _75 => _75()]), () => ( []))
4357
+ ..._nullishCoalesce(_optionalChain([globalTools\u03A3, 'optionalAccess', _74 => _74.entries, 'call', _75 => _75()]), () => ( [])),
4358
+ ..._nullishCoalesce(_optionalChain([scopedTools\u03A3, 'optionalAccess', _76 => _76.entries, 'call', _77 => _77()]), () => ( []))
4350
4359
  ]).flatMap(([name, tool\u03A3]) => {
4351
4360
  const tool = tool\u03A3.get();
4352
4361
  return tool && (_nullishCoalesce(tool.enabled, () => ( true))) ? [{ name, description: tool.description, parameters: tool.parameters }] : [];
@@ -4449,7 +4458,7 @@ function createStore_forChatMessages(toolsStore, setToolResultFn) {
4449
4458
  } else {
4450
4459
  continue;
4451
4460
  }
4452
- const executeFn = _optionalChain([toolsStore, 'access', _76 => _76.getTool\u03A3, 'call', _77 => _77(toolInvocation.name, message.chatId), 'access', _78 => _78.get, 'call', _79 => _79(), 'optionalAccess', _80 => _80.execute]);
4461
+ const executeFn = _optionalChain([toolsStore, 'access', _78 => _78.getTool\u03A3, 'call', _79 => _79(toolInvocation.name, message.chatId), 'access', _80 => _80.get, 'call', _81 => _81(), 'optionalAccess', _82 => _82.execute]);
4453
4462
  if (executeFn) {
4454
4463
  (async () => {
4455
4464
  const result = await executeFn(toolInvocation.args, {
@@ -4548,8 +4557,8 @@ function createStore_forChatMessages(toolsStore, setToolResultFn) {
4548
4557
  const spine = [];
4549
4558
  let lastVisitedMessage = null;
4550
4559
  for (const message2 of pool.walkUp(leaf.id)) {
4551
- const prev = _nullishCoalesce(_optionalChain([first, 'call', _81 => _81(pool.walkLeft(message2.id, isAlive)), 'optionalAccess', _82 => _82.id]), () => ( null));
4552
- const next = _nullishCoalesce(_optionalChain([first, 'call', _83 => _83(pool.walkRight(message2.id, isAlive)), 'optionalAccess', _84 => _84.id]), () => ( null));
4560
+ const prev = _nullishCoalesce(_optionalChain([first, 'call', _83 => _83(pool.walkLeft(message2.id, isAlive)), 'optionalAccess', _84 => _84.id]), () => ( null));
4561
+ const next = _nullishCoalesce(_optionalChain([first, 'call', _85 => _85(pool.walkRight(message2.id, isAlive)), 'optionalAccess', _86 => _86.id]), () => ( null));
4553
4562
  if (!message2.deletedAt || prev || next) {
4554
4563
  const node = {
4555
4564
  ...message2,
@@ -4615,7 +4624,7 @@ function createStore_forChatMessages(toolsStore, setToolResultFn) {
4615
4624
  const latest = pool.sorted.findRight(
4616
4625
  (m) => m.role === "assistant" && !m.deletedAt
4617
4626
  );
4618
- return _optionalChain([latest, 'optionalAccess', _85 => _85.copilotId]);
4627
+ return _optionalChain([latest, 'optionalAccess', _87 => _87.copilotId]);
4619
4628
  }
4620
4629
  return {
4621
4630
  // Readers
@@ -4646,11 +4655,11 @@ function createStore_forChatMessages(toolsStore, setToolResultFn) {
4646
4655
  *getAutoExecutingMessageIds() {
4647
4656
  for (const messageId of myMessages) {
4648
4657
  const message = getMessageById(messageId);
4649
- if (_optionalChain([message, 'optionalAccess', _86 => _86.role]) === "assistant" && message.status === "awaiting-tool") {
4658
+ if (_optionalChain([message, 'optionalAccess', _88 => _88.role]) === "assistant" && message.status === "awaiting-tool") {
4650
4659
  const isAutoExecuting = message.contentSoFar.some((part) => {
4651
4660
  if (part.type === "tool-invocation" && part.stage === "executing") {
4652
4661
  const tool = toolsStore.getTool\u03A3(part.name, message.chatId).get();
4653
- return typeof _optionalChain([tool, 'optionalAccess', _87 => _87.execute]) === "function";
4662
+ return typeof _optionalChain([tool, 'optionalAccess', _89 => _89.execute]) === "function";
4654
4663
  }
4655
4664
  return false;
4656
4665
  });
@@ -4798,7 +4807,7 @@ function createAi(config) {
4798
4807
  flushPendingDeltas();
4799
4808
  switch (msg.event) {
4800
4809
  case "cmd-failed":
4801
- _optionalChain([pendingCmd, 'optionalAccess', _88 => _88.reject, 'call', _89 => _89(new Error(msg.error))]);
4810
+ _optionalChain([pendingCmd, 'optionalAccess', _90 => _90.reject, 'call', _91 => _91(new Error(msg.error))]);
4802
4811
  break;
4803
4812
  case "settle": {
4804
4813
  context.messagesStore.upsert(msg.message);
@@ -4875,7 +4884,7 @@ function createAi(config) {
4875
4884
  return assertNever(msg, "Unhandled case");
4876
4885
  }
4877
4886
  }
4878
- _optionalChain([pendingCmd, 'optionalAccess', _90 => _90.resolve, 'call', _91 => _91(msg)]);
4887
+ _optionalChain([pendingCmd, 'optionalAccess', _92 => _92.resolve, 'call', _93 => _93(msg)]);
4879
4888
  }
4880
4889
  managedSocket.events.onMessage.subscribe(handleServerMessage);
4881
4890
  managedSocket.events.statusDidChange.subscribe(onStatusDidChange);
@@ -4951,9 +4960,9 @@ function createAi(config) {
4951
4960
  invocationId,
4952
4961
  result,
4953
4962
  generationOptions: {
4954
- copilotId: _optionalChain([options, 'optionalAccess', _92 => _92.copilotId]),
4955
- stream: _optionalChain([options, 'optionalAccess', _93 => _93.stream]),
4956
- timeout: _optionalChain([options, 'optionalAccess', _94 => _94.timeout]),
4963
+ copilotId: _optionalChain([options, 'optionalAccess', _94 => _94.copilotId]),
4964
+ stream: _optionalChain([options, 'optionalAccess', _95 => _95.stream]),
4965
+ timeout: _optionalChain([options, 'optionalAccess', _96 => _96.timeout]),
4957
4966
  // Knowledge and tools aren't coming from the options, but retrieved
4958
4967
  // from the global context
4959
4968
  knowledge: knowledge.length > 0 ? knowledge : void 0,
@@ -4971,7 +4980,7 @@ function createAi(config) {
4971
4980
  }
4972
4981
  }
4973
4982
  const win = typeof window !== "undefined" ? window : void 0;
4974
- _optionalChain([win, 'optionalAccess', _95 => _95.addEventListener, 'call', _96 => _96("beforeunload", handleBeforeUnload, { once: true })]);
4983
+ _optionalChain([win, 'optionalAccess', _97 => _97.addEventListener, 'call', _98 => _98("beforeunload", handleBeforeUnload, { once: true })]);
4975
4984
  return Object.defineProperty(
4976
4985
  {
4977
4986
  [kInternal]: {
@@ -4990,7 +4999,7 @@ function createAi(config) {
4990
4999
  clearChat: (chatId) => sendClientMsgWithResponse({ cmd: "clear-chat", chatId }),
4991
5000
  askUserMessageInChat: async (chatId, userMessage, targetMessageId, options) => {
4992
5001
  const knowledge = context.knowledgeStore.getKnowledgeForChat(chatId);
4993
- const requestKnowledge = _optionalChain([options, 'optionalAccess', _97 => _97.knowledge]) || [];
5002
+ const requestKnowledge = _optionalChain([options, 'optionalAccess', _99 => _99.knowledge]) || [];
4994
5003
  const combinedKnowledge = [...knowledge, ...requestKnowledge];
4995
5004
  const tools = context.toolsStore.getToolDescriptions(chatId);
4996
5005
  messagesStore.markMine(targetMessageId);
@@ -5000,9 +5009,9 @@ function createAi(config) {
5000
5009
  sourceMessage: userMessage,
5001
5010
  targetMessageId,
5002
5011
  generationOptions: {
5003
- copilotId: _optionalChain([options, 'optionalAccess', _98 => _98.copilotId]),
5004
- stream: _optionalChain([options, 'optionalAccess', _99 => _99.stream]),
5005
- timeout: _optionalChain([options, 'optionalAccess', _100 => _100.timeout]),
5012
+ copilotId: _optionalChain([options, 'optionalAccess', _100 => _100.copilotId]),
5013
+ stream: _optionalChain([options, 'optionalAccess', _101 => _101.stream]),
5014
+ timeout: _optionalChain([options, 'optionalAccess', _102 => _102.timeout]),
5006
5015
  // Combine global knowledge with request-specific knowledge
5007
5016
  knowledge: combinedKnowledge.length > 0 ? combinedKnowledge : void 0,
5008
5017
  tools: tools.length > 0 ? tools : void 0
@@ -5074,7 +5083,7 @@ function replaceOrAppend(content, newItem, keyFn, now2) {
5074
5083
  }
5075
5084
  }
5076
5085
  function closePart(prevPart, endedAt) {
5077
- if (_optionalChain([prevPart, 'optionalAccess', _101 => _101.type]) === "reasoning") {
5086
+ if (_optionalChain([prevPart, 'optionalAccess', _103 => _103.type]) === "reasoning") {
5078
5087
  prevPart.endedAt ??= endedAt;
5079
5088
  }
5080
5089
  }
@@ -5089,7 +5098,7 @@ function patchContentWithDelta(content, delta) {
5089
5098
  const lastPart = parts[parts.length - 1];
5090
5099
  switch (delta.type) {
5091
5100
  case "text-delta":
5092
- if (_optionalChain([lastPart, 'optionalAccess', _102 => _102.type]) === "text") {
5101
+ if (_optionalChain([lastPart, 'optionalAccess', _104 => _104.type]) === "text") {
5093
5102
  lastPart.text += delta.textDelta;
5094
5103
  } else {
5095
5104
  closePart(lastPart, now2);
@@ -5097,7 +5106,7 @@ function patchContentWithDelta(content, delta) {
5097
5106
  }
5098
5107
  break;
5099
5108
  case "reasoning-delta":
5100
- if (_optionalChain([lastPart, 'optionalAccess', _103 => _103.type]) === "reasoning") {
5109
+ if (_optionalChain([lastPart, 'optionalAccess', _105 => _105.type]) === "reasoning") {
5101
5110
  lastPart.text += delta.textDelta;
5102
5111
  } else {
5103
5112
  closePart(lastPart, now2);
@@ -5117,8 +5126,8 @@ function patchContentWithDelta(content, delta) {
5117
5126
  break;
5118
5127
  }
5119
5128
  case "tool-delta": {
5120
- if (_optionalChain([lastPart, 'optionalAccess', _104 => _104.type]) === "tool-invocation" && lastPart.stage === "receiving") {
5121
- _optionalChain([lastPart, 'access', _105 => _105.__appendDelta, 'optionalCall', _106 => _106(delta.delta)]);
5129
+ if (_optionalChain([lastPart, 'optionalAccess', _106 => _106.type]) === "tool-invocation" && lastPart.stage === "receiving") {
5130
+ _optionalChain([lastPart, 'access', _107 => _107.__appendDelta, 'optionalCall', _108 => _108(delta.delta)]);
5122
5131
  }
5123
5132
  break;
5124
5133
  }
@@ -5192,6 +5201,15 @@ var Permission = {
5192
5201
  CommentsWrite: "comments:write",
5193
5202
  CommentsRead: "comments:read",
5194
5203
  CommentsNone: "comments:none",
5204
+ CommentsPublicWrite: "comments:public:write",
5205
+ CommentsPublicRead: "comments:public:read",
5206
+ CommentsPublicNone: "comments:public:none",
5207
+ CommentsPrivateWrite: "comments:private:write",
5208
+ CommentsPrivateRead: "comments:private:read",
5209
+ CommentsPrivateNone: "comments:private:none",
5210
+ CommentsPersonalWrite: "comments:personal:write",
5211
+ CommentsPersonalRead: "comments:personal:read",
5212
+ CommentsPersonalNone: "comments:personal:none",
5195
5213
  /**
5196
5214
  * Feeds
5197
5215
  */
@@ -5204,152 +5222,125 @@ var Permission = {
5204
5222
  LegacyRoomPresenceWrite: "room:presence:write"
5205
5223
  };
5206
5224
  var ACCESS_LEVELS = ["none", "read", "write"];
5207
- var basePermissionScopes = /* @__PURE__ */ new Set([
5208
- Permission.Read,
5209
- Permission.Write,
5210
- Permission.RoomRead,
5211
- Permission.RoomWrite
5212
- ]);
5213
5225
  var ACCESS_LEVEL_RANKS = {
5214
5226
  none: 0,
5215
5227
  read: 1,
5216
5228
  write: 2
5217
5229
  };
5218
- var PERMISSIONS_BY_RESOURCE = {
5219
- room: {
5220
- read: [Permission.Read, Permission.RoomRead],
5221
- write: [Permission.Write, Permission.RoomWrite]
5222
- },
5223
- personal: {
5224
- write: []
5225
- },
5226
- storage: {
5227
- write: [Permission.StorageWrite],
5228
- read: [Permission.StorageRead],
5229
- none: [Permission.StorageNone]
5230
- },
5231
- comments: {
5232
- write: [Permission.CommentsWrite],
5233
- read: [Permission.CommentsRead],
5234
- none: [Permission.CommentsNone]
5235
- },
5236
- feeds: {
5237
- write: [Permission.FeedsWrite],
5238
- read: [Permission.FeedsRead],
5239
- none: [Permission.FeedsNone]
5240
- }
5230
+ var BASE_PERMISSIONS_BY_ACCESS = {
5231
+ read: [Permission.Read, Permission.RoomRead],
5232
+ write: [Permission.Write, Permission.RoomWrite]
5241
5233
  };
5242
5234
  var NO_PERMISSION_MATRIX = {
5243
5235
  room: "none",
5244
5236
  storage: "none",
5245
5237
  comments: "none",
5238
+ "comments:public": "none",
5239
+ "comments:private": "none",
5240
+ "comments:personal": "none",
5246
5241
  feeds: "none",
5247
5242
  personal: "none"
5248
5243
  };
5249
5244
  var BASE_PERMISSION_RESOURCE = "room";
5250
- var ROOM_PERMISSION_RESOURCES = [
5245
+ var basePermissionScopes = /* @__PURE__ */ new Set([
5246
+ Permission.Read,
5247
+ Permission.Write,
5248
+ Permission.RoomRead,
5249
+ Permission.RoomWrite
5250
+ ]);
5251
+ var ROOM_PERMISSION_RESOURCES = Object.freeze([
5251
5252
  "storage",
5252
5253
  "comments",
5254
+ "comments:public",
5255
+ "comments:private",
5256
+ "comments:personal",
5253
5257
  "feeds"
5254
- ];
5255
- var VALID_PERMISSIONS = new Set(Object.values(Permission));
5256
- function isPermission(permission) {
5257
- return VALID_PERMISSIONS.has(permission);
5258
- }
5259
- function resolveResourceAccess(scopes, resource) {
5260
- const permissions = PERMISSIONS_BY_RESOURCE[resource];
5261
- let resourceAccess;
5262
- for (const access of ACCESS_LEVELS) {
5263
- const scopedPermissions = permissions[access];
5264
- if (scopedPermissions !== void 0 && scopedPermissions.some((permission) => scopes.includes(permission))) {
5265
- resourceAccess = access;
5266
- }
5267
- }
5268
- return resourceAccess;
5269
- }
5270
- function permissionMatrixFromResolvedScopes(resolved) {
5271
- if (!resolved.hasDefaultPermission) {
5272
- return { ...NO_PERMISSION_MATRIX };
5273
- }
5274
- const matrix = {
5275
- ...NO_PERMISSION_MATRIX,
5276
- [BASE_PERMISSION_RESOURCE]: resolved.baseAccess,
5277
- personal: "write"
5278
- };
5258
+ ]);
5259
+ var CHILD_ROOM_PERMISSION_RESOURCES = (() => {
5260
+ const result = /* @__PURE__ */ new Map();
5279
5261
  for (const resource of ROOM_PERMISSION_RESOURCES) {
5280
- matrix[resource] = _nullishCoalesce(resolved.matrix[resource], () => ( resolved.baseAccess));
5262
+ const childResourcePrefix = `${resource}:`;
5263
+ result.set(
5264
+ resource,
5265
+ Object.freeze(
5266
+ ROOM_PERMISSION_RESOURCES.filter((candidate) => {
5267
+ if (!candidate.startsWith(childResourcePrefix)) {
5268
+ return false;
5269
+ }
5270
+ return !candidate.slice(childResourcePrefix.length).includes(":");
5271
+ })
5272
+ )
5273
+ );
5281
5274
  }
5282
- return matrix;
5283
- }
5284
- function permissionMatrixFromScopes(scopes) {
5285
- return permissionMatrixFromResolvedScopes(resolvePermissionScopes(scopes));
5286
- }
5287
- function resolvePermissionScopes(scopes) {
5288
- const hasDefaultPermission = scopes.includes(Permission.Write) || scopes.includes(Permission.Read) || scopes.includes(Permission.RoomWrite) || scopes.includes(Permission.RoomRead);
5289
- const baseAccess = scopes.includes(Permission.Write) || scopes.includes(Permission.RoomWrite) ? "write" : scopes.includes(Permission.Read) || scopes.includes(Permission.RoomRead) ? "read" : "none";
5290
- const matrix = {};
5275
+ return result;
5276
+ })();
5277
+ var LEAF_ROOM_PERMISSION_RESOURCES_BY_PARENT = (() => {
5278
+ const result = /* @__PURE__ */ new Map();
5291
5279
  for (const resource of ROOM_PERMISSION_RESOURCES) {
5292
- const access = resolveResourceAccess(scopes, resource);
5293
- if (access !== void 0) {
5294
- matrix[resource] = access;
5295
- }
5296
- }
5297
- return { hasDefaultPermission, baseAccess, matrix };
5298
- }
5299
- function hasPermissionAccess(matrix, resource, requiredAccess) {
5300
- const access = _nullishCoalesce(matrix[resource], () => ( "none"));
5301
- return ACCESS_LEVEL_RANKS[access] >= ACCESS_LEVEL_RANKS[requiredAccess];
5302
- }
5303
- function resolveRoomPermissionMatrix(permissions, roomId) {
5304
- const matchedPermissions = permissions.filter(
5305
- (entry) => roomPatternMatches(entry.pattern, roomId)
5306
- );
5307
- if (matchedPermissions.length === 0) {
5308
- return void 0;
5280
+ result.set(resource, Object.freeze(getLeafResources(resource)));
5309
5281
  }
5310
- let hasDefaultPermission = false;
5311
- let baseAccess = "none";
5312
- const explicitMatrix = {};
5313
- const explicitSpecificity = {};
5314
- for (const entry of matchedPermissions) {
5315
- const resolved = resolvePermissionScopes(entry.scopes);
5316
- const specificity = roomPatternSpecificity(entry.pattern);
5317
- if (resolved.hasDefaultPermission) {
5318
- hasDefaultPermission = true;
5319
- baseAccess = strongestAccess(baseAccess, resolved.baseAccess);
5320
- }
5321
- for (const resource of ROOM_PERMISSION_RESOURCES) {
5322
- const access = resolved.matrix[resource];
5323
- if (access !== void 0) {
5324
- const currentSpecificity = _nullishCoalesce(explicitSpecificity[resource], () => ( -1));
5325
- if (specificity > currentSpecificity) {
5326
- explicitMatrix[resource] = access;
5327
- explicitSpecificity[resource] = specificity;
5328
- } else if (specificity === currentSpecificity) {
5329
- explicitMatrix[resource] = strongestAccess(
5330
- _nullishCoalesce(explicitMatrix[resource], () => ( "none")),
5331
- access
5332
- );
5333
- }
5334
- }
5282
+ return result;
5283
+ })();
5284
+ var PARENT_ROOM_PERMISSION_RESOURCES = (() => {
5285
+ const result = /* @__PURE__ */ new Map();
5286
+ for (const parentResource of ROOM_PERMISSION_RESOURCES) {
5287
+ for (const childResource of childResourcesOf(parentResource)) {
5288
+ result.set(childResource, parentResource);
5335
5289
  }
5336
5290
  }
5337
- return permissionMatrixFromResolvedScopes({
5338
- hasDefaultPermission,
5339
- baseAccess,
5340
- matrix: explicitMatrix
5341
- });
5342
- }
5291
+ return result;
5292
+ })();
5293
+ var LEAF_ROOM_PERMISSION_RESOURCES = Object.freeze(
5294
+ ROOM_PERMISSION_RESOURCES.filter(
5295
+ (resource) => childResourcesOf(resource).length === 0
5296
+ )
5297
+ );
5298
+ var PERMISSIONS_BY_ROOM_RESOURCE = {
5299
+ storage: {
5300
+ write: [Permission.StorageWrite],
5301
+ read: [Permission.StorageRead],
5302
+ none: [Permission.StorageNone]
5303
+ },
5304
+ comments: {
5305
+ write: [Permission.CommentsWrite],
5306
+ read: [Permission.CommentsRead],
5307
+ none: [Permission.CommentsNone]
5308
+ },
5309
+ "comments:public": {
5310
+ write: [Permission.CommentsPublicWrite],
5311
+ read: [Permission.CommentsPublicRead],
5312
+ none: [Permission.CommentsPublicNone]
5313
+ },
5314
+ "comments:private": {
5315
+ write: [Permission.CommentsPrivateWrite],
5316
+ read: [Permission.CommentsPrivateRead],
5317
+ none: [Permission.CommentsPrivateNone]
5318
+ },
5319
+ "comments:personal": {
5320
+ write: [Permission.CommentsPersonalWrite],
5321
+ read: [Permission.CommentsPersonalRead],
5322
+ none: [Permission.CommentsPersonalNone]
5323
+ },
5324
+ feeds: {
5325
+ write: [Permission.FeedsWrite],
5326
+ read: [Permission.FeedsRead],
5327
+ none: [Permission.FeedsNone]
5328
+ }
5329
+ };
5330
+ var VALID_PERMISSIONS = new Set(Object.values(Permission));
5343
5331
  function normalizeRoomPermissions(permissions) {
5344
5332
  if (!Array.isArray(permissions)) {
5345
5333
  throw new Error("Permission list must be an array");
5346
5334
  }
5347
5335
  const result = [];
5348
5336
  for (const permission of permissions) {
5349
- if (!isPermission(permission)) {
5337
+ const knownPermission = Object.values(Permission).find(
5338
+ (value) => value === permission
5339
+ );
5340
+ if (knownPermission === void 0) {
5350
5341
  throw new Error(`Not a valid permission: ${permission}`);
5351
5342
  }
5352
- result.push(permission);
5343
+ result.push(knownPermission);
5353
5344
  }
5354
5345
  return result;
5355
5346
  }
@@ -5375,6 +5366,31 @@ function normalizeUpdateRoomAccesses(accesses) {
5375
5366
  ])
5376
5367
  );
5377
5368
  }
5369
+ function validatePermissionsSet(scopes) {
5370
+ const unknownScopes = scopes.filter((scope) => !VALID_PERMISSIONS.has(scope));
5371
+ if (unknownScopes.length > 0) {
5372
+ return `Unknown permission scope(s): ${unknownScopes.join(", ")}`;
5373
+ }
5374
+ const baseScopes = scopes.filter((scope) => basePermissionScopes.has(scope));
5375
+ if (baseScopes.length !== 1) {
5376
+ 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(", ")}`;
5377
+ }
5378
+ const seenFeatures = /* @__PURE__ */ new Set();
5379
+ for (const scope of scopes) {
5380
+ if (basePermissionScopes.has(scope) || scope === Permission.LegacyRoomPresenceWrite) {
5381
+ continue;
5382
+ }
5383
+ const feature = scope.split(":").slice(0, -1).join(":");
5384
+ if (seenFeatures.has(feature)) {
5385
+ return `Permissions can include at most one scope per feature, got multiple "${feature}" scopes`;
5386
+ }
5387
+ seenFeatures.add(feature);
5388
+ }
5389
+ return true;
5390
+ }
5391
+ function permissionMatrixFromScopes(scopes) {
5392
+ return permissionMatrixFromResolvedScopes(resolvePermissionScopes(scopes));
5393
+ }
5378
5394
  function permissionMatrixToScopes(matrix) {
5379
5395
  const scopes = [];
5380
5396
  const baseAccess = matrix.room;
@@ -5382,13 +5398,59 @@ function permissionMatrixToScopes(matrix) {
5382
5398
  scopes.push(permissionForAccessLevel(BASE_PERMISSION_RESOURCE, baseAccess));
5383
5399
  }
5384
5400
  for (const resource of ROOM_PERMISSION_RESOURCES) {
5385
- const access = matrix[resource];
5386
- if (access !== baseAccess) {
5387
- scopes.push(permissionForAccessLevel(resource, access));
5401
+ if (parentResourceOf(resource) === void 0) {
5402
+ pushResourcePermissions(scopes, matrix, resource, baseAccess);
5388
5403
  }
5389
5404
  }
5390
5405
  return scopes;
5391
5406
  }
5407
+ function hasPermissionAccess(matrix, resource, requiredAccess) {
5408
+ const access = _nullishCoalesce(matrix[resource], () => ( "none"));
5409
+ return ACCESS_LEVEL_RANKS[access] >= ACCESS_LEVEL_RANKS[requiredAccess];
5410
+ }
5411
+ function resolveRoomPermissionMatrix(permissions, roomId) {
5412
+ const matchedPermissions = permissions.filter((entry) => {
5413
+ if (entry.pattern.includes("*")) {
5414
+ return roomId.startsWith(entry.pattern.replace("*", ""));
5415
+ }
5416
+ return entry.pattern === roomId;
5417
+ });
5418
+ if (matchedPermissions.length === 0) {
5419
+ return void 0;
5420
+ }
5421
+ let hasDefaultPermission = false;
5422
+ let baseAccess = "none";
5423
+ const leafAccesses = {};
5424
+ const leafSpecificity = {};
5425
+ for (const entry of matchedPermissions) {
5426
+ const resolved = resolvePermissionScopes(entry.scopes);
5427
+ const specificity = entry.pattern.replace("*", "").length;
5428
+ if (resolved.baseAccess !== void 0) {
5429
+ hasDefaultPermission = true;
5430
+ baseAccess = strongestAccess(baseAccess, resolved.baseAccess);
5431
+ }
5432
+ for (const resource of LEAF_ROOM_PERMISSION_RESOURCES) {
5433
+ if (resolved.leafAccesses[resource] === void 0) {
5434
+ continue;
5435
+ }
5436
+ const access = resolveLeafAccessFromSource(resolved, resource);
5437
+ const currentSpecificity = _nullishCoalesce(leafSpecificity[resource], () => ( -1));
5438
+ if (specificity > currentSpecificity) {
5439
+ leafAccesses[resource] = access;
5440
+ leafSpecificity[resource] = specificity;
5441
+ } else if (specificity === currentSpecificity) {
5442
+ leafAccesses[resource] = strongestAccess(
5443
+ _nullishCoalesce(leafAccesses[resource], () => ( "none")),
5444
+ access
5445
+ );
5446
+ }
5447
+ }
5448
+ }
5449
+ return permissionMatrixFromResolvedScopes({
5450
+ baseAccess: hasDefaultPermission ? baseAccess : void 0,
5451
+ leafAccesses
5452
+ });
5453
+ }
5392
5454
  function mergeRoomPermissionScopes({
5393
5455
  defaultAccesses,
5394
5456
  groupsAccesses,
@@ -5402,90 +5464,158 @@ function mergeRoomPermissionScopes({
5402
5464
  resolvePermissionScopes(userAccesses)
5403
5465
  ];
5404
5466
  const merged = {
5405
- hasDefaultPermission: false,
5406
- baseAccess: "none",
5407
- matrix: {}
5467
+ leafAccesses: {}
5408
5468
  };
5409
5469
  for (const source of sources) {
5410
- if (source.hasDefaultPermission) {
5411
- merged.hasDefaultPermission = true;
5470
+ if (source.baseAccess !== void 0) {
5412
5471
  merged.baseAccess = source.baseAccess;
5413
5472
  }
5414
- for (const resource of ROOM_PERMISSION_RESOURCES) {
5415
- const access = source.matrix[resource];
5416
- if (access !== void 0) {
5417
- merged.matrix[resource] = access;
5473
+ for (const resource of LEAF_ROOM_PERMISSION_RESOURCES) {
5474
+ const sourceAccess = source.leafAccesses[resource];
5475
+ if (sourceAccess === void 0) {
5476
+ continue;
5418
5477
  }
5478
+ merged.leafAccesses[resource] = sourceAccess;
5419
5479
  }
5420
5480
  }
5421
5481
  return permissionMatrixToScopes(permissionMatrixFromResolvedScopes(merged));
5422
5482
  }
5483
+ function resolvePermissionScopes(scopes) {
5484
+ const baseAccess = resolveAccess(scopes, BASE_PERMISSIONS_BY_ACCESS);
5485
+ const leafAccesses = {};
5486
+ for (const resource of ROOM_PERMISSION_RESOURCES) {
5487
+ const access = resolveResourceAccess(scopes, resource);
5488
+ if (access !== void 0) {
5489
+ for (const leafResource of leafResourcesOf(resource)) {
5490
+ leafAccesses[leafResource] = access;
5491
+ }
5492
+ }
5493
+ }
5494
+ return { baseAccess, leafAccesses };
5495
+ }
5496
+ function resolveResourceAccess(scopes, resource) {
5497
+ return resolveAccess(scopes, PERMISSIONS_BY_ROOM_RESOURCE[resource]);
5498
+ }
5499
+ function resolveAccess(scopes, permissions) {
5500
+ let resourceAccess;
5501
+ for (const access of ACCESS_LEVELS) {
5502
+ const scopedPermissions = permissions[access];
5503
+ if (scopedPermissions !== void 0 && scopedPermissions.some((permission) => scopes.includes(permission))) {
5504
+ resourceAccess = access;
5505
+ }
5506
+ }
5507
+ return resourceAccess;
5508
+ }
5509
+ function permissionMatrixFromResolvedScopes(resolved) {
5510
+ if (resolved.baseAccess === void 0) {
5511
+ return { ...NO_PERMISSION_MATRIX };
5512
+ }
5513
+ const matrix = {
5514
+ ...NO_PERMISSION_MATRIX,
5515
+ [BASE_PERMISSION_RESOURCE]: resolved.baseAccess,
5516
+ personal: "write"
5517
+ };
5518
+ for (const resource of LEAF_ROOM_PERMISSION_RESOURCES) {
5519
+ matrix[resource] = resolveLeafAccessFromSource(resolved, resource);
5520
+ }
5521
+ for (const resource of ROOM_PERMISSION_RESOURCES) {
5522
+ if (childResourcesOf(resource).length > 0) {
5523
+ let strongest = "none";
5524
+ for (const leafResource of leafResourcesOf(resource)) {
5525
+ strongest = strongestAccess(strongest, matrix[leafResource]);
5526
+ }
5527
+ matrix[resource] = strongest;
5528
+ }
5529
+ }
5530
+ return matrix;
5531
+ }
5532
+ function resolveLeafAccessFromSource(source, resource) {
5533
+ const access = source.leafAccesses[resource];
5534
+ if (access !== void 0) {
5535
+ return access;
5536
+ }
5537
+ return _nullishCoalesce(source.baseAccess, () => ( "none"));
5538
+ }
5539
+ function pushResourcePermissions(scopes, matrix, resource, baseAccess) {
5540
+ const childResources = childResourcesOf(resource);
5541
+ if (childResources.length === 0) {
5542
+ const access = matrix[resource];
5543
+ if (access !== baseAccess) {
5544
+ scopes.push(permissionForAccessLevel(resource, access));
5545
+ }
5546
+ return;
5547
+ }
5548
+ const leafResources = leafResourcesOf(resource);
5549
+ let sharedAccess;
5550
+ let allLeavesShareAccess = true;
5551
+ for (const leafResource of leafResources) {
5552
+ const access = matrix[leafResource];
5553
+ sharedAccess ??= access;
5554
+ if (access !== sharedAccess) {
5555
+ allLeavesShareAccess = false;
5556
+ break;
5557
+ }
5558
+ }
5559
+ if (sharedAccess !== void 0 && sharedAccess !== baseAccess && allLeavesShareAccess) {
5560
+ scopes.push(permissionForAccessLevel(resource, sharedAccess));
5561
+ return;
5562
+ }
5563
+ for (const childResource of childResources) {
5564
+ pushResourcePermissions(scopes, matrix, childResource, baseAccess);
5565
+ }
5566
+ }
5423
5567
  function mergeResolvedScopesByHighestAccess(sources) {
5424
5568
  const merged = {
5425
- hasDefaultPermission: false,
5426
- baseAccess: "none",
5427
- matrix: {}
5569
+ leafAccesses: {}
5428
5570
  };
5429
5571
  for (const source of sources) {
5430
- if (source.hasDefaultPermission) {
5431
- merged.hasDefaultPermission = true;
5432
- merged.baseAccess = strongestAccess(merged.baseAccess, source.baseAccess);
5433
- }
5434
- for (const resource of ROOM_PERMISSION_RESOURCES) {
5435
- const access = source.matrix[resource];
5436
- if (access !== void 0) {
5437
- merged.matrix[resource] = strongestAccess(
5438
- _nullishCoalesce(merged.matrix[resource], () => ( "none")),
5439
- access
5440
- );
5572
+ if (source.baseAccess !== void 0) {
5573
+ merged.baseAccess = strongestAccess(
5574
+ _nullishCoalesce(merged.baseAccess, () => ( "none")),
5575
+ source.baseAccess
5576
+ );
5577
+ }
5578
+ for (const resource of LEAF_ROOM_PERMISSION_RESOURCES) {
5579
+ const sourceAccess = source.leafAccesses[resource];
5580
+ if (sourceAccess === void 0) {
5581
+ continue;
5441
5582
  }
5583
+ merged.leafAccesses[resource] = strongestAccess(
5584
+ _nullishCoalesce(merged.leafAccesses[resource], () => ( "none")),
5585
+ sourceAccess
5586
+ );
5442
5587
  }
5443
5588
  }
5444
5589
  return merged;
5445
5590
  }
5446
5591
  function permissionForAccessLevel(resource, access, field = resource) {
5447
- const levels = PERMISSIONS_BY_RESOURCE[resource];
5448
- const permissions = levels[access];
5449
- if (permissions === void 0 || permissions.length === 0) {
5450
- throw new Error(
5451
- `Invalid permission level for ${field}: ${_nullishCoalesce(JSON.stringify(access), () => ( String(access)))}`
5452
- );
5592
+ const permissions = resource === "room" ? BASE_PERMISSIONS_BY_ACCESS[access] : resource === "personal" ? void 0 : PERMISSIONS_BY_ROOM_RESOURCE[resource][access];
5593
+ const permission = _optionalChain([permissions, 'optionalAccess', _109 => _109[0]]);
5594
+ if (permission !== void 0) {
5595
+ return permission;
5453
5596
  }
5454
- return permissions[0];
5597
+ throw new Error(
5598
+ `Invalid permission level for ${field}: ${_nullishCoalesce(JSON.stringify(access), () => ( String(access)))}`
5599
+ );
5455
5600
  }
5456
5601
  function strongestAccess(left, right) {
5457
5602
  return ACCESS_LEVEL_RANKS[right] > ACCESS_LEVEL_RANKS[left] ? right : left;
5458
5603
  }
5459
- function roomPatternMatches(pattern, roomId) {
5460
- if (pattern.includes("*")) {
5461
- return roomId.startsWith(pattern.replace("*", ""));
5462
- }
5463
- return pattern === roomId;
5604
+ function leafResourcesOf(resource) {
5605
+ return _nullishCoalesce(LEAF_ROOM_PERMISSION_RESOURCES_BY_PARENT.get(resource), () => ( []));
5464
5606
  }
5465
- function roomPatternSpecificity(pattern) {
5466
- return pattern.replace("*", "").length;
5607
+ function childResourcesOf(resource) {
5608
+ return _nullishCoalesce(CHILD_ROOM_PERMISSION_RESOURCES.get(resource), () => ( []));
5467
5609
  }
5468
- function validatePermissionsSet(scopes) {
5469
- const unknownScopes = scopes.filter((scope) => !VALID_PERMISSIONS.has(scope));
5470
- if (unknownScopes.length > 0) {
5471
- return `Unknown permission scope(s): ${unknownScopes.join(", ")}`;
5472
- }
5473
- const baseScopes = scopes.filter((scope) => basePermissionScopes.has(scope));
5474
- if (baseScopes.length !== 1) {
5475
- 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(", ")}`;
5476
- }
5477
- const seenFeatures = /* @__PURE__ */ new Set();
5478
- for (const scope of scopes) {
5479
- if (basePermissionScopes.has(scope) || scope === Permission.LegacyRoomPresenceWrite) {
5480
- continue;
5481
- }
5482
- const feature = scope.slice(0, scope.indexOf(":"));
5483
- if (seenFeatures.has(feature)) {
5484
- return `Permissions can include at most one scope per feature, got multiple "${feature}" scopes`;
5485
- }
5486
- seenFeatures.add(feature);
5610
+ function parentResourceOf(resource) {
5611
+ return PARENT_ROOM_PERMISSION_RESOURCES.get(resource);
5612
+ }
5613
+ function getLeafResources(resource) {
5614
+ const childResources = childResourcesOf(resource);
5615
+ if (childResources.length === 0) {
5616
+ return [resource];
5487
5617
  }
5488
- return true;
5618
+ return childResources.flatMap(getLeafResources);
5489
5619
  }
5490
5620
 
5491
5621
  // src/protocol/AuthToken.ts
@@ -5548,7 +5678,7 @@ function createAuthManager(authOptions, onAuthenticate) {
5548
5678
  return void 0;
5549
5679
  }
5550
5680
  async function makeAuthRequest(options) {
5551
- const fetcher = _nullishCoalesce(_optionalChain([authOptions, 'access', _107 => _107.polyfills, 'optionalAccess', _108 => _108.fetch]), () => ( (typeof window === "undefined" ? void 0 : window.fetch)));
5681
+ const fetcher = _nullishCoalesce(_optionalChain([authOptions, 'access', _110 => _110.polyfills, 'optionalAccess', _111 => _111.fetch]), () => ( (typeof window === "undefined" ? void 0 : window.fetch)));
5552
5682
  if (authentication.type === "private") {
5553
5683
  if (fetcher === void 0) {
5554
5684
  throw new StopRetrying(
@@ -5561,14 +5691,14 @@ function createAuthManager(authOptions, onAuthenticate) {
5561
5691
  const parsed = parseAuthToken(response.token);
5562
5692
  if (seenTokens.has(parsed.raw)) {
5563
5693
  const cachedToken = getCachedToken(options);
5564
- if (_optionalChain([cachedToken, 'optionalAccess', _109 => _109.raw]) === parsed.raw) {
5694
+ if (_optionalChain([cachedToken, 'optionalAccess', _112 => _112.raw]) === parsed.raw) {
5565
5695
  return cachedToken;
5566
5696
  }
5567
5697
  throw new StopRetrying(
5568
5698
  "The same Liveblocks auth token was issued from the backend before. Caching Liveblocks tokens is not supported."
5569
5699
  );
5570
5700
  }
5571
- _optionalChain([onAuthenticate, 'optionalCall', _110 => _110(parsed.parsed)]);
5701
+ _optionalChain([onAuthenticate, 'optionalCall', _113 => _113(parsed.parsed)]);
5572
5702
  return parsed;
5573
5703
  }
5574
5704
  if (authentication.type === "custom") {
@@ -5576,7 +5706,7 @@ function createAuthManager(authOptions, onAuthenticate) {
5576
5706
  if (response && typeof response === "object") {
5577
5707
  if (typeof response.token === "string") {
5578
5708
  const parsed = parseAuthToken(response.token);
5579
- _optionalChain([onAuthenticate, 'optionalCall', _111 => _111(parsed.parsed)]);
5709
+ _optionalChain([onAuthenticate, 'optionalCall', _114 => _114(parsed.parsed)]);
5580
5710
  return parsed;
5581
5711
  } else if (typeof response.error === "string") {
5582
5712
  const reason = `Authentication failed: ${"reason" in response && typeof response.reason === "string" ? response.reason : "Forbidden"}`;
@@ -5768,15 +5898,13 @@ var OpCode = Object.freeze({
5768
5898
  DELETE_CRDT: 5,
5769
5899
  DELETE_OBJECT_KEY: 6,
5770
5900
  CREATE_MAP: 7,
5771
- CREATE_REGISTER: 8,
5772
- CREATE_TEXT: 9,
5773
- UPDATE_TEXT: 10
5901
+ CREATE_REGISTER: 8
5774
5902
  });
5775
5903
  function isIgnoredOp(op) {
5776
5904
  return op.type === OpCode.DELETE_CRDT && op.id === "ACK";
5777
5905
  }
5778
5906
  function isCreateOp(op) {
5779
- return op.type === OpCode.CREATE_OBJECT || op.type === OpCode.CREATE_REGISTER || op.type === OpCode.CREATE_MAP || op.type === OpCode.CREATE_LIST || op.type === OpCode.CREATE_TEXT;
5907
+ return op.type === OpCode.CREATE_OBJECT || op.type === OpCode.CREATE_REGISTER || op.type === OpCode.CREATE_MAP || op.type === OpCode.CREATE_LIST;
5780
5908
  }
5781
5909
 
5782
5910
  // src/protocol/StorageNode.ts
@@ -5784,8 +5912,7 @@ var CrdtType = Object.freeze({
5784
5912
  OBJECT: 0,
5785
5913
  LIST: 1,
5786
5914
  MAP: 2,
5787
- REGISTER: 3,
5788
- TEXT: 4
5915
+ REGISTER: 3
5789
5916
  });
5790
5917
  function isRootStorageNode(node) {
5791
5918
  return node[0] === "root";
@@ -5802,9 +5929,6 @@ function isMapStorageNode(node) {
5802
5929
  function isRegisterStorageNode(node) {
5803
5930
  return node[1].type === CrdtType.REGISTER;
5804
5931
  }
5805
- function isTextStorageNode(node) {
5806
- return node[1].type === CrdtType.TEXT;
5807
- }
5808
5932
  function isCompactRootNode(node) {
5809
5933
  return node[0] === "root";
5810
5934
  }
@@ -5827,9 +5951,6 @@ function* compactNodesToNodeStream(compactNodes) {
5827
5951
  case CrdtType.REGISTER:
5828
5952
  yield [cnode[0], { type: CrdtType.REGISTER, parentId: cnode[2], parentKey: cnode[3], data: cnode[4] }];
5829
5953
  break;
5830
- case CrdtType.TEXT:
5831
- yield [cnode[0], { type: CrdtType.TEXT, parentId: cnode[2], parentKey: cnode[3], data: cnode[4], version: cnode[5] }];
5832
- break;
5833
5954
  default:
5834
5955
  }
5835
5956
  }
@@ -5858,17 +5979,6 @@ function* nodeStreamToCompactNodes(nodes) {
5858
5979
  const id = node[0];
5859
5980
  const crdt = node[1];
5860
5981
  yield [id, CrdtType.REGISTER, crdt.parentId, crdt.parentKey, crdt.data];
5861
- } else if (isTextStorageNode(node)) {
5862
- const id = node[0];
5863
- const crdt = node[1];
5864
- yield [
5865
- id,
5866
- CrdtType.TEXT,
5867
- crdt.parentId,
5868
- crdt.parentKey,
5869
- crdt.data,
5870
- crdt.version
5871
- ];
5872
5982
  } else {
5873
5983
  }
5874
5984
  }
@@ -6071,10 +6181,6 @@ ${parentKey}`;
6071
6181
  get size() {
6072
6182
  return this.#byOpId.size;
6073
6183
  }
6074
- /** The still-unacknowledged op with the given opId, if any. */
6075
- get(opId) {
6076
- return this.#byOpId.get(opId);
6077
- }
6078
6184
  /**
6079
6185
  * Mark the given Op as still unacknowledged.
6080
6186
  */
@@ -6111,12 +6217,12 @@ ${parentKey}`;
6111
6217
  if (isCreateOp(op)) {
6112
6218
  const posKey = this.#posKey(op.parentId, op.parentKey);
6113
6219
  const atPosition = this.#createOpsByPosition.get(posKey);
6114
- _optionalChain([atPosition, 'optionalAccess', _112 => _112.delete, 'call', _113 => _113(opId)]);
6220
+ _optionalChain([atPosition, 'optionalAccess', _115 => _115.delete, 'call', _116 => _116(opId)]);
6115
6221
  if (atPosition !== void 0 && atPosition.size === 0) {
6116
6222
  this.#createOpsByPosition.delete(posKey);
6117
6223
  }
6118
6224
  const inParent = this.#createOpsByParent.get(op.parentId);
6119
- _optionalChain([inParent, 'optionalAccess', _114 => _114.delete, 'call', _115 => _115(opId)]);
6225
+ _optionalChain([inParent, 'optionalAccess', _117 => _117.delete, 'call', _118 => _118(opId)]);
6120
6226
  if (inParent !== void 0 && inParent.size === 0) {
6121
6227
  this.#createOpsByParent.delete(op.parentId);
6122
6228
  }
@@ -6128,14 +6234,14 @@ ${parentKey}`;
6128
6234
  * Empty if none.
6129
6235
  */
6130
6236
  getByParentIdAndKey(parentId, parentKey) {
6131
- 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()]), () => ( []));
6237
+ return _nullishCoalesce(_optionalChain([this, 'access', _119 => _119.#createOpsByPosition, 'access', _120 => _120.get, 'call', _121 => _121(this.#posKey(parentId, parentKey)), 'optionalAccess', _122 => _122.values, 'call', _123 => _123()]), () => ( []));
6132
6238
  }
6133
6239
  /**
6134
6240
  * The still-unacknowledged Create ops with the given `parentId` (across all
6135
6241
  * positions), in dispatch order. O(1) lookup. Empty if none.
6136
6242
  */
6137
6243
  getByParentId(parentId) {
6138
- return _nullishCoalesce(_optionalChain([this, 'access', _121 => _121.#createOpsByParent, 'access', _122 => _122.get, 'call', _123 => _123(parentId), 'optionalAccess', _124 => _124.values, 'call', _125 => _125()]), () => ( []));
6244
+ return _nullishCoalesce(_optionalChain([this, 'access', _124 => _124.#createOpsByParent, 'access', _125 => _125.get, 'call', _126 => _126(parentId), 'optionalAccess', _127 => _127.values, 'call', _128 => _128()]), () => ( []));
6139
6245
  }
6140
6246
  /** All still-unacknowledged ops, in dispatch order. */
6141
6247
  values() {
@@ -6175,8 +6281,8 @@ function createManagedPool(roomId, options) {
6175
6281
  deleteNode: (id) => void nodes.delete(id),
6176
6282
  generateId: () => `${getCurrentConnectionId()}:${clock++}`,
6177
6283
  generateOpId: () => `${getCurrentConnectionId()}:${opClock++}`,
6178
- dispatch(ops, reverse, storageUpdates, options2) {
6179
- _optionalChain([onDispatch, 'optionalCall', _126 => _126(ops, reverse, storageUpdates, options2)]);
6284
+ dispatch(ops, reverse, storageUpdates) {
6285
+ _optionalChain([onDispatch, 'optionalCall', _129 => _129(ops, reverse, storageUpdates)]);
6180
6286
  },
6181
6287
  assertStorageIsWritable: () => {
6182
6288
  if (!isStorageWritable()) {
@@ -6900,7 +7006,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
6900
7006
  #applyInsertUndoRedo(op) {
6901
7007
  const { id, parentKey: key } = op;
6902
7008
  const child = creationOpToLiveNode(op);
6903
- if (_optionalChain([this, 'access', _127 => _127._pool, 'optionalAccess', _128 => _128.getNode, 'call', _129 => _129(id)]) !== void 0) {
7009
+ if (_optionalChain([this, 'access', _130 => _130._pool, 'optionalAccess', _131 => _131.getNode, 'call', _132 => _132(id)]) !== void 0) {
6904
7010
  return { modified: false };
6905
7011
  }
6906
7012
  child._attach(id, nn(this._pool));
@@ -6908,8 +7014,8 @@ var LiveList = class _LiveList extends AbstractCrdt {
6908
7014
  const existingItemIndex = this._indexOfPosition(key);
6909
7015
  let newKey = key;
6910
7016
  if (existingItemIndex !== -1) {
6911
- const before2 = _optionalChain([this, 'access', _130 => _130.#items, 'access', _131 => _131.at, 'call', _132 => _132(existingItemIndex), 'optionalAccess', _133 => _133._parentPos]);
6912
- const after2 = _optionalChain([this, 'access', _134 => _134.#items, 'access', _135 => _135.at, 'call', _136 => _136(existingItemIndex + 1), 'optionalAccess', _137 => _137._parentPos]);
7017
+ const before2 = _optionalChain([this, 'access', _133 => _133.#items, 'access', _134 => _134.at, 'call', _135 => _135(existingItemIndex), 'optionalAccess', _136 => _136._parentPos]);
7018
+ const after2 = _optionalChain([this, 'access', _137 => _137.#items, 'access', _138 => _138.at, 'call', _139 => _139(existingItemIndex + 1), 'optionalAccess', _140 => _140._parentPos]);
6913
7019
  newKey = makePosition(before2, after2);
6914
7020
  child._setParentLink(this, newKey);
6915
7021
  }
@@ -6923,7 +7029,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
6923
7029
  #applySetUndoRedo(op) {
6924
7030
  const { id, parentKey: key } = op;
6925
7031
  const child = creationOpToLiveNode(op);
6926
- if (_optionalChain([this, 'access', _138 => _138._pool, 'optionalAccess', _139 => _139.getNode, 'call', _140 => _140(id)]) !== void 0) {
7032
+ if (_optionalChain([this, 'access', _141 => _141._pool, 'optionalAccess', _142 => _142.getNode, 'call', _143 => _143(id)]) !== void 0) {
6927
7033
  return { modified: false };
6928
7034
  }
6929
7035
  const indexOfItemWithSameKey = this._indexOfPosition(key);
@@ -7044,7 +7150,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
7044
7150
  } else {
7045
7151
  this.#updateItemPositionAt(
7046
7152
  existingItemIndex,
7047
- makePosition(newKey, _optionalChain([this, 'access', _141 => _141.#items, 'access', _142 => _142.at, 'call', _143 => _143(existingItemIndex + 1), 'optionalAccess', _144 => _144._parentPos]))
7153
+ makePosition(newKey, _optionalChain([this, 'access', _144 => _144.#items, 'access', _145 => _145.at, 'call', _146 => _146(existingItemIndex + 1), 'optionalAccess', _147 => _147._parentPos]))
7048
7154
  );
7049
7155
  const previousIndex = this.#items.findIndex((item) => item === child);
7050
7156
  this.#updateItemPosition(child, newKey);
@@ -7071,7 +7177,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
7071
7177
  this,
7072
7178
  makePosition(
7073
7179
  newKey,
7074
- _optionalChain([this, 'access', _145 => _145.#items, 'access', _146 => _146.at, 'call', _147 => _147(existingItemIndex + 1), 'optionalAccess', _148 => _148._parentPos])
7180
+ _optionalChain([this, 'access', _148 => _148.#items, 'access', _149 => _149.at, 'call', _150 => _150(existingItemIndex + 1), 'optionalAccess', _151 => _151._parentPos])
7075
7181
  )
7076
7182
  );
7077
7183
  this.#items.reposition(existingItem);
@@ -7095,7 +7201,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
7095
7201
  existingItemIndex,
7096
7202
  makePosition(
7097
7203
  newKey,
7098
- _optionalChain([this, 'access', _149 => _149.#items, 'access', _150 => _150.at, 'call', _151 => _151(existingItemIndex + 1), 'optionalAccess', _152 => _152._parentPos])
7204
+ _optionalChain([this, 'access', _152 => _152.#items, 'access', _153 => _153.at, 'call', _154 => _154(existingItemIndex + 1), 'optionalAccess', _155 => _155._parentPos])
7099
7205
  )
7100
7206
  );
7101
7207
  }
@@ -7123,7 +7229,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
7123
7229
  if (existingItemIndex !== -1) {
7124
7230
  actualNewKey = makePosition(
7125
7231
  newKey,
7126
- _optionalChain([this, 'access', _153 => _153.#items, 'access', _154 => _154.at, 'call', _155 => _155(existingItemIndex + 1), 'optionalAccess', _156 => _156._parentPos])
7232
+ _optionalChain([this, 'access', _156 => _156.#items, 'access', _157 => _157.at, 'call', _158 => _158(existingItemIndex + 1), 'optionalAccess', _159 => _159._parentPos])
7127
7233
  );
7128
7234
  }
7129
7235
  this.#updateItemPosition(child, actualNewKey);
@@ -7197,14 +7303,14 @@ var LiveList = class _LiveList extends AbstractCrdt {
7197
7303
  * instead of resolving its position against the client's stale view.
7198
7304
  */
7199
7305
  #injectAt(element, index, intent) {
7200
- _optionalChain([this, 'access', _157 => _157._pool, 'optionalAccess', _158 => _158.assertStorageIsWritable, 'call', _159 => _159()]);
7306
+ _optionalChain([this, 'access', _160 => _160._pool, 'optionalAccess', _161 => _161.assertStorageIsWritable, 'call', _162 => _162()]);
7201
7307
  if (index < 0 || index > this.#items.length) {
7202
7308
  throw new Error(
7203
7309
  `Cannot insert list item at index "${index}". index should be between 0 and ${this.#items.length}`
7204
7310
  );
7205
7311
  }
7206
- const before2 = _optionalChain([this, 'access', _160 => _160.#items, 'access', _161 => _161.at, 'call', _162 => _162(index - 1), 'optionalAccess', _163 => _163._parentPos]);
7207
- const after2 = _optionalChain([this, 'access', _164 => _164.#items, 'access', _165 => _165.at, 'call', _166 => _166(index), 'optionalAccess', _167 => _167._parentPos]);
7312
+ const before2 = _optionalChain([this, 'access', _163 => _163.#items, 'access', _164 => _164.at, 'call', _165 => _165(index - 1), 'optionalAccess', _166 => _166._parentPos]);
7313
+ const after2 = _optionalChain([this, 'access', _167 => _167.#items, 'access', _168 => _168.at, 'call', _169 => _169(index), 'optionalAccess', _170 => _170._parentPos]);
7208
7314
  const position = makePosition(before2, after2);
7209
7315
  const value = lsonToLiveNode(element);
7210
7316
  value._setParentLink(this, position);
@@ -7228,7 +7334,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
7228
7334
  * @param targetIndex The index where the element should be after moving.
7229
7335
  */
7230
7336
  move(index, targetIndex) {
7231
- _optionalChain([this, 'access', _168 => _168._pool, 'optionalAccess', _169 => _169.assertStorageIsWritable, 'call', _170 => _170()]);
7337
+ _optionalChain([this, 'access', _171 => _171._pool, 'optionalAccess', _172 => _172.assertStorageIsWritable, 'call', _173 => _173()]);
7232
7338
  if (targetIndex < 0) {
7233
7339
  throw new Error("targetIndex cannot be less than 0");
7234
7340
  }
@@ -7246,11 +7352,11 @@ var LiveList = class _LiveList extends AbstractCrdt {
7246
7352
  let beforePosition = null;
7247
7353
  let afterPosition = null;
7248
7354
  if (index < targetIndex) {
7249
- 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]);
7355
+ afterPosition = targetIndex === this.#items.length - 1 ? void 0 : _optionalChain([this, 'access', _174 => _174.#items, 'access', _175 => _175.at, 'call', _176 => _176(targetIndex + 1), 'optionalAccess', _177 => _177._parentPos]);
7250
7356
  beforePosition = this.#items.at(targetIndex)._parentPos;
7251
7357
  } else {
7252
7358
  afterPosition = this.#items.at(targetIndex)._parentPos;
7253
- beforePosition = targetIndex === 0 ? void 0 : _optionalChain([this, 'access', _175 => _175.#items, 'access', _176 => _176.at, 'call', _177 => _177(targetIndex - 1), 'optionalAccess', _178 => _178._parentPos]);
7359
+ beforePosition = targetIndex === 0 ? void 0 : _optionalChain([this, 'access', _178 => _178.#items, 'access', _179 => _179.at, 'call', _180 => _180(targetIndex - 1), 'optionalAccess', _181 => _181._parentPos]);
7254
7360
  }
7255
7361
  const position = makePosition(beforePosition, afterPosition);
7256
7362
  const item = this.#items.at(index);
@@ -7285,7 +7391,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
7285
7391
  * @param index The index of the element to delete
7286
7392
  */
7287
7393
  delete(index) {
7288
- _optionalChain([this, 'access', _179 => _179._pool, 'optionalAccess', _180 => _180.assertStorageIsWritable, 'call', _181 => _181()]);
7394
+ _optionalChain([this, 'access', _182 => _182._pool, 'optionalAccess', _183 => _183.assertStorageIsWritable, 'call', _184 => _184()]);
7289
7395
  if (index < 0 || index >= this.#items.length) {
7290
7396
  throw new Error(
7291
7397
  `Cannot delete list item at index "${index}". index should be between 0 and ${this.#items.length - 1}`
@@ -7318,7 +7424,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
7318
7424
  }
7319
7425
  }
7320
7426
  clear() {
7321
- _optionalChain([this, 'access', _182 => _182._pool, 'optionalAccess', _183 => _183.assertStorageIsWritable, 'call', _184 => _184()]);
7427
+ _optionalChain([this, 'access', _185 => _185._pool, 'optionalAccess', _186 => _186.assertStorageIsWritable, 'call', _187 => _187()]);
7322
7428
  if (this._pool) {
7323
7429
  const ops = [];
7324
7430
  const reverseOps = [];
@@ -7352,7 +7458,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
7352
7458
  }
7353
7459
  }
7354
7460
  set(index, item) {
7355
- _optionalChain([this, 'access', _185 => _185._pool, 'optionalAccess', _186 => _186.assertStorageIsWritable, 'call', _187 => _187()]);
7461
+ _optionalChain([this, 'access', _188 => _188._pool, 'optionalAccess', _189 => _189.assertStorageIsWritable, 'call', _190 => _190()]);
7356
7462
  if (index < 0 || index >= this.#items.length) {
7357
7463
  throw new Error(
7358
7464
  `Cannot set list item at index "${index}". index should be between 0 and ${this.#items.length - 1}`
@@ -7511,7 +7617,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
7511
7617
  #shiftItemPosition(index, key) {
7512
7618
  const shiftedPosition = makePosition(
7513
7619
  key,
7514
- 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
7620
+ this.#items.length > index + 1 ? _optionalChain([this, 'access', _191 => _191.#items, 'access', _192 => _192.at, 'call', _193 => _193(index + 1), 'optionalAccess', _194 => _194._parentPos]) : void 0
7515
7621
  );
7516
7622
  this.#updateItemPositionAt(index, shiftedPosition);
7517
7623
  }
@@ -7760,7 +7866,7 @@ var LiveMap = class _LiveMap extends AbstractCrdt {
7760
7866
  * @param value The value of the element to add. Should be serializable to JSON.
7761
7867
  */
7762
7868
  set(key, value) {
7763
- _optionalChain([this, 'access', _192 => _192._pool, 'optionalAccess', _193 => _193.assertStorageIsWritable, 'call', _194 => _194()]);
7869
+ _optionalChain([this, 'access', _195 => _195._pool, 'optionalAccess', _196 => _196.assertStorageIsWritable, 'call', _197 => _197()]);
7764
7870
  const oldValue = this.#map.get(key);
7765
7871
  if (oldValue) {
7766
7872
  oldValue._detach();
@@ -7806,7 +7912,7 @@ var LiveMap = class _LiveMap extends AbstractCrdt {
7806
7912
  * @returns true if an element existed and has been removed, or false if the element does not exist.
7807
7913
  */
7808
7914
  delete(key) {
7809
- _optionalChain([this, 'access', _195 => _195._pool, 'optionalAccess', _196 => _196.assertStorageIsWritable, 'call', _197 => _197()]);
7915
+ _optionalChain([this, 'access', _198 => _198._pool, 'optionalAccess', _199 => _199.assertStorageIsWritable, 'call', _200 => _200()]);
7810
7916
  const item = this.#map.get(key);
7811
7917
  if (item === void 0) {
7812
7918
  return false;
@@ -8418,20 +8524,20 @@ var LiveObject = (_class2 = class _LiveObject extends AbstractCrdt {
8418
8524
  * Caveat: this method will not add changes to the undo/redo stack.
8419
8525
  */
8420
8526
  setLocal(key, value) {
8421
- _optionalChain([this, 'access', _198 => _198._pool, 'optionalAccess', _199 => _199.assertStorageIsWritable, 'call', _200 => _200()]);
8527
+ _optionalChain([this, 'access', _201 => _201._pool, 'optionalAccess', _202 => _202.assertStorageIsWritable, 'call', _203 => _203()]);
8422
8528
  const deleteResult = this.#prepareDelete(key);
8423
8529
  this.#local.set(key, value);
8424
8530
  this.invalidate();
8425
8531
  if (this._pool !== void 0 && this._id !== void 0) {
8426
- const ops = _nullishCoalesce(_optionalChain([deleteResult, 'optionalAccess', _201 => _201[0]]), () => ( []));
8427
- const reverse = _nullishCoalesce(_optionalChain([deleteResult, 'optionalAccess', _202 => _202[1]]), () => ( []));
8428
- const storageUpdates = _nullishCoalesce(_optionalChain([deleteResult, 'optionalAccess', _203 => _203[2]]), () => ( /* @__PURE__ */ new Map()));
8532
+ const ops = _nullishCoalesce(_optionalChain([deleteResult, 'optionalAccess', _204 => _204[0]]), () => ( []));
8533
+ const reverse = _nullishCoalesce(_optionalChain([deleteResult, 'optionalAccess', _205 => _205[1]]), () => ( []));
8534
+ const storageUpdates = _nullishCoalesce(_optionalChain([deleteResult, 'optionalAccess', _206 => _206[2]]), () => ( /* @__PURE__ */ new Map()));
8429
8535
  const existing = storageUpdates.get(this._id);
8430
8536
  storageUpdates.set(this._id, {
8431
8537
  node: this,
8432
8538
  type: "LiveObject",
8433
8539
  updates: {
8434
- ..._optionalChain([existing, 'optionalAccess', _204 => _204.updates]),
8540
+ ..._optionalChain([existing, 'optionalAccess', _207 => _207.updates]),
8435
8541
  [key]: { type: "update" }
8436
8542
  }
8437
8543
  });
@@ -8451,7 +8557,7 @@ var LiveObject = (_class2 = class _LiveObject extends AbstractCrdt {
8451
8557
  * #synced or pool/id are unavailable. Does NOT dispatch.
8452
8558
  */
8453
8559
  #prepareDelete(key) {
8454
- _optionalChain([this, 'access', _205 => _205._pool, 'optionalAccess', _206 => _206.assertStorageIsWritable, 'call', _207 => _207()]);
8560
+ _optionalChain([this, 'access', _208 => _208._pool, 'optionalAccess', _209 => _209.assertStorageIsWritable, 'call', _210 => _210()]);
8455
8561
  const k = key;
8456
8562
  if (this.#local.has(k) && !this.#synced.has(k)) {
8457
8563
  const oldValue2 = this.#local.get(k);
@@ -8527,7 +8633,7 @@ var LiveObject = (_class2 = class _LiveObject extends AbstractCrdt {
8527
8633
  const result = this.#prepareDelete(key);
8528
8634
  if (result) {
8529
8635
  const [ops, reverse, storageUpdates] = result;
8530
- _optionalChain([this, 'access', _208 => _208._pool, 'optionalAccess', _209 => _209.dispatch, 'call', _210 => _210(ops, reverse, storageUpdates)]);
8636
+ _optionalChain([this, 'access', _211 => _211._pool, 'optionalAccess', _212 => _212.dispatch, 'call', _213 => _213(ops, reverse, storageUpdates)]);
8531
8637
  }
8532
8638
  }
8533
8639
  /**
@@ -8535,7 +8641,7 @@ var LiveObject = (_class2 = class _LiveObject extends AbstractCrdt {
8535
8641
  * @param patch The object used to overrides properties
8536
8642
  */
8537
8643
  update(patch) {
8538
- _optionalChain([this, 'access', _211 => _211._pool, 'optionalAccess', _212 => _212.assertStorageIsWritable, 'call', _213 => _213()]);
8644
+ _optionalChain([this, 'access', _214 => _214._pool, 'optionalAccess', _215 => _215.assertStorageIsWritable, 'call', _216 => _216()]);
8539
8645
  if (_LiveObject.detectLargeObjects) {
8540
8646
  const data = {};
8541
8647
  for (const [key, value] of this.#synced) {
@@ -8735,1105 +8841,6 @@ var LiveObject = (_class2 = class _LiveObject extends AbstractCrdt {
8735
8841
  }
8736
8842
  }, _class2.__initStatic(), _class2);
8737
8843
 
8738
- // src/crdts/liveTextOps.ts
8739
- function attributesEqual(left, right) {
8740
- if (left === right) {
8741
- return true;
8742
- }
8743
- if (left === void 0 || right === void 0) {
8744
- return false;
8745
- }
8746
- const leftKeys = Object.keys(left);
8747
- const rightKeys = Object.keys(right);
8748
- if (leftKeys.length !== rightKeys.length) {
8749
- return false;
8750
- }
8751
- for (const key of leftKeys) {
8752
- if (left[key] !== right[key]) {
8753
- return false;
8754
- }
8755
- }
8756
- return true;
8757
- }
8758
- function cloneAttributes(attributes) {
8759
- return attributes === void 0 ? void 0 : freeze({ ...attributes });
8760
- }
8761
- function normalizeSegments(segments) {
8762
- const normalized = [];
8763
- for (const segment of segments) {
8764
- if (segment.text.length === 0) {
8765
- continue;
8766
- }
8767
- const last = normalized.at(-1);
8768
- const attributes = cloneAttributes(segment.attributes);
8769
- if (last !== void 0 && attributesEqual(last.attributes, attributes)) {
8770
- last.text += segment.text;
8771
- } else {
8772
- normalized.push({ text: segment.text, attributes });
8773
- }
8774
- }
8775
- return normalized;
8776
- }
8777
- function dataToSegments(data) {
8778
- return normalizeSegments(
8779
- data.map(([text, attributes]) => ({
8780
- text,
8781
- attributes
8782
- }))
8783
- );
8784
- }
8785
- function segmentsToData(segments) {
8786
- return segments.map(
8787
- (segment) => segment.attributes === void 0 ? [segment.text] : [segment.text, { ...segment.attributes }]
8788
- );
8789
- }
8790
- function textLength(segments) {
8791
- return segments.reduce((sum, segment) => sum + segment.text.length, 0);
8792
- }
8793
- function splitSegmentsAt(segments, index) {
8794
- const result = [];
8795
- let offset = 0;
8796
- for (const segment of segments) {
8797
- const end = offset + segment.text.length;
8798
- if (index > offset && index < end) {
8799
- const before2 = segment.text.slice(0, index - offset);
8800
- const after2 = segment.text.slice(index - offset);
8801
- result.push({ text: before2, attributes: segment.attributes });
8802
- result.push({ text: after2, attributes: segment.attributes });
8803
- } else {
8804
- result.push({ text: segment.text, attributes: segment.attributes });
8805
- }
8806
- offset = end;
8807
- }
8808
- return result;
8809
- }
8810
- function clipRange(index, length, contentLength) {
8811
- const clippedIndex = Math.max(0, Math.min(index, contentLength));
8812
- const clippedEnd = Math.max(
8813
- clippedIndex,
8814
- Math.min(index + length, contentLength)
8815
- );
8816
- return { index: clippedIndex, length: clippedEnd - clippedIndex };
8817
- }
8818
- function applyInsert(segments, index, text, attributes) {
8819
- if (text.length === 0) {
8820
- return normalizeSegments(segments);
8821
- }
8822
- const split = splitSegmentsAt(segments, index);
8823
- const result = [];
8824
- let offset = 0;
8825
- let inserted = false;
8826
- for (const segment of split) {
8827
- if (!inserted && offset === index) {
8828
- result.push({ text, attributes });
8829
- inserted = true;
8830
- }
8831
- result.push(segment);
8832
- offset += segment.text.length;
8833
- }
8834
- if (!inserted) {
8835
- result.push({ text, attributes });
8836
- }
8837
- return normalizeSegments(result);
8838
- }
8839
- function extractDeletedSegments(segments, index, length) {
8840
- const split = splitSegmentsAt(
8841
- splitSegmentsAt(segments, index),
8842
- index + length
8843
- );
8844
- const deleted = [];
8845
- let offset = 0;
8846
- for (const segment of split) {
8847
- const end = offset + segment.text.length;
8848
- if (offset >= index && end <= index + length) {
8849
- deleted.push({
8850
- text: segment.text,
8851
- attributes: segment.attributes
8852
- });
8853
- }
8854
- offset = end;
8855
- }
8856
- return normalizeSegments(deleted);
8857
- }
8858
- function applyDelete(segments, index, length) {
8859
- const deletedSegments = extractDeletedSegments(segments, index, length);
8860
- const split = splitSegmentsAt(
8861
- splitSegmentsAt(segments, index),
8862
- index + length
8863
- );
8864
- const result = [];
8865
- let offset = 0;
8866
- let deletedText = "";
8867
- for (const segment of split) {
8868
- const end = offset + segment.text.length;
8869
- if (offset >= index && end <= index + length) {
8870
- deletedText += segment.text;
8871
- } else {
8872
- result.push(segment);
8873
- }
8874
- offset = end;
8875
- }
8876
- return {
8877
- segments: normalizeSegments(result),
8878
- deletedText,
8879
- deletedSegments
8880
- };
8881
- }
8882
- function applyFormat(segments, index, length, attributes) {
8883
- const split = splitSegmentsAt(
8884
- splitSegmentsAt(segments, index),
8885
- index + length
8886
- );
8887
- const result = [];
8888
- let offset = 0;
8889
- for (const segment of split) {
8890
- const end = offset + segment.text.length;
8891
- if (offset >= index && end <= index + length) {
8892
- const nextAttributes = {
8893
- ..._nullishCoalesce(segment.attributes, () => ( {}))
8894
- };
8895
- for (const [key, value] of Object.entries(attributes)) {
8896
- if (value === null) {
8897
- delete nextAttributes[key];
8898
- } else {
8899
- nextAttributes[key] = value;
8900
- }
8901
- }
8902
- result.push({
8903
- text: segment.text,
8904
- attributes: Object.keys(nextAttributes).length === 0 ? void 0 : freeze(nextAttributes)
8905
- });
8906
- } else {
8907
- result.push(segment);
8908
- }
8909
- offset = end;
8910
- }
8911
- return normalizeSegments(result);
8912
- }
8913
- function formatReverseOperations(segments, index, length, patch) {
8914
- const split = splitSegmentsAt(
8915
- splitSegmentsAt(segments, index),
8916
- index + length
8917
- );
8918
- const result = [];
8919
- let offset = 0;
8920
- for (const segment of split) {
8921
- const end = offset + segment.text.length;
8922
- if (offset >= index && end <= index + length) {
8923
- const attributes = {};
8924
- for (const key of Object.keys(patch)) {
8925
- attributes[key] = _nullishCoalesce(_optionalChain([segment, 'access', _214 => _214.attributes, 'optionalAccess', _215 => _215[key]]), () => ( null));
8926
- }
8927
- result.push({
8928
- type: "format",
8929
- index: offset,
8930
- length: segment.text.length,
8931
- attributes
8932
- });
8933
- }
8934
- offset = end;
8935
- }
8936
- return result;
8937
- }
8938
- function mapIndexThroughOperation(index, op) {
8939
- if (op.type === "insert") {
8940
- return op.index <= index ? index + op.text.length : index;
8941
- } else if (op.type === "delete") {
8942
- if (op.index >= index) {
8943
- return index;
8944
- }
8945
- return Math.max(op.index, index - op.length);
8946
- } else {
8947
- return index;
8948
- }
8949
- }
8950
- function mapTextIndexThroughOperations(index, ops) {
8951
- let mapped = index;
8952
- for (const op of ops) {
8953
- mapped = mapIndexThroughOperation(mapped, op);
8954
- }
8955
- return mapped;
8956
- }
8957
- function inverseMapIndexThroughOperation(index, op) {
8958
- if (op.type === "insert") {
8959
- if (index <= op.index) {
8960
- return index;
8961
- }
8962
- return Math.max(op.index, index - op.text.length);
8963
- } else if (op.type === "delete") {
8964
- return op.index <= index ? index + op.length : index;
8965
- } else {
8966
- return index;
8967
- }
8968
- }
8969
- function inverseMapTextIndexThroughOperations(index, ops) {
8970
- let mapped = index;
8971
- for (let i = ops.length - 1; i >= 0; i--) {
8972
- mapped = inverseMapIndexThroughOperation(mapped, ops[i]);
8973
- }
8974
- return mapped;
8975
- }
8976
- function oppositeOrder(order) {
8977
- return order === "before" ? "after" : "before";
8978
- }
8979
- function mapIndexOverDelete(index, deleteIndex, deleteLength) {
8980
- if (deleteIndex >= index) {
8981
- return index;
8982
- }
8983
- return Math.max(deleteIndex, index - deleteLength);
8984
- }
8985
- function transformInsert(op, over, order) {
8986
- if (over.type === "insert") {
8987
- const shifts = over.index < op.index || over.index === op.index && order === "after";
8988
- return [shifts ? { ...op, index: op.index + over.text.length } : { ...op }];
8989
- } else if (over.type === "delete") {
8990
- return [
8991
- { ...op, index: mapIndexOverDelete(op.index, over.index, over.length) }
8992
- ];
8993
- } else {
8994
- return [{ ...op }];
8995
- }
8996
- }
8997
- function transformDelete(op, over) {
8998
- const start = op.index;
8999
- const end = op.index + op.length;
9000
- if (over.type === "insert") {
9001
- const at = over.index;
9002
- const len = over.text.length;
9003
- if (at <= start) {
9004
- return [{ ...op, index: start + len }];
9005
- }
9006
- if (at >= end) {
9007
- return [{ ...op }];
9008
- }
9009
- return [
9010
- { type: "delete", index: start, length: at - start },
9011
- { type: "delete", index: start + len, length: end - at }
9012
- ];
9013
- } else if (over.type === "delete") {
9014
- const newStart = mapIndexOverDelete(start, over.index, over.length);
9015
- const newEnd = mapIndexOverDelete(end, over.index, over.length);
9016
- return newEnd - newStart > 0 ? [{ type: "delete", index: newStart, length: newEnd - newStart }] : [];
9017
- } else {
9018
- return [{ ...op }];
9019
- }
9020
- }
9021
- function transformFormat(op, over, order) {
9022
- const start = op.index;
9023
- const end = op.index + op.length;
9024
- if (over.type === "insert") {
9025
- const at = over.index;
9026
- const len = over.text.length;
9027
- if (at <= start) {
9028
- return [{ ...op, index: start + len }];
9029
- }
9030
- if (at >= end) {
9031
- return [{ ...op }];
9032
- }
9033
- return [
9034
- {
9035
- type: "format",
9036
- index: start,
9037
- length: at - start,
9038
- attributes: op.attributes
9039
- },
9040
- {
9041
- type: "format",
9042
- index: at + len,
9043
- length: end - at,
9044
- attributes: op.attributes
9045
- }
9046
- ];
9047
- } else if (over.type === "delete") {
9048
- const newStart = mapIndexOverDelete(start, over.index, over.length);
9049
- const newEnd = mapIndexOverDelete(end, over.index, over.length);
9050
- return newEnd - newStart > 0 ? [
9051
- {
9052
- type: "format",
9053
- index: newStart,
9054
- length: newEnd - newStart,
9055
- attributes: op.attributes
9056
- }
9057
- ] : [];
9058
- } else {
9059
- if (order === "after") {
9060
- return [{ ...op }];
9061
- }
9062
- const overlapStart = Math.max(start, over.index);
9063
- const overlapEnd = Math.min(end, over.index + over.length);
9064
- if (overlapStart >= overlapEnd) {
9065
- return [{ ...op }];
9066
- }
9067
- const hasConflict = Object.keys(op.attributes).some(
9068
- (key) => key in over.attributes
9069
- );
9070
- if (!hasConflict) {
9071
- return [{ ...op }];
9072
- }
9073
- const reduced = {};
9074
- for (const [key, value] of Object.entries(op.attributes)) {
9075
- if (!(key in over.attributes)) {
9076
- reduced[key] = value;
9077
- }
9078
- }
9079
- const pieces = [];
9080
- if (start < overlapStart) {
9081
- pieces.push({
9082
- type: "format",
9083
- index: start,
9084
- length: overlapStart - start,
9085
- attributes: op.attributes
9086
- });
9087
- }
9088
- if (Object.keys(reduced).length > 0) {
9089
- pieces.push({
9090
- type: "format",
9091
- index: overlapStart,
9092
- length: overlapEnd - overlapStart,
9093
- attributes: reduced
9094
- });
9095
- }
9096
- if (overlapEnd < end) {
9097
- pieces.push({
9098
- type: "format",
9099
- index: overlapEnd,
9100
- length: end - overlapEnd,
9101
- attributes: op.attributes
9102
- });
9103
- }
9104
- return pieces;
9105
- }
9106
- }
9107
- function transformSingle(op, over, order) {
9108
- switch (op.type) {
9109
- case "insert":
9110
- return transformInsert(op, over, order);
9111
- case "delete":
9112
- return transformDelete(op, over);
9113
- case "format":
9114
- return transformFormat(op, over, order);
9115
- }
9116
- }
9117
- function transformTextOperationsX(a, b, order) {
9118
- if (a.length === 0 || b.length === 0) {
9119
- return [[...a], [...b]];
9120
- }
9121
- if (a.length === 1 && b.length === 1) {
9122
- return [
9123
- transformSingle(a[0], b[0], order),
9124
- transformSingle(b[0], a[0], oppositeOrder(order))
9125
- ];
9126
- }
9127
- if (a.length > 1) {
9128
- const [headA1, b1] = transformTextOperationsX([a[0]], b, order);
9129
- const [restA1, b2] = transformTextOperationsX(a.slice(1), b1, order);
9130
- return [[...headA1, ...restA1], b2];
9131
- }
9132
- const [a1, headB1] = transformTextOperationsX(a, [b[0]], order);
9133
- const [a2, restB1] = transformTextOperationsX(a1, b.slice(1), order);
9134
- return [a2, [...headB1, ...restB1]];
9135
- }
9136
- function transformTextOperations(ops, over, order) {
9137
- return transformTextOperationsX(ops, over, order)[0];
9138
- }
9139
- function textOperationsEqual(a, b) {
9140
- return a === b || stableStringify(a) === stableStringify(b);
9141
- }
9142
- function applyTextOperationsToSegments(segments, ops) {
9143
- let next = [...segments];
9144
- for (const op of ops) {
9145
- if (op.type === "insert") {
9146
- const index = Math.max(0, Math.min(op.index, textLength(next)));
9147
- next = applyInsert(next, index, op.text, op.attributes);
9148
- } else if (op.type === "delete") {
9149
- const index = Math.max(0, Math.min(op.index, textLength(next)));
9150
- const clipped = clipRange(index, op.length, textLength(next));
9151
- next = applyDelete(next, clipped.index, clipped.length).segments;
9152
- } else {
9153
- const index = Math.max(0, Math.min(op.index, textLength(next)));
9154
- const clipped = clipRange(index, op.length, textLength(next));
9155
- next = applyFormat(next, clipped.index, clipped.length, op.attributes);
9156
- }
9157
- }
9158
- return next;
9159
- }
9160
- function applyLiveTextOperations(data, ops) {
9161
- return segmentsToData(
9162
- applyTextOperationsToSegments(dataToSegments(data), ops)
9163
- );
9164
- }
9165
- function invertTextOperations(segments, ops) {
9166
- let shadow = [...segments];
9167
- const reverse = [];
9168
- for (const op of ops) {
9169
- if (op.type === "insert") {
9170
- shadow = applyInsert(shadow, op.index, op.text, op.attributes);
9171
- reverse.unshift({
9172
- type: "delete",
9173
- index: op.index,
9174
- length: op.text.length
9175
- });
9176
- } else if (op.type === "delete") {
9177
- const deletedSegments = extractDeletedSegments(
9178
- shadow,
9179
- op.index,
9180
- op.length
9181
- );
9182
- shadow = applyDelete(shadow, op.index, op.length).segments;
9183
- const inserts = [];
9184
- let insertIndex = op.index;
9185
- for (const segment of deletedSegments) {
9186
- inserts.push({
9187
- type: "insert",
9188
- index: insertIndex,
9189
- text: segment.text,
9190
- attributes: segment.attributes
9191
- });
9192
- insertIndex += segment.text.length;
9193
- }
9194
- for (let index = inserts.length - 1; index >= 0; index--) {
9195
- reverse.unshift(inserts[index]);
9196
- }
9197
- } else {
9198
- const inverse = formatReverseOperations(
9199
- shadow,
9200
- op.index,
9201
- op.length,
9202
- op.attributes
9203
- );
9204
- shadow = applyFormat(shadow, op.index, op.length, op.attributes);
9205
- reverse.unshift(...inverse.reverse());
9206
- }
9207
- }
9208
- return reverse;
9209
- }
9210
-
9211
- // src/crdts/LiveText.ts
9212
- var ACCEPTED_OPS_HISTORY_LIMIT = 1e3;
9213
- var LiveText = class _LiveText extends AbstractCrdt {
9214
- /** The local document: #confirmed ⊕ #inFlightOps ⊕ #queuedOps. */
9215
- #segments;
9216
- /** The server-confirmed document (only authoritative ops applied). */
9217
- #confirmed;
9218
- #version;
9219
- /** The op currently awaiting server acknowledgement (at most one). */
9220
- #inFlightOpId;
9221
- /** Its ops, continuously re-expressed against current server state. */
9222
- #inFlightOps = [];
9223
- /** Local edits made while an op is in flight; sent after the ack. */
9224
- #queuedOps = [];
9225
- #acceptedOps = [];
9226
- /**
9227
- * Creates a new LiveText document.
9228
- *
9229
- * @param textOrData Initial plain text, or an array of `[text]` /
9230
- * `[text, attributes]` segments. Defaults to an empty document.
9231
- *
9232
- * @example
9233
- * new LiveText();
9234
- * new LiveText("Hello world");
9235
- * new LiveText([["Hello ", { bold: true }], ["world"]]);
9236
- */
9237
- constructor(textOrData = "", version = 0) {
9238
- super();
9239
- this.#segments = typeof textOrData === "string" ? textOrData.length === 0 ? [] : [{ text: textOrData }] : dataToSegments(textOrData);
9240
- this.#confirmed = [...this.#segments];
9241
- this.#version = version;
9242
- Object.defineProperty(this, kInternal, {
9243
- value: {
9244
- encodeIndex: (localIndex) => this.#encodeIndex(localIndex),
9245
- decodeIndex: (index, fromVersion) => this.#decodeIndex(index, fromVersion)
9246
- },
9247
- enumerable: false
9248
- });
9249
- }
9250
- get version() {
9251
- return this.#version;
9252
- }
9253
- get length() {
9254
- return textLength(this.#segments);
9255
- }
9256
- /** @internal */
9257
- static _deserialize([id, item], _parentToChildren, pool) {
9258
- const text = new _LiveText(item.data, item.version);
9259
- text._attach(id, pool);
9260
- return text;
9261
- }
9262
- /** @internal */
9263
- _toOps(parentId, parentKey) {
9264
- if (this._id === void 0) {
9265
- throw new Error("Cannot serialize LiveText if it is not attached");
9266
- }
9267
- return [
9268
- {
9269
- type: OpCode.CREATE_TEXT,
9270
- id: this._id,
9271
- parentId,
9272
- parentKey,
9273
- data: this.toJSON(),
9274
- version: this.#version
9275
- }
9276
- ];
9277
- }
9278
- /** @internal */
9279
- _serialize() {
9280
- if (this.parent.type !== "HasParent") {
9281
- throw new Error("Cannot serialize LiveText if parent is missing");
9282
- }
9283
- return {
9284
- type: CrdtType.TEXT,
9285
- parentId: nn(this.parent.node._id, "Parent node expected to have ID"),
9286
- parentKey: this.parent.key,
9287
- data: this.toJSON(),
9288
- version: this.#version
9289
- };
9290
- }
9291
- /** @internal */
9292
- _attachChild(_op) {
9293
- throw new Error("LiveText cannot contain child nodes");
9294
- }
9295
- /** @internal */
9296
- _detachChild(_crdt) {
9297
- throw new Error("LiveText cannot contain child nodes");
9298
- }
9299
- /** @internal */
9300
- _apply(op, isLocal) {
9301
- if (op.type !== OpCode.UPDATE_TEXT) {
9302
- return super._apply(op, isLocal);
9303
- }
9304
- if (isLocal) {
9305
- return this.#applyLocal(op);
9306
- }
9307
- if (op.opId !== void 0 && op.opId === this.#inFlightOpId) {
9308
- return this.#applyAck(op);
9309
- }
9310
- if (op.opId !== void 0 && this.#acceptedOps.some((entry) => entry.opId === op.opId)) {
9311
- this.#version = Math.max(this.#version, _nullishCoalesce(op.version, () => ( op.baseVersion + 1)));
9312
- return { modified: false };
9313
- }
9314
- return this.#applyRemote(op);
9315
- }
9316
- /**
9317
- * Inserts text at the given index.
9318
- *
9319
- * @param index Character index at which to insert. Values outside the
9320
- * document range are clipped.
9321
- * @param text Text to insert.
9322
- * @param attributes Optional inline attributes for the inserted text.
9323
- *
9324
- * @example
9325
- * const text = new LiveText("Hello");
9326
- * text.insert(5, " world");
9327
- * text.insert(0, "Say: ", { italic: true });
9328
- */
9329
- insert(index, text, attributes) {
9330
- const clippedIndex = Math.max(0, Math.min(index, this.length));
9331
- this.#dispatch([{ type: "insert", index: clippedIndex, text, attributes }]);
9332
- }
9333
- /**
9334
- * Deletes `length` characters starting at `index`.
9335
- *
9336
- * @example
9337
- * const text = new LiveText("Hello world");
9338
- * text.delete(5, 6); // "Hello"
9339
- */
9340
- delete(index, length) {
9341
- const clipped = clipRange(index, length, this.length);
9342
- if (clipped.length === 0) {
9343
- return;
9344
- }
9345
- this.#dispatch([
9346
- { type: "delete", index: clipped.index, length: clipped.length }
9347
- ]);
9348
- }
9349
- /**
9350
- * Replaces a range of text with new text.
9351
- *
9352
- * @example
9353
- * const text = new LiveText("Hello world");
9354
- * text.replace(0, 5, "Hi"); // "Hi world"
9355
- */
9356
- replace(index, length, text, attributes) {
9357
- const clipped = clipRange(index, length, this.length);
9358
- const ops = [];
9359
- if (clipped.length > 0) {
9360
- ops.push({
9361
- type: "delete",
9362
- index: clipped.index,
9363
- length: clipped.length
9364
- });
9365
- }
9366
- if (text.length > 0) {
9367
- ops.push({ type: "insert", index: clipped.index, text, attributes });
9368
- }
9369
- this.#dispatch(ops);
9370
- }
9371
- /**
9372
- * Encode a local-document index (an offset into this LiveText's current
9373
- * #segments, which CodeMirror or any consumer mirrors as its document)
9374
- * into server-confirmed coordinates suitable for broadcasting to peers via
9375
- * presence or any other side channel.
9376
- *
9377
- * The returned index is in this LiveText's current #confirmed coordinates
9378
- * — that is, with this client's local pending ops inverse-mapped out.
9379
- * Pair it with the current {@link LiveText.version} when sending so the
9380
- * receiver can call {@link PrivateLiveTextApi.decodeIndex} to land the
9381
- * position in their own local document coordinates regardless of their
9382
- * private pending ops.
9383
- *
9384
- * Index ambiguity at boundaries is resolved by an inverse-of-forward
9385
- * convention: a position at or before a local insertion is reported as
9386
- * the position right before the insertion in #confirmed; a position past
9387
- * the insertion shifts left by the insertion's length. Positions inside
9388
- * an own-pending insertion collapse to the insertion point.
9389
- */
9390
- #encodeIndex(localIndex) {
9391
- let mapped = Math.max(0, Math.min(localIndex, this.length));
9392
- mapped = inverseMapTextIndexThroughOperations(mapped, this.#queuedOps);
9393
- mapped = inverseMapTextIndexThroughOperations(mapped, this.#inFlightOps);
9394
- return mapped;
9395
- }
9396
- /**
9397
- * Decode an `(index, fromVersion)` pair produced by
9398
- * {@link PrivateLiveTextApi.encodeIndex} — typically on a peer — into an
9399
- * offset in this LiveText's current local document (an index suitable for
9400
- * placing a CodeMirror marker, an annotation anchor, or anything else that
9401
- * lives over #segments).
9402
- *
9403
- * Composes the accepted ops applied since `fromVersion` (drawn from
9404
- * #acceptedOps in locally-applied form) with this client's own local
9405
- * pending ops, in that order. The result is in current #segments
9406
- * coordinates.
9407
- *
9408
- * Returns `null` when the position cannot be decoded against the current
9409
- * state:
9410
- * - `fromVersion` is greater than this LiveText's current version: the
9411
- * peer is ahead of us. The caller should park the message and retry
9412
- * after more accepted ops arrive.
9413
- * - `fromVersion` falls outside the retained accepted-ops history. This
9414
- * only happens after very long-lived disconnections; the caller can
9415
- * fall back to using the raw index and letting subsequent local
9416
- * transactions map it (with bounded drift).
9417
- */
9418
- #decodeIndex(index, fromVersion) {
9419
- if (fromVersion > this.#version) {
9420
- return null;
9421
- }
9422
- if (fromVersion < this.#version) {
9423
- const oldest = _optionalChain([this, 'access', _216 => _216.#acceptedOps, 'access', _217 => _217[0], 'optionalAccess', _218 => _218.version]);
9424
- if (oldest === void 0 || oldest > fromVersion + 1) {
9425
- return null;
9426
- }
9427
- }
9428
- let mapped = index;
9429
- for (const entry of this.#acceptedOps) {
9430
- if (entry.version <= fromVersion) continue;
9431
- if (entry.version > this.#version) break;
9432
- if (entry.ops.length === 0) continue;
9433
- mapped = mapTextIndexThroughOperations(mapped, entry.ops);
9434
- }
9435
- mapped = mapTextIndexThroughOperations(mapped, this.#inFlightOps);
9436
- mapped = mapTextIndexThroughOperations(mapped, this.#queuedOps);
9437
- return Math.max(0, Math.min(mapped, this.length));
9438
- }
9439
- /**
9440
- * Applies or removes inline attributes on a range of text.
9441
- *
9442
- * Set an attribute to `null` to remove it from the range.
9443
- *
9444
- * @example
9445
- * const text = new LiveText("Hello world");
9446
- * text.format(0, 5, { bold: true });
9447
- * text.format(0, 5, { bold: null });
9448
- */
9449
- format(index, length, attributes) {
9450
- const clipped = clipRange(index, length, this.length);
9451
- if (clipped.length === 0) {
9452
- return;
9453
- }
9454
- this.#dispatch([
9455
- {
9456
- type: "format",
9457
- index: clipped.index,
9458
- length: clipped.length,
9459
- attributes
9460
- }
9461
- ]);
9462
- }
9463
- /** Local edits made through the public API. */
9464
- #dispatch(ops) {
9465
- if (ops.length === 0) {
9466
- return;
9467
- }
9468
- _optionalChain([this, 'access', _219 => _219._pool, 'optionalAccess', _220 => _220.assertStorageIsWritable, 'call', _221 => _221()]);
9469
- const attached = this._pool !== void 0 && this._id !== void 0;
9470
- const reverse = attached ? this.#invertOperations(ops) : [];
9471
- const changes = this.#applyOperationsLocally(ops);
9472
- if (!attached) {
9473
- return;
9474
- }
9475
- const pool = nn(this._pool);
9476
- const id = nn(this._id);
9477
- const updates = /* @__PURE__ */ new Map([
9478
- [
9479
- id,
9480
- {
9481
- type: "LiveText",
9482
- node: this,
9483
- version: this.#version,
9484
- updates: changes
9485
- }
9486
- ]
9487
- ]);
9488
- if (this.#inFlightOpId === void 0) {
9489
- const opId = pool.generateOpId();
9490
- this.#inFlightOpId = opId;
9491
- this.#inFlightOps = [...ops];
9492
- pool.dispatch(
9493
- [
9494
- {
9495
- type: OpCode.UPDATE_TEXT,
9496
- id,
9497
- opId,
9498
- baseVersion: this.#version,
9499
- ops: [...ops]
9500
- }
9501
- ],
9502
- reverse,
9503
- updates
9504
- );
9505
- } else {
9506
- this.#queuedOps.push(...ops);
9507
- pool.dispatch([], reverse, updates, { clearRedoStack: true });
9508
- }
9509
- }
9510
- /**
9511
- * A local replay of an existing wire op: an undo/redo frame, or an
9512
- * unacknowledged op re-sent after a reconnect.
9513
- */
9514
- #applyLocal(op) {
9515
- const mutableOp = op;
9516
- if (op.opId !== void 0 && op.opId === this.#inFlightOpId) {
9517
- this.#inFlightOps = [...this.#inFlightOps, ...this.#queuedOps];
9518
- this.#queuedOps = [];
9519
- mutableOp.baseVersion = this.#version;
9520
- mutableOp.ops = [...this.#inFlightOps];
9521
- return { modified: false };
9522
- }
9523
- let ops = op.ops;
9524
- for (const entry of this.#acceptedOps) {
9525
- if (entry.version > op.baseVersion && entry.ops.length > 0) {
9526
- ops = transformTextOperations(ops, entry.ops, "after");
9527
- }
9528
- }
9529
- const reverse = this.#invertOperations(ops);
9530
- const changes = this.#applyOperationsLocally(ops);
9531
- if (this.#inFlightOpId === void 0 && ops.length > 0) {
9532
- this.#inFlightOpId = nn(op.opId, "Local ops must have an opId");
9533
- this.#inFlightOps = [...ops];
9534
- mutableOp.baseVersion = this.#version;
9535
- mutableOp.ops = [...ops];
9536
- } else {
9537
- this.#queuedOps.push(...ops);
9538
- mutableOp.baseVersion = this.#version;
9539
- mutableOp.ops = [];
9540
- }
9541
- if (changes.length === 0) {
9542
- return { modified: false };
9543
- }
9544
- return {
9545
- reverse,
9546
- modified: {
9547
- type: "LiveText",
9548
- node: this,
9549
- version: this.#version,
9550
- updates: changes
9551
- }
9552
- };
9553
- }
9554
- /** Server acknowledgement of our in-flight op. */
9555
- #applyAck(op) {
9556
- const ackedVersion = _nullishCoalesce(op.version, () => ( Math.max(this.#version, op.baseVersion + 1)));
9557
- const predicted = this.#inFlightOps;
9558
- const opId = this.#inFlightOpId;
9559
- this.#confirmed = applyTextOperationsToSegments(this.#confirmed, op.ops);
9560
- this.#inFlightOpId = void 0;
9561
- this.#inFlightOps = [];
9562
- let appliedOps = [];
9563
- let result = { modified: false };
9564
- if (!textOperationsEqual(op.ops, predicted)) {
9565
- error2(
9566
- "LiveText: acknowledgement did not match the local prediction; resynchronizing"
9567
- );
9568
- const rebuilt = this.#rebuildLocalFromConfirmed();
9569
- appliedOps = rebuilt.appliedOps;
9570
- if (rebuilt.changes.length > 0) {
9571
- result = {
9572
- reverse: [],
9573
- modified: {
9574
- type: "LiveText",
9575
- node: this,
9576
- version: ackedVersion,
9577
- updates: rebuilt.changes
9578
- }
9579
- };
9580
- }
9581
- }
9582
- this.#version = Math.max(this.#version, ackedVersion);
9583
- this.#recordAccepted(ackedVersion, appliedOps, opId);
9584
- this.#flushQueued();
9585
- return result;
9586
- }
9587
- /** An accepted op from another client (or a server-fabricated fix op). */
9588
- #applyRemote(op) {
9589
- const version = _nullishCoalesce(op.version, () => ( this.#version + 1));
9590
- this.#confirmed = applyTextOperationsToSegments(this.#confirmed, op.ops);
9591
- const [overInFlight, inFlight] = transformTextOperationsX(
9592
- op.ops,
9593
- this.#inFlightOps,
9594
- "before"
9595
- );
9596
- const [applied, queued] = transformTextOperationsX(
9597
- overInFlight,
9598
- this.#queuedOps,
9599
- "before"
9600
- );
9601
- this.#inFlightOps = inFlight;
9602
- this.#queuedOps = queued;
9603
- this.#recordAccepted(version, applied, op.opId);
9604
- if (applied.length === 0) {
9605
- this.#version = Math.max(this.#version, version);
9606
- return { modified: false };
9607
- }
9608
- const reverse = this.#invertOperations(applied);
9609
- const changes = this.#applyOperationsLocally(applied);
9610
- this.#version = Math.max(this.#version, version);
9611
- return {
9612
- reverse,
9613
- modified: {
9614
- type: "LiveText",
9615
- node: this,
9616
- version: this.#version,
9617
- updates: changes
9618
- }
9619
- };
9620
- }
9621
- /** Send the queued ops as the next in-flight op (after an ack). */
9622
- #flushQueued() {
9623
- if (this.#queuedOps.length === 0 || this._pool === void 0 || this._id === void 0) {
9624
- return;
9625
- }
9626
- const opId = this._pool.generateOpId();
9627
- this.#inFlightOpId = opId;
9628
- this.#inFlightOps = this.#queuedOps;
9629
- this.#queuedOps = [];
9630
- this._pool.dispatch(
9631
- [
9632
- {
9633
- type: OpCode.UPDATE_TEXT,
9634
- id: this._id,
9635
- opId,
9636
- baseVersion: this.#version,
9637
- ops: [...this.#inFlightOps]
9638
- }
9639
- ],
9640
- [],
9641
- /* @__PURE__ */ new Map(),
9642
- // The local content was already applied (and made undoable) when the
9643
- // edits happened; this is purely an outbound flush.
9644
- { clearRedoStack: false }
9645
- );
9646
- }
9647
- /**
9648
- * Rebuild the local document as confirmed ⊕ queued ops, returning the
9649
- * coarse delta that was applied. Only used by defensive recovery paths.
9650
- */
9651
- #rebuildLocalFromConfirmed() {
9652
- const before2 = this.#segments;
9653
- const after2 = applyTextOperationsToSegments(this.#confirmed, [
9654
- ...this.#inFlightOps,
9655
- ...this.#queuedOps
9656
- ]);
9657
- if (stableStringify(segmentsToData(before2)) === stableStringify(segmentsToData(after2))) {
9658
- this.#segments = after2;
9659
- return { appliedOps: [], changes: [] };
9660
- }
9661
- const beforeText = before2.map((segment) => segment.text).join("");
9662
- this.#segments = after2;
9663
- this.invalidate();
9664
- const appliedOps = [];
9665
- const changes = [];
9666
- if (beforeText.length > 0) {
9667
- appliedOps.push({ type: "delete", index: 0, length: beforeText.length });
9668
- changes.push({
9669
- type: "delete",
9670
- index: 0,
9671
- length: beforeText.length,
9672
- deletedText: beforeText
9673
- });
9674
- }
9675
- let index = 0;
9676
- for (const segment of after2) {
9677
- appliedOps.push({
9678
- type: "insert",
9679
- index,
9680
- text: segment.text,
9681
- attributes: segment.attributes
9682
- });
9683
- changes.push({
9684
- type: "insert",
9685
- index,
9686
- text: segment.text,
9687
- attributes: segment.attributes
9688
- });
9689
- index += segment.text.length;
9690
- }
9691
- return { appliedOps, changes };
9692
- }
9693
- /**
9694
- * Reconcile this node against an authoritative storage snapshot (e.g.
9695
- * after a reconnect). The confirmed state and version are replaced by the
9696
- * snapshot's; pending (in-flight + queued) ops are preserved on top and
9697
- * will be re-sent by the offline-ops replay.
9698
- *
9699
- * @internal
9700
- */
9701
- _resyncText(data, version) {
9702
- this.#confirmed = dataToSegments(data);
9703
- this.#version = version;
9704
- this.#acceptedOps = [];
9705
- const rebuilt = this.#rebuildLocalFromConfirmed();
9706
- if (rebuilt.changes.length === 0) {
9707
- return void 0;
9708
- }
9709
- return {
9710
- type: "LiveText",
9711
- node: this,
9712
- version: this.#version,
9713
- updates: rebuilt.changes
9714
- };
9715
- }
9716
- /**
9717
- * Called when the server rejected one of our ops. Drops all pending state
9718
- * for this node (edits queued behind a rejected op cannot be trusted
9719
- * either); the room follows up with a storage resync.
9720
- *
9721
- * @internal
9722
- */
9723
- _rejectPendingOp(opId) {
9724
- if (opId !== this.#inFlightOpId) {
9725
- return;
9726
- }
9727
- this.#inFlightOpId = void 0;
9728
- this.#inFlightOps = [];
9729
- this.#queuedOps = [];
9730
- }
9731
- #recordAccepted(version, ops, opId) {
9732
- if (this.#acceptedOps.some((entry) => entry.version === version)) {
9733
- return;
9734
- }
9735
- this.#acceptedOps.push({ version, opId, ops: [...ops] });
9736
- this.#acceptedOps.sort((left, right) => left.version - right.version);
9737
- if (this.#acceptedOps.length > ACCEPTED_OPS_HISTORY_LIMIT) {
9738
- this.#acceptedOps.splice(
9739
- 0,
9740
- this.#acceptedOps.length - ACCEPTED_OPS_HISTORY_LIMIT
9741
- );
9742
- }
9743
- }
9744
- #applyOperationsLocally(ops) {
9745
- const changes = [];
9746
- for (const op of ops) {
9747
- if (op.type === "insert") {
9748
- this.#segments = applyInsert(
9749
- this.#segments,
9750
- op.index,
9751
- op.text,
9752
- op.attributes
9753
- );
9754
- changes.push({
9755
- type: "insert",
9756
- index: op.index,
9757
- text: op.text,
9758
- attributes: op.attributes
9759
- });
9760
- } else if (op.type === "delete") {
9761
- const result = applyDelete(this.#segments, op.index, op.length);
9762
- this.#segments = result.segments;
9763
- changes.push({
9764
- type: "delete",
9765
- index: op.index,
9766
- length: op.length,
9767
- deletedText: result.deletedText
9768
- });
9769
- } else {
9770
- this.#segments = applyFormat(
9771
- this.#segments,
9772
- op.index,
9773
- op.length,
9774
- op.attributes
9775
- );
9776
- changes.push({
9777
- type: "format",
9778
- index: op.index,
9779
- length: op.length,
9780
- attributes: op.attributes
9781
- });
9782
- }
9783
- }
9784
- this.invalidate();
9785
- return changes;
9786
- }
9787
- #invertOperations(ops) {
9788
- return [
9789
- {
9790
- type: OpCode.UPDATE_TEXT,
9791
- id: nn(this._id),
9792
- baseVersion: this.#version,
9793
- ops: invertTextOperations(this.#segments, ops)
9794
- }
9795
- ];
9796
- }
9797
- /** Returns the plain text content without attributes. Equivalent to joining the text from each segment in {@link LiveText.toJSON}. */
9798
- toString() {
9799
- return this.#segments.map((segment) => segment.text).join("");
9800
- }
9801
- /**
9802
- * Returns a JSON-compatible snapshot of the document as a {@link LiveTextData}
9803
- * array.
9804
- *
9805
- * @example
9806
- * new LiveText([["Hello ", { bold: true }], ["world"]]).toJSON();
9807
- * // [["Hello ", { bold: true }], ["world"]]
9808
- */
9809
- toJSON() {
9810
- return super.toJSON();
9811
- }
9812
- /** @internal */
9813
- _toJSON() {
9814
- return segmentsToData(this.#segments);
9815
- }
9816
- /** @internal */
9817
- _toTreeNode(key) {
9818
- return {
9819
- type: "LiveText",
9820
- id: _nullishCoalesce(this._id, () => ( nanoid())),
9821
- key,
9822
- payload: [
9823
- {
9824
- type: "Json",
9825
- id: `${_nullishCoalesce(this._id, () => ( nanoid()))}:text`,
9826
- key: "text",
9827
- payload: this.toString()
9828
- }
9829
- ]
9830
- };
9831
- }
9832
- clone() {
9833
- return new _LiveText(this.toJSON(), this.#version);
9834
- }
9835
- };
9836
-
9837
8844
  // src/crdts/liveblocks-helpers.ts
9838
8845
  function creationOpToLiveNode(op) {
9839
8846
  return lsonToLiveNode(creationOpToLson(op));
@@ -9848,8 +8855,6 @@ function creationOpToLson(op) {
9848
8855
  return new LiveMap();
9849
8856
  case OpCode.CREATE_LIST:
9850
8857
  return new LiveList([]);
9851
- case OpCode.CREATE_TEXT:
9852
- return new LiveText(op.data, op.version);
9853
8858
  default:
9854
8859
  return assertNever(op, "Unknown creation Op");
9855
8860
  }
@@ -9872,8 +8877,6 @@ function deserialize(node, parentToChildren, pool) {
9872
8877
  return LiveMap._deserialize(node, parentToChildren, pool);
9873
8878
  } else if (isRegisterStorageNode(node)) {
9874
8879
  return LiveRegister._deserialize(node, parentToChildren, pool);
9875
- } else if (isTextStorageNode(node)) {
9876
- return LiveText._deserialize(node, parentToChildren, pool);
9877
8880
  } else {
9878
8881
  throw new Error("Unexpected CRDT type");
9879
8882
  }
@@ -9887,14 +8890,12 @@ function deserializeToLson(node, parentToChildren, pool) {
9887
8890
  return LiveMap._deserialize(node, parentToChildren, pool);
9888
8891
  } else if (isRegisterStorageNode(node)) {
9889
8892
  return node[1].data;
9890
- } else if (isTextStorageNode(node)) {
9891
- return LiveText._deserialize(node, parentToChildren, pool);
9892
8893
  } else {
9893
8894
  throw new Error("Unexpected CRDT type");
9894
8895
  }
9895
8896
  }
9896
8897
  function isLiveStructure(value) {
9897
- return isLiveList(value) || isLiveMap(value) || isLiveObject(value) || isLiveText(value);
8898
+ return isLiveList(value) || isLiveMap(value) || isLiveObject(value);
9898
8899
  }
9899
8900
  function isLiveNode(value) {
9900
8901
  return isLiveStructure(value) || isLiveRegister(value);
@@ -9908,9 +8909,6 @@ function isLiveMap(value) {
9908
8909
  function isLiveObject(value) {
9909
8910
  return value instanceof LiveObject;
9910
8911
  }
9911
- function isLiveText(value) {
9912
- return value instanceof LiveText;
9913
- }
9914
8912
  function isLiveRegister(value) {
9915
8913
  return value instanceof LiveRegister;
9916
8914
  }
@@ -9920,14 +8918,14 @@ function cloneLson(value) {
9920
8918
  function liveNodeToLson(obj) {
9921
8919
  if (obj instanceof LiveRegister) {
9922
8920
  return obj.data;
9923
- } else if (obj instanceof LiveList || obj instanceof LiveMap || obj instanceof LiveObject || obj instanceof LiveText) {
8921
+ } else if (obj instanceof LiveList || obj instanceof LiveMap || obj instanceof LiveObject) {
9924
8922
  return obj;
9925
8923
  } else {
9926
8924
  return assertNever(obj, "Unknown AbstractCrdt");
9927
8925
  }
9928
8926
  }
9929
8927
  function lsonToLiveNode(value) {
9930
- if (value instanceof LiveObject || value instanceof LiveMap || value instanceof LiveList || value instanceof LiveText) {
8928
+ if (value instanceof LiveObject || value instanceof LiveMap || value instanceof LiveList) {
9931
8929
  return value;
9932
8930
  } else {
9933
8931
  return new LiveRegister(value);
@@ -10070,16 +9068,6 @@ function diffNodeMap(prev, next) {
10070
9068
  parentKey: crdt.parentKey
10071
9069
  });
10072
9070
  break;
10073
- case CrdtType.TEXT:
10074
- ops.push({
10075
- type: OpCode.CREATE_TEXT,
10076
- id,
10077
- parentId: crdt.parentId,
10078
- parentKey: crdt.parentKey,
10079
- data: crdt.data,
10080
- version: crdt.version
10081
- });
10082
- break;
10083
9071
  }
10084
9072
  }
10085
9073
  });
@@ -10112,43 +9100,19 @@ function mergeListStorageUpdates(first, second) {
10112
9100
  updates: updates.concat(second.updates)
10113
9101
  };
10114
9102
  }
10115
- function mergeTextStorageUpdates(first, second) {
10116
- return {
10117
- ...second,
10118
- updates: first.updates.concat(second.updates)
10119
- };
10120
- }
10121
9103
  function mergeStorageUpdates(first, second) {
10122
9104
  if (first === void 0) {
10123
9105
  return second;
10124
9106
  }
10125
- let merged;
10126
9107
  if (first.type === "LiveObject" && second.type === "LiveObject") {
10127
- merged = mergeObjectStorageUpdates(first, second);
9108
+ return mergeObjectStorageUpdates(first, second);
10128
9109
  } else if (first.type === "LiveMap" && second.type === "LiveMap") {
10129
- merged = mergeMapStorageUpdates(first, second);
9110
+ return mergeMapStorageUpdates(first, second);
10130
9111
  } else if (first.type === "LiveList" && second.type === "LiveList") {
10131
- merged = mergeListStorageUpdates(first, second);
10132
- } else if (first.type === "LiveText" && second.type === "LiveText") {
10133
- merged = mergeTextStorageUpdates(first, second);
9112
+ return mergeListStorageUpdates(first, second);
10134
9113
  } else {
10135
- merged = second;
10136
- }
10137
- const sa = first[kStorageUpdateSource];
10138
- const sb = second[kStorageUpdateSource];
10139
- if (sa !== void 0 || sb !== void 0) {
10140
- if (_optionalChain([sa, 'optionalAccess', _222 => _222.origin]) === "remote" || _optionalChain([sb, 'optionalAccess', _223 => _223.origin]) === "remote") {
10141
- merged[kStorageUpdateSource] = { origin: "remote" };
10142
- } else if (_optionalChain([sa, 'optionalAccess', _224 => _224.via]) === "history" || _optionalChain([sb, 'optionalAccess', _225 => _225.via]) === "history") {
10143
- const historySource = _optionalChain([sb, 'optionalAccess', _226 => _226.via]) === "history" ? sb : _optionalChain([sa, 'optionalAccess', _227 => _227.via]) === "history" ? sa : void 0;
10144
- if (_optionalChain([historySource, 'optionalAccess', _228 => _228.via]) === "history") {
10145
- merged[kStorageUpdateSource] = historySource;
10146
- }
10147
- } else {
10148
- merged[kStorageUpdateSource] = { origin: "local", via: "mutation" };
10149
- }
10150
9114
  }
10151
- return merged;
9115
+ return second;
10152
9116
  }
10153
9117
 
10154
9118
  // src/devtools/bridge.ts
@@ -10164,7 +9128,7 @@ function sendToPanel(message, options) {
10164
9128
  ...message,
10165
9129
  source: "liveblocks-devtools-client"
10166
9130
  };
10167
- if (!(_optionalChain([options, 'optionalAccess', _229 => _229.force]) || _bridgeActive)) {
9131
+ if (!(_optionalChain([options, 'optionalAccess', _217 => _217.force]) || _bridgeActive)) {
10168
9132
  return;
10169
9133
  }
10170
9134
  window.postMessage(fullMsg, "*");
@@ -10172,7 +9136,7 @@ function sendToPanel(message, options) {
10172
9136
  var eventSource = makeEventSource();
10173
9137
  if (process.env.NODE_ENV !== "production" && typeof window !== "undefined") {
10174
9138
  window.addEventListener("message", (event) => {
10175
- if (event.source === window && _optionalChain([event, 'access', _230 => _230.data, 'optionalAccess', _231 => _231.source]) === "liveblocks-devtools-panel") {
9139
+ if (event.source === window && _optionalChain([event, 'access', _218 => _218.data, 'optionalAccess', _219 => _219.source]) === "liveblocks-devtools-panel") {
10176
9140
  eventSource.notify(event.data);
10177
9141
  } else {
10178
9142
  }
@@ -10314,7 +9278,7 @@ function fullSync(room) {
10314
9278
  msg: "room::sync::full",
10315
9279
  roomId: room.id,
10316
9280
  status: room.getStatus(),
10317
- storage: _nullishCoalesce(_optionalChain([root, 'optionalAccess', _232 => _232.toTreeNode, 'call', _233 => _233("root"), 'access', _234 => _234.payload]), () => ( null)),
9281
+ storage: _nullishCoalesce(_optionalChain([root, 'optionalAccess', _220 => _220.toTreeNode, 'call', _221 => _221("root"), 'access', _222 => _222.payload]), () => ( null)),
10318
9282
  me,
10319
9283
  others
10320
9284
  });
@@ -11001,15 +9965,15 @@ function installBackgroundTabSpy() {
11001
9965
  const doc = typeof document !== "undefined" ? document : void 0;
11002
9966
  const inBackgroundSince = { current: null };
11003
9967
  function onVisibilityChange() {
11004
- if (_optionalChain([doc, 'optionalAccess', _235 => _235.visibilityState]) === "hidden") {
9968
+ if (_optionalChain([doc, 'optionalAccess', _223 => _223.visibilityState]) === "hidden") {
11005
9969
  inBackgroundSince.current = _nullishCoalesce(inBackgroundSince.current, () => ( Date.now()));
11006
9970
  } else {
11007
9971
  inBackgroundSince.current = null;
11008
9972
  }
11009
9973
  }
11010
- _optionalChain([doc, 'optionalAccess', _236 => _236.addEventListener, 'call', _237 => _237("visibilitychange", onVisibilityChange)]);
9974
+ _optionalChain([doc, 'optionalAccess', _224 => _224.addEventListener, 'call', _225 => _225("visibilitychange", onVisibilityChange)]);
11011
9975
  const unsub = () => {
11012
- _optionalChain([doc, 'optionalAccess', _238 => _238.removeEventListener, 'call', _239 => _239("visibilitychange", onVisibilityChange)]);
9976
+ _optionalChain([doc, 'optionalAccess', _226 => _226.removeEventListener, 'call', _227 => _227("visibilitychange", onVisibilityChange)]);
11013
9977
  };
11014
9978
  return [inBackgroundSince, unsub];
11015
9979
  }
@@ -11092,8 +10056,6 @@ function createRoom(options, config) {
11092
10056
  activeBatch: null,
11093
10057
  unacknowledgedOps
11094
10058
  };
11095
- let nextHistoryItemId = 0;
11096
- let historyDisabled = 0;
11097
10059
  const nodeMapBuffer = makeNodeMapBuffer();
11098
10060
  const stopwatch = config.enableDebugLogging ? makeStopWatch() : void 0;
11099
10061
  let lastTokenKey;
@@ -11178,10 +10140,7 @@ function createRoom(options, config) {
11178
10140
  }
11179
10141
  }
11180
10142
  });
11181
- function onDispatch(ops, reverse, storageUpdates, options2) {
11182
- for (const value of storageUpdates.values()) {
11183
- value[kStorageUpdateSource] = { origin: "local", via: "mutation" };
11184
- }
10143
+ function onDispatch(ops, reverse, storageUpdates) {
11185
10144
  if (context.activeBatch) {
11186
10145
  for (const op of ops) {
11187
10146
  context.activeBatch.ops.push(op);
@@ -11200,17 +10159,15 @@ function createRoom(options, config) {
11200
10159
  if (reverse.length > 0) {
11201
10160
  addToUndoStack(reverse);
11202
10161
  }
11203
- if (_nullishCoalesce(_optionalChain([options2, 'optionalAccess', _240 => _240.clearRedoStack]), () => ( ops.length > 0))) {
11204
- clearRedoStack();
11205
- }
11206
10162
  if (ops.length > 0) {
10163
+ context.redoStack.length = 0;
11207
10164
  dispatchOps(ops);
11208
10165
  }
11209
10166
  notify({ storageUpdates });
11210
10167
  }
11211
10168
  }
11212
10169
  function isStorageWritable() {
11213
- const permissionMatrix = _optionalChain([context, 'access', _241 => _241.dynamicSessionInfoSig, 'access', _242 => _242.get, 'call', _243 => _243(), 'optionalAccess', _244 => _244.permissionMatrix]);
10170
+ const permissionMatrix = _optionalChain([context, 'access', _228 => _228.dynamicSessionInfoSig, 'access', _229 => _229.get, 'call', _230 => _230(), 'optionalAccess', _231 => _231.permissionMatrix]);
11214
10171
  return permissionMatrix !== void 0 ? hasPermissionAccess(permissionMatrix, "storage", "write") : true;
11215
10172
  }
11216
10173
  const eventHub = {
@@ -11223,7 +10180,6 @@ function createRoom(options, config) {
11223
10180
  others: makeEventSource(),
11224
10181
  storageBatch: makeEventSource(),
11225
10182
  history: makeEventSource(),
11226
- privateHistory: makeEventSource(),
11227
10183
  storageDidLoad: makeEventSource(),
11228
10184
  storageStatus: makeEventSource(),
11229
10185
  ydoc: makeEventSource(),
@@ -11316,23 +10272,6 @@ function createRoom(options, config) {
11316
10272
  }
11317
10273
  const ops = diffNodeMap(currentItems, nodes);
11318
10274
  const result = applyRemoteOps(ops);
11319
- for (const [id, crdt] of nodes) {
11320
- if (crdt.type === CrdtType.TEXT) {
11321
- const node = context.pool.nodes.get(id);
11322
- if (node !== void 0 && isLiveText(node)) {
11323
- const update = node._resyncText(crdt.data, crdt.version);
11324
- if (update !== void 0) {
11325
- result.updates.storageUpdates.set(
11326
- id,
11327
- mergeStorageUpdates(
11328
- result.updates.storageUpdates.get(id),
11329
- update
11330
- )
11331
- );
11332
- }
11333
- }
11334
- }
11335
- }
11336
10275
  notify(result.updates);
11337
10276
  } else {
11338
10277
  context.root = LiveObject._fromItems(
@@ -11340,7 +10279,7 @@ function createRoom(options, config) {
11340
10279
  context.pool
11341
10280
  );
11342
10281
  }
11343
- const canWrite = _nullishCoalesce(_optionalChain([self, 'access', _245 => _245.get, 'call', _246 => _246(), 'optionalAccess', _247 => _247.canWrite]), () => ( true));
10282
+ const canWrite = _nullishCoalesce(_optionalChain([self, 'access', _232 => _232.get, 'call', _233 => _233(), 'optionalAccess', _234 => _234.canWrite]), () => ( true));
11344
10283
  const root = context.root;
11345
10284
  disableHistory(() => {
11346
10285
  for (const key in context.initialStorage) {
@@ -11356,26 +10295,11 @@ function createRoom(options, config) {
11356
10295
  }
11357
10296
  });
11358
10297
  }
11359
- function notifyPrivateHistory(event) {
11360
- if (historyDisabled > 0) return;
11361
- eventHub.privateHistory.notify(event);
11362
- }
11363
- function clearRedoStack() {
11364
- if (context.redoStack.length === 0) return;
11365
- const ids = context.redoStack.map((item) => item.id);
11366
- context.redoStack.length = 0;
11367
- notifyPrivateHistory({ action: "discard", ids });
11368
- }
11369
10298
  function _addToRealUndoStack(frames) {
11370
10299
  if (context.undoStack.length >= 50) {
11371
- const evicted = context.undoStack.shift();
11372
- if (evicted !== void 0) {
11373
- notifyPrivateHistory({ action: "discard", ids: [evicted.id] });
11374
- }
10300
+ context.undoStack.shift();
11375
10301
  }
11376
- const id = nextHistoryItemId++;
11377
- context.undoStack.push({ id, frames });
11378
- notifyPrivateHistory({ action: "push", id });
10302
+ context.undoStack.push(frames);
11379
10303
  onHistoryChange();
11380
10304
  }
11381
10305
  function addToUndoStack(frames) {
@@ -11413,7 +10337,7 @@ function createRoom(options, config) {
11413
10337
  "Internal. Tried to get connection id but connection was never open"
11414
10338
  );
11415
10339
  }
11416
- function applyLocalOps(frames, localStorageUpdateSource = { origin: "local", via: "mutation" }) {
10340
+ function applyLocalOps(frames) {
11417
10341
  const [pframes, ops] = partition(
11418
10342
  frames,
11419
10343
  (f) => f.type === "presence"
@@ -11425,8 +10349,7 @@ function createRoom(options, config) {
11425
10349
  pframes,
11426
10350
  opsWithOpIds,
11427
10351
  /* isLocal */
11428
- true,
11429
- localStorageUpdateSource
10352
+ true
11430
10353
  );
11431
10354
  return { opsToEmit: opsWithOpIds, reverse, updates };
11432
10355
  }
@@ -11438,7 +10361,7 @@ function createRoom(options, config) {
11438
10361
  false
11439
10362
  );
11440
10363
  }
11441
- function applyOps(pframes, ops, isLocal, localStorageUpdateSource = { origin: "local", via: "mutation" }) {
10364
+ function applyOps(pframes, ops, isLocal) {
11442
10365
  const output = {
11443
10366
  reverse: new Deque(),
11444
10367
  storageUpdates: /* @__PURE__ */ new Map(),
@@ -11476,7 +10399,6 @@ function createRoom(options, config) {
11476
10399
  }
11477
10400
  const applyOpResult = applyOp(op, source);
11478
10401
  if (applyOpResult.modified) {
11479
- applyOpResult.modified[kStorageUpdateSource] = source === 1 /* THEIRS */ ? { origin: "remote" } : localStorageUpdateSource;
11480
10402
  const nodeId = applyOpResult.modified.node._id;
11481
10403
  if (!(nodeId && createdNodeIds.has(nodeId))) {
11482
10404
  output.storageUpdates.set(
@@ -11488,7 +10410,7 @@ function createRoom(options, config) {
11488
10410
  );
11489
10411
  output.reverse.pushLeft(applyOpResult.reverse);
11490
10412
  }
11491
- if (op.type === OpCode.CREATE_LIST || op.type === OpCode.CREATE_MAP || op.type === OpCode.CREATE_OBJECT || op.type === OpCode.CREATE_TEXT) {
10413
+ if (op.type === OpCode.CREATE_LIST || op.type === OpCode.CREATE_MAP || op.type === OpCode.CREATE_OBJECT) {
11492
10414
  createdNodeIds.add(op.id);
11493
10415
  }
11494
10416
  }
@@ -11508,7 +10430,6 @@ function createRoom(options, config) {
11508
10430
  switch (op.type) {
11509
10431
  case OpCode.DELETE_OBJECT_KEY:
11510
10432
  case OpCode.UPDATE_OBJECT:
11511
- case OpCode.UPDATE_TEXT:
11512
10433
  case OpCode.DELETE_CRDT: {
11513
10434
  const node = context.pool.nodes.get(op.id);
11514
10435
  if (node === void 0) {
@@ -11533,7 +10454,6 @@ function createRoom(options, config) {
11533
10454
  case OpCode.CREATE_OBJECT:
11534
10455
  case OpCode.CREATE_LIST:
11535
10456
  case OpCode.CREATE_MAP:
11536
- case OpCode.CREATE_TEXT:
11537
10457
  case OpCode.CREATE_REGISTER: {
11538
10458
  if (op.parentId === void 0) {
11539
10459
  return { modified: false };
@@ -11564,7 +10484,7 @@ function createRoom(options, config) {
11564
10484
  }
11565
10485
  context.myPresence.patch(patch);
11566
10486
  if (context.activeBatch) {
11567
- if (_optionalChain([options2, 'optionalAccess', _248 => _248.addToHistory])) {
10487
+ if (_optionalChain([options2, 'optionalAccess', _235 => _235.addToHistory])) {
11568
10488
  context.activeBatch.reverseOps.pushLeft({
11569
10489
  type: "presence",
11570
10490
  data: oldValues
@@ -11573,7 +10493,7 @@ function createRoom(options, config) {
11573
10493
  context.activeBatch.updates.presence = true;
11574
10494
  } else {
11575
10495
  flushNowOrSoon();
11576
- if (_optionalChain([options2, 'optionalAccess', _249 => _249.addToHistory])) {
10496
+ if (_optionalChain([options2, 'optionalAccess', _236 => _236.addToHistory])) {
11577
10497
  addToUndoStack([{ type: "presence", data: oldValues }]);
11578
10498
  }
11579
10499
  notify({ presence: true });
@@ -11752,11 +10672,11 @@ function createRoom(options, config) {
11752
10672
  break;
11753
10673
  }
11754
10674
  case ServerMsgCode.STORAGE_CHUNK:
11755
- _optionalChain([stopwatch, 'optionalAccess', _250 => _250.lap, 'call', _251 => _251()]);
10675
+ _optionalChain([stopwatch, 'optionalAccess', _237 => _237.lap, 'call', _238 => _238()]);
11756
10676
  nodeMapBuffer.append(compactNodesToNodeStream(message.nodes));
11757
10677
  break;
11758
10678
  case ServerMsgCode.STORAGE_STREAM_END: {
11759
- const timing = _optionalChain([stopwatch, 'optionalAccess', _252 => _252.stop, 'call', _253 => _253()]);
10679
+ const timing = _optionalChain([stopwatch, 'optionalAccess', _239 => _239.stop, 'call', _240 => _240()]);
11760
10680
  if (timing) {
11761
10681
  const ms = (v) => `${v.toFixed(1)}ms`;
11762
10682
  const rest = timing.laps.slice(1);
@@ -11783,37 +10703,16 @@ function createRoom(options, config) {
11783
10703
  }
11784
10704
  break;
11785
10705
  }
11786
- // Receiving a RejectedOps message means the server refused some of
11787
- // our ops, so our optimistic local state is out of sync with the
11788
- // server. For LiveText ops this is a normal (if rare) situation
11789
- // e.g. a client that was offline long enough to fall outside the
11790
- // server's retained history window — and we can recover: drop the
11791
- // rejected pending state and re-fetch the authoritative storage
11792
- // snapshot. For other ops (e.g. permission rejections), rolling back
11793
- // particular Ops is hard/impossible, so we keep the old behavior of
11794
- // accepting the out-of-sync reality and surfacing an error.
10706
+ // Receiving a RejectedOps message in the client means that the server is no
10707
+ // longer in sync with the client. Trying to synchronize the client again by
10708
+ // rolling back particular Ops may be hard/impossible. It's fine to not try and
10709
+ // accept the out-of-sync reality and throw an error.
11795
10710
  case ServerMsgCode.REJECT_STORAGE_OP: {
11796
10711
  errorWithTitle(
11797
10712
  "Storage mutation rejection error",
11798
10713
  message.reason
11799
10714
  );
11800
- let needsStorageResync = false;
11801
- for (const opId of message.opIds) {
11802
- const rejectedOp = context.unacknowledgedOps.get(opId);
11803
- context.unacknowledgedOps.delete(opId);
11804
- context.buffer.storageOperations = context.buffer.storageOperations.filter((op) => op.opId !== opId);
11805
- if (rejectedOp !== void 0 && rejectedOp.type === OpCode.UPDATE_TEXT) {
11806
- const node = context.pool.nodes.get(rejectedOp.id);
11807
- if (node !== void 0 && isLiveText(node)) {
11808
- node._rejectPendingOp(opId);
11809
- needsStorageResync = true;
11810
- }
11811
- }
11812
- }
11813
- if (needsStorageResync) {
11814
- refreshStorage();
11815
- flushNowOrSoon();
11816
- } else if (process.env.NODE_ENV !== "production") {
10715
+ if (process.env.NODE_ENV !== "production") {
11817
10716
  throw new Error(
11818
10717
  `Storage mutations rejected by server: ${message.reason}`
11819
10718
  );
@@ -11912,11 +10811,11 @@ function createRoom(options, config) {
11912
10811
  } else if (pendingFeedsRequests.has(requestId)) {
11913
10812
  const pending = pendingFeedsRequests.get(requestId);
11914
10813
  pendingFeedsRequests.delete(requestId);
11915
- _optionalChain([pending, 'optionalAccess', _254 => _254.reject, 'call', _255 => _255(err)]);
10814
+ _optionalChain([pending, 'optionalAccess', _241 => _241.reject, 'call', _242 => _242(err)]);
11916
10815
  } else if (pendingFeedMessagesRequests.has(requestId)) {
11917
10816
  const pending = pendingFeedMessagesRequests.get(requestId);
11918
10817
  pendingFeedMessagesRequests.delete(requestId);
11919
- _optionalChain([pending, 'optionalAccess', _256 => _256.reject, 'call', _257 => _257(err)]);
10818
+ _optionalChain([pending, 'optionalAccess', _243 => _243.reject, 'call', _244 => _244(err)]);
11920
10819
  }
11921
10820
  eventHub.feeds.notify(message);
11922
10821
  break;
@@ -12070,10 +10969,10 @@ function createRoom(options, config) {
12070
10969
  timeoutId,
12071
10970
  kind,
12072
10971
  feedId,
12073
- messageId: _optionalChain([options2, 'optionalAccess', _258 => _258.messageId]),
12074
- expectedClientMessageId: _optionalChain([options2, 'optionalAccess', _259 => _259.expectedClientMessageId])
10972
+ messageId: _optionalChain([options2, 'optionalAccess', _245 => _245.messageId]),
10973
+ expectedClientMessageId: _optionalChain([options2, 'optionalAccess', _246 => _246.expectedClientMessageId])
12075
10974
  });
12076
- if (kind === "add-message" && _optionalChain([options2, 'optionalAccess', _260 => _260.expectedClientMessageId]) === void 0) {
10975
+ if (kind === "add-message" && _optionalChain([options2, 'optionalAccess', _247 => _247.expectedClientMessageId]) === void 0) {
12077
10976
  const q = _nullishCoalesce(pendingAddMessageFifoByFeed.get(feedId), () => ( []));
12078
10977
  q.push(requestId);
12079
10978
  pendingAddMessageFifoByFeed.set(feedId, q);
@@ -12124,10 +11023,10 @@ function createRoom(options, config) {
12124
11023
  }
12125
11024
  if (!matched) {
12126
11025
  const q = pendingAddMessageFifoByFeed.get(message.feedId);
12127
- const headId = _optionalChain([q, 'optionalAccess', _261 => _261[0]]);
11026
+ const headId = _optionalChain([q, 'optionalAccess', _248 => _248[0]]);
12128
11027
  if (headId !== void 0) {
12129
11028
  const pending = pendingFeedMutations.get(headId);
12130
- if (_optionalChain([pending, 'optionalAccess', _262 => _262.kind]) === "add-message" && pending.expectedClientMessageId === void 0) {
11029
+ if (_optionalChain([pending, 'optionalAccess', _249 => _249.kind]) === "add-message" && pending.expectedClientMessageId === void 0) {
12131
11030
  settleFeedMutation(headId, "ok");
12132
11031
  }
12133
11032
  }
@@ -12163,7 +11062,7 @@ function createRoom(options, config) {
12163
11062
  const unacknowledgedOps2 = [...context.unacknowledgedOps.values()];
12164
11063
  createOrUpdateRootFromMessage(nodes);
12165
11064
  applyAndSendOfflineOps(unacknowledgedOps2);
12166
- _optionalChain([_resolveStoragePromise, 'optionalCall', _263 => _263()]);
11065
+ _optionalChain([_resolveStoragePromise, 'optionalCall', _250 => _250()]);
12167
11066
  notifyStorageStatus();
12168
11067
  eventHub.storageDidLoad.notify();
12169
11068
  }
@@ -12172,7 +11071,7 @@ function createRoom(options, config) {
12172
11071
  if (!messages.some((msg) => msg.type === ClientMsgCode.FETCH_STORAGE)) {
12173
11072
  messages.push({ type: ClientMsgCode.FETCH_STORAGE });
12174
11073
  nodeMapBuffer.take();
12175
- _optionalChain([stopwatch, 'optionalAccess', _264 => _264.start, 'call', _265 => _265()]);
11074
+ _optionalChain([stopwatch, 'optionalAccess', _251 => _251.start, 'call', _252 => _252()]);
12176
11075
  }
12177
11076
  }
12178
11077
  function startLoadingStorage() {
@@ -12226,10 +11125,10 @@ function createRoom(options, config) {
12226
11125
  const message = {
12227
11126
  type: ClientMsgCode.FETCH_FEEDS,
12228
11127
  requestId,
12229
- cursor: _optionalChain([options2, 'optionalAccess', _266 => _266.cursor]),
12230
- since: _optionalChain([options2, 'optionalAccess', _267 => _267.since]),
12231
- limit: _optionalChain([options2, 'optionalAccess', _268 => _268.limit]),
12232
- metadata: _optionalChain([options2, 'optionalAccess', _269 => _269.metadata])
11128
+ cursor: _optionalChain([options2, 'optionalAccess', _253 => _253.cursor]),
11129
+ since: _optionalChain([options2, 'optionalAccess', _254 => _254.since]),
11130
+ limit: _optionalChain([options2, 'optionalAccess', _255 => _255.limit]),
11131
+ metadata: _optionalChain([options2, 'optionalAccess', _256 => _256.metadata])
12233
11132
  };
12234
11133
  context.buffer.messages.push(message);
12235
11134
  flushNowOrSoon();
@@ -12249,9 +11148,9 @@ function createRoom(options, config) {
12249
11148
  type: ClientMsgCode.FETCH_FEED_MESSAGES,
12250
11149
  requestId,
12251
11150
  feedId,
12252
- cursor: _optionalChain([options2, 'optionalAccess', _270 => _270.cursor]),
12253
- since: _optionalChain([options2, 'optionalAccess', _271 => _271.since]),
12254
- limit: _optionalChain([options2, 'optionalAccess', _272 => _272.limit])
11151
+ cursor: _optionalChain([options2, 'optionalAccess', _257 => _257.cursor]),
11152
+ since: _optionalChain([options2, 'optionalAccess', _258 => _258.since]),
11153
+ limit: _optionalChain([options2, 'optionalAccess', _259 => _259.limit])
12255
11154
  };
12256
11155
  context.buffer.messages.push(message);
12257
11156
  flushNowOrSoon();
@@ -12270,8 +11169,8 @@ function createRoom(options, config) {
12270
11169
  type: ClientMsgCode.ADD_FEED,
12271
11170
  requestId,
12272
11171
  feedId,
12273
- metadata: _optionalChain([options2, 'optionalAccess', _273 => _273.metadata]),
12274
- createdAt: _optionalChain([options2, 'optionalAccess', _274 => _274.createdAt])
11172
+ metadata: _optionalChain([options2, 'optionalAccess', _260 => _260.metadata]),
11173
+ createdAt: _optionalChain([options2, 'optionalAccess', _261 => _261.createdAt])
12275
11174
  };
12276
11175
  context.buffer.messages.push(message);
12277
11176
  flushNowOrSoon();
@@ -12305,15 +11204,15 @@ function createRoom(options, config) {
12305
11204
  function addFeedMessage(feedId, data, options2) {
12306
11205
  const requestId = nanoid();
12307
11206
  const promise = registerFeedMutation(requestId, "add-message", feedId, {
12308
- expectedClientMessageId: _optionalChain([options2, 'optionalAccess', _275 => _275.id])
11207
+ expectedClientMessageId: _optionalChain([options2, 'optionalAccess', _262 => _262.id])
12309
11208
  });
12310
11209
  const message = {
12311
11210
  type: ClientMsgCode.ADD_FEED_MESSAGE,
12312
11211
  requestId,
12313
11212
  feedId,
12314
11213
  data,
12315
- id: _optionalChain([options2, 'optionalAccess', _276 => _276.id]),
12316
- createdAt: _optionalChain([options2, 'optionalAccess', _277 => _277.createdAt])
11214
+ id: _optionalChain([options2, 'optionalAccess', _263 => _263.id]),
11215
+ createdAt: _optionalChain([options2, 'optionalAccess', _264 => _264.createdAt])
12317
11216
  };
12318
11217
  context.buffer.messages.push(message);
12319
11218
  flushNowOrSoon();
@@ -12330,7 +11229,7 @@ function createRoom(options, config) {
12330
11229
  feedId,
12331
11230
  messageId,
12332
11231
  data,
12333
- updatedAt: _optionalChain([options2, 'optionalAccess', _278 => _278.updatedAt])
11232
+ updatedAt: _optionalChain([options2, 'optionalAccess', _265 => _265.updatedAt])
12334
11233
  };
12335
11234
  context.buffer.messages.push(message);
12336
11235
  flushNowOrSoon();
@@ -12355,19 +11254,14 @@ function createRoom(options, config) {
12355
11254
  if (context.activeBatch) {
12356
11255
  throw new Error("undo is not allowed during a batch");
12357
11256
  }
12358
- const item = context.undoStack.pop();
12359
- if (item === void 0) {
11257
+ const frames = context.undoStack.pop();
11258
+ if (frames === void 0) {
12360
11259
  return;
12361
11260
  }
12362
11261
  context.pausedHistory = null;
12363
- const result = applyLocalOps(item.frames, {
12364
- origin: "local",
12365
- via: "history",
12366
- action: "undo"
12367
- });
12368
- context.redoStack.push({ id: item.id, frames: result.reverse });
12369
- notifyPrivateHistory({ action: "undo", id: item.id });
11262
+ const result = applyLocalOps(frames);
12370
11263
  notify(result.updates);
11264
+ context.redoStack.push(result.reverse);
12371
11265
  onHistoryChange();
12372
11266
  for (const op of result.opsToEmit) {
12373
11267
  context.buffer.storageOperations.push(op);
@@ -12378,19 +11272,14 @@ function createRoom(options, config) {
12378
11272
  if (context.activeBatch) {
12379
11273
  throw new Error("redo is not allowed during a batch");
12380
11274
  }
12381
- const item = context.redoStack.pop();
12382
- if (item === void 0) {
11275
+ const frames = context.redoStack.pop();
11276
+ if (frames === void 0) {
12383
11277
  return;
12384
11278
  }
12385
11279
  context.pausedHistory = null;
12386
- const result = applyLocalOps(item.frames, {
12387
- origin: "local",
12388
- via: "history",
12389
- action: "redo"
12390
- });
12391
- context.undoStack.push({ id: item.id, frames: result.reverse });
12392
- notifyPrivateHistory({ action: "redo", id: item.id });
11280
+ const result = applyLocalOps(frames);
12393
11281
  notify(result.updates);
11282
+ context.undoStack.push(result.reverse);
12394
11283
  onHistoryChange();
12395
11284
  for (const op of result.opsToEmit) {
12396
11285
  context.buffer.storageOperations.push(op);
@@ -12400,8 +11289,6 @@ function createRoom(options, config) {
12400
11289
  function clear() {
12401
11290
  context.undoStack.length = 0;
12402
11291
  context.redoStack.length = 0;
12403
- notifyPrivateHistory({ action: "clear" });
12404
- onHistoryChange();
12405
11292
  }
12406
11293
  function batch2(callback) {
12407
11294
  if (context.activeBatch) {
@@ -12430,7 +11317,7 @@ function createRoom(options, config) {
12430
11317
  commitPausedHistoryToUndoStack();
12431
11318
  }
12432
11319
  if (currentBatch.ops.length > 0) {
12433
- clearRedoStack();
11320
+ context.redoStack.length = 0;
12434
11321
  }
12435
11322
  if (currentBatch.ops.length > 0) {
12436
11323
  dispatchOps(currentBatch.ops);
@@ -12459,6 +11346,7 @@ function createRoom(options, config) {
12459
11346
  }
12460
11347
  commitPausedHistoryToUndoStack();
12461
11348
  }
11349
+ let historyDisabled = 0;
12462
11350
  function disableHistory(fn) {
12463
11351
  const origUndo = context.undoStack;
12464
11352
  const origRedo = context.redoStack;
@@ -12548,8 +11436,8 @@ function createRoom(options, config) {
12548
11436
  async function getThreads(options2) {
12549
11437
  return httpClient.getThreads({
12550
11438
  roomId,
12551
- query: _optionalChain([options2, 'optionalAccess', _279 => _279.query]),
12552
- cursor: _optionalChain([options2, 'optionalAccess', _280 => _280.cursor])
11439
+ query: _optionalChain([options2, 'optionalAccess', _266 => _266.query]),
11440
+ cursor: _optionalChain([options2, 'optionalAccess', _267 => _267.cursor])
12553
11441
  });
12554
11442
  }
12555
11443
  async function getThread(threadId) {
@@ -12560,6 +11448,7 @@ function createRoom(options, config) {
12560
11448
  roomId,
12561
11449
  threadId: options2.threadId,
12562
11450
  commentId: options2.commentId,
11451
+ visibility: options2.visibility,
12563
11452
  metadata: options2.metadata,
12564
11453
  body: options2.body,
12565
11454
  commentMetadata: options2.commentMetadata,
@@ -12671,7 +11560,7 @@ function createRoom(options, config) {
12671
11560
  function getSubscriptionSettings(options2) {
12672
11561
  return httpClient.getSubscriptionSettings({
12673
11562
  roomId,
12674
- signal: _optionalChain([options2, 'optionalAccess', _281 => _281.signal])
11563
+ signal: _optionalChain([options2, 'optionalAccess', _268 => _268.signal])
12675
11564
  });
12676
11565
  }
12677
11566
  function updateSubscriptionSettings(settings) {
@@ -12693,39 +11582,24 @@ function createRoom(options, config) {
12693
11582
  {
12694
11583
  [kInternal]: {
12695
11584
  get presenceBuffer() {
12696
- return deepClone(_nullishCoalesce(_optionalChain([context, 'access', _282 => _282.buffer, 'access', _283 => _283.presenceUpdates, 'optionalAccess', _284 => _284.data]), () => ( null)));
11585
+ return deepClone(_nullishCoalesce(_optionalChain([context, 'access', _269 => _269.buffer, 'access', _270 => _270.presenceUpdates, 'optionalAccess', _271 => _271.data]), () => ( null)));
12697
11586
  },
12698
11587
  // prettier-ignore
12699
11588
  get undoStack() {
12700
- return structuredClone(
12701
- context.undoStack.map((item) => ({
12702
- id: item.id,
12703
- frames: item.frames
12704
- }))
12705
- );
12706
- },
12707
- // prettier-ignore
12708
- get redoStack() {
12709
- return structuredClone(
12710
- context.redoStack.map((item) => ({
12711
- id: item.id,
12712
- frames: item.frames
12713
- }))
12714
- );
11589
+ return deepClone(context.undoStack);
12715
11590
  },
12716
11591
  // prettier-ignore
12717
11592
  get nodeCount() {
12718
11593
  return context.pool.nodes.size;
12719
11594
  },
12720
11595
  // prettier-ignore
12721
- history: eventHub.privateHistory.observable,
12722
11596
  getYjsProvider() {
12723
11597
  return context.yjsProvider;
12724
11598
  },
12725
11599
  setYjsProvider(newProvider) {
12726
- _optionalChain([context, 'access', _285 => _285.yjsProvider, 'optionalAccess', _286 => _286.off, 'call', _287 => _287("status", yjsStatusDidChange)]);
11600
+ _optionalChain([context, 'access', _272 => _272.yjsProvider, 'optionalAccess', _273 => _273.off, 'call', _274 => _274("status", yjsStatusDidChange)]);
12727
11601
  context.yjsProvider = newProvider;
12728
- _optionalChain([newProvider, 'optionalAccess', _288 => _288.on, 'call', _289 => _289("status", yjsStatusDidChange)]);
11602
+ _optionalChain([newProvider, 'optionalAccess', _275 => _275.on, 'call', _276 => _276("status", yjsStatusDidChange)]);
12729
11603
  context.yjsProviderDidChange.notify();
12730
11604
  },
12731
11605
  yjsProviderDidChange: context.yjsProviderDidChange.observable,
@@ -12785,7 +11659,7 @@ ${dumpPool(
12785
11659
  source.dispose();
12786
11660
  }
12787
11661
  eventHub.roomWillDestroy.notify();
12788
- _optionalChain([context, 'access', _290 => _290.yjsProvider, 'optionalAccess', _291 => _291.off, 'call', _292 => _292("status", yjsStatusDidChange)]);
11662
+ _optionalChain([context, 'access', _277 => _277.yjsProvider, 'optionalAccess', _278 => _278.off, 'call', _279 => _279("status", yjsStatusDidChange)]);
12789
11663
  syncSourceForStorage.destroy();
12790
11664
  syncSourceForYjs.destroy();
12791
11665
  uninstallBgTabSpy();
@@ -12947,7 +11821,7 @@ function makeClassicSubscribeFn(roomId, events, errorEvents) {
12947
11821
  }
12948
11822
  if (isLiveNode(first)) {
12949
11823
  const node = first;
12950
- if (_optionalChain([options, 'optionalAccess', _293 => _293.isDeep])) {
11824
+ if (_optionalChain([options, 'optionalAccess', _280 => _280.isDeep])) {
12951
11825
  const storageCallback = second;
12952
11826
  return subscribeToLiveStructureDeeply(node, storageCallback);
12953
11827
  } else {
@@ -13037,8 +11911,8 @@ function createClient(options) {
13037
11911
  const authManager = createAuthManager(options, (token) => {
13038
11912
  currentUserId.set(() => token.uid);
13039
11913
  });
13040
- const fetchPolyfill = _optionalChain([clientOptions, 'access', _294 => _294.polyfills, 'optionalAccess', _295 => _295.fetch]) || /* istanbul ignore next */
13041
- _optionalChain([globalThis, 'access', _296 => _296.fetch, 'optionalAccess', _297 => _297.bind, 'call', _298 => _298(globalThis)]);
11914
+ const fetchPolyfill = _optionalChain([clientOptions, 'access', _281 => _281.polyfills, 'optionalAccess', _282 => _282.fetch]) || /* istanbul ignore next */
11915
+ _optionalChain([globalThis, 'access', _283 => _283.fetch, 'optionalAccess', _284 => _284.bind, 'call', _285 => _285(globalThis)]);
13042
11916
  const httpClient = createApiClient({
13043
11917
  baseUrl,
13044
11918
  fetchPolyfill,
@@ -13055,7 +11929,7 @@ function createClient(options) {
13055
11929
  delegates: {
13056
11930
  createSocket: makeCreateSocketDelegateForAi(
13057
11931
  baseUrl,
13058
- _optionalChain([clientOptions, 'access', _299 => _299.polyfills, 'optionalAccess', _300 => _300.WebSocket])
11932
+ _optionalChain([clientOptions, 'access', _286 => _286.polyfills, 'optionalAccess', _287 => _287.WebSocket])
13059
11933
  ),
13060
11934
  authenticate: async () => {
13061
11935
  const resp = await authManager.getAuthValue({
@@ -13126,7 +12000,7 @@ function createClient(options) {
13126
12000
  createSocket: makeCreateSocketDelegateForRoom(
13127
12001
  roomId,
13128
12002
  baseUrl,
13129
- _optionalChain([clientOptions, 'access', _301 => _301.polyfills, 'optionalAccess', _302 => _302.WebSocket])
12003
+ _optionalChain([clientOptions, 'access', _288 => _288.polyfills, 'optionalAccess', _289 => _289.WebSocket])
13130
12004
  ),
13131
12005
  authenticate: makeAuthDelegateForRoom(roomId, authManager)
13132
12006
  })),
@@ -13148,7 +12022,7 @@ function createClient(options) {
13148
12022
  const shouldConnect = _nullishCoalesce(options2.autoConnect, () => ( true));
13149
12023
  if (shouldConnect) {
13150
12024
  if (typeof atob === "undefined") {
13151
- if (_optionalChain([clientOptions, 'access', _303 => _303.polyfills, 'optionalAccess', _304 => _304.atob]) === void 0) {
12025
+ if (_optionalChain([clientOptions, 'access', _290 => _290.polyfills, 'optionalAccess', _291 => _291.atob]) === void 0) {
13152
12026
  throw new Error(
13153
12027
  "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"
13154
12028
  );
@@ -13160,7 +12034,7 @@ function createClient(options) {
13160
12034
  return leaseRoom(newRoomDetails);
13161
12035
  }
13162
12036
  function getRoom(roomId) {
13163
- const room = _optionalChain([roomsById, 'access', _305 => _305.get, 'call', _306 => _306(roomId), 'optionalAccess', _307 => _307.room]);
12037
+ const room = _optionalChain([roomsById, 'access', _292 => _292.get, 'call', _293 => _293(roomId), 'optionalAccess', _294 => _294.room]);
13164
12038
  return room ? room : null;
13165
12039
  }
13166
12040
  function logout() {
@@ -13176,7 +12050,7 @@ function createClient(options) {
13176
12050
  const batchedResolveUsers = new Batch(
13177
12051
  async (batchedUserIds) => {
13178
12052
  const userIds = batchedUserIds.flat();
13179
- const users = await _optionalChain([resolveUsers, 'optionalCall', _308 => _308({ userIds })]);
12053
+ const users = await _optionalChain([resolveUsers, 'optionalCall', _295 => _295({ userIds })]);
13180
12054
  warnOnceIf(
13181
12055
  !resolveUsers,
13182
12056
  "Set the resolveUsers option in createClient to specify user info."
@@ -13193,7 +12067,7 @@ function createClient(options) {
13193
12067
  const batchedResolveRoomsInfo = new Batch(
13194
12068
  async (batchedRoomIds) => {
13195
12069
  const roomIds = batchedRoomIds.flat();
13196
- const roomsInfo = await _optionalChain([resolveRoomsInfo, 'optionalCall', _309 => _309({ roomIds })]);
12070
+ const roomsInfo = await _optionalChain([resolveRoomsInfo, 'optionalCall', _296 => _296({ roomIds })]);
13197
12071
  warnOnceIf(
13198
12072
  !resolveRoomsInfo,
13199
12073
  "Set the resolveRoomsInfo option in createClient to specify room info."
@@ -13210,7 +12084,7 @@ function createClient(options) {
13210
12084
  const batchedResolveGroupsInfo = new Batch(
13211
12085
  async (batchedGroupIds) => {
13212
12086
  const groupIds = batchedGroupIds.flat();
13213
- const groupsInfo = await _optionalChain([resolveGroupsInfo, 'optionalCall', _310 => _310({ groupIds })]);
12087
+ const groupsInfo = await _optionalChain([resolveGroupsInfo, 'optionalCall', _297 => _297({ groupIds })]);
13214
12088
  warnOnceIf(
13215
12089
  !resolveGroupsInfo,
13216
12090
  "Set the resolveGroupsInfo option in createClient to specify group info."
@@ -13269,7 +12143,7 @@ function createClient(options) {
13269
12143
  }
13270
12144
  };
13271
12145
  const win = typeof window !== "undefined" ? window : void 0;
13272
- _optionalChain([win, 'optionalAccess', _311 => _311.addEventListener, 'call', _312 => _312("beforeunload", maybePreventClose)]);
12146
+ _optionalChain([win, 'optionalAccess', _298 => _298.addEventListener, 'call', _299 => _299("beforeunload", maybePreventClose)]);
13273
12147
  }
13274
12148
  async function getNotificationSettings(options2) {
13275
12149
  const plainSettings = await httpClient.getNotificationSettings(options2);
@@ -13397,7 +12271,7 @@ var commentBodyElementsTypes = {
13397
12271
  mention: "inline"
13398
12272
  };
13399
12273
  function traverseCommentBody(body, elementOrVisitor, possiblyVisitor) {
13400
- if (!body || !_optionalChain([body, 'optionalAccess', _313 => _313.content])) {
12274
+ if (!body || !_optionalChain([body, 'optionalAccess', _300 => _300.content])) {
13401
12275
  return;
13402
12276
  }
13403
12277
  const element = typeof elementOrVisitor === "string" ? elementOrVisitor : void 0;
@@ -13407,13 +12281,13 @@ function traverseCommentBody(body, elementOrVisitor, possiblyVisitor) {
13407
12281
  for (const block of body.content) {
13408
12282
  if (type === "all" || type === "block") {
13409
12283
  if (guard(block)) {
13410
- _optionalChain([visitor, 'optionalCall', _314 => _314(block)]);
12284
+ _optionalChain([visitor, 'optionalCall', _301 => _301(block)]);
13411
12285
  }
13412
12286
  }
13413
12287
  if (type === "all" || type === "inline") {
13414
12288
  for (const inline of block.children) {
13415
12289
  if (guard(inline)) {
13416
- _optionalChain([visitor, 'optionalCall', _315 => _315(inline)]);
12290
+ _optionalChain([visitor, 'optionalCall', _302 => _302(inline)]);
13417
12291
  }
13418
12292
  }
13419
12293
  }
@@ -13583,7 +12457,7 @@ var stringifyCommentBodyPlainElements = {
13583
12457
  text: ({ element }) => element.text,
13584
12458
  link: ({ element }) => _nullishCoalesce(element.text, () => ( element.url)),
13585
12459
  mention: ({ element, user, group }) => {
13586
- return `@${_nullishCoalesce(_nullishCoalesce(_optionalChain([user, 'optionalAccess', _316 => _316.name]), () => ( _optionalChain([group, 'optionalAccess', _317 => _317.name]))), () => ( element.id))}`;
12460
+ return `@${_nullishCoalesce(_nullishCoalesce(_optionalChain([user, 'optionalAccess', _303 => _303.name]), () => ( _optionalChain([group, 'optionalAccess', _304 => _304.name]))), () => ( element.id))}`;
13587
12461
  }
13588
12462
  };
13589
12463
  var stringifyCommentBodyHtmlElements = {
@@ -13613,7 +12487,7 @@ var stringifyCommentBodyHtmlElements = {
13613
12487
  return html`<a href="${href}" target="_blank" rel="noopener noreferrer">${element.text ? html`${element.text}` : element.url}</a>`;
13614
12488
  },
13615
12489
  mention: ({ element, user, group }) => {
13616
- return html`<span data-mention>@${_optionalChain([user, 'optionalAccess', _318 => _318.name]) ? html`${_optionalChain([user, 'optionalAccess', _319 => _319.name])}` : _optionalChain([group, 'optionalAccess', _320 => _320.name]) ? html`${_optionalChain([group, 'optionalAccess', _321 => _321.name])}` : element.id}</span>`;
12490
+ return html`<span data-mention>@${_optionalChain([user, 'optionalAccess', _305 => _305.name]) ? html`${_optionalChain([user, 'optionalAccess', _306 => _306.name])}` : _optionalChain([group, 'optionalAccess', _307 => _307.name]) ? html`${_optionalChain([group, 'optionalAccess', _308 => _308.name])}` : element.id}</span>`;
13617
12491
  }
13618
12492
  };
13619
12493
  var stringifyCommentBodyMarkdownElements = {
@@ -13643,20 +12517,20 @@ var stringifyCommentBodyMarkdownElements = {
13643
12517
  return markdown`[${_nullishCoalesce(element.text, () => ( element.url))}](${href})`;
13644
12518
  },
13645
12519
  mention: ({ element, user, group }) => {
13646
- return markdown`@${_nullishCoalesce(_nullishCoalesce(_optionalChain([user, 'optionalAccess', _322 => _322.name]), () => ( _optionalChain([group, 'optionalAccess', _323 => _323.name]))), () => ( element.id))}`;
12520
+ return markdown`@${_nullishCoalesce(_nullishCoalesce(_optionalChain([user, 'optionalAccess', _309 => _309.name]), () => ( _optionalChain([group, 'optionalAccess', _310 => _310.name]))), () => ( element.id))}`;
13647
12521
  }
13648
12522
  };
13649
12523
  async function stringifyCommentBody(body, options) {
13650
- const format = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _324 => _324.format]), () => ( "plain"));
13651
- const separator = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _325 => _325.separator]), () => ( (format === "markdown" ? "\n\n" : "\n")));
12524
+ const format = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _311 => _311.format]), () => ( "plain"));
12525
+ const separator = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _312 => _312.separator]), () => ( (format === "markdown" ? "\n\n" : "\n")));
13652
12526
  const elements = {
13653
12527
  ...format === "html" ? stringifyCommentBodyHtmlElements : format === "markdown" ? stringifyCommentBodyMarkdownElements : stringifyCommentBodyPlainElements,
13654
- ..._optionalChain([options, 'optionalAccess', _326 => _326.elements])
12528
+ ..._optionalChain([options, 'optionalAccess', _313 => _313.elements])
13655
12529
  };
13656
12530
  const { users: resolvedUsers, groups: resolvedGroupsInfo } = await resolveMentionsInCommentBody(
13657
12531
  body,
13658
- _optionalChain([options, 'optionalAccess', _327 => _327.resolveUsers]),
13659
- _optionalChain([options, 'optionalAccess', _328 => _328.resolveGroupsInfo])
12532
+ _optionalChain([options, 'optionalAccess', _314 => _314.resolveUsers]),
12533
+ _optionalChain([options, 'optionalAccess', _315 => _315.resolveGroupsInfo])
13660
12534
  );
13661
12535
  const blocks = body.content.flatMap((block, blockIndex) => {
13662
12536
  switch (block.type) {
@@ -13738,12 +12612,6 @@ function toPlainLson(lson) {
13738
12612
  liveblocksType: "LiveList",
13739
12613
  data: [...lson].map((item) => toPlainLson(item))
13740
12614
  };
13741
- } else if (lson instanceof LiveText) {
13742
- return {
13743
- liveblocksType: "LiveText",
13744
- data: lson.toJSON(),
13745
- version: lson.version
13746
- };
13747
12615
  } else {
13748
12616
  return lson;
13749
12617
  }
@@ -13797,9 +12665,9 @@ function makePoller(callback, intervalMs, options) {
13797
12665
  const startTime = performance.now();
13798
12666
  const doc = typeof document !== "undefined" ? document : void 0;
13799
12667
  const win = typeof window !== "undefined" ? window : void 0;
13800
- const maxStaleTimeMs = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _329 => _329.maxStaleTimeMs]), () => ( Number.POSITIVE_INFINITY));
12668
+ const maxStaleTimeMs = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _316 => _316.maxStaleTimeMs]), () => ( Number.POSITIVE_INFINITY));
13801
12669
  const context = {
13802
- inForeground: _optionalChain([doc, 'optionalAccess', _330 => _330.visibilityState]) !== "hidden",
12670
+ inForeground: _optionalChain([doc, 'optionalAccess', _317 => _317.visibilityState]) !== "hidden",
13803
12671
  lastSuccessfulPollAt: startTime,
13804
12672
  count: 0,
13805
12673
  backoff: 0
@@ -13880,11 +12748,11 @@ function makePoller(callback, intervalMs, options) {
13880
12748
  pollNowIfStale();
13881
12749
  }
13882
12750
  function onVisibilityChange() {
13883
- setInForeground(_optionalChain([doc, 'optionalAccess', _331 => _331.visibilityState]) !== "hidden");
12751
+ setInForeground(_optionalChain([doc, 'optionalAccess', _318 => _318.visibilityState]) !== "hidden");
13884
12752
  }
13885
- _optionalChain([doc, 'optionalAccess', _332 => _332.addEventListener, 'call', _333 => _333("visibilitychange", onVisibilityChange)]);
13886
- _optionalChain([win, 'optionalAccess', _334 => _334.addEventListener, 'call', _335 => _335("online", onVisibilityChange)]);
13887
- _optionalChain([win, 'optionalAccess', _336 => _336.addEventListener, 'call', _337 => _337("focus", pollNowIfStale)]);
12753
+ _optionalChain([doc, 'optionalAccess', _319 => _319.addEventListener, 'call', _320 => _320("visibilitychange", onVisibilityChange)]);
12754
+ _optionalChain([win, 'optionalAccess', _321 => _321.addEventListener, 'call', _322 => _322("online", onVisibilityChange)]);
12755
+ _optionalChain([win, 'optionalAccess', _323 => _323.addEventListener, 'call', _324 => _324("focus", pollNowIfStale)]);
13888
12756
  fsm.start();
13889
12757
  return {
13890
12758
  inc,
@@ -14029,10 +12897,5 @@ detectDupes(PKG_NAME, PKG_VERSION, PKG_FORMAT);
14029
12897
 
14030
12898
 
14031
12899
 
14032
-
14033
-
14034
-
14035
-
14036
-
14037
- 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.LiveText = LiveText; 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.applyLiveTextOperations = applyLiveTextOperations; 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.isTextStorageNode = isTextStorageNode; exports.isUrl = isUrl; exports.kInternal = kInternal; exports.kStorageUpdateSource = kStorageUpdateSource; 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.transformTextOperations = transformTextOperations; exports.tryParseJson = tryParseJson; exports.url = url; exports.urljoin = urljoin; exports.validatePermissionsSet = validatePermissionsSet; exports.wait = wait; exports.warnOnce = warnOnce; exports.warnOnceIf = warnOnceIf; exports.withTimeout = withTimeout;
12900
+ 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;
14038
12901
  //# sourceMappingURL=index.cjs.map