@liveblocks/core 1.12.0-test1 → 1.12.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
@@ -6,7 +6,7 @@ var __export = (target, all) => {
6
6
 
7
7
  // src/version.ts
8
8
  var PKG_NAME = "@liveblocks/core";
9
- var PKG_VERSION = "1.12.0-test1";
9
+ var PKG_VERSION = "1.12.0";
10
10
  var PKG_FORMAT = "esm";
11
11
 
12
12
  // src/dupe-detection.ts
@@ -782,9 +782,13 @@ function logPrematureErrorOrCloseEvent(e) {
782
782
  };
783
783
  }
784
784
  function logCloseEvent(event) {
785
+ const details = [`code: ${event.code}`];
786
+ if (event.reason) {
787
+ details.push(`reason: ${event.reason}`);
788
+ }
785
789
  return (ctx) => {
786
790
  warn(
787
- `Connection to Liveblocks websocket server closed (code: ${event.code}). Retrying in ${ctx.backoffDelay}ms.`
791
+ `Connection to Liveblocks websocket server closed (${details.join(", ")}). Retrying in ${ctx.backoffDelay}ms.`
788
792
  );
789
793
  };
790
794
  }
@@ -1385,7 +1389,6 @@ function createAuthManager(authOptions) {
1385
1389
  room: options.roomId
1386
1390
  });
1387
1391
  const parsed = parseAuthToken(response.token);
