@liveblocks/core 3.6.0 → 3.7.0-preview1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ var __export = (target, all) => {
6
6
 
7
7
  // src/version.ts
8
8
  var PKG_NAME = "@liveblocks/core";
9
- var PKG_VERSION = "3.6.0";
9
+ var PKG_VERSION = "3.7.0-preview1";
10
10
  var PKG_FORMAT = "esm";
11
11
 
12
12
  // src/dupe-detection.ts
@@ -851,6 +851,38 @@ function convertToSubscriptionDeleteInfo(data) {
851
851
  deletedAt
852
852
  };
853
853
  }
854
+ function convertToGroupData(data) {
855
+ const createdAt = new Date(data.createdAt);
856
+ const updatedAt = new Date(data.updatedAt);
857
+ const members = data.members.map((member) => ({
858
+ ...member,
859
+ addedAt: new Date(member.addedAt)
860
+ }));
861
+ return {
862
+ ...data,
863
+ createdAt,
864
+ updatedAt,
865
+ members
866
+ };
867
+ }
868
+
869
+ // src/lib/assert.ts
870
+ function assertNever(_value, errmsg) {
871
+ throw new Error(errmsg);
872
+ }
873
+ function assert(condition, errmsg) {
874
+ if (process.env.NODE_ENV !== "production") {
875
+ if (!condition) {
876
+ const err = new Error(errmsg);
877
+ err.name = "Assertion failure";
878
+ throw err;
879
+ }
880
+ }
881
+ }
882
+ function nn(value, errmsg = "Expected value to be non-nullable") {
883
+ assert(value !== null && value !== void 0, errmsg);
884
+ return value;
885
+ }
854
886
 
855
887
  // src/lib/fancy-console.ts
856
888
  var fancy_console_exports = {};
@@ -1128,11 +1160,20 @@ function createBatchStore(batch2) {
1128
1160
  });
1129
1161
  }
1130
1162
  }
1163
+ function fill(input, data) {
1164
+ const cacheKey = getCacheKey(input);
1165
+ update(cacheKey, { isLoading: false, data });
1166
+ }
1131
1167
  function getItemState(input) {
1132
1168
  const cacheKey = getCacheKey(input);
1133
1169
  const cache = signal.get();
1134
1170
  return cache.get(cacheKey);
1135
1171
  }
