@liveblocks/core 1.2.4 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,6 +1,12 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __export = (target, all) => {
3
+ for (var name in all)
4
+ __defProp(target, name, { get: all[name], enumerable: true });
5
+ };
6
+
1
7
  // src/version.ts
2
8
  var PKG_NAME = "@liveblocks/core";
3
- var PKG_VERSION = "1.2.4";
9
+ var PKG_VERSION = "1.3.0";
4
10
  var PKG_FORMAT = "esm";
5
11
 
6
12
  // src/dupe-detection.ts
@@ -150,6 +156,13 @@ function makeEventSource() {
150
156
  }
151
157
 
152
158
  // src/lib/fancy-console.ts
159
+ var fancy_console_exports = {};
160
+ __export(fancy_console_exports, {
161
+ error: () => error2,
162
+ errorWithTitle: () => errorWithTitle,
163
+ warn: () => warn,
164
+ warnWithTitle: () => warnWithTitle
165
+ });
153
166
  var badge = "background:#0e0d12;border-radius:9999px;color:#fff;padding:3px 7px;font-family:sans-serif;font-weight:600;";
154
167
  var bold = "font-weight:600";
155
168
  function wrap(method) {
@@ -624,6 +637,11 @@ var ServerMsgCode = /* @__PURE__ */ ((ServerMsgCode2) => {
624
637
  ServerMsgCode2[ServerMsgCode2["UPDATE_STORAGE"] = 201] = "UPDATE_STORAGE";
625
638
  ServerMsgCode2[ServerMsgCode2["REJECT_STORAGE_OP"] = 299] = "REJECT_STORAGE_OP";
626
639
  ServerMsgCode2[ServerMsgCode2["UPDATE_YDOC"] = 300] = "UPDATE_YDOC";
640
+ ServerMsgCode2[ServerMsgCode2["THREAD_CREATED"] = 400] = "THREAD_CREATED";
641
+ ServerMsgCode2[ServerMsgCode2["THREAD_METADATA_UPDATED"] = 401] = "THREAD_METADATA_UPDATED";
642
+ ServerMsgCode2[ServerMsgCode2["COMMENT_CREATED"] = 402] = "COMMENT_CREATED";
643
+ ServerMsgCode2[ServerMsgCode2["COMMENT_EDITED"] = 403] = "COMMENT_EDITED";
644
+ ServerMsgCode2[ServerMsgCode2["COMMENT_DELETED"] = 404] = "COMMENT_DELETED";
627
645
  return ServerMsgCode2;
628
646
  })(ServerMsgCode || {});
629
647
 
@@ -1152,10 +1170,10 @@ function createConnectionStateMachine(delegates, options) {
1152
1170
  };
1153
1171
  }