1388
- verifyTokenPermissions(parsed, options);
1389
1392
  if (seenTokens.has(parsed.raw)) {
1390
1393
  throw new StopRetrying(
1391
1394
  "The same Liveblocks auth token was issued from the backend before. Caching Liveblocks tokens is not supported."
@@ -1398,7 +1401,6 @@ function createAuthManager(authOptions) {
1398
1401
  if (response && typeof response === "object") {
1399
1402
  if (typeof response.token === "string") {
1400
1403
  const parsed = parseAuthToken(response.token);
1401
- verifyTokenPermissions(parsed, options);
1402
1404
  return parsed;
1403
1405
  } else if (typeof response.error === "string") {
1404
1406
  const reason = `Authentication failed: ${"reason" in response && typeof response.reason === "string" ? response.reason : "Forbidden"}`;
@@ -1417,23 +1419,6 @@ function createAuthManager(authOptions) {
1417
1419
  "Unexpected authentication type. Must be private or custom."
1418
1420
  );
1419
1421
  }
1420
- function verifyTokenPermissions(parsedToken, options) {
1421
- if (!options.roomId && parsedToken.parsed.k === "acc" /* ACCESS_TOKEN */) {
1422
- if (Object.entries(parsedToken.parsed.perms).length === 0) {
1423
- return;
1424
- }
1425
- for (const [resource, scopes] of Object.entries(
1426
- parsedToken.parsed.perms
1427
- )) {
1428
- if (resource.includes("*") && hasCorrespondingScopes(options.requestedScope, scopes)) {
1429
- return;
1430
- }
1431
- }
1432
- throw new StopRetrying(
1433
- "The issued access token doesn't grant enough permissions. Please follow the instructions at https://liveblocks.io/docs/errors/liveblocks-client/access-tokens-not-enough-permissions"
1434
- );
1435
- }
1436
- }
1437
1422
  async function getAuthValue(requestOptions) {
1438
1423
  if (authentication.type === "public") {
1439
1424
  return { type: "public", publicApiKey: authentication.publicApiKey };
@@ -4776,6 +4761,115 @@ function isJsonObject(data) {
4776
4761
  return !isJsonScalar(data) && !isJsonArray(data);
4777
4762
  }
4778
4763
 
4764
+ // src/lib/objectToQuery.ts
4765
+ var identifierRegex = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
4766
+ function objectToQuery(obj) {
4767
+ let filterList = [];
4768
+ const entries2 = Object.entries(obj);
4769
+ const keyValuePairs = [];
4770
+ const keyValuePairsWithOperator = [];
4771
+ const indexedKeys = [];
4772
+ entries2.forEach(([key, value]) => {
4773
+ if (!identifierRegex.test(key)) {
4774
+ throw new Error("Key must only contain letters, numbers, _");
4775
+ }
4776
+ if (isSimpleValue(value)) {
4777
+ keyValuePairs.push([key, value]);
4778
+ } else if (isValueWithOperator(value)) {
4779
+ keyValuePairsWithOperator.push([key, value]);
4780
+ } else if (typeof value === "object" && !("startsWith" in value)) {
4781
+ indexedKeys.push([key, value]);
4782
+ }
4783
+ });
4784
+ filterList = [
4785
+ ...getFiltersFromKeyValuePairs(keyValuePairs),
4786
+ ...getFiltersFromKeyValuePairsWithOperator(keyValuePairsWithOperator)
4787
+ ];
4788
+ indexedKeys.forEach(([key, value]) => {
4789
+ const nestedEntries = Object.entries(value);
4790
+ const nKeyValuePairs = [];
4791
+ const nKeyValuePairsWithOperator = [];
4792
+ nestedEntries.forEach(([nestedKey, nestedValue]) => {
4793
+ if (isStringEmpty(nestedKey)) {
4794
+ throw new Error("Key cannot be empty");
4795
+ }
4796
+ if (isSimpleValue(nestedValue)) {
4797
+ nKeyValuePairs.push([formatFilterKey(key, nestedKey), nestedValue]);
4798
+ } else if (isValueWithOperator(nestedValue)) {
4799
+ nKeyValuePairsWithOperator.push([
4800
+ formatFilterKey(key, nestedKey),
4801
+ nestedValue
4802
+ ]);
4803
+ }
4804
+ });
4805
+ filterList = [
4806
+ ...filterList,
4807
+ ...getFiltersFromKeyValuePairs(nKeyValuePairs),
4808
+ ...getFiltersFromKeyValuePairsWithOperator(nKeyValuePairsWithOperator)
4809
+ ];
4810
+ });
4811
+ return filterList.map(
4812
+ ({ key, operator, value }) => formatFilter(key, operator, formatFilterValue(value))
4813
+ ).join(" AND ");
4814
+ }
4815
+ var getFiltersFromKeyValuePairs = (keyValuePairs) => {
4816
+ const filters = [];
4817
+ keyValuePairs.forEach(([key, value]) => {
4818
+ filters.push({
4819
+ key,
4820
+ operator: ":",
4821
+ value
4822
+ });
4823
+ });
4824
+ return filters;
4825
+ };
4826
+ var getFiltersFromKeyValuePairsWithOperator = (keyValuePairsWithOperator) => {
4827
+ const filters = [];
4828
+ keyValuePairsWithOperator.forEach(([key, value]) => {
4829
+ if ("startsWith" in value && typeof value.startsWith === "string") {
4830
+ filters.push({
4831
+ key,
4832
+ operator: "^",
4833
+ value: value.startsWith
4834
+ });
4835
+ }
4836
+ });
4837
+ return filters;
4838
+ };
4839
+ var isSimpleValue = (value) => {
4840
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
4841
+ return true;
4842
+ }
4843
+ return false;
4844
+ };
4845
+ var isValueWithOperator = (value) => {
4846
+ if (typeof value === "object" && value !== null && "startsWith" in value) {
4847
+ return true;
4848
+ }
4849
+ return false;
4850
+ };
4851
+ var formatFilter = (key, operator, value) => {
4852
+ return `${key}${operator}${value}`;
4853
+ };
4854
+ var formatFilterKey = (key, nestedKey) => {
4855
+ if (nestedKey) {
4856
+ return `${key}[${JSON.stringify(nestedKey)}]`;
4857
+ }
4858
+ return key;
4859
+ };
4860
+ var formatFilterValue = (value) => {
4861
+ if (typeof value === "string") {
4862
+ if (isStringEmpty(value)) {
4863
+ throw new Error("Value cannot be empty");
4864
+ }
4865
+ return JSON.stringify(value);
4866
+ }
4867
+ return value.toString();
4868
+ };
4869
+ var isStringEmpty = (value) => {
4870
+ return !value || value.toString().trim() === "";
4871
+ };
4872
+
4779
4873
  // src/protocol/ClientMsg.ts
4780
4874
  var ClientMsgCode = /* @__PURE__ */ ((ClientMsgCode2) => {
4781
4875
  ClientMsgCode2[ClientMsgCode2["UPDATE_PRESENCE"] = 100] = "UPDATE_PRESENCE";
@@ -5078,19 +5172,20 @@ function createCommentsApi(roomId, getAuthValue, fetchClientApi) {
5078
5172
  return body;
5079
5173
  }
5080
5174
  async function getThreads(options) {
5175
+ let query;
5176
+ if (options?.query) {
5177
+ query = objectToQuery(options.query);
5178
+ }
5081
5179
  const response = await fetchCommentsApi(
5082
- "/threads/search",
5180
+ "/threads",
5083
5181
  {
5084
- since: options?.since?.toISOString()
5182
+ since: options?.since?.toISOString(),
5183
+ query
5085
5184
  },
5086
5185
  {
5087
- body: JSON.stringify({
5088
- ...options?.query?.metadata && { metadata: options.query.metadata }
5089
- }),
5090
5186
  headers: {
5091
5187
  "Content-Type": "application/json"
5092
- },
5093
- method: "POST"
5188
+ }
5094
5189
  }
5095
5190
  );
5096
5191
  if (response.ok) {
@@ -5444,7 +5539,9 @@ function createRoom(options, config) {
5444
5539
  }
5445
5540
  }
5446
5541
  if (activeBatch) {
5447
- activeBatch.ops.push(...ops);
5542
+ for (const op of ops) {
5543
+ activeBatch.ops.push(op);
5544
+ }
5448
5545
  for (const [key, value] of storageUpdates) {
5449
5546
  activeBatch.updates.storageUpdates.set(
5450
5547
  key,
@@ -6123,7 +6220,10 @@ ${Array.from(traces).join("\n\n")}`
6123
6220
  flushNowOrSoon();
6124
6221
  }
6125
6222
  function dispatchOps(ops) {
6126
- context.buffer.storageOperations.push(...ops);
6223
+ const { storageOperations } = context.buffer;
6224
+ for (const op of ops) {
6225
+ storageOperations.push(op);
6226
+ }
6127
6227
  flushNowOrSoon();
6128
6228
  }
6129
6229
  let _getStorage$ = null;
@@ -6620,7 +6720,7 @@ function createClientStore() {
6620
6720
  threads: deleteKeyImmutable(state.threads, threadId),
6621
6721
  inboxNotifications: Object.fromEntries(
6622
6722
  Object.entries(state.inboxNotifications).filter(
6623
- ([_id, notification]) => notification.kind === "thread" && notification.threadId !== threadId
6723
+ ([_id, notification]) => notification.kind === "thread" && notification.threadId === threadId
6624
6724
  )
6625
6725
  )
6626
6726
  };
@@ -6762,7 +6862,7 @@ function applyOptimisticUpdates(state) {
6762
6862
  optimisticUpdate.comment
6763
6863
  );
6764
6864
  const inboxNotification = Object.values(result.inboxNotifications).find(
6765
- (notification) => notification.kind === "thread" && notification.threadId !== thread.id
6865
+ (notification) => notification.kind === "thread" && notification.threadId === thread.id
6766
6866
  );
6767
6867
  if (inboxNotification === void 0) {
6768
6868
  break;
@@ -8148,6 +8248,7 @@ export {
8148
8248
  makePoller,
8149
8249
  makePosition,
8150
8250
  nn,
8251
+ objectToQuery,
8151
8252
  patchLiveObjectKey,
8152
8253
  raise,
8153
8254
  removeReaction,