1172
+ function getData(input) {
1173
+ const cacheKey = getCacheKey(input);
1174
+ const cache = signal.get();
1175
+ return cache.get(cacheKey)?.data;
1176
+ }
1136
1177
  function _cacheKeys() {
1137
1178
  const cache = signal.get();
1138
1179
  return [...cache.keys()];
@@ -1140,7 +1181,9 @@ function createBatchStore(batch2) {
1140
1181
  return {
1141
1182
  subscribe: signal.subscribe,
1142
1183
  enqueue,
1184
+ fill,
1143
1185
  getItemState,
1186
+ getData,
1144
1187
  invalidate,
1145
1188
  batch: batch2,
1146
1189
  _cacheKeys
@@ -1962,6 +2005,9 @@ function createApiClient({
1962
2005
  return batch2.get(options.inboxNotificationId);
1963
2006
  }
1964
2007
  async function createTextMention(options) {
2008
+ if (options.mention.kind !== "user" && options.mention.kind !== "group") {
2009
+ return assertNever(options.mention, "Unexpected mention kind");
2010
+ }
1965
2011
  await httpClient.rawPost(
1966
2012
  url`/v2/c/rooms/${options.roomId}/text-mentions`,
1967
2013
  await authManager.getAuthValue({
@@ -1969,7 +2015,9 @@ function createApiClient({
1969
2015
  roomId: options.roomId
1970
2016
  }),
1971
2017
  {
1972
- userId: options.userId,
2018
+ userId: options.mention.kind === "user" ? options.mention.id : void 0,
2019
+ groupId: options.mention.kind === "group" ? options.mention.id : void 0,
2020
+ userIds: options.mention.kind === "group" ? options.mention.userIds : void 0,
1973
2021
  mentionId: options.mentionId
1974
2022
  }
1975
2023
  );
@@ -2108,6 +2156,10 @@ function createApiClient({
2108
2156
  limit: PAGE_SIZE
2109
2157
  }
2110
2158
  );
2159
+ const groups = json.groups.map(convertToGroupData);
2160
+ for (const group of groups) {
2161
+ groupsStore.fill(group.id, group);
2162
+ }
2111
2163
  return {
2112
2164
  inboxNotifications: json.inboxNotifications.map(
2113
2165
  convertToInboxNotificationData
@@ -2258,6 +2310,28 @@ function createApiClient({
2258
2310
  permissionHints: json.meta.permissionHints
2259
2311
  };
2260
2312
  }
2313
+ const batchedGetGroups = new Batch(
2314
+ async (batchedGroupIds) => {
2315
+ const groupIds = batchedGroupIds.flat();
2316
+ const { groups: plainGroups } = await httpClient.post(
2317
+ url`/v2/c/groups/find`,
2318
+ await authManager.getAuthValue({
2319
+ requestedScope: "comments:read"
2320
+ }),
2321
+ { groupIds }
2322
+ );
2323
+ const groups = /* @__PURE__ */ new Map();
2324
+ for (const group of plainGroups) {
2325
+ groups.set(group.id, convertToGroupData(group));
2326
+ }
2327
+ return groupIds.map((groupId) => groups.get(groupId));
2328
+ },
2329
+ { delay: 50 }
2330
+ );
2331
+ const groupsStore = createBatchStore(batchedGetGroups);
2332
+ function getGroup(groupId) {
2333
+ return batchedGetGroups.get(groupId);
2334
+ }
2261
2335
  return {
2262
2336
  // Room threads
2263
2337
  getThreads,
@@ -2311,6 +2385,9 @@ function createApiClient({
2311
2385
  // User threads
2312
2386
  getUserThreads_experimental,
2313
2387
  getUserThreadsSince_experimental,
2388
+ // Groups
2389
+ groupsStore,
2390
+ getGroup,
2314
2391
  // AI
2315
2392
  executeContextualPrompt
2316
2393
  };
@@ -2468,24 +2545,6 @@ var HttpClient = class {
2468
2545
  }
2469
2546
  };
2470
2547
 
2471
- // src/lib/assert.ts
2472
- function assertNever(_value, errmsg) {
2473
- throw new Error(errmsg);
2474
- }
2475
- function assert(condition, errmsg) {
2476
- if (process.env.NODE_ENV !== "production") {
2477
- if (!condition) {
2478
- const err = new Error(errmsg);
2479
- err.name = "Assertion failure";
2480
- throw err;
2481
- }
2482
- }
2483
- }
2484
- function nn(value, errmsg = "Expected value to be non-nullable") {
2485
- assert(value !== null && value !== void 0, errmsg);
2486
- return value;
2487
- }
2488
-
2489
2548
  // src/lib/fsm.ts
2490
2549
  function distance(state1, state2) {
2491
2550
  if (state1 === state2) {
@@ -5121,6 +5180,7 @@ async function fetchAuthEndpoint(fetch, endpoint, body) {
5121
5180
 
5122
5181
  // src/constants.ts
5123
5182
  var DEFAULT_BASE_URL = "https://api.liveblocks.io";
5183
+ var MENTION_CHARACTER = "@";
5124
5184
 
5125
5185
  // src/devtools/bridge.ts
5126
5186
  var _bridgeActive = false;
@@ -5340,6 +5400,22 @@ function unlinkDevTools(roomId) {
5340
5400
  });
5341
5401
  }
5342
5402
 
5403
+ // src/lib/warnings.ts
5404
+ var _emittedWarnings = /* @__PURE__ */ new Set();
5405
+ function warnOnce(message, key = message) {
5406
+ if (process.env.NODE_ENV !== "production") {
5407
+ if (!_emittedWarnings.has(key)) {
5408
+ _emittedWarnings.add(key);
5409
+ warn(message);
5410
+ }
5411
+ }
5412
+ }
5413
+ function warnOnceIf(condition, message, key = message) {
5414
+ if (typeof condition === "function" ? condition() : condition) {
5415
+ warnOnce(message, key);
5416
+ }
5417
+ }
5418
+
5343
5419
  // src/protocol/NotificationSettings.ts
5344
5420
  var kPlain = Symbol("notification-settings-plain");
5345
5421
  function createNotificationSettings(plain) {
@@ -8554,8 +8630,8 @@ function createRoom(options, config) {
8554
8630
  comments: makeEventSource(),
8555
8631
  roomWillDestroy: makeEventSource()
8556
8632
  };
8557
- async function createTextMention(userId, mentionId) {
8558
- return httpClient.createTextMention({ roomId, userId, mentionId });
8633
+ async function createTextMention(mentionId, mention) {
8634
+ return httpClient.createTextMention({ roomId, mentionId, mention });
8559
8635
  }
8560
8636
  async function deleteTextMention(mentionId) {
8561
8637
  return httpClient.deleteTextMention({ roomId, mentionId });
@@ -9876,6 +9952,7 @@ var MAX_LOST_CONNECTION_TIMEOUT = 3e4;
9876
9952
  var DEFAULT_LOST_CONNECTION_TIMEOUT = 5e3;
9877
9953
  var RESOLVE_USERS_BATCH_DELAY = 50;
9878
9954
  var RESOLVE_ROOMS_INFO_BATCH_DELAY = 50;
9955
+ var RESOLVE_GROUPS_INFO_BATCH_DELAY = 50;
9879
9956
  function getBaseUrl(baseUrl) {
9880
9957
  if (typeof baseUrl === "string" && baseUrl.startsWith("http")) {
9881
9958
  return baseUrl;
@@ -10033,15 +10110,14 @@ function createClient(options) {
10033
10110
  }
10034
10111
  }
10035
10112
  const resolveUsers = clientOptions.resolveUsers;
10036
- const warnIfNoResolveUsers = createDevelopmentWarning(
10037
- () => !resolveUsers,
10038
- "Set the resolveUsers option in createClient to specify user info."
10039
- );
10040
10113
  const batchedResolveUsers = new Batch(
10041
10114
  async (batchedUserIds) => {
10042
10115
  const userIds = batchedUserIds.flat();
10043
10116
  const users = await resolveUsers?.({ userIds });
10044
- warnIfNoResolveUsers();
10117
+ warnOnceIf(
10118
+ !resolveUsers,
10119
+ "Set the resolveUsers option in createClient to specify user info."
10120
+ );
10045
10121
  return users ?? userIds.map(() => void 0);
10046
10122
  },
10047
10123
  { delay: RESOLVE_USERS_BATCH_DELAY }
@@ -10051,15 +10127,14 @@ function createClient(options) {
10051
10127
  usersStore.invalidate(userIds);
10052
10128
  }
10053
10129
  const resolveRoomsInfo = clientOptions.resolveRoomsInfo;
10054
- const warnIfNoResolveRoomsInfo = createDevelopmentWarning(
10055
- () => !resolveRoomsInfo,
10056
- "Set the resolveRoomsInfo option in createClient to specify room info."
10057
- );
10058
10130
  const batchedResolveRoomsInfo = new Batch(
10059
10131
  async (batchedRoomIds) => {
10060
10132
  const roomIds = batchedRoomIds.flat();
10061
10133
  const roomsInfo = await resolveRoomsInfo?.({ roomIds });
10062
- warnIfNoResolveRoomsInfo();
10134
+ warnOnceIf(
10135
+ !resolveRoomsInfo,
10136
+ "Set the resolveRoomsInfo option in createClient to specify room info."
10137
+ );
10063
10138
  return roomsInfo ?? roomIds.map(() => void 0);
10064
10139
  },
10065
10140
  { delay: RESOLVE_ROOMS_INFO_BATCH_DELAY }
@@ -10068,6 +10143,23 @@ function createClient(options) {
10068
10143
  function invalidateResolvedRoomsInfo(roomIds) {
10069
10144
  roomsInfoStore.invalidate(roomIds);
10070
10145
  }
10146
+ const resolveGroupsInfo = clientOptions.resolveGroupsInfo;
10147
+ const batchedResolveGroupsInfo = new Batch(
10148
+ async (batchedGroupIds) => {
10149
+ const groupIds = batchedGroupIds.flat();
10150
+ const groupsInfo = await resolveGroupsInfo?.({ groupIds });
10151
+ warnOnceIf(
10152
+ !resolveGroupsInfo,
10153
+ "Set the resolveGroupsInfo option in createClient to specify group info."
10154
+ );
10155
+ return groupsInfo ?? groupIds.map(() => void 0);
10156
+ },
10157
+ { delay: RESOLVE_GROUPS_INFO_BATCH_DELAY }
10158
+ );
10159
+ const groupsInfoStore = createBatchStore(batchedResolveGroupsInfo);
10160
+ function invalidateResolvedGroupsInfo(groupIds) {
10161
+ groupsInfoStore.invalidate(groupIds);
10162
+ }
10071
10163
  const mentionSuggestionsCache = /* @__PURE__ */ new Map();
10072
10164
  function invalidateResolvedMentionSuggestions() {
10073
10165
  mentionSuggestionsCache.clear();
@@ -10143,6 +10235,7 @@ function createClient(options) {
10143
10235
  resolvers: {
10144
10236
  invalidateUsers: invalidateResolvedUsers,
10145
10237
  invalidateRoomsInfo: invalidateResolvedRoomsInfo,
10238
+ invalidateGroupsInfo: invalidateResolvedGroupsInfo,
10146
10239
  invalidateMentionSuggestions: invalidateResolvedMentionSuggestions
10147
10240
  },
10148
10241
  getSyncStatus,
@@ -10158,6 +10251,7 @@ function createClient(options) {
10158
10251
  resolveMentionSuggestions: clientOptions.resolveMentionSuggestions,
10159
10252
  usersStore,
10160
10253
  roomsInfoStore,
10254
+ groupsInfoStore,
10161
10255
  getRoomIds() {
10162
10256
  return Array.from(roomsById.keys());
10163
10257
  },
@@ -10209,20 +10303,6 @@ function getLostConnectionTimeout(value) {
10209
10303
  RECOMMENDED_MIN_LOST_CONNECTION_TIMEOUT
10210
10304
  );
10211
10305
  }
10212
- function createDevelopmentWarning(condition, ...args) {
10213
- let hasWarned = false;
10214
- if (process.env.NODE_ENV !== "production") {
10215
- return () => {
10216
- if (!hasWarned && (typeof condition === "function" ? condition() : condition)) {
10217
- warn(...args);
10218
- hasWarned = true;
10219
- }
10220
- };
10221
- } else {
10222
- return () => {
10223
- };
10224
- }
10225
- }
10226
10306
 
10227
10307
  // src/comments/comment-body.ts
10228
10308
  function isCommentBodyParagraph(element) {
@@ -10287,25 +10367,42 @@ function getMentionsFromCommentBody(body, predicate) {
10287
10367
  });
10288
10368
  return mentions;
10289
10369
  }
10290
- async function resolveUsersInCommentBody(body, resolveUsers) {
10370
+ async function resolveMentionsInCommentBody(body, resolveUsers, resolveGroupsInfo) {
10291
10371
  const resolvedUsers = /* @__PURE__ */ new Map();
10292
- if (!resolveUsers) {
10293
- return resolvedUsers;
10372
+ const resolvedGroupsInfo = /* @__PURE__ */ new Map();
10373
+ if (!resolveUsers && !resolveGroupsInfo) {
10374
+ return {
10375
+ users: resolvedUsers,
10376
+ groups: resolvedGroupsInfo
10377
+ };
10294
10378
  }
10295
- const userIds = getMentionsFromCommentBody(
10296
- body,
10297
- (mention) => mention.kind === "user"
10298
- ).map((mention) => mention.id);
10299
- const users = await resolveUsers({
10300
- userIds
10301
- });
10302
- for (const [index, userId] of userIds.entries()) {
10303
- const user = users?.[index];
10304
- if (user) {
10305
- resolvedUsers.set(userId, user);
10379
+ const mentions = getMentionsFromCommentBody(body);
10380
+ const userIds = mentions.filter((mention) => mention.kind === "user").map((mention) => mention.id);
10381
+ const groupIds = mentions.filter((mention) => mention.kind === "group").map((mention) => mention.id);
10382
+ const [users, groups] = await Promise.all([
10383
+ resolveUsers && userIds.length > 0 ? resolveUsers({ userIds }) : void 0,
10384
+ resolveGroupsInfo && groupIds.length > 0 ? resolveGroupsInfo({ groupIds }) : void 0
10385
+ ]);
10386
+ if (users) {
10387
+ for (const [index, userId] of userIds.entries()) {
10388
+ const user = users[index];
10389
+ if (user) {
10390
+ resolvedUsers.set(userId, user);
10391
+ }
10392
+ }
10393
+ }
10394
+ if (groups) {
10395
+ for (const [index, groupId] of groupIds.entries()) {
10396
+ const group = groups[index];
10397
+ if (group) {
10398
+ resolvedGroupsInfo.set(groupId, group);
10399
+ }
10306
10400
  }
10307
10401
  }
10308
- return resolvedUsers;
10402
+ return {
10403
+ users: resolvedUsers,
10404
+ groups: resolvedGroupsInfo
10405
+ };
10309
10406
  }
10310
10407
  var htmlEscapables = {
10311
10408
  "&": "&",
@@ -10418,8 +10515,8 @@ var stringifyCommentBodyPlainElements = {
10418
10515
  paragraph: ({ children }) => children,
10419
10516
  text: ({ element }) => element.text,
10420
10517
  link: ({ element }) => element.text ?? element.url,
10421
- mention: ({ element, user }) => {
10422
- return `@${user?.name ?? element.id}`;
10518
+ mention: ({ element, user, group }) => {
10519
+ return `@${user?.name ?? group?.name ?? element.id}`;
10423
10520
  }
10424
10521
  };
10425
10522
  var stringifyCommentBodyHtmlElements = {
@@ -10448,8 +10545,8 @@ var stringifyCommentBodyHtmlElements = {
10448
10545
  link: ({ element, href }) => {
10449
10546
  return html`<a href="${href}" target="_blank" rel="noopener noreferrer">${element.text ? html`${element.text}` : element.url}</a>`;
10450
10547
  },
10451
- mention: ({ element, user }) => {
10452
- return html`<span data-mention>@${user?.name ? html`${user?.name}` : element.id}</span>`;
10548
+ mention: ({ element, user, group }) => {
10549
+ return html`<span data-mention>@${user?.name ? html`${user?.name}` : group?.name ? html`${group?.name}` : element.id}</span>`;
10453
10550
  }
10454
10551
  };
10455
10552
  var stringifyCommentBodyMarkdownElements = {
@@ -10478,8 +10575,8 @@ var stringifyCommentBodyMarkdownElements = {
10478
10575
  link: ({ element, href }) => {
10479
10576
  return markdown`[${element.text ?? element.url}](${href})`;
10480
10577
  },
10481
- mention: ({ element, user }) => {
10482
- return markdown`@${user?.name ?? element.id}`;
10578
+ mention: ({ element, user, group }) => {
10579
+ return markdown`@${user?.name ?? group?.name ?? element.id}`;
10483
10580
  }
10484
10581
  };
10485
10582
  async function stringifyCommentBody(body, options) {
@@ -10489,9 +10586,10 @@ async function stringifyCommentBody(body, options) {
10489
10586
  ...format === "html" ? stringifyCommentBodyHtmlElements : format === "markdown" ? stringifyCommentBodyMarkdownElements : stringifyCommentBodyPlainElements,
10490
10587
  ...options?.elements
10491
10588
  };
10492
- const resolvedUsers = await resolveUsersInCommentBody(
10589
+ const { users: resolvedUsers, groups: resolvedGroupsInfo } = await resolveMentionsInCommentBody(
10493
10590
  body,
10494
- options?.resolveUsers
10591
+ options?.resolveUsers,
10592
+ options?.resolveGroupsInfo
10495
10593
  );
10496
10594
  const blocks = body.content.flatMap((block, blockIndex) => {
10497
10595
  switch (block.type) {
@@ -10502,7 +10600,8 @@ async function stringifyCommentBody(body, options) {
10502
10600
  elements.mention(
10503
10601
  {
10504
10602
  element: inline,
10505
- user: resolvedUsers.get(inline.id)
10603
+ user: inline.kind === "user" ? resolvedUsers.get(inline.id) : void 0,
10604
+ group: inline.kind === "group" ? resolvedGroupsInfo.get(inline.id) : void 0
10506
10605
  },
10507
10606
  inlineIndex
10508
10607
  )
@@ -11056,6 +11155,7 @@ export {
11056
11155
  LiveMap,
11057
11156
  LiveObject,
11058
11157
  LiveblocksError,
11158
+ MENTION_CHARACTER,
11059
11159
  MutableSignal,
11060
11160
  OpCode,
11061
11161
  Permission,
@@ -11079,6 +11179,7 @@ export {
11079
11179
  fancy_console_exports as console,
11080
11180
  convertToCommentData,
11081
11181
  convertToCommentUserReaction,
11182
+ convertToGroupData,
11082
11183
  convertToInboxNotificationData,
11083
11184
  convertToSubscriptionData,
11084
11185
  convertToThreadData,
@@ -11132,7 +11233,7 @@ export {
11132
11233
  patchLiveObjectKey,
11133
11234
  patchNotificationSettings,
11134
11235
  raise,
11135
- resolveUsersInCommentBody,
11236
+ resolveMentionsInCommentBody,
11136
11237
  sanitizeUrl,
11137
11238
  shallow,
11138
11239
  shallow2,
@@ -11144,6 +11245,8 @@ export {
11144
11245
  url,
11145
11246
  urljoin,
11146
11247
  wait,
11248
+ warnOnce,
11249
+ warnOnceIf,
11147
11250
  withTimeout
11148
11251
  };
11149
11252
  //# sourceMappingURL=index.js.map