1154
1172
  var ManagedSocket = class {
1155
- constructor(delegates, enableDebugLogging = false) {
1173
+ constructor(delegates, enableDebugLogging = false, waitForActorId = true) {
1156
1174
  const { machine, events, cleanups } = createConnectionStateMachine(
1157
1175
  delegates,
1158
- { waitForActorId: true, enableDebugLogging }
1176
+ { waitForActorId, enableDebugLogging }
1159
1177
  );
1160
1178
  this.machine = machine;
1161
1179
  this.events = events;
@@ -1237,6 +1255,9 @@ var ManagedSocket = class {
1237
1255
  function canWriteStorage(scopes) {
1238
1256
  return scopes.includes("room:write" /* Write */);
1239
1257
  }
1258
+ function canComment(scopes) {
1259
+ return scopes.includes("comments:write" /* CommentsWrite */) || scopes.includes("room:write" /* Write */);
1260
+ }
1240
1261
  function isValidAuthTokenPayload(data) {
1241
1262
  return isPlainObject(data) && (data.k === "acc" /* ACCESS_TOKEN */ || data.k === "id" /* ID_TOKEN */ || data.k === "sec-legacy" /* SECRET_LEGACY */);
1242
1263
  }
@@ -1647,6 +1668,149 @@ function errorIf(condition, message) {
1647
1668
  }
1648
1669
  }
1649
1670
 
1671
+ // src/comments/index.ts
1672
+ function getAuthBearerHeaderFromAuthValue(authValue) {
1673
+ if (authValue.type === "public") {
1674
+ return authValue.publicApiKey;
1675
+ } else {
1676
+ return authValue.token.raw;
1677
+ }
1678
+ }
1679
+ function createCommentsApi(roomId, getAuthValue, { serverEndpoint }) {
1680
+ async function fetchJson(endpoint, options) {
1681
+ const response = await fetchApi(roomId, endpoint, options);
1682
+ if (!response.ok) {
1683
+ if (response.status >= 400 && response.status < 600) {
1684
+ let errorMessage = "";
1685
+ try {
1686
+ const errorBody = await response.json();
1687
+ errorMessage = errorBody.message;
1688
+ } catch (error3) {
1689
+ errorMessage = response.statusText;
1690
+ }
1691
+ throw new Error(
1692
+ `Request failed with status ${response.status}: ${errorMessage}`
1693
+ );
1694
+ }
1695
+ }
1696
+ let body;
1697
+ try {
1698
+ body = await response.json();
1699
+ } catch {
1700
+ body = {};
1701
+ }
1702
+ return body;
1703
+ }
1704
+ async function fetchApi(roomId2, endpoint, options) {
1705
+ const authValue = await getAuthValue();
1706
+ const url = `${serverEndpoint}/c/rooms/${roomId2}${endpoint}`;
1707
+ return await fetch(url, {
1708
+ ...options,
1709
+ headers: {
1710
+ ...options?.headers,
1711
+ Authorization: `Bearer ${getAuthBearerHeaderFromAuthValue(authValue)}`
1712
+ }
1713
+ });
1714
+ }
1715
+ async function getThreads() {
1716
+ const response = await fetchApi(roomId, "/threads");
1717
+ if (response.ok) {
1718
+ const json = await response.json();
1719
+ return json.data;
1720
+ } else if (response.status === 404) {
1721
+ return [];
1722
+ } else {
1723
+ throw new Error("There was an error while getting threads.");
1724
+ }
1725
+ }
1726
+ function createThread({
1727
+ metadata,
1728
+ body,
1729
+ commentId,
1730
+ threadId
1731
+ }) {
1732
+ return fetchJson("/threads", {
1733
+ method: "POST",
1734
+ headers: {
1735
+ "Content-Type": "application/json"
1736
+ },
1737
+ body: JSON.stringify({
1738
+ id: threadId,
1739
+ comment: {
1740
+ id: commentId,
1741
+ body
1742
+ },
1743
+ metadata
1744
+ })
1745
+ });
1746
+ }
1747
+ function editThreadMetadata({
1748
+ metadata,
1749
+ threadId
1750
+ }) {
1751
+ return fetchJson(
1752
+ `/threads/${threadId}/metadata`,
1753
+ {
1754
+ method: "POST",
1755
+ headers: {
1756
+ "Content-Type": "application/json"
1757
+ },
1758
+ body: JSON.stringify(metadata)
1759
+ }
1760
+ );
1761
+ }
1762
+ function createComment({
1763
+ threadId,
1764
+ commentId,
1765
+ body
1766
+ }) {
1767
+ return fetchJson(`/threads/${threadId}/comments`, {
1768
+ method: "POST",
1769
+ headers: {
1770
+ "Content-Type": "application/json"
1771
+ },
1772
+ body: JSON.stringify({
1773
+ id: commentId,
1774
+ body
1775
+ })
1776
+ });
1777
+ }
1778
+ function editComment({
1779
+ threadId,
1780
+ commentId,
1781
+ body
1782
+ }) {
1783
+ return fetchJson(
1784
+ `/threads/${threadId}/comments/${commentId}`,
1785
+ {
1786
+ method: "POST",
1787
+ headers: {
1788
+ "Content-Type": "application/json"
1789
+ },
1790
+ body: JSON.stringify({
1791
+ body
1792
+ })
1793
+ }
1794
+ );
1795
+ }
1796
+ async function deleteComment({
1797
+ threadId,
1798
+ commentId
1799
+ }) {
1800
+ await fetchJson(`/threads/${threadId}/comments/${commentId}`, {
1801
+ method: "DELETE"
1802
+ });
1803
+ }
1804
+ return {
1805
+ getThreads,
1806
+ createThread,
1807
+ editThreadMetadata,
1808
+ createComment,
1809
+ editComment,
1810
+ deleteComment
1811
+ };
1812
+ }
1813
+
1650
1814
  // src/lib/position.ts
1651
1815
  var MIN_CODE = 32;
1652
1816
  var MAX_CODE = 126;
@@ -4190,19 +4354,6 @@ var ClientMsgCode = /* @__PURE__ */ ((ClientMsgCode2) => {
4190
4354
  return ClientMsgCode2;
4191
4355
  })(ClientMsgCode || {});
4192
4356
 
4193
- // src/lib/LegacyArray.ts
4194
- function asArrayWithLegacyMethods(arr) {
4195
- Object.defineProperty(arr, "count", {
4196
- value: arr.length,
4197
- enumerable: false
4198
- });
4199
- Object.defineProperty(arr, "toArray", {
4200
- value: () => arr,
4201
- enumerable: false
4202
- });
4203
- return freeze(arr);
4204
- }
4205
-
4206
4357
  // src/refs/ImmutableRef.ts
4207
4358
  function merge(target, patch) {
4208
4359
  let updated = false;
@@ -4249,6 +4400,7 @@ function makeUser(conn, presence) {
4249
4400
  id,
4250
4401
  info,
4251
4402
  canWrite,
4403
+ canComment: canComment(conn.scopes),
4252
4404
  isReadOnly: !canWrite,
4253
4405
  // Deprecated, kept for backward-compatibility
4254
4406
  presence
@@ -4275,7 +4427,7 @@ var OthersRef = class extends ImmutableRef {
4275
4427
  (connectionId) => this.getUser(Number(connectionId))
4276
4428
  )
4277
4429
  );
4278
- return asArrayWithLegacyMethods(users);
4430
+ return users;
4279
4431
  }
4280
4432
  clearOthers() {
4281
4433
  this._connections = /* @__PURE__ */ new Map();
@@ -4636,7 +4788,8 @@ function createRoom(options, config) {
4636
4788
  history: makeEventSource(),
4637
4789
  storageDidLoad: makeEventSource(),
4638
4790
  storageStatus: makeEventSource(),
4639
- ydoc: makeEventSource()
4791
+ ydoc: makeEventSource(),
4792
+ comments: makeEventSource()
4640
4793
  };
4641
4794
  function sendMessages(messageOrMessages) {
4642
4795
  const message = JSON.stringify(messageOrMessages);
@@ -4677,6 +4830,7 @@ function createRoom(options, config) {
4677
4830
  info: staticSession.userInfo,
4678
4831
  presence: myPresence,
4679
4832
  canWrite,
4833
+ canComment: canComment(dynamicSession.scopes),
4680
4834
  isReadOnly: !canWrite
4681
4835
  // Deprecated, kept for backward-compatibility
4682
4836
  };
@@ -5135,6 +5289,14 @@ ${Array.from(traces).join("\n\n")}`
5135
5289
  }
5136
5290
  break;
5137
5291
  }
5292
+ case 400 /* THREAD_CREATED */:
5293
+ case 401 /* THREAD_METADATA_UPDATED */:
5294
+ case 402 /* COMMENT_CREATED */:
5295
+ case 403 /* COMMENT_EDITED */:
5296
+ case 404 /* COMMENT_DELETED */: {
5297
+ eventHub.comments.notify(message);
5298
+ break;
5299
+ }
5138
5300
  }
5139
5301
  }
5140
5302
  notify(updates, doNotBatchUpdates);
@@ -5401,8 +5563,12 @@ ${Array.from(traces).join("\n\n")}`
5401
5563
  history: eventHub.history.observable,
5402
5564
  storageDidLoad: eventHub.storageDidLoad.observable,
5403
5565
  storageStatus: eventHub.storageStatus.observable,
5404
- ydoc: eventHub.ydoc.observable
5566
+ ydoc: eventHub.ydoc.observable,
5567
+ comments: eventHub.comments.observable
5405
5568
  };
5569
+ const commentsApi = createCommentsApi(config.roomId, delegates.authenticate, {
5570
+ serverEndpoint: "https://api.liveblocks.io/v2"
5571
+ });
5406
5572
  return Object.defineProperty(
5407
5573
  {
5408
5574
  /* NOTE: Exposing __internal here only to allow testing implementation details in unit tests */
@@ -5460,7 +5626,8 @@ ${Array.from(traces).join("\n\n")}`
5460
5626
  getSelf: () => self.current,
5461
5627
  // Presence
5462
5628
  getPresence: () => context.myPresence.current,
5463
- getOthers: () => context.others.current
5629
+ getOthers: () => context.others.current,
5630
+ ...commentsApi
5464
5631
  },
5465
5632
  // Explictly make the __internal field non-enumerable, to avoid aggressive
5466
5633
  // freezing when used with Immer
@@ -6085,6 +6252,222 @@ function shallow(a, b) {
6085
6252
  return shallowObj(a, b);
6086
6253
  }
6087
6254
 
6255
+ // src/lib/AsyncCache.ts
6256
+ var noop = () => {
6257
+ };
6258
+ function isShallowEqual(a, b) {
6259
+ if (a.isLoading !== b.isLoading || a.data === void 0 !== (b.data === void 0) || a.error === void 0 !== (b.error === void 0)) {
6260
+ return false;
6261
+ } else {
6262
+ return shallow(a.data, b.data) && shallow(a.error, b.error);
6263
+ }
6264
+ }
6265
+ function createCacheItem(key, defaultAsyncFunction, options) {
6266
+ let asyncFunction = defaultAsyncFunction;
6267
+ const context = {
6268
+ isInvalid: true
6269
+ };
6270
+ let state = { isLoading: false };
6271
+ let previousState = { isLoading: false };
6272
+ const eventSource2 = makeEventSource();
6273
+ function notify() {
6274
+ const isEqual = options?.isStateEqual ?? isShallowEqual;
6275
+ if (!isEqual(previousState, state)) {
6276
+ previousState = state;
6277
+ eventSource2.notify(state);
6278
+ }
6279
+ }
6280
+ async function resolve() {
6281
+ if (!context.promise) {
6282
+ return;
6283
+ }
6284
+ try {
6285
+ const data = await context.promise;
6286
+ context.isInvalid = false;
6287
+ state = {
6288
+ isLoading: false,
6289
+ data
6290
+ };
6291
+ } catch (error3) {
6292
+ state = {
6293
+ isLoading: false,
6294
+ data: state.data,
6295
+ error: error3
6296
+ };
6297
+ }
6298
+ context.promise = void 0;
6299
+ notify();
6300
+ }
6301
+ async function revalidate() {
6302
+ context.isInvalid = true;
6303
+ return get();
6304
+ }
6305
+ async function get() {
6306
+ if (context.isInvalid) {
6307
+ if (!context.promise) {
6308
+ context.isInvalid = true;
6309
+ context.promise = asyncFunction(key);
6310
+ state = { isLoading: true, data: state.data };
6311
+ notify();
6312
+ }
6313
+ await resolve();
6314
+ }
6315
+ return getState();
6316
+ }
6317
+ function getState() {
6318
+ return state;
6319
+ }
6320
+ function setAsyncFunction(overrideAsyncFunction) {
6321
+ asyncFunction = overrideAsyncFunction;
6322
+ }
6323
+ return {
6324
+ ...eventSource2.observable,
6325
+ setAsyncFunction,
6326
+ get,
6327
+ getState,
6328
+ revalidate
6329
+ };
6330
+ }
6331
+ function createAsyncCache(asyncFunction, options) {
6332
+ const cache = /* @__PURE__ */ new Map();
6333
+ function create(key, overrideAsyncFunction) {
6334
+ let cacheItem = cache.get(key);
6335
+ if (cacheItem) {
6336
+ if (overrideAsyncFunction) {
6337
+ cacheItem.setAsyncFunction(overrideAsyncFunction);
6338
+ }
6339
+ return cacheItem;
6340
+ }
6341
+ cacheItem = createCacheItem(
6342
+ key,
6343
+ overrideAsyncFunction ?? asyncFunction,
6344
+ options
6345
+ );
6346
+ cache.set(key, cacheItem);
6347
+ return cacheItem;
6348
+ }
6349
+ function get(key) {
6350
+ return create(key).get();
6351
+ }
6352
+ function getState(key) {
6353
+ return cache.get(key)?.getState();
6354
+ }
6355
+ function revalidate(key) {
6356
+ return create(key).revalidate();
6357
+ }
6358
+ function subscribe(key, callback) {
6359
+ return create(key).subscribe(callback) ?? noop;
6360
+ }
6361
+ function subscribeOnce(key, callback) {
6362
+ return create(key).subscribeOnce(callback) ?? noop;
6363
+ }
6364
+ function has(key) {
6365
+ return cache.has(key);
6366
+ }
6367
+ function clear() {
6368
+ cache.clear();
6369
+ }
6370
+ return {
6371
+ create,
6372
+ get,
6373
+ getState,
6374
+ revalidate,
6375
+ subscribe,
6376
+ subscribeOnce,
6377
+ has,
6378
+ clear
6379
+ };
6380
+ }
6381
+
6382
+ // src/lib/Poller.ts
6383
+ function makePoller(callback) {
6384
+ let context = {
6385
+ state: "stopped",
6386
+ timeoutHandle: null,
6387
+ interval: null,
6388
+ lastScheduledAt: null,
6389
+ remainingInterval: null
6390
+ };
6391
+ function poll() {
6392
+ if (context.state === "running") {
6393
+ schedule(context.interval);
6394
+ }
6395
+ void callback();
6396
+ }
6397
+ function schedule(interval) {
6398
+ context = {
6399
+ state: "running",
6400
+ interval: context.state !== "stopped" ? context.interval : interval,
6401
+ lastScheduledAt: performance.now(),
6402
+ timeoutHandle: setTimeout(poll, interval),
6403
+ remainingInterval: null
6404
+ };
6405
+ }
6406
+ function scheduleRemaining(remaining) {
6407
+ if (context.state !== "paused") {
6408
+ return;
6409
+ }
6410
+ context = {
6411
+ state: "running",
6412
+ interval: context.interval,
6413
+ lastScheduledAt: context.lastScheduledAt,
6414
+ timeoutHandle: setTimeout(poll, remaining),
6415
+ remainingInterval: null
6416
+ };
6417
+ }
6418
+ function start(interval) {
6419
+ if (context.state === "running") {
6420
+ return;
6421
+ }
6422
+ schedule(interval);
6423
+ }
6424
+ function restart(interval) {
6425
+ stop();
6426
+ start(interval);
6427
+ }
6428
+ function pause() {
6429
+ if (context.state !== "running") {
6430
+ return;
6431
+ }
6432
+ clearTimeout(context.timeoutHandle);
6433
+ context = {
6434
+ state: "paused",
6435
+ interval: context.interval,
6436
+ lastScheduledAt: context.lastScheduledAt,
6437
+ timeoutHandle: null,
6438
+ remainingInterval: context.interval - (performance.now() - context.lastScheduledAt)
6439
+ };
6440
+ }
6441
+ function resume() {
6442
+ if (context.state !== "paused") {
6443
+ return;
6444
+ }
6445
+ scheduleRemaining(context.remainingInterval);
6446
+ }
6447
+ function stop() {
6448
+ if (context.state === "stopped") {
6449
+ return;
6450
+ }
6451
+ if (context.timeoutHandle) {
6452
+ clearTimeout(context.timeoutHandle);
6453
+ }
6454
+ context = {
6455
+ state: "stopped",
6456
+ interval: null,
6457
+ lastScheduledAt: null,
6458
+ timeoutHandle: null,
6459
+ remainingInterval: null
6460
+ };
6461
+ }
6462
+ return {
6463
+ start,
6464
+ restart,
6465
+ pause,
6466
+ resume,
6467
+ stop
6468
+ };
6469
+ }
6470
+
6088
6471
  // src/index.ts
6089
6472
  detectDupes(PKG_NAME, PKG_VERSION, PKG_FORMAT);
6090
6473
  export {
@@ -6096,12 +6479,14 @@ export {
6096
6479
  OpCode,
6097
6480
  ServerMsgCode,
6098
6481
  WebsocketCloseCodes,
6099
- asArrayWithLegacyMethods,
6100
6482
  asPos,
6101
6483
  assert,
6102
6484
  assertNever,
6103
6485
  b64decode,
6486
+ fancy_console_exports as console,
6487
+ createAsyncCache,
6104
6488
  createClient,
6489
+ createCommentsApi,
6105
6490
  deprecate,
6106
6491
  deprecateIf,
6107
6492
  detectDupes,
@@ -6115,6 +6500,8 @@ export {
6115
6500
  isRootCrdt,
6116
6501
  legacy_patchImmutableObject,
6117
6502
  lsonToJson,
6503
+ makeEventSource,
6504
+ makePoller,
6118
6505
  makePosition,
6119
6506
  nn,
6120
6507
  patchLiveObjectKey,