@liveblocks/core 1.19.0-test1 → 2.0.0-alpha1
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.d.mts +1081 -868
- package/dist/index.d.ts +1081 -868
- package/dist/index.js +2015 -957
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2210 -1152
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -1
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 = "
|
|
9
|
+
var PKG_VERSION = "2.0.0-alpha1";
|
|
10
10
|
var PKG_FORMAT = "esm";
|
|
11
11
|
|
|
12
12
|
// src/dupe-detection.ts
|
|
@@ -362,23 +362,29 @@ var FSM = class {
|
|
|
362
362
|
}
|
|
363
363
|
onEnterAsync(nameOrPattern, promiseFn, onOK, onError) {
|
|
364
364
|
return this.onEnter(nameOrPattern, () => {
|
|
365
|
-
|
|
366
|
-
|
|
365
|
+
const abortController = new AbortController();
|
|
366
|
+
const signal = abortController.signal;
|
|
367
|
+
let done = false;
|
|
368
|
+
void promiseFn(this.currentContext.current, signal).then(
|
|
367
369
|
// On OK
|
|
368
370
|
(data) => {
|
|
369
|
-
if (!
|
|
371
|
+
if (!signal.aborted) {
|
|
372
|
+
done = true;
|
|
370
373
|
this.transition({ type: "ASYNC_OK", data }, onOK);
|
|
371
374
|
}
|
|
372
375
|
},
|
|
373
376
|
// On Error
|
|
374
377
|
(reason) => {
|
|
375
|
-
if (!
|
|
378
|
+
if (!signal.aborted) {
|
|
379
|
+
done = true;
|
|
376
380
|
this.transition({ type: "ASYNC_ERROR", reason }, onError);
|
|
377
381
|
}
|
|
378
382
|
}
|
|
379
383
|
);
|
|
380
384
|
return () => {
|
|
381
|
-
|
|
385
|
+
if (!done) {
|
|
386
|
+
abortController.abort();
|
|
387
|
+
}
|
|
382
388
|
};
|
|
383
389
|
});
|
|
384
390
|
}
|
|
@@ -652,6 +658,7 @@ var ServerMsgCode = /* @__PURE__ */ ((ServerMsgCode2) => {
|
|
|
652
658
|
|
|
653
659
|
// src/types/IWebSocket.ts
|
|
654
660
|
var WebsocketCloseCodes = /* @__PURE__ */ ((WebsocketCloseCodes2) => {
|
|
661
|
+
WebsocketCloseCodes2[WebsocketCloseCodes2["CLOSE_NORMAL"] = 1e3] = "CLOSE_NORMAL";
|
|
655
662
|
WebsocketCloseCodes2[WebsocketCloseCodes2["CLOSE_ABNORMAL"] = 1006] = "CLOSE_ABNORMAL";
|
|
656
663
|
WebsocketCloseCodes2[WebsocketCloseCodes2["UNEXPECTED_CONDITION"] = 1011] = "UNEXPECTED_CONDITION";
|
|
657
664
|
WebsocketCloseCodes2[WebsocketCloseCodes2["TRY_AGAIN_LATER"] = 1013] = "TRY_AGAIN_LATER";
|
|
@@ -661,6 +668,8 @@ var WebsocketCloseCodes = /* @__PURE__ */ ((WebsocketCloseCodes2) => {
|
|
|
661
668
|
WebsocketCloseCodes2[WebsocketCloseCodes2["MAX_NUMBER_OF_CONCURRENT_CONNECTIONS"] = 4003] = "MAX_NUMBER_OF_CONCURRENT_CONNECTIONS";
|
|
662
669
|
WebsocketCloseCodes2[WebsocketCloseCodes2["MAX_NUMBER_OF_MESSAGES_PER_DAY_PER_APP"] = 4004] = "MAX_NUMBER_OF_MESSAGES_PER_DAY_PER_APP";
|
|
663
670
|
WebsocketCloseCodes2[WebsocketCloseCodes2["MAX_NUMBER_OF_CONCURRENT_CONNECTIONS_PER_ROOM"] = 4005] = "MAX_NUMBER_OF_CONCURRENT_CONNECTIONS_PER_ROOM";
|
|
671
|
+
WebsocketCloseCodes2[WebsocketCloseCodes2["ROOM_ID_UPDATED"] = 4006] = "ROOM_ID_UPDATED";
|
|
672
|
+
WebsocketCloseCodes2[WebsocketCloseCodes2["KICKED"] = 4100] = "KICKED";
|
|
664
673
|
WebsocketCloseCodes2[WebsocketCloseCodes2["TOKEN_EXPIRED"] = 4109] = "TOKEN_EXPIRED";
|
|
665
674
|
WebsocketCloseCodes2[WebsocketCloseCodes2["CLOSE_WITHOUT_RETRY"] = 4999] = "CLOSE_WITHOUT_RETRY";
|
|
666
675
|
return WebsocketCloseCodes2;
|
|
@@ -679,22 +688,6 @@ function shouldRetryWithoutReauth(code) {
|
|
|
679
688
|
function isIdle(status) {
|
|
680
689
|
return status === "initial" || status === "disconnected";
|
|
681
690
|
}
|
|
682
|
-
function newToLegacyStatus(status) {
|
|
683
|
-
switch (status) {
|
|
684
|
-
case "connecting":
|
|
685
|
-
return "connecting";
|
|
686
|
-
case "connected":
|
|
687
|
-
return "open";
|
|
688
|
-
case "reconnecting":
|
|
689
|
-
return "unavailable";
|
|
690
|
-
case "disconnected":
|
|
691
|
-
return "failed";
|
|
692
|
-
case "initial":
|
|
693
|
-
return "closed";
|
|
694
|
-
default:
|
|
695
|
-
return "closed";
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
691
|
function toNewConnectionStatus(machine) {
|
|
699
692
|
const state = machine.currentState;
|
|
700
693
|
switch (state) {
|
|
@@ -728,16 +721,19 @@ var StopRetrying = class extends Error {
|
|
|
728
721
|
}
|
|
729
722
|
};
|
|
730
723
|
var LiveblocksError = class extends Error {
|
|
724
|
+
/** @internal */
|
|
731
725
|
constructor(message, code) {
|
|
732
726
|
super(message);
|
|
733
727
|
this.code = code;
|
|
734
728
|
}
|
|
735
729
|
};
|
|
736
|
-
function nextBackoffDelay(currentDelay, delays
|
|
730
|
+
function nextBackoffDelay(currentDelay, delays) {
|
|
737
731
|
return delays.find((delay) => delay > currentDelay) ?? delays[delays.length - 1];
|
|
738
732
|
}
|
|
739
733
|
function increaseBackoffDelay(context) {
|
|
740
|
-
context.patch({
|
|
734
|
+
context.patch({
|
|
735
|
+
backoffDelay: nextBackoffDelay(context.backoffDelay, BACKOFF_DELAYS)
|
|
736
|
+
});
|
|
741
737
|
}
|
|
742
738
|
function increaseBackoffDelayAggressively(context) {
|
|
743
739
|
context.patch({
|
|
@@ -770,9 +766,13 @@ function logPrematureErrorOrCloseEvent(e) {
|
|
|
770
766
|
};
|
|
771
767
|
}
|
|
772
768
|
function logCloseEvent(event) {
|
|
769
|
+
const details = [`code: ${event.code}`];
|
|
770
|
+
if (event.reason) {
|
|
771
|
+
details.push(`reason: ${event.reason}`);
|
|
772
|
+
}
|
|
773
773
|
return (ctx) => {
|
|
774
774
|
warn(
|
|
775
|
-
`Connection to Liveblocks websocket server closed (
|
|
775
|
+
`Connection to Liveblocks websocket server closed (${details.join(", ")}). Retrying in ${ctx.backoffDelay}ms.`
|
|
776
776
|
);
|
|
777
777
|
};
|
|
778
778
|
}
|
|
@@ -884,8 +884,7 @@ function createConnectionStateMachine(delegates, options) {
|
|
|
884
884
|
(okEvent) => ({
|
|
885
885
|
target: "@connecting.busy",
|
|
886
886
|
effect: assign({
|
|
887
|
-
authValue: okEvent.data
|
|
888
|
-
backoffDelay: RESET_DELAY
|
|
887
|
+
authValue: okEvent.data
|
|
889
888
|
})
|
|
890
889
|
}),
|
|
891
890
|
// Auth failed
|
|
@@ -942,14 +941,16 @@ function createConnectionStateMachine(delegates, options) {
|
|
|
942
941
|
// When the "open" event happens, we're ready to transition to the
|
|
943
942
|
// OK state. This is done by resolving the Promise.
|
|
944
943
|
//
|
|
945
|
-
async (ctx) => {
|
|
944
|
+
async (ctx, signal) => {
|
|
946
945
|
let capturedPrematureEvent = null;
|
|
946
|
+
let unconfirmedSocket = null;
|
|
947
947
|
const connect$ = new Promise(
|
|
948
948
|
(resolve, rej) => {
|
|
949
949
|
if (ctx.authValue === null) {
|
|
950
950
|
throw new Error("No auth authValue");
|
|
951
951
|
}
|
|
952
952
|
const socket = delegates.createSocket(ctx.authValue);
|
|
953
|
+
unconfirmedSocket = socket;
|
|
953
954
|
function reject(event) {
|
|
954
955
|
capturedPrematureEvent = event;
|
|
955
956
|
socket.removeEventListener("message", onSocketMessage);
|
|
@@ -1005,12 +1006,18 @@ function createConnectionStateMachine(delegates, options) {
|
|
|
1005
1006
|
//
|
|
1006
1007
|
([socket, unsub]) => {
|
|
1007
1008
|
unsub();
|
|
1009
|
+
if (signal.aborted) {
|
|
1010
|
+
throw new Error("Aborted");
|
|
1011
|
+
}
|
|
1008
1012
|
if (capturedPrematureEvent) {
|
|
1009
1013
|
throw capturedPrematureEvent;
|
|
1010
1014
|
}
|
|
1011
1015
|
return socket;
|
|
1012
1016
|
}
|
|
1013
|
-
)
|
|
1017
|
+
).catch((e) => {
|
|
1018
|
+
teardownSocket(unconfirmedSocket);
|
|
1019
|
+
throw e;
|
|
1020
|
+
});
|
|
1014
1021
|
},
|
|
1015
1022
|
// Only transition to OK state after a successfully opened WebSocket connection
|
|
1016
1023
|
(okEvent) => ({
|
|
@@ -1205,9 +1212,6 @@ var ManagedSocket = class {
|
|
|
1205
1212
|
this.events = events;
|
|
1206
1213
|
this.cleanups = cleanups;
|
|
1207
1214
|
}
|
|
1208
|
-
getLegacyStatus() {
|
|
1209
|
-
return newToLegacyStatus(this.getStatus());
|
|
1210
|
-
}
|
|
1211
1215
|
getStatus() {
|
|
1212
1216
|
try {
|
|
1213
1217
|
return toNewConnectionStatus(this.machine);
|
|
@@ -1325,7 +1329,7 @@ function createAuthManager(authOptions) {
|
|
|
1325
1329
|
}
|
|
1326
1330
|
return false;
|
|
1327
1331
|
}
|
|
1328
|
-
function getCachedToken(
|
|
1332
|
+
function getCachedToken(requestOptions) {
|
|
1329
1333
|
const now = Math.ceil(Date.now() / 1e3);
|
|
1330
1334
|
for (let i = tokens.length - 1; i >= 0; i--) {
|
|
1331
1335
|
const token = tokens[i];
|
|
@@ -1338,8 +1342,15 @@ function createAuthManager(authOptions) {
|
|
|
1338
1342
|
if (token.parsed.k === "id" /* ID_TOKEN */) {
|
|
1339
1343
|
return token;
|
|
1340
1344
|
} else if (token.parsed.k === "acc" /* ACCESS_TOKEN */) {
|
|
1345
|
+
if (!requestOptions.roomId && Object.entries(token.parsed.perms).length === 0) {
|
|
1346
|
+
return token;
|
|
1347
|
+
}
|
|
1341
1348
|
for (const [resource, scopes] of Object.entries(token.parsed.perms)) {
|
|
1342
|
-
if (
|
|
1349
|
+
if (!requestOptions.roomId) {
|
|
1350
|
+
if (resource.includes("*") && hasCorrespondingScopes(requestOptions.requestedScope, scopes)) {
|
|
1351
|
+
return token;
|
|
1352
|
+
}
|
|
1353
|
+
} else if (resource.includes("*") && requestOptions.roomId.startsWith(resource.replace("*", "")) || requestOptions.roomId === resource && hasCorrespondingScopes(requestOptions.requestedScope, scopes)) {
|
|
1343
1354
|
return token;
|
|
1344
1355
|
}
|
|
1345
1356
|
}
|
|
@@ -1347,7 +1358,7 @@ function createAuthManager(authOptions) {
|
|
|
1347
1358
|
}
|
|
1348
1359
|
return void 0;
|
|
1349
1360
|
}
|
|
1350
|
-
async function makeAuthRequest(
|
|
1361
|
+
async function makeAuthRequest(options) {
|
|
1351
1362
|
const fetcher = authOptions.polyfills?.fetch ?? (typeof window === "undefined" ? void 0 : window.fetch);
|
|
1352
1363
|
if (authentication.type === "private") {
|
|
1353
1364
|
if (fetcher === void 0) {
|
|
@@ -1356,7 +1367,7 @@ function createAuthManager(authOptions) {
|
|
|
1356
1367
|
);
|
|
1357
1368
|
}
|
|
1358
1369
|
const response = await fetchAuthEndpoint(fetcher, authentication.url, {
|
|
1359
|
-
room: roomId
|
|
1370
|
+
room: options.roomId
|
|
1360
1371
|
});
|
|
1361
1372
|
const parsed = parseAuthToken(response.token);
|
|
1362
1373
|
if (seenTokens.has(parsed.raw)) {
|
|
@@ -1367,10 +1378,11 @@ function createAuthManager(authOptions) {
|
|
|
1367
1378
|
return parsed;
|
|
1368
1379
|
}
|
|
1369
1380
|
if (authentication.type === "custom") {
|
|
1370
|
-
const response = await authentication.callback(roomId);
|
|
1381
|
+
const response = await authentication.callback(options.roomId);
|
|
1371
1382
|
if (response && typeof response === "object") {
|
|
1372
1383
|
if (typeof response.token === "string") {
|
|
1373
|
-
|
|
1384
|
+
const parsed = parseAuthToken(response.token);
|
|
1385
|
+
return parsed;
|
|
1374
1386
|
} else if (typeof response.error === "string") {
|
|
1375
1387
|
const reason = `Authentication failed: ${"reason" in response && typeof response.reason === "string" ? response.reason : "Forbidden"}`;
|
|
1376
1388
|
if (response.error === "forbidden") {
|
|
@@ -1388,18 +1400,27 @@ function createAuthManager(authOptions) {
|
|
|
1388
1400
|
"Unexpected authentication type. Must be private or custom."
|
|
1389
1401
|
);
|
|
1390
1402
|
}
|
|
1391
|
-
async function getAuthValue(
|
|
1403
|
+
async function getAuthValue(requestOptions) {
|
|
1392
1404
|
if (authentication.type === "public") {
|
|
1393
1405
|
return { type: "public", publicApiKey: authentication.publicApiKey };
|
|
1394
1406
|
}
|
|
1395
|
-
const cachedToken = getCachedToken(
|
|
1407
|
+
const cachedToken = getCachedToken(requestOptions);
|
|
1396
1408
|
if (cachedToken !== void 0) {
|
|
1397
1409
|
return { type: "secret", token: cachedToken };
|
|
1398
1410
|
}
|
|
1399
|
-
let currentPromise
|
|
1400
|
-
if (
|
|
1401
|
-
currentPromise =
|
|
1402
|
-
|
|
1411
|
+
let currentPromise;
|
|
1412
|
+
if (requestOptions.roomId) {
|
|
1413
|
+
currentPromise = requestPromises.get(requestOptions.roomId);
|
|
1414
|
+
if (currentPromise === void 0) {
|
|
1415
|
+
currentPromise = makeAuthRequest(requestOptions);
|
|
1416
|
+
requestPromises.set(requestOptions.roomId, currentPromise);
|
|
1417
|
+
}
|
|
1418
|
+
} else {
|
|
1419
|
+
currentPromise = requestPromises.get("liveblocks-user-token");
|
|
1420
|
+
if (currentPromise === void 0) {
|
|
1421
|
+
currentPromise = makeAuthRequest(requestOptions);
|
|
1422
|
+
requestPromises.set("liveblocks-user-token", currentPromise);
|
|
1423
|
+
}
|
|
1403
1424
|
}
|
|
1404
1425
|
try {
|
|
1405
1426
|
const token = await currentPromise;
|
|
@@ -1412,7 +1433,11 @@ function createAuthManager(authOptions) {
|
|
|
1412
1433
|
}
|
|
1413
1434
|
return { type: "secret", token };
|
|
1414
1435
|
} finally {
|
|
1415
|
-
|
|
1436
|
+
if (requestOptions.roomId) {
|
|
1437
|
+
requestPromises.delete(requestOptions.roomId);
|
|
1438
|
+
} else {
|
|
1439
|
+
requestPromises.delete("liveblocks-user-token");
|
|
1440
|
+
}
|
|
1416
1441
|
}
|
|
1417
1442
|
}
|
|
1418
1443
|
return {
|
|
@@ -1501,6 +1526,9 @@ async function fetchAuthEndpoint(fetch2, endpoint, body) {
|
|
|
1501
1526
|
// src/constants.ts
|
|
1502
1527
|
var DEFAULT_BASE_URL = "https://api.liveblocks.io";
|
|
1503
1528
|
|
|
1529
|
+
// src/internal.ts
|
|
1530
|
+
var kInternal = Symbol();
|
|
1531
|
+
|
|
1504
1532
|
// src/devtools/bridge.ts
|
|
1505
1533
|
var _bridgeActive = false;
|
|
1506
1534
|
function activateBridge(allowed) {
|
|
@@ -1630,7 +1658,7 @@ function partialSyncStorage(room) {
|
|
|
1630
1658
|
}
|
|
1631
1659
|
}
|
|
1632
1660
|
function partialSyncMe(room) {
|
|
1633
|
-
const me = room.
|
|
1661
|
+
const me = room[kInternal].getSelf_forDevTools();
|
|
1634
1662
|
if (me) {
|
|
1635
1663
|
sendToPanel({
|
|
1636
1664
|
msg: "room::sync::partial",
|
|
@@ -1640,7 +1668,7 @@ function partialSyncMe(room) {
|
|
|
1640
1668
|
}
|
|
1641
1669
|
}
|
|
1642
1670
|
function partialSyncOthers(room) {
|
|
1643
|
-
const others = room.
|
|
1671
|
+
const others = room[kInternal].getOthers_forDevTools();
|
|
1644
1672
|
if (others) {
|
|
1645
1673
|
sendToPanel({
|
|
1646
1674
|
msg: "room::sync::partial",
|
|
@@ -1651,8 +1679,8 @@ function partialSyncOthers(room) {
|
|
|
1651
1679
|
}
|
|
1652
1680
|
function fullSync(room) {
|
|
1653
1681
|
const root = room.getStorageSnapshot();
|
|
1654
|
-
const me = room.
|
|
1655
|
-
const others = room.
|
|
1682
|
+
const me = room[kInternal].getSelf_forDevTools();
|
|
1683
|
+
const others = room[kInternal].getOthers_forDevTools();
|
|
1656
1684
|
room.fetchYDoc("");
|
|
1657
1685
|
sendToPanel({
|
|
1658
1686
|
msg: "room::sync::full",
|
|
@@ -1711,6 +1739,183 @@ function unlinkDevTools(roomId) {
|
|
|
1711
1739
|
});
|
|
1712
1740
|
}
|
|
1713
1741
|
|
|
1742
|
+
// src/lib/stringify.ts
|
|
1743
|
+
function stringify(object, ...args) {
|
|
1744
|
+
if (typeof object !== "object" || object === null || Array.isArray(object)) {
|
|
1745
|
+
return JSON.stringify(object, ...args);
|
|
1746
|
+
}
|
|
1747
|
+
const sortedObject = Object.keys(object).sort().reduce(
|
|
1748
|
+
(sortedObject2, key) => {
|
|
1749
|
+
sortedObject2[key] = object[key];
|
|
1750
|
+
return sortedObject2;
|
|
1751
|
+
},
|
|
1752
|
+
{}
|
|
1753
|
+
);
|
|
1754
|
+
return JSON.stringify(sortedObject, ...args);
|
|
1755
|
+
}
|
|
1756
|
+
|
|
1757
|
+
// src/lib/batch.ts
|
|
1758
|
+
var DEFAULT_SIZE = 50;
|
|
1759
|
+
var DEFAULT_DELAY = 100;
|
|
1760
|
+
var noop = () => {
|
|
1761
|
+
};
|
|
1762
|
+
var BatchCall = class {
|
|
1763
|
+
constructor(args) {
|
|
1764
|
+
this.resolve = noop;
|
|
1765
|
+
this.reject = noop;
|
|
1766
|
+
this.promise = new Promise(noop);
|
|
1767
|
+
this.args = args;
|
|
1768
|
+
}
|
|
1769
|
+
};
|
|
1770
|
+
var Batch = class {
|
|
1771
|
+
constructor(callback, options) {
|
|
1772
|
+
this.queue = [];
|
|
1773
|
+
this.error = false;
|
|
1774
|
+
this.callback = callback;
|
|
1775
|
+
this.size = options?.size ?? DEFAULT_SIZE;
|
|
1776
|
+
this.delay = options?.delay ?? DEFAULT_DELAY;
|
|
1777
|
+
}
|
|
1778
|
+
clearDelayTimeout() {
|
|
1779
|
+
if (this.delayTimeoutId !== void 0) {
|
|
1780
|
+
clearTimeout(this.delayTimeoutId);
|
|
1781
|
+
this.delayTimeoutId = void 0;
|
|
1782
|
+
}
|
|
1783
|
+
}
|
|
1784
|
+
schedule() {
|
|
1785
|
+
if (this.queue.length === this.size) {
|
|
1786
|
+
void this.flush();
|
|
1787
|
+
} else if (this.queue.length === 1) {
|
|
1788
|
+
this.clearDelayTimeout();
|
|
1789
|
+
this.delayTimeoutId = setTimeout(() => void this.flush(), this.delay);
|
|
1790
|
+
}
|
|
1791
|
+
}
|
|
1792
|
+
async flush() {
|
|
1793
|
+
if (this.queue.length === 0) {
|
|
1794
|
+
return;
|
|
1795
|
+
}
|
|
1796
|
+
const calls = this.queue.splice(0);
|
|
1797
|
+
const args = calls.map((call) => call.args);
|
|
1798
|
+
try {
|
|
1799
|
+
const results = await this.callback(args);
|
|
1800
|
+
this.error = false;
|
|
1801
|
+
calls.forEach((call, index) => {
|
|
1802
|
+
const result = results?.[index];
|
|
1803
|
+
if (!Array.isArray(results)) {
|
|
1804
|
+
call.reject(new Error("Callback must return an array."));
|
|
1805
|
+
} else if (calls.length !== results.length) {
|
|
1806
|
+
call.reject(
|
|
1807
|
+
new Error(
|
|
1808
|
+
`Callback must return an array of the same length as the number of provided items. Expected ${calls.length}, but got ${results.length}.`
|
|
1809
|
+
)
|
|
1810
|
+
);
|
|
1811
|
+
} else if (result instanceof Error) {
|
|
1812
|
+
call.reject(result);
|
|
1813
|
+
} else {
|
|
1814
|
+
call.resolve(result);
|
|
1815
|
+
}
|
|
1816
|
+
});
|
|
1817
|
+
} catch (error3) {
|
|
1818
|
+
this.error = true;
|
|
1819
|
+
calls.forEach((call) => {
|
|
1820
|
+
call.reject(error3);
|
|
1821
|
+
});
|
|
1822
|
+
}
|
|
1823
|
+
}
|
|
1824
|
+
get(...args) {
|
|
1825
|
+
const existingCall = this.queue.find(
|
|
1826
|
+
(call2) => stringify(call2.args) === stringify(args)
|
|
1827
|
+
);
|
|
1828
|
+
if (existingCall) {
|
|
1829
|
+
return existingCall.promise;
|
|
1830
|
+
}
|
|
1831
|
+
const call = new BatchCall(args);
|
|
1832
|
+
call.promise = new Promise((resolve, reject) => {
|
|
1833
|
+
call.resolve = resolve;
|
|
1834
|
+
call.reject = reject;
|
|
1835
|
+
});
|
|
1836
|
+
this.queue.push(call);
|
|
1837
|
+
this.schedule();
|
|
1838
|
+
return call.promise;
|
|
1839
|
+
}
|
|
1840
|
+
clear() {
|
|
1841
|
+
this.queue = [];
|
|
1842
|
+
this.error = false;
|
|
1843
|
+
this.clearDelayTimeout();
|
|
1844
|
+
}
|
|
1845
|
+
};
|
|
1846
|
+
function createBatchStore(callback, options) {
|
|
1847
|
+
const batch = new Batch(callback, options);
|
|
1848
|
+
const cache = /* @__PURE__ */ new Map();
|
|
1849
|
+
const eventSource2 = makeEventSource();
|
|
1850
|
+
function getCacheKey(args) {
|
|
1851
|
+
return stringify(args);
|
|
1852
|
+
}
|
|
1853
|
+
function setStateAndNotify(cacheKey, state) {
|
|
1854
|
+
if (state) {
|
|
1855
|
+
cache.set(cacheKey, state);
|
|
1856
|
+
} else {
|
|
1857
|
+
cache.delete(cacheKey);
|
|
1858
|
+
}
|
|
1859
|
+
eventSource2.notify(state);
|
|
1860
|
+
}
|
|
1861
|
+
async function get(...args) {
|
|
1862
|
+
const cacheKey = getCacheKey(args);
|
|
1863
|
+
if (cache.has(cacheKey)) {
|
|
1864
|
+
return;
|
|
1865
|
+
}
|
|
1866
|
+
try {
|
|
1867
|
+
setStateAndNotify(cacheKey, { isLoading: true });
|
|
1868
|
+
const result = await batch.get(...args);
|
|
1869
|
+
setStateAndNotify(cacheKey, { isLoading: false, data: result });
|
|
1870
|
+
} catch (error3) {
|
|
1871
|
+
setStateAndNotify(cacheKey, {
|
|
1872
|
+
isLoading: false,
|
|
1873
|
+
error: error3
|
|
1874
|
+
});
|
|
1875
|
+
}
|
|
1876
|
+
}
|
|
1877
|
+
function getState(...args) {
|
|
1878
|
+
const cacheKey = getCacheKey(args);
|
|
1879
|
+
return cache.get(cacheKey);
|
|
1880
|
+
}
|
|
1881
|
+
return {
|
|
1882
|
+
...eventSource2,
|
|
1883
|
+
get,
|
|
1884
|
+
getState
|
|
1885
|
+
};
|
|
1886
|
+
}
|
|
1887
|
+
|
|
1888
|
+
// src/lib/create-store.ts
|
|
1889
|
+
function createStore(initialState) {
|
|
1890
|
+
let state = initialState;
|
|
1891
|
+
const subscribers = /* @__PURE__ */ new Set();
|
|
1892
|
+
function get() {
|
|
1893
|
+
return state;
|
|
1894
|
+
}
|
|
1895
|
+
function set(callback) {
|
|
1896
|
+
const newState = callback(state);
|
|
1897
|
+
if (state === newState) {
|
|
1898
|
+
return;
|
|
1899
|
+
}
|
|
1900
|
+
state = newState;
|
|
1901
|
+
for (const subscriber of subscribers) {
|
|
1902
|
+
subscriber(state);
|
|
1903
|
+
}
|
|
1904
|
+
}
|
|
1905
|
+
function subscribe(callback) {
|
|
1906
|
+
subscribers.add(callback);
|
|
1907
|
+
callback(state);
|
|
1908
|
+
return () => {
|
|
1909
|
+
subscribers.delete(callback);
|
|
1910
|
+
};
|
|
1911
|
+
}
|
|
1912
|
+
return {
|
|
1913
|
+
get,
|
|
1914
|
+
set,
|
|
1915
|
+
subscribe
|
|
1916
|
+
};
|
|
1917
|
+
}
|
|
1918
|
+
|
|
1714
1919
|
// src/lib/deprecation.ts
|
|
1715
1920
|
var _emittedDeprecationWarnings = /* @__PURE__ */ new Set();
|
|
1716
1921
|
function deprecate(message, key = message) {
|
|
@@ -1744,886 +1949,538 @@ function errorIf(condition, message) {
|
|
|
1744
1949
|
}
|
|
1745
1950
|
}
|
|
1746
1951
|
|
|
1747
|
-
// src/
|
|
1748
|
-
function
|
|
1749
|
-
|
|
1952
|
+
// src/convert-plain-data.ts
|
|
1953
|
+
function convertToCommentData(data) {
|
|
1954
|
+
const editedAt = data.editedAt ? new Date(data.editedAt) : void 0;
|
|
1955
|
+
const createdAt = new Date(data.createdAt);
|
|
1956
|
+
const reactions = data.reactions.map((reaction) => ({
|
|
1957
|
+
...reaction,
|
|
1958
|
+
createdAt: new Date(reaction.createdAt)
|
|
1959
|
+
}));
|
|
1960
|
+
if (data.body) {
|
|
1961
|
+
return {
|
|
1962
|
+
...data,
|
|
1963
|
+
reactions,
|
|
1964
|
+
createdAt,
|
|
1965
|
+
editedAt
|
|
1966
|
+
};
|
|
1967
|
+
} else {
|
|
1968
|
+
const deletedAt = new Date(data.deletedAt);
|
|
1969
|
+
return {
|
|
1970
|
+
...data,
|
|
1971
|
+
reactions,
|
|
1972
|
+
createdAt,
|
|
1973
|
+
editedAt,
|
|
1974
|
+
deletedAt
|
|
1975
|
+
};
|
|
1976
|
+
}
|
|
1750
1977
|
}
|
|
1751
|
-
function
|
|
1752
|
-
|
|
1978
|
+
function convertToThreadData(data) {
|
|
1979
|
+
const updatedAt = data.updatedAt ? new Date(data.updatedAt) : void 0;
|
|
1980
|
+
const createdAt = new Date(data.createdAt);
|
|
1981
|
+
const comments = data.comments.map(
|
|
1982
|
+
(comment) => convertToCommentData(comment)
|
|
1983
|
+
);
|
|
1984
|
+
return {
|
|
1985
|
+
...data,
|
|
1986
|
+
createdAt,
|
|
1987
|
+
updatedAt,
|
|
1988
|
+
comments
|
|
1989
|
+
};
|
|
1753
1990
|
}
|
|
1754
|
-
function
|
|
1755
|
-
return
|
|
1991
|
+
function convertToCommentUserReaction(data) {
|
|
1992
|
+
return {
|
|
1993
|
+
...data,
|
|
1994
|
+
createdAt: new Date(data.createdAt)
|
|
1995
|
+
};
|
|
1756
1996
|
}
|
|
1757
|
-
function
|
|
1758
|
-
|
|
1997
|
+
function convertToInboxNotificationData(data) {
|
|
1998
|
+
const notifiedAt = new Date(data.notifiedAt);
|
|
1999
|
+
const readAt = data.readAt ? new Date(data.readAt) : null;
|
|
2000
|
+
if ("activities" in data) {
|
|
2001
|
+
const activities = data.activities.map((activity) => ({
|
|
2002
|
+
...activity,
|
|
2003
|
+
createdAt: new Date(activity.createdAt)
|
|
2004
|
+
}));
|
|
2005
|
+
return {
|
|
2006
|
+
...data,
|
|
2007
|
+
notifiedAt,
|
|
2008
|
+
readAt,
|
|
2009
|
+
activities
|
|
2010
|
+
};
|
|
2011
|
+
}
|
|
2012
|
+
return {
|
|
2013
|
+
...data,
|
|
2014
|
+
notifiedAt,
|
|
2015
|
+
readAt
|
|
2016
|
+
};
|
|
1759
2017
|
}
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
};
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
2018
|
+
function convertToThreadDeleteInfo(data) {
|
|
2019
|
+
const deletedAt = new Date(data.deletedAt);
|
|
2020
|
+
return {
|
|
2021
|
+
...data,
|
|
2022
|
+
deletedAt
|
|
2023
|
+
};
|
|
2024
|
+
}
|
|
2025
|
+
function convertToInboxNotificationDeleteInfo(data) {
|
|
2026
|
+
const deletedAt = new Date(data.deletedAt);
|
|
2027
|
+
return {
|
|
2028
|
+
...data,
|
|
2029
|
+
deletedAt
|
|
2030
|
+
};
|
|
2031
|
+
}
|
|
2032
|
+
|
|
2033
|
+
// src/lib/url.ts
|
|
2034
|
+
function toURLSearchParams(params) {
|
|
2035
|
+
const result = new URLSearchParams();
|
|
2036
|
+
for (const [key, value] of Object.entries(params)) {
|
|
2037
|
+
if (value !== void 0 && value !== null) {
|
|
2038
|
+
result.set(key, value.toString());
|
|
2039
|
+
}
|
|
1775
2040
|
}
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
const
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
2041
|
+
return result;
|
|
2042
|
+
}
|
|
2043
|
+
function urljoin(baseUrl, path, params) {
|
|
2044
|
+
const url = new URL(path, baseUrl);
|
|
2045
|
+
if (params !== void 0) {
|
|
2046
|
+
url.search = (params instanceof URLSearchParams ? params : toURLSearchParams(params)).toString();
|
|
2047
|
+
}
|
|
2048
|
+
return url.toString();
|
|
2049
|
+
}
|
|
2050
|
+
|
|
2051
|
+
// src/notifications.ts
|
|
2052
|
+
var MARK_INBOX_NOTIFICATIONS_AS_READ_BATCH_DELAY = 50;
|
|
2053
|
+
function createNotificationsApi({
|
|
2054
|
+
baseUrl,
|
|
2055
|
+
authManager,
|
|
2056
|
+
currentUserIdStore,
|
|
2057
|
+
fetcher
|
|
2058
|
+
}) {
|
|
2059
|
+
async function fetchJson(endpoint, options, params) {
|
|
2060
|
+
const authValue = await authManager.getAuthValue({
|
|
2061
|
+
requestedScope: "comments:read"
|
|
2062
|
+
});
|
|
2063
|
+
if (authValue.type === "secret" && authValue.token.parsed.k === "acc" /* ACCESS_TOKEN */) {
|
|
2064
|
+
const userId = authValue.token.parsed.uid;
|
|
2065
|
+
currentUserIdStore.set(() => userId);
|
|
1785
2066
|
}
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
2067
|
+
const url = urljoin(baseUrl, `/v2/c${endpoint}`, params);
|
|
2068
|
+
const response = await fetcher(url.toString(), {
|
|
2069
|
+
...options,
|
|
2070
|
+
headers: {
|
|
2071
|
+
...options?.headers,
|
|
2072
|
+
Authorization: `Bearer ${getAuthBearerHeaderFromAuthValue(authValue)}`
|
|
2073
|
+
}
|
|
2074
|
+
});
|
|
2075
|
+
if (!response.ok) {
|
|
2076
|
+
if (response.status >= 400 && response.status < 600) {
|
|
2077
|
+
let error3;
|
|
2078
|
+
try {
|
|
2079
|
+
const errorBody = await response.json();
|
|
2080
|
+
error3 = new NotificationsApiError(
|
|
2081
|
+
errorBody.message,
|
|
2082
|
+
response.status,
|
|
2083
|
+
errorBody
|
|
2084
|
+
);
|
|
2085
|
+
} catch {
|
|
2086
|
+
error3 = new NotificationsApiError(
|
|
2087
|
+
response.statusText,
|
|
2088
|
+
response.status
|
|
2089
|
+
);
|
|
1790
2090
|
}
|
|
2091
|
+
throw error3;
|
|
1791
2092
|
}
|
|
1792
2093
|
}
|
|
2094
|
+
let body;
|
|
2095
|
+
try {
|
|
2096
|
+
body = await response.json();
|
|
2097
|
+
} catch {
|
|
2098
|
+
body = {};
|
|
2099
|
+
}
|
|
2100
|
+
return body;
|
|
1793
2101
|
}
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
2102
|
+
async function getInboxNotifications(options) {
|
|
2103
|
+
const json = await fetchJson("/inbox-notifications", void 0, {
|
|
2104
|
+
limit: options?.limit,
|
|
2105
|
+
since: options?.since?.toISOString()
|
|
2106
|
+
});
|
|
2107
|
+
return {
|
|
2108
|
+
threads: json.threads.map((thread) => convertToThreadData(thread)),
|
|
2109
|
+
inboxNotifications: json.inboxNotifications.map(
|
|
2110
|
+
(notification) => convertToInboxNotificationData(notification)
|
|
2111
|
+
),
|
|
2112
|
+
deletedThreads: json.deletedThreads.map(
|
|
2113
|
+
(info) => convertToThreadDeleteInfo(info)
|
|
2114
|
+
),
|
|
2115
|
+
deletedInboxNotifications: json.deletedInboxNotifications.map(
|
|
2116
|
+
(info) => convertToInboxNotificationDeleteInfo(info)
|
|
2117
|
+
),
|
|
2118
|
+
meta: {
|
|
2119
|
+
requestedAt: new Date(json.meta.requestedAt)
|
|
2120
|
+
}
|
|
2121
|
+
};
|
|
1808
2122
|
}
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
});
|
|
1813
|
-
for (const [index, userId] of userIds.entries()) {
|
|
1814
|
-
const user = users?.[index];
|
|
1815
|
-
if (user) {
|
|
1816
|
-
resolvedUsers.set(userId, user);
|
|
1817
|
-
}
|
|
2123
|
+
async function getUnreadInboxNotificationsCount() {
|
|
2124
|
+
const { count } = await fetchJson("/inbox-notifications/count");
|
|
2125
|
+
return count;
|
|
1818
2126
|
}
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
};
|
|
1828
|
-
var htmlEscapablesRegex = new RegExp(
|
|
1829
|
-
Object.keys(htmlEscapables).map((entity) => `\\${entity}`).join("|"),
|
|
1830
|
-
"g"
|
|
1831
|
-
);
|
|
1832
|
-
function htmlSafe(value) {
|
|
1833
|
-
return new HtmlSafeString([String(value)], []);
|
|
1834
|
-
}
|
|
1835
|
-
function joinHtml(strings) {
|
|
1836
|
-
if (strings.length <= 0) {
|
|
1837
|
-
return new HtmlSafeString([""], []);
|
|
2127
|
+
async function markAllInboxNotificationsAsRead() {
|
|
2128
|
+
await fetchJson("/inbox-notifications/read", {
|
|
2129
|
+
method: "POST",
|
|
2130
|
+
headers: {
|
|
2131
|
+
"Content-Type": "application/json"
|
|
2132
|
+
},
|
|
2133
|
+
body: JSON.stringify({ inboxNotificationIds: "all" })
|
|
2134
|
+
});
|
|
1838
2135
|
}
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
2136
|
+
async function markInboxNotificationsAsRead(inboxNotificationIds) {
|
|
2137
|
+
await fetchJson("/inbox-notifications/read", {
|
|
2138
|
+
method: "POST",
|
|
2139
|
+
headers: {
|
|
2140
|
+
"Content-Type": "application/json"
|
|
2141
|
+
},
|
|
2142
|
+
body: JSON.stringify({ inboxNotificationIds })
|
|
2143
|
+
});
|
|
2144
|
+
}
|
|
2145
|
+
const batchedMarkInboxNotificationsAsRead = new Batch(
|
|
2146
|
+
async (batchedInboxNotificationIds) => {
|
|
2147
|
+
const inboxNotificationIds = batchedInboxNotificationIds.flat();
|
|
2148
|
+
await markInboxNotificationsAsRead(inboxNotificationIds);
|
|
2149
|
+
return inboxNotificationIds;
|
|
2150
|
+
},
|
|
2151
|
+
{ delay: MARK_INBOX_NOTIFICATIONS_AS_READ_BATCH_DELAY }
|
|
1842
2152
|
);
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
if (value instanceof HtmlSafeString) {
|
|
1846
|
-
return value.toString();
|
|
2153
|
+
async function markInboxNotificationAsRead(inboxNotificationId) {
|
|
2154
|
+
await batchedMarkInboxNotificationsAsRead.get(inboxNotificationId);
|
|
1847
2155
|
}
|
|
1848
|
-
|
|
1849
|
-
|
|
2156
|
+
return {
|
|
2157
|
+
getInboxNotifications,
|
|
2158
|
+
getUnreadInboxNotificationsCount,
|
|
2159
|
+
markAllInboxNotificationsAsRead,
|
|
2160
|
+
markInboxNotificationAsRead
|
|
2161
|
+
};
|
|
2162
|
+
}
|
|
2163
|
+
|
|
2164
|
+
// src/lib/position.ts
|
|
2165
|
+
var MIN_CODE = 32;
|
|
2166
|
+
var MAX_CODE = 126;
|
|
2167
|
+
var NUM_DIGITS = MAX_CODE - MIN_CODE + 1;
|
|
2168
|
+
var ZERO = nthDigit(0);
|
|
2169
|
+
var ONE = nthDigit(1);
|
|
2170
|
+
var ZERO_NINE = ZERO + nthDigit(-1);
|
|
2171
|
+
function nthDigit(n) {
|
|
2172
|
+
const code = MIN_CODE + (n < 0 ? NUM_DIGITS + n : n);
|
|
2173
|
+
if (code < MIN_CODE || code > MAX_CODE) {
|
|
2174
|
+
throw new Error(`Invalid n value: ${n}`);
|
|
1850
2175
|
}
|
|
1851
|
-
return String(
|
|
1852
|
-
htmlEscapablesRegex,
|
|
1853
|
-
(character) => htmlEscapables[character]
|
|
1854
|
-
);
|
|
2176
|
+
return String.fromCharCode(code);
|
|
1855
2177
|
}
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
2178
|
+
function makePosition(x, y) {
|
|
2179
|
+
if (x !== void 0 && y !== void 0) {
|
|
2180
|
+
return between(x, y);
|
|
2181
|
+
} else if (x !== void 0) {
|
|
2182
|
+
return after(x);
|
|
2183
|
+
} else if (y !== void 0) {
|
|
2184
|
+
return before(y);
|
|
2185
|
+
} else {
|
|
2186
|
+
return ONE;
|
|
1860
2187
|
}
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
2188
|
+
}
|
|
2189
|
+
function before(pos) {
|
|
2190
|
+
const lastIndex = pos.length - 1;
|
|
2191
|
+
for (let i = 0; i <= lastIndex; i++) {
|
|
2192
|
+
const code = pos.charCodeAt(i);
|
|
2193
|
+
if (code <= MIN_CODE) {
|
|
2194
|
+
continue;
|
|
2195
|
+
}
|
|
2196
|
+
if (i === lastIndex) {
|
|
2197
|
+
if (code === MIN_CODE + 1) {
|
|
2198
|
+
return pos.substring(0, i) + ZERO_NINE;
|
|
2199
|
+
} else {
|
|
2200
|
+
return pos.substring(0, i) + String.fromCharCode(code - 1);
|
|
2201
|
+
}
|
|
2202
|
+
} else {
|
|
2203
|
+
return pos.substring(0, i + 1);
|
|
2204
|
+
}
|
|
1865
2205
|
}
|
|
1866
|
-
|
|
1867
|
-
function html(strings, ...values) {
|
|
1868
|
-
return new HtmlSafeString(strings, values);
|
|
2206
|
+
return ONE;
|
|
1869
2207
|
}
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
"|": "\\|",
|
|
1878
|
-
"(": "\\(",
|
|
1879
|
-
")": "\\)",
|
|
1880
|
-
"{": "\\{",
|
|
1881
|
-
"}": "\\}",
|
|
1882
|
-
"[": "\\[",
|
|
1883
|
-
"]": "\\]"
|
|
1884
|
-
};
|
|
1885
|
-
var markdownEscapablesRegex = new RegExp(
|
|
1886
|
-
Object.keys(markdownEscapables).map((entity) => `\\${entity}`).join("|"),
|
|
1887
|
-
"g"
|
|
1888
|
-
);
|
|
1889
|
-
function joinMarkdown(strings) {
|
|
1890
|
-
if (strings.length <= 0) {
|
|
1891
|
-
return new MarkdownSafeString([""], []);
|
|
2208
|
+
function after(pos) {
|
|
2209
|
+
for (let i = 0; i <= pos.length - 1; i++) {
|
|
2210
|
+
const code = pos.charCodeAt(i);
|
|
2211
|
+
if (code >= MAX_CODE) {
|
|
2212
|
+
continue;
|
|
2213
|
+
}
|
|
2214
|
+
return pos.substring(0, i) + String.fromCharCode(code + 1);
|
|
1892
2215
|
}
|
|
1893
|
-
return
|
|
1894
|
-
["", ...Array(strings.length - 1).fill(""), ""],
|
|
1895
|
-
strings
|
|
1896
|
-
);
|
|
2216
|
+
return pos + ONE;
|
|
1897
2217
|
}
|
|
1898
|
-
function
|
|
1899
|
-
if (
|
|
1900
|
-
return
|
|
2218
|
+
function between(lo, hi) {
|
|
2219
|
+
if (lo < hi) {
|
|
2220
|
+
return _between(lo, hi);
|
|
2221
|
+
} else if (lo > hi) {
|
|
2222
|
+
return _between(hi, lo);
|
|
2223
|
+
} else {
|
|
2224
|
+
throw new Error("Cannot compute value between two equal positions");
|
|
1901
2225
|
}
|
|
1902
|
-
|
|
1903
|
-
|
|
2226
|
+
}
|
|
2227
|
+
function _between(lo, hi) {
|
|
2228
|
+
let index = 0;
|
|
2229
|
+
const loLen = lo.length;
|
|
2230
|
+
const hiLen = hi.length;
|
|
2231
|
+
while (true) {
|
|
2232
|
+
const loCode = index < loLen ? lo.charCodeAt(index) : MIN_CODE;
|
|
2233
|
+
const hiCode = index < hiLen ? hi.charCodeAt(index) : MAX_CODE;
|
|
2234
|
+
if (loCode === hiCode) {
|
|
2235
|
+
index++;
|
|
2236
|
+
continue;
|
|
2237
|
+
}
|
|
2238
|
+
if (hiCode - loCode === 1) {
|
|
2239
|
+
const size = index + 1;
|
|
2240
|
+
let prefix = lo.substring(0, size);
|
|
2241
|
+
if (prefix.length < size) {
|
|
2242
|
+
prefix += ZERO.repeat(size - prefix.length);
|
|
2243
|
+
}
|
|
2244
|
+
const suffix = lo.substring(size);
|
|
2245
|
+
const nines = "";
|
|
2246
|
+
return prefix + _between(suffix, nines);
|
|
2247
|
+
} else {
|
|
2248
|
+
return takeN(lo, index) + String.fromCharCode(hiCode + loCode >> 1);
|
|
2249
|
+
}
|
|
1904
2250
|
}
|
|
1905
|
-
return String(value).replace(
|
|
1906
|
-
markdownEscapablesRegex,
|
|
1907
|
-
(character) => markdownEscapables[character]
|
|
1908
|
-
);
|
|
1909
2251
|
}
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
2252
|
+
function takeN(pos, n) {
|
|
2253
|
+
return n < pos.length ? pos.substring(0, n) : pos + ZERO.repeat(n - pos.length);
|
|
2254
|
+
}
|
|
2255
|
+
var MIN_NON_ZERO_CODE = MIN_CODE + 1;
|
|
2256
|
+
function isPos(str) {
|
|
2257
|
+
if (str === "") {
|
|
2258
|
+
return false;
|
|
1914
2259
|
}
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
2260
|
+
const lastIdx = str.length - 1;
|
|
2261
|
+
const last = str.charCodeAt(lastIdx);
|
|
2262
|
+
if (last < MIN_NON_ZERO_CODE || last > MAX_CODE) {
|
|
2263
|
+
return false;
|
|
1919
2264
|
}
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
if (url.startsWith("http://") || url.startsWith("https://")) {
|
|
1926
|
-
return url;
|
|
1927
|
-
} else if (url.startsWith("www.")) {
|
|
1928
|
-
return "https://" + url;
|
|
2265
|
+
for (let i = 0; i < lastIdx; i++) {
|
|
2266
|
+
const code = str.charCodeAt(i);
|
|
2267
|
+
if (code < MIN_CODE || code > MAX_CODE) {
|
|
2268
|
+
return false;
|
|
2269
|
+
}
|
|
1929
2270
|
}
|
|
1930
|
-
return;
|
|
2271
|
+
return true;
|
|
1931
2272
|
}
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
return `@${user?.name ?? element.id}`;
|
|
2273
|
+
function convertToPos(str) {
|
|
2274
|
+
const codes = [];
|
|
2275
|
+
for (let i = 0; i < str.length; i++) {
|
|
2276
|
+
const code = str.charCodeAt(i);
|
|
2277
|
+
codes.push(code < MIN_CODE ? MIN_CODE : code > MAX_CODE ? MAX_CODE : code);
|
|
1938
2278
|
}
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
paragraph: ({ children }) => {
|
|
1942
|
-
return children ? html`<p>${htmlSafe(children)}</p>` : children;
|
|
1943
|
-
},
|
|
1944
|
-
text: ({ element }) => {
|
|
1945
|
-
let children = element.text;
|
|
1946
|
-
if (!children) {
|
|
1947
|
-
return children;
|
|
1948
|
-
}
|
|
1949
|
-
if (element.bold) {
|
|
1950
|
-
children = html`<strong>${children}</strong>`;
|
|
1951
|
-
}
|
|
1952
|
-
if (element.italic) {
|
|
1953
|
-
children = html`<em>${children}</em>`;
|
|
1954
|
-
}
|
|
1955
|
-
if (element.strikethrough) {
|
|
1956
|
-
children = html`<s>${children}</s>`;
|
|
1957
|
-
}
|
|
1958
|
-
if (element.code) {
|
|
1959
|
-
children = html`<code>${children}</code>`;
|
|
1960
|
-
}
|
|
1961
|
-
return children;
|
|
1962
|
-
},
|
|
1963
|
-
link: ({ element, href }) => {
|
|
1964
|
-
return html`<a href="${href}" target="_blank" rel="noopener noreferrer">${element.url}</a>`;
|
|
1965
|
-
},
|
|
1966
|
-
mention: ({ element, user }) => {
|
|
1967
|
-
return html`<span data-mention>@${user?.name ?? element.id}</span>`;
|
|
2279
|
+
while (codes.length > 0 && codes[codes.length - 1] === MIN_CODE) {
|
|
2280
|
+
codes.length--;
|
|
1968
2281
|
}
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
return children;
|
|
1973
|
-
},
|
|
1974
|
-
text: ({ element }) => {
|
|
1975
|
-
let children = element.text;
|
|
1976
|
-
if (!children) {
|
|
1977
|
-
return children;
|
|
1978
|
-
}
|
|
1979
|
-
if (element.bold) {
|
|
1980
|
-
children = markdown`**${children}**`;
|
|
1981
|
-
}
|
|
1982
|
-
if (element.italic) {
|
|
1983
|
-
children = markdown`_${children}_`;
|
|
1984
|
-
}
|
|
1985
|
-
if (element.strikethrough) {
|
|
1986
|
-
children = markdown`~~${children}~~`;
|
|
1987
|
-
}
|
|
1988
|
-
if (element.code) {
|
|
1989
|
-
children = markdown`\`${children}\``;
|
|
1990
|
-
}
|
|
1991
|
-
return children;
|
|
1992
|
-
},
|
|
1993
|
-
link: ({ element, href }) => {
|
|
1994
|
-
return markdown`[${element.url}](${href})`;
|
|
1995
|
-
},
|
|
1996
|
-
mention: ({ element, user }) => {
|
|
1997
|
-
return markdown`@${user?.name ?? element.id}`;
|
|
1998
|
-
}
|
|
1999
|
-
};
|
|
2000
|
-
async function stringifyCommentBody(body, options) {
|
|
2001
|
-
const format = options?.format ?? "plain";
|
|
2002
|
-
const separator = options?.separator ?? (format === "markdown" ? "\n\n" : "\n");
|
|
2003
|
-
const elements = {
|
|
2004
|
-
...format === "html" ? stringifyCommentBodyHtmlElements : format === "markdown" ? stringifyCommentBodyMarkdownElements : stringifyCommentBodyPlainElements,
|
|
2005
|
-
...options?.elements
|
|
2006
|
-
};
|
|
2007
|
-
const resolvedUsers = await resolveUsersInCommentBody(
|
|
2008
|
-
body,
|
|
2009
|
-
options?.resolveUsers
|
|
2282
|
+
return codes.length > 0 ? String.fromCharCode(...codes) : (
|
|
2283
|
+
// Edge case: the str was a 0-only string, which is invalid. Default back to .1
|
|
2284
|
+
ONE
|
|
2010
2285
|
);
|
|
2011
|
-
const blocks = body.content.flatMap((block, blockIndex) => {
|
|
2012
|
-
switch (block.type) {
|
|
2013
|
-
case "paragraph": {
|
|
2014
|
-
const inlines = block.children.flatMap((inline, inlineIndex) => {
|
|
2015
|
-
if (isCommentBodyMention(inline)) {
|
|
2016
|
-
return inline.id ? [
|
|
2017
|
-
elements.mention(
|
|
2018
|
-
{
|
|
2019
|
-
element: inline,
|
|
2020
|
-
user: resolvedUsers.get(inline.id)
|
|
2021
|
-
},
|
|
2022
|
-
inlineIndex
|
|
2023
|
-
)
|
|
2024
|
-
] : [];
|
|
2025
|
-
}
|
|
2026
|
-
if (isCommentBodyLink(inline)) {
|
|
2027
|
-
return [
|
|
2028
|
-
elements.link(
|
|
2029
|
-
{
|
|
2030
|
-
element: inline,
|
|
2031
|
-
href: toAbsoluteUrl(inline.url) ?? inline.url
|
|
2032
|
-
},
|
|
2033
|
-
inlineIndex
|
|
2034
|
-
)
|
|
2035
|
-
];
|
|
2036
|
-
}
|
|
2037
|
-
if (isCommentBodyText(inline)) {
|
|
2038
|
-
return [elements.text({ element: inline }, inlineIndex)];
|
|
2039
|
-
}
|
|
2040
|
-
return [];
|
|
2041
|
-
});
|
|
2042
|
-
return [
|
|
2043
|
-
elements.paragraph(
|
|
2044
|
-
{ element: block, children: inlines.join("") },
|
|
2045
|
-
blockIndex
|
|
2046
|
-
)
|
|
2047
|
-
];
|
|
2048
|
-
}
|
|
2049
|
-
default:
|
|
2050
|
-
return [];
|
|
2051
|
-
}
|
|
2052
|
-
});
|
|
2053
|
-
return blocks.join(separator);
|
|
2054
2286
|
}
|
|
2055
|
-
function
|
|
2056
|
-
|
|
2057
|
-
const createdAt = new Date(data.createdAt);
|
|
2058
|
-
const reactions = data.reactions.map((reaction) => ({
|
|
2059
|
-
...reaction,
|
|
2060
|
-
createdAt: new Date(reaction.createdAt)
|
|
2061
|
-
}));
|
|
2062
|
-
if (data.body) {
|
|
2063
|
-
return {
|
|
2064
|
-
...data,
|
|
2065
|
-
reactions,
|
|
2066
|
-
createdAt,
|
|
2067
|
-
editedAt
|
|
2068
|
-
};
|
|
2069
|
-
} else {
|
|
2070
|
-
const deletedAt = new Date(data.deletedAt);
|
|
2071
|
-
return {
|
|
2072
|
-
...data,
|
|
2073
|
-
reactions,
|
|
2074
|
-
createdAt,
|
|
2075
|
-
editedAt,
|
|
2076
|
-
deletedAt
|
|
2077
|
-
};
|
|
2078
|
-
}
|
|
2287
|
+
function asPos(str) {
|
|
2288
|
+
return isPos(str) ? str : convertToPos(str);
|
|
2079
2289
|
}
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2290
|
+
|
|
2291
|
+
// src/protocol/Op.ts
|
|
2292
|
+
var OpCode = /* @__PURE__ */ ((OpCode2) => {
|
|
2293
|
+
OpCode2[OpCode2["INIT"] = 0] = "INIT";
|
|
2294
|
+
OpCode2[OpCode2["SET_PARENT_KEY"] = 1] = "SET_PARENT_KEY";
|
|
2295
|
+
OpCode2[OpCode2["CREATE_LIST"] = 2] = "CREATE_LIST";
|
|
2296
|
+
OpCode2[OpCode2["UPDATE_OBJECT"] = 3] = "UPDATE_OBJECT";
|
|
2297
|
+
OpCode2[OpCode2["CREATE_OBJECT"] = 4] = "CREATE_OBJECT";
|
|
2298
|
+
OpCode2[OpCode2["DELETE_CRDT"] = 5] = "DELETE_CRDT";
|
|
2299
|
+
OpCode2[OpCode2["DELETE_OBJECT_KEY"] = 6] = "DELETE_OBJECT_KEY";
|
|
2300
|
+
OpCode2[OpCode2["CREATE_MAP"] = 7] = "CREATE_MAP";
|
|
2301
|
+
OpCode2[OpCode2["CREATE_REGISTER"] = 8] = "CREATE_REGISTER";
|
|
2302
|
+
return OpCode2;
|
|
2303
|
+
})(OpCode || {});
|
|
2304
|
+
function ackOp(opId) {
|
|
2086
2305
|
return {
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2306
|
+
type: 5 /* DELETE_CRDT */,
|
|
2307
|
+
id: "ACK",
|
|
2308
|
+
// (H)ACK
|
|
2309
|
+
opId
|
|
2091
2310
|
};
|
|
2092
2311
|
}
|
|
2093
|
-
function
|
|
2094
|
-
return
|
|
2095
|
-
...data,
|
|
2096
|
-
createdAt: new Date(data.createdAt)
|
|
2097
|
-
};
|
|
2312
|
+
function isAckOp(op) {
|
|
2313
|
+
return op.type === 5 /* DELETE_CRDT */ && op.id === "ACK";
|
|
2098
2314
|
}
|
|
2099
2315
|
|
|
2100
|
-
// src/
|
|
2101
|
-
function
|
|
2102
|
-
|
|
2103
|
-
return authValue.publicApiKey;
|
|
2104
|
-
} else {
|
|
2105
|
-
return authValue.token.raw;
|
|
2106
|
-
}
|
|
2316
|
+
// src/crdts/AbstractCrdt.ts
|
|
2317
|
+
function crdtAsLiveNode(value) {
|
|
2318
|
+
return value;
|
|
2107
2319
|
}
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2320
|
+
function HasParent(node, key, pos = asPos(key)) {
|
|
2321
|
+
return Object.freeze({ type: "HasParent", node, key, pos });
|
|
2322
|
+
}
|
|
2323
|
+
var NoParent = Object.freeze({ type: "NoParent" });
|
|
2324
|
+
function Orphaned(oldKey, oldPos = asPos(oldKey)) {
|
|
2325
|
+
return Object.freeze({ type: "Orphaned", oldKey, oldPos });
|
|
2326
|
+
}
|
|
2327
|
+
var AbstractCrdt = class {
|
|
2328
|
+
constructor() {
|
|
2329
|
+
/** @internal */
|
|
2330
|
+
this._parent = NoParent;
|
|
2114
2331
|
}
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
response.status,
|
|
2127
|
-
errorBody
|
|
2128
|
-
);
|
|
2129
|
-
} catch {
|
|
2130
|
-
error3 = new CommentsApiError(response.statusText, response.status);
|
|
2131
|
-
}
|
|
2132
|
-
throw error3;
|
|
2133
|
-
}
|
|
2332
|
+
/** @internal */
|
|
2333
|
+
_getParentKeyOrThrow() {
|
|
2334
|
+
switch (this.parent.type) {
|
|
2335
|
+
case "HasParent":
|
|
2336
|
+
return this.parent.key;
|
|
2337
|
+
case "NoParent":
|
|
2338
|
+
throw new Error("Parent key is missing");
|
|
2339
|
+
case "Orphaned":
|
|
2340
|
+
return this.parent.oldKey;
|
|
2341
|
+
default:
|
|
2342
|
+
return assertNever(this.parent, "Unknown state");
|
|
2134
2343
|
}
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2344
|
+
}
|
|
2345
|
+
/** @internal */
|
|
2346
|
+
get _parentPos() {
|
|
2347
|
+
switch (this.parent.type) {
|
|
2348
|
+
case "HasParent":
|
|
2349
|
+
return this.parent.pos;
|
|
2350
|
+
case "NoParent":
|
|
2351
|
+
throw new Error("Parent key is missing");
|
|
2352
|
+
case "Orphaned":
|
|
2353
|
+
return this.parent.oldPos;
|
|
2354
|
+
default:
|
|
2355
|
+
return assertNever(this.parent, "Unknown state");
|
|
2140
2356
|
}
|
|
2141
|
-
return body;
|
|
2142
2357
|
}
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
`/v2/c/rooms/${encodeURIComponent(roomId2)}${endpoint}`,
|
|
2147
|
-
config.baseUrl
|
|
2148
|
-
);
|
|
2149
|
-
return await fetch(url.toString(), {
|
|
2150
|
-
...options,
|
|
2151
|
-
headers: {
|
|
2152
|
-
...options?.headers,
|
|
2153
|
-
Authorization: `Bearer ${getAuthBearerHeaderFromAuthValue(authValue)}`
|
|
2154
|
-
}
|
|
2155
|
-
});
|
|
2358
|
+
/** @internal */
|
|
2359
|
+
get _pool() {
|
|
2360
|
+
return this.__pool;
|
|
2156
2361
|
}
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
body: JSON.stringify({
|
|
2160
|
-
...options?.query?.metadata && { metadata: options.query.metadata }
|
|
2161
|
-
}),
|
|
2162
|
-
headers: {
|
|
2163
|
-
"Content-Type": "application/json"
|
|
2164
|
-
},
|
|
2165
|
-
method: "POST"
|
|
2166
|
-
});
|
|
2167
|
-
if (response.ok) {
|
|
2168
|
-
const json = await response.json();
|
|
2169
|
-
return json.data.map((thread) => convertToThreadData(thread));
|
|
2170
|
-
} else if (response.status === 404) {
|
|
2171
|
-
return [];
|
|
2172
|
-
} else {
|
|
2173
|
-
throw new Error("There was an error while getting threads.");
|
|
2174
|
-
}
|
|
2362
|
+
get roomId() {
|
|
2363
|
+
return this.__pool ? this.__pool.roomId : null;
|
|
2175
2364
|
}
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
commentId,
|
|
2180
|
-
threadId
|
|
2181
|
-
}) {
|
|
2182
|
-
const thread = await fetchJson(
|
|
2183
|
-
"/threads",
|
|
2184
|
-
{
|
|
2185
|
-
method: "POST",
|
|
2186
|
-
headers: {
|
|
2187
|
-
"Content-Type": "application/json"
|
|
2188
|
-
},
|
|
2189
|
-
body: JSON.stringify({
|
|
2190
|
-
id: threadId,
|
|
2191
|
-
comment: {
|
|
2192
|
-
id: commentId,
|
|
2193
|
-
body
|
|
2194
|
-
},
|
|
2195
|
-
metadata
|
|
2196
|
-
})
|
|
2197
|
-
}
|
|
2198
|
-
);
|
|
2199
|
-
return convertToThreadData(thread);
|
|
2365
|
+
/** @internal */
|
|
2366
|
+
get _id() {
|
|
2367
|
+
return this.__id;
|
|
2200
2368
|
}
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
}) {
|
|
2205
|
-
return await fetchJson(
|
|
2206
|
-
`/threads/${encodeURIComponent(threadId)}/metadata`,
|
|
2207
|
-
{
|
|
2208
|
-
method: "POST",
|
|
2209
|
-
headers: {
|
|
2210
|
-
"Content-Type": "application/json"
|
|
2211
|
-
},
|
|
2212
|
-
body: JSON.stringify(metadata)
|
|
2213
|
-
}
|
|
2214
|
-
);
|
|
2369
|
+
/** @internal */
|
|
2370
|
+
get parent() {
|
|
2371
|
+
return this._parent;
|
|
2215
2372
|
}
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
body: JSON.stringify({
|
|
2229
|
-
id: commentId,
|
|
2230
|
-
body
|
|
2231
|
-
})
|
|
2232
|
-
}
|
|
2233
|
-
);
|
|
2234
|
-
return convertToCommentData(comment);
|
|
2373
|
+
/** @internal */
|
|
2374
|
+
get _parentKey() {
|
|
2375
|
+
switch (this.parent.type) {
|
|
2376
|
+
case "HasParent":
|
|
2377
|
+
return this.parent.key;
|
|
2378
|
+
case "NoParent":
|
|
2379
|
+
return null;
|
|
2380
|
+
case "Orphaned":
|
|
2381
|
+
return this.parent.oldKey;
|
|
2382
|
+
default:
|
|
2383
|
+
return assertNever(this.parent, "Unknown state");
|
|
2384
|
+
}
|
|
2235
2385
|
}
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
)}`,
|
|
2245
|
-
{
|
|
2246
|
-
method: "POST",
|
|
2247
|
-
headers: {
|
|
2248
|
-
"Content-Type": "application/json"
|
|
2249
|
-
},
|
|
2250
|
-
body: JSON.stringify({
|
|
2251
|
-
body
|
|
2252
|
-
})
|
|
2386
|
+
/** @internal */
|
|
2387
|
+
_apply(op, _isLocal) {
|
|
2388
|
+
switch (op.type) {
|
|
2389
|
+
case 5 /* DELETE_CRDT */: {
|
|
2390
|
+
if (this.parent.type === "HasParent") {
|
|
2391
|
+
return this.parent.node._detachChild(crdtAsLiveNode(this));
|
|
2392
|
+
}
|
|
2393
|
+
return { modified: false };
|
|
2253
2394
|
}
|
|
2254
|
-
|
|
2255
|
-
return
|
|
2395
|
+
}
|
|
2396
|
+
return { modified: false };
|
|
2256
2397
|
}
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2398
|
+
/** @internal */
|
|
2399
|
+
_setParentLink(newParentNode, newParentKey) {
|
|
2400
|
+
switch (this.parent.type) {
|
|
2401
|
+
case "HasParent":
|
|
2402
|
+
if (this.parent.node !== newParentNode) {
|
|
2403
|
+
throw new Error("Cannot set parent: node already has a parent");
|
|
2404
|
+
} else {
|
|
2405
|
+
this._parent = HasParent(newParentNode, newParentKey);
|
|
2406
|
+
return;
|
|
2407
|
+
}
|
|
2408
|
+
case "Orphaned":
|
|
2409
|
+
case "NoParent": {
|
|
2410
|
+
this._parent = HasParent(newParentNode, newParentKey);
|
|
2411
|
+
return;
|
|
2267
2412
|
}
|
|
2268
|
-
|
|
2413
|
+
default:
|
|
2414
|
+
return assertNever(this.parent, "Unknown state");
|
|
2415
|
+
}
|
|
2269
2416
|
}
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
)}/reactions`,
|
|
2279
|
-
{
|
|
2280
|
-
method: "POST",
|
|
2281
|
-
headers: {
|
|
2282
|
-
"Content-Type": "application/json"
|
|
2283
|
-
},
|
|
2284
|
-
body: JSON.stringify({ emoji })
|
|
2285
|
-
}
|
|
2286
|
-
);
|
|
2287
|
-
return convertToCommentUserReaction(reaction);
|
|
2417
|
+
/** @internal */
|
|
2418
|
+
_attach(id, pool) {
|
|
2419
|
+
if (this.__id || this.__pool) {
|
|
2420
|
+
throw new Error("Cannot attach node: already attached");
|
|
2421
|
+
}
|
|
2422
|
+
pool.addNode(id, crdtAsLiveNode(this));
|
|
2423
|
+
this.__id = id;
|
|
2424
|
+
this.__pool = pool;
|
|
2288
2425
|
}
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
{
|
|
2299
|
-
method: "DELETE"
|
|
2426
|
+
/** @internal */
|
|
2427
|
+
_detach() {
|
|
2428
|
+
if (this.__pool && this.__id) {
|
|
2429
|
+
this.__pool.deleteNode(this.__id);
|
|
2430
|
+
}
|
|
2431
|
+
switch (this.parent.type) {
|
|
2432
|
+
case "HasParent": {
|
|
2433
|
+
this._parent = Orphaned(this.parent.key, this.parent.pos);
|
|
2434
|
+
break;
|
|
2300
2435
|
}
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
addReaction,
|
|
2311
|
-
removeReaction
|
|
2312
|
-
};
|
|
2313
|
-
}
|
|
2314
|
-
|
|
2315
|
-
// src/lib/position.ts
|
|
2316
|
-
var MIN_CODE = 32;
|
|
2317
|
-
var MAX_CODE = 126;
|
|
2318
|
-
var NUM_DIGITS = MAX_CODE - MIN_CODE + 1;
|
|
2319
|
-
var ZERO = nthDigit(0);
|
|
2320
|
-
var ONE = nthDigit(1);
|
|
2321
|
-
var ZERO_NINE = ZERO + nthDigit(-1);
|
|
2322
|
-
function nthDigit(n) {
|
|
2323
|
-
const code = MIN_CODE + (n < 0 ? NUM_DIGITS + n : n);
|
|
2324
|
-
if (code < MIN_CODE || code > MAX_CODE) {
|
|
2325
|
-
throw new Error(`Invalid n value: ${n}`);
|
|
2326
|
-
}
|
|
2327
|
-
return String.fromCharCode(code);
|
|
2328
|
-
}
|
|
2329
|
-
function makePosition(x, y) {
|
|
2330
|
-
if (x !== void 0 && y !== void 0) {
|
|
2331
|
-
return between(x, y);
|
|
2332
|
-
} else if (x !== void 0) {
|
|
2333
|
-
return after(x);
|
|
2334
|
-
} else if (y !== void 0) {
|
|
2335
|
-
return before(y);
|
|
2336
|
-
} else {
|
|
2337
|
-
return ONE;
|
|
2338
|
-
}
|
|
2339
|
-
}
|
|
2340
|
-
function before(pos) {
|
|
2341
|
-
const lastIndex = pos.length - 1;
|
|
2342
|
-
for (let i = 0; i <= lastIndex; i++) {
|
|
2343
|
-
const code = pos.charCodeAt(i);
|
|
2344
|
-
if (code <= MIN_CODE) {
|
|
2345
|
-
continue;
|
|
2436
|
+
case "NoParent": {
|
|
2437
|
+
this._parent = NoParent;
|
|
2438
|
+
break;
|
|
2439
|
+
}
|
|
2440
|
+
case "Orphaned": {
|
|
2441
|
+
break;
|
|
2442
|
+
}
|
|
2443
|
+
default:
|
|
2444
|
+
assertNever(this.parent, "Unknown state");
|
|
2346
2445
|
}
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2446
|
+
this.__pool = void 0;
|
|
2447
|
+
}
|
|
2448
|
+
/**
|
|
2449
|
+
* @internal
|
|
2450
|
+
*
|
|
2451
|
+
* Clear the Immutable cache, so that the next call to `.toImmutable()` will
|
|
2452
|
+
* recompute the equivalent Immutable value again. Call this after every
|
|
2453
|
+
* mutation to the Live node.
|
|
2454
|
+
*/
|
|
2455
|
+
invalidate() {
|
|
2456
|
+
if (this._cachedImmutable !== void 0 || this._cachedTreeNode !== void 0) {
|
|
2457
|
+
this._cachedImmutable = void 0;
|
|
2458
|
+
this._cachedTreeNode = void 0;
|
|
2459
|
+
if (this.parent.type === "HasParent") {
|
|
2460
|
+
this.parent.node.invalidate();
|
|
2352
2461
|
}
|
|
2353
|
-
} else {
|
|
2354
|
-
return pos.substring(0, i + 1);
|
|
2355
2462
|
}
|
|
2356
2463
|
}
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2464
|
+
/**
|
|
2465
|
+
* @internal
|
|
2466
|
+
*
|
|
2467
|
+
* Return an snapshot of this Live tree for use in DevTools.
|
|
2468
|
+
*/
|
|
2469
|
+
toTreeNode(key) {
|
|
2470
|
+
if (this._cachedTreeNode === void 0 || this._cachedTreeNodeKey !== key) {
|
|
2471
|
+
this._cachedTreeNodeKey = key;
|
|
2472
|
+
this._cachedTreeNode = this._toTreeNode(key);
|
|
2364
2473
|
}
|
|
2365
|
-
return
|
|
2474
|
+
return this._cachedTreeNode;
|
|
2366
2475
|
}
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
throw new Error("Cannot compute value between two equal positions");
|
|
2376
|
-
}
|
|
2377
|
-
}
|
|
2378
|
-
function _between(lo, hi) {
|
|
2379
|
-
let index = 0;
|
|
2380
|
-
const loLen = lo.length;
|
|
2381
|
-
const hiLen = hi.length;
|
|
2382
|
-
while (true) {
|
|
2383
|
-
const loCode = index < loLen ? lo.charCodeAt(index) : MIN_CODE;
|
|
2384
|
-
const hiCode = index < hiLen ? hi.charCodeAt(index) : MAX_CODE;
|
|
2385
|
-
if (loCode === hiCode) {
|
|
2386
|
-
index++;
|
|
2387
|
-
continue;
|
|
2388
|
-
}
|
|
2389
|
-
if (hiCode - loCode === 1) {
|
|
2390
|
-
const size = index + 1;
|
|
2391
|
-
let prefix = lo.substring(0, size);
|
|
2392
|
-
if (prefix.length < size) {
|
|
2393
|
-
prefix += ZERO.repeat(size - prefix.length);
|
|
2394
|
-
}
|
|
2395
|
-
const suffix = lo.substring(size);
|
|
2396
|
-
const nines = "";
|
|
2397
|
-
return prefix + _between(suffix, nines);
|
|
2398
|
-
} else {
|
|
2399
|
-
return takeN(lo, index) + String.fromCharCode(hiCode + loCode >> 1);
|
|
2400
|
-
}
|
|
2401
|
-
}
|
|
2402
|
-
}
|
|
2403
|
-
function takeN(pos, n) {
|
|
2404
|
-
return n < pos.length ? pos.substring(0, n) : pos + ZERO.repeat(n - pos.length);
|
|
2405
|
-
}
|
|
2406
|
-
var MIN_NON_ZERO_CODE = MIN_CODE + 1;
|
|
2407
|
-
function isPos(str) {
|
|
2408
|
-
if (str === "") {
|
|
2409
|
-
return false;
|
|
2410
|
-
}
|
|
2411
|
-
const lastIdx = str.length - 1;
|
|
2412
|
-
const last = str.charCodeAt(lastIdx);
|
|
2413
|
-
if (last < MIN_NON_ZERO_CODE || last > MAX_CODE) {
|
|
2414
|
-
return false;
|
|
2415
|
-
}
|
|
2416
|
-
for (let i = 0; i < lastIdx; i++) {
|
|
2417
|
-
const code = str.charCodeAt(i);
|
|
2418
|
-
if (code < MIN_CODE || code > MAX_CODE) {
|
|
2419
|
-
return false;
|
|
2420
|
-
}
|
|
2421
|
-
}
|
|
2422
|
-
return true;
|
|
2423
|
-
}
|
|
2424
|
-
function convertToPos(str) {
|
|
2425
|
-
const codes = [];
|
|
2426
|
-
for (let i = 0; i < str.length; i++) {
|
|
2427
|
-
const code = str.charCodeAt(i);
|
|
2428
|
-
codes.push(code < MIN_CODE ? MIN_CODE : code > MAX_CODE ? MAX_CODE : code);
|
|
2429
|
-
}
|
|
2430
|
-
while (codes.length > 0 && codes[codes.length - 1] === MIN_CODE) {
|
|
2431
|
-
codes.length--;
|
|
2432
|
-
}
|
|
2433
|
-
return codes.length > 0 ? String.fromCharCode(...codes) : (
|
|
2434
|
-
// Edge case: the str was a 0-only string, which is invalid. Default back to .1
|
|
2435
|
-
ONE
|
|
2436
|
-
);
|
|
2437
|
-
}
|
|
2438
|
-
function asPos(str) {
|
|
2439
|
-
return isPos(str) ? str : convertToPos(str);
|
|
2440
|
-
}
|
|
2441
|
-
|
|
2442
|
-
// src/protocol/Op.ts
|
|
2443
|
-
var OpCode = /* @__PURE__ */ ((OpCode2) => {
|
|
2444
|
-
OpCode2[OpCode2["INIT"] = 0] = "INIT";
|
|
2445
|
-
OpCode2[OpCode2["SET_PARENT_KEY"] = 1] = "SET_PARENT_KEY";
|
|
2446
|
-
OpCode2[OpCode2["CREATE_LIST"] = 2] = "CREATE_LIST";
|
|
2447
|
-
OpCode2[OpCode2["UPDATE_OBJECT"] = 3] = "UPDATE_OBJECT";
|
|
2448
|
-
OpCode2[OpCode2["CREATE_OBJECT"] = 4] = "CREATE_OBJECT";
|
|
2449
|
-
OpCode2[OpCode2["DELETE_CRDT"] = 5] = "DELETE_CRDT";
|
|
2450
|
-
OpCode2[OpCode2["DELETE_OBJECT_KEY"] = 6] = "DELETE_OBJECT_KEY";
|
|
2451
|
-
OpCode2[OpCode2["CREATE_MAP"] = 7] = "CREATE_MAP";
|
|
2452
|
-
OpCode2[OpCode2["CREATE_REGISTER"] = 8] = "CREATE_REGISTER";
|
|
2453
|
-
return OpCode2;
|
|
2454
|
-
})(OpCode || {});
|
|
2455
|
-
function isAckOp(op) {
|
|
2456
|
-
return op.type === 5 /* DELETE_CRDT */ && op.id === "ACK";
|
|
2457
|
-
}
|
|
2458
|
-
|
|
2459
|
-
// src/crdts/AbstractCrdt.ts
|
|
2460
|
-
function crdtAsLiveNode(value) {
|
|
2461
|
-
return value;
|
|
2462
|
-
}
|
|
2463
|
-
function HasParent(node, key, pos = asPos(key)) {
|
|
2464
|
-
return Object.freeze({ type: "HasParent", node, key, pos });
|
|
2465
|
-
}
|
|
2466
|
-
var NoParent = Object.freeze({ type: "NoParent" });
|
|
2467
|
-
function Orphaned(oldKey, oldPos = asPos(oldKey)) {
|
|
2468
|
-
return Object.freeze({ type: "Orphaned", oldKey, oldPos });
|
|
2469
|
-
}
|
|
2470
|
-
var AbstractCrdt = class {
|
|
2471
|
-
constructor() {
|
|
2472
|
-
/** @internal */
|
|
2473
|
-
this._parent = NoParent;
|
|
2474
|
-
}
|
|
2475
|
-
/** @internal */
|
|
2476
|
-
_getParentKeyOrThrow() {
|
|
2477
|
-
switch (this.parent.type) {
|
|
2478
|
-
case "HasParent":
|
|
2479
|
-
return this.parent.key;
|
|
2480
|
-
case "NoParent":
|
|
2481
|
-
throw new Error("Parent key is missing");
|
|
2482
|
-
case "Orphaned":
|
|
2483
|
-
return this.parent.oldKey;
|
|
2484
|
-
default:
|
|
2485
|
-
return assertNever(this.parent, "Unknown state");
|
|
2486
|
-
}
|
|
2487
|
-
}
|
|
2488
|
-
/** @internal */
|
|
2489
|
-
get _parentPos() {
|
|
2490
|
-
switch (this.parent.type) {
|
|
2491
|
-
case "HasParent":
|
|
2492
|
-
return this.parent.pos;
|
|
2493
|
-
case "NoParent":
|
|
2494
|
-
throw new Error("Parent key is missing");
|
|
2495
|
-
case "Orphaned":
|
|
2496
|
-
return this.parent.oldPos;
|
|
2497
|
-
default:
|
|
2498
|
-
return assertNever(this.parent, "Unknown state");
|
|
2499
|
-
}
|
|
2500
|
-
}
|
|
2501
|
-
/** @internal */
|
|
2502
|
-
get _pool() {
|
|
2503
|
-
return this.__pool;
|
|
2504
|
-
}
|
|
2505
|
-
get roomId() {
|
|
2506
|
-
return this.__pool ? this.__pool.roomId : null;
|
|
2507
|
-
}
|
|
2508
|
-
/** @internal */
|
|
2509
|
-
get _id() {
|
|
2510
|
-
return this.__id;
|
|
2511
|
-
}
|
|
2512
|
-
/** @internal */
|
|
2513
|
-
get parent() {
|
|
2514
|
-
return this._parent;
|
|
2515
|
-
}
|
|
2516
|
-
/** @internal */
|
|
2517
|
-
get _parentKey() {
|
|
2518
|
-
switch (this.parent.type) {
|
|
2519
|
-
case "HasParent":
|
|
2520
|
-
return this.parent.key;
|
|
2521
|
-
case "NoParent":
|
|
2522
|
-
return null;
|
|
2523
|
-
case "Orphaned":
|
|
2524
|
-
return this.parent.oldKey;
|
|
2525
|
-
default:
|
|
2526
|
-
return assertNever(this.parent, "Unknown state");
|
|
2527
|
-
}
|
|
2528
|
-
}
|
|
2529
|
-
/** @internal */
|
|
2530
|
-
_apply(op, _isLocal) {
|
|
2531
|
-
switch (op.type) {
|
|
2532
|
-
case 5 /* DELETE_CRDT */: {
|
|
2533
|
-
if (this.parent.type === "HasParent") {
|
|
2534
|
-
return this.parent.node._detachChild(crdtAsLiveNode(this));
|
|
2535
|
-
}
|
|
2536
|
-
return { modified: false };
|
|
2537
|
-
}
|
|
2538
|
-
}
|
|
2539
|
-
return { modified: false };
|
|
2540
|
-
}
|
|
2541
|
-
/** @internal */
|
|
2542
|
-
_setParentLink(newParentNode, newParentKey) {
|
|
2543
|
-
switch (this.parent.type) {
|
|
2544
|
-
case "HasParent":
|
|
2545
|
-
if (this.parent.node !== newParentNode) {
|
|
2546
|
-
throw new Error("Cannot set parent: node already has a parent");
|
|
2547
|
-
} else {
|
|
2548
|
-
this._parent = HasParent(newParentNode, newParentKey);
|
|
2549
|
-
return;
|
|
2550
|
-
}
|
|
2551
|
-
case "Orphaned":
|
|
2552
|
-
case "NoParent": {
|
|
2553
|
-
this._parent = HasParent(newParentNode, newParentKey);
|
|
2554
|
-
return;
|
|
2555
|
-
}
|
|
2556
|
-
default:
|
|
2557
|
-
return assertNever(this.parent, "Unknown state");
|
|
2558
|
-
}
|
|
2559
|
-
}
|
|
2560
|
-
/** @internal */
|
|
2561
|
-
_attach(id, pool) {
|
|
2562
|
-
if (this.__id || this.__pool) {
|
|
2563
|
-
throw new Error("Cannot attach node: already attached");
|
|
2564
|
-
}
|
|
2565
|
-
pool.addNode(id, crdtAsLiveNode(this));
|
|
2566
|
-
this.__id = id;
|
|
2567
|
-
this.__pool = pool;
|
|
2568
|
-
}
|
|
2569
|
-
/** @internal */
|
|
2570
|
-
_detach() {
|
|
2571
|
-
if (this.__pool && this.__id) {
|
|
2572
|
-
this.__pool.deleteNode(this.__id);
|
|
2573
|
-
}
|
|
2574
|
-
switch (this.parent.type) {
|
|
2575
|
-
case "HasParent": {
|
|
2576
|
-
this._parent = Orphaned(this.parent.key, this.parent.pos);
|
|
2577
|
-
break;
|
|
2578
|
-
}
|
|
2579
|
-
case "NoParent": {
|
|
2580
|
-
this._parent = NoParent;
|
|
2581
|
-
break;
|
|
2582
|
-
}
|
|
2583
|
-
case "Orphaned": {
|
|
2584
|
-
break;
|
|
2585
|
-
}
|
|
2586
|
-
default:
|
|
2587
|
-
assertNever(this.parent, "Unknown state");
|
|
2588
|
-
}
|
|
2589
|
-
this.__pool = void 0;
|
|
2590
|
-
}
|
|
2591
|
-
/**
|
|
2592
|
-
* @internal
|
|
2593
|
-
*
|
|
2594
|
-
* Clear the Immutable cache, so that the next call to `.toImmutable()` will
|
|
2595
|
-
* recompute the equivalent Immutable value again. Call this after every
|
|
2596
|
-
* mutation to the Live node.
|
|
2597
|
-
*/
|
|
2598
|
-
invalidate() {
|
|
2599
|
-
if (this._cachedImmutable !== void 0 || this._cachedTreeNode !== void 0) {
|
|
2600
|
-
this._cachedImmutable = void 0;
|
|
2601
|
-
this._cachedTreeNode = void 0;
|
|
2602
|
-
if (this.parent.type === "HasParent") {
|
|
2603
|
-
this.parent.node.invalidate();
|
|
2604
|
-
}
|
|
2605
|
-
}
|
|
2606
|
-
}
|
|
2607
|
-
/**
|
|
2608
|
-
* @internal
|
|
2609
|
-
*
|
|
2610
|
-
* Return an snapshot of this Live tree for use in DevTools.
|
|
2611
|
-
*/
|
|
2612
|
-
toTreeNode(key) {
|
|
2613
|
-
if (this._cachedTreeNode === void 0 || this._cachedTreeNodeKey !== key) {
|
|
2614
|
-
this._cachedTreeNodeKey = key;
|
|
2615
|
-
this._cachedTreeNode = this._toTreeNode(key);
|
|
2616
|
-
}
|
|
2617
|
-
return this._cachedTreeNode;
|
|
2618
|
-
}
|
|
2619
|
-
/**
|
|
2620
|
-
* Return an immutable snapshot of this Live node and its children.
|
|
2621
|
-
*/
|
|
2622
|
-
toImmutable() {
|
|
2623
|
-
if (this._cachedImmutable === void 0) {
|
|
2624
|
-
this._cachedImmutable = this._toImmutable();
|
|
2625
|
-
}
|
|
2626
|
-
return this._cachedImmutable;
|
|
2476
|
+
/**
|
|
2477
|
+
* Return an immutable snapshot of this Live node and its children.
|
|
2478
|
+
*/
|
|
2479
|
+
toImmutable() {
|
|
2480
|
+
if (this._cachedImmutable === void 0) {
|
|
2481
|
+
this._cachedImmutable = this._toImmutable();
|
|
2482
|
+
}
|
|
2483
|
+
return this._cachedImmutable;
|
|
2627
2484
|
}
|
|
2628
2485
|
};
|
|
2629
2486
|
|
|
@@ -4100,15 +3957,14 @@ var LiveObject = class _LiveObject extends AbstractCrdt {
|
|
|
4100
3957
|
constructor(obj = {}) {
|
|
4101
3958
|
super();
|
|
4102
3959
|
this._propToLastUpdate = /* @__PURE__ */ new Map();
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
} else if (isLiveNode(value)) {
|
|
3960
|
+
const o = compactObject(obj);
|
|
3961
|
+
for (const key of Object.keys(o)) {
|
|
3962
|
+
const value = o[key];
|
|
3963
|
+
if (isLiveNode(value)) {
|
|
4108
3964
|
value._setParentLink(this, key);
|
|
4109
3965
|
}
|
|
4110
3966
|
}
|
|
4111
|
-
this._map = new Map(Object.entries(
|
|
3967
|
+
this._map = new Map(Object.entries(o));
|
|
4112
3968
|
}
|
|
4113
3969
|
/** @internal */
|
|
4114
3970
|
static _buildRootAndParentToChildren(items) {
|
|
@@ -4886,16 +4742,125 @@ function isJsonObject(data) {
|
|
|
4886
4742
|
return !isJsonScalar(data) && !isJsonArray(data);
|
|
4887
4743
|
}
|
|
4888
4744
|
|
|
4889
|
-
// src/
|
|
4890
|
-
var
|
|
4891
|
-
|
|
4892
|
-
|
|
4893
|
-
|
|
4894
|
-
|
|
4895
|
-
|
|
4896
|
-
|
|
4897
|
-
|
|
4898
|
-
|
|
4745
|
+
// src/lib/objectToQuery.ts
|
|
4746
|
+
var identifierRegex = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
|
|
4747
|
+
function objectToQuery(obj) {
|
|
4748
|
+
let filterList = [];
|
|
4749
|
+
const entries2 = Object.entries(obj);
|
|
4750
|
+
const keyValuePairs = [];
|
|
4751
|
+
const keyValuePairsWithOperator = [];
|
|
4752
|
+
const indexedKeys = [];
|
|
4753
|
+
entries2.forEach(([key, value]) => {
|
|
4754
|
+
if (!identifierRegex.test(key)) {
|
|
4755
|
+
throw new Error("Key must only contain letters, numbers, _");
|
|
4756
|
+
}
|
|
4757
|
+
if (isSimpleValue(value)) {
|
|
4758
|
+
keyValuePairs.push([key, value]);
|
|
4759
|
+
} else if (isValueWithOperator(value)) {
|
|
4760
|
+
keyValuePairsWithOperator.push([key, value]);
|
|
4761
|
+
} else if (typeof value === "object" && !("startsWith" in value)) {
|
|
4762
|
+
indexedKeys.push([key, value]);
|
|
4763
|
+
}
|
|
4764
|
+
});
|
|
4765
|
+
filterList = [
|
|
4766
|
+
...getFiltersFromKeyValuePairs(keyValuePairs),
|
|
4767
|
+
...getFiltersFromKeyValuePairsWithOperator(keyValuePairsWithOperator)
|
|
4768
|
+
];
|
|
4769
|
+
indexedKeys.forEach(([key, value]) => {
|
|
4770
|
+
const nestedEntries = Object.entries(value);
|
|
4771
|
+
const nKeyValuePairs = [];
|
|
4772
|
+
const nKeyValuePairsWithOperator = [];
|
|
4773
|
+
nestedEntries.forEach(([nestedKey, nestedValue]) => {
|
|
4774
|
+
if (isStringEmpty(nestedKey)) {
|
|
4775
|
+
throw new Error("Key cannot be empty");
|
|
4776
|
+
}
|
|
4777
|
+
if (isSimpleValue(nestedValue)) {
|
|
4778
|
+
nKeyValuePairs.push([formatFilterKey(key, nestedKey), nestedValue]);
|
|
4779
|
+
} else if (isValueWithOperator(nestedValue)) {
|
|
4780
|
+
nKeyValuePairsWithOperator.push([
|
|
4781
|
+
formatFilterKey(key, nestedKey),
|
|
4782
|
+
nestedValue
|
|
4783
|
+
]);
|
|
4784
|
+
}
|
|
4785
|
+
});
|
|
4786
|
+
filterList = [
|
|
4787
|
+
...filterList,
|
|
4788
|
+
...getFiltersFromKeyValuePairs(nKeyValuePairs),
|
|
4789
|
+
...getFiltersFromKeyValuePairsWithOperator(nKeyValuePairsWithOperator)
|
|
4790
|
+
];
|
|
4791
|
+
});
|
|
4792
|
+
return filterList.map(
|
|
4793
|
+
({ key, operator, value }) => formatFilter(key, operator, formatFilterValue(value))
|
|
4794
|
+
).join(" AND ");
|
|
4795
|
+
}
|
|
4796
|
+
var getFiltersFromKeyValuePairs = (keyValuePairs) => {
|
|
4797
|
+
const filters = [];
|
|
4798
|
+
keyValuePairs.forEach(([key, value]) => {
|
|
4799
|
+
filters.push({
|
|
4800
|
+
key,
|
|
4801
|
+
operator: ":",
|
|
4802
|
+
value
|
|
4803
|
+
});
|
|
4804
|
+
});
|
|
4805
|
+
return filters;
|
|
4806
|
+
};
|
|
4807
|
+
var getFiltersFromKeyValuePairsWithOperator = (keyValuePairsWithOperator) => {
|
|
4808
|
+
const filters = [];
|
|
4809
|
+
keyValuePairsWithOperator.forEach(([key, value]) => {
|
|
4810
|
+
if ("startsWith" in value && typeof value.startsWith === "string") {
|
|
4811
|
+
filters.push({
|
|
4812
|
+
key,
|
|
4813
|
+
operator: "^",
|
|
4814
|
+
value: value.startsWith
|
|
4815
|
+
});
|
|
4816
|
+
}
|
|
4817
|
+
});
|
|
4818
|
+
return filters;
|
|
4819
|
+
};
|
|
4820
|
+
var isSimpleValue = (value) => {
|
|
4821
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
4822
|
+
return true;
|
|
4823
|
+
}
|
|
4824
|
+
return false;
|
|
4825
|
+
};
|
|
4826
|
+
var isValueWithOperator = (value) => {
|
|
4827
|
+
if (typeof value === "object" && value !== null && "startsWith" in value) {
|
|
4828
|
+
return true;
|
|
4829
|
+
}
|
|
4830
|
+
return false;
|
|
4831
|
+
};
|
|
4832
|
+
var formatFilter = (key, operator, value) => {
|
|
4833
|
+
return `${key}${operator}${value}`;
|
|
4834
|
+
};
|
|
4835
|
+
var formatFilterKey = (key, nestedKey) => {
|
|
4836
|
+
if (nestedKey) {
|
|
4837
|
+
return `${key}[${JSON.stringify(nestedKey)}]`;
|
|
4838
|
+
}
|
|
4839
|
+
return key;
|
|
4840
|
+
};
|
|
4841
|
+
var formatFilterValue = (value) => {
|
|
4842
|
+
if (typeof value === "string") {
|
|
4843
|
+
if (isStringEmpty(value)) {
|
|
4844
|
+
throw new Error("Value cannot be empty");
|
|
4845
|
+
}
|
|
4846
|
+
return JSON.stringify(value);
|
|
4847
|
+
}
|
|
4848
|
+
return value.toString();
|
|
4849
|
+
};
|
|
4850
|
+
var isStringEmpty = (value) => {
|
|
4851
|
+
return !value || value.toString().trim() === "";
|
|
4852
|
+
};
|
|
4853
|
+
|
|
4854
|
+
// src/protocol/ClientMsg.ts
|
|
4855
|
+
var ClientMsgCode = /* @__PURE__ */ ((ClientMsgCode2) => {
|
|
4856
|
+
ClientMsgCode2[ClientMsgCode2["UPDATE_PRESENCE"] = 100] = "UPDATE_PRESENCE";
|
|
4857
|
+
ClientMsgCode2[ClientMsgCode2["BROADCAST_EVENT"] = 103] = "BROADCAST_EVENT";
|
|
4858
|
+
ClientMsgCode2[ClientMsgCode2["FETCH_STORAGE"] = 200] = "FETCH_STORAGE";
|
|
4859
|
+
ClientMsgCode2[ClientMsgCode2["UPDATE_STORAGE"] = 201] = "UPDATE_STORAGE";
|
|
4860
|
+
ClientMsgCode2[ClientMsgCode2["FETCH_YDOC"] = 300] = "FETCH_YDOC";
|
|
4861
|
+
ClientMsgCode2[ClientMsgCode2["UPDATE_YDOC"] = 301] = "UPDATE_YDOC";
|
|
4862
|
+
return ClientMsgCode2;
|
|
4863
|
+
})(ClientMsgCode || {});
|
|
4899
4864
|
|
|
4900
4865
|
// src/refs/ImmutableRef.ts
|
|
4901
4866
|
function merge(target, patch) {
|
|
@@ -5129,7 +5094,13 @@ function userToTreeNode(key, user) {
|
|
|
5129
5094
|
type: "User",
|
|
5130
5095
|
id: `${user.connectionId}`,
|
|
5131
5096
|
key,
|
|
5132
|
-
payload:
|
|
5097
|
+
payload: {
|
|
5098
|
+
connectionId: user.connectionId,
|
|
5099
|
+
id: user.id,
|
|
5100
|
+
info: user.info,
|
|
5101
|
+
presence: user.presence,
|
|
5102
|
+
isReadOnly: !user.canWrite
|
|
5103
|
+
}
|
|
5133
5104
|
};
|
|
5134
5105
|
}
|
|
5135
5106
|
function installBackgroundTabSpy() {
|
|
@@ -5148,6 +5119,246 @@ function installBackgroundTabSpy() {
|
|
|
5148
5119
|
};
|
|
5149
5120
|
return [inBackgroundSince, unsub];
|
|
5150
5121
|
}
|
|
5122
|
+
var CommentsApiError = class extends Error {
|
|
5123
|
+
constructor(message, status, details) {
|
|
5124
|
+
super(message);
|
|
5125
|
+
this.message = message;
|
|
5126
|
+
this.status = status;
|
|
5127
|
+
this.details = details;
|
|
5128
|
+
}
|
|
5129
|
+
};
|
|
5130
|
+
function createCommentsApi(roomId, getAuthValue, fetchClientApi) {
|
|
5131
|
+
async function fetchCommentsApi(endpoint, params, options) {
|
|
5132
|
+
const authValue = await getAuthValue();
|
|
5133
|
+
return fetchClientApi(roomId, endpoint, authValue, options, params);
|
|
5134
|
+
}
|
|
5135
|
+
async function fetchJson(endpoint, options, params) {
|
|
5136
|
+
const response = await fetchCommentsApi(endpoint, params, options);
|
|
5137
|
+
if (!response.ok) {
|
|
5138
|
+
if (response.status >= 400 && response.status < 600) {
|
|
5139
|
+
let error3;
|
|
5140
|
+
try {
|
|
5141
|
+
const errorBody = await response.json();
|
|
5142
|
+
error3 = new CommentsApiError(
|
|
5143
|
+
errorBody.message,
|
|
5144
|
+
response.status,
|
|
5145
|
+
errorBody
|
|
5146
|
+
);
|
|
5147
|
+
} catch {
|
|
5148
|
+
error3 = new CommentsApiError(response.statusText, response.status);
|
|
5149
|
+
}
|
|
5150
|
+
throw error3;
|
|
5151
|
+
}
|
|
5152
|
+
}
|
|
5153
|
+
let body;
|
|
5154
|
+
try {
|
|
5155
|
+
body = await response.json();
|
|
5156
|
+
} catch {
|
|
5157
|
+
body = {};
|
|
5158
|
+
}
|
|
5159
|
+
return body;
|
|
5160
|
+
}
|
|
5161
|
+
async function getThreads(options) {
|
|
5162
|
+
let query;
|
|
5163
|
+
if (options?.query) {
|
|
5164
|
+
query = objectToQuery(options.query);
|
|
5165
|
+
}
|
|
5166
|
+
const response = await fetchCommentsApi(
|
|
5167
|
+
"/threads",
|
|
5168
|
+
{
|
|
5169
|
+
since: options?.since?.toISOString(),
|
|
5170
|
+
query
|
|
5171
|
+
},
|
|
5172
|
+
{
|
|
5173
|
+
headers: {
|
|
5174
|
+
"Content-Type": "application/json"
|
|
5175
|
+
}
|
|
5176
|
+
}
|
|
5177
|
+
);
|
|
5178
|
+
if (response.ok) {
|
|
5179
|
+
const json = await response.json();
|
|
5180
|
+
return {
|
|
5181
|
+
threads: json.data.map((thread) => convertToThreadData(thread)),
|
|
5182
|
+
inboxNotifications: json.inboxNotifications.map(
|
|
5183
|
+
(notification) => convertToInboxNotificationData(notification)
|
|
5184
|
+
),
|
|
5185
|
+
deletedThreads: json.deletedThreads.map(
|
|
5186
|
+
(info) => convertToThreadDeleteInfo(info)
|
|
5187
|
+
),
|
|
5188
|
+
deletedInboxNotifications: json.deletedInboxNotifications.map(
|
|
5189
|
+
(info) => convertToInboxNotificationDeleteInfo(info)
|
|
5190
|
+
),
|
|
5191
|
+
meta: {
|
|
5192
|
+
requestedAt: new Date(json.meta.requestedAt)
|
|
5193
|
+
}
|
|
5194
|
+
};
|
|
5195
|
+
} else if (response.status === 404) {
|
|
5196
|
+
return {
|
|
5197
|
+
threads: [],
|
|
5198
|
+
inboxNotifications: [],
|
|
5199
|
+
deletedThreads: [],
|
|
5200
|
+
deletedInboxNotifications: [],
|
|
5201
|
+
meta: {
|
|
5202
|
+
requestedAt: /* @__PURE__ */ new Date()
|
|
5203
|
+
}
|
|
5204
|
+
};
|
|
5205
|
+
} else {
|
|
5206
|
+
throw new Error("There was an error while getting threads.");
|
|
5207
|
+
}
|
|
5208
|
+
}
|
|
5209
|
+
async function getThread({ threadId }) {
|
|
5210
|
+
const response = await fetchCommentsApi(
|
|
5211
|
+
`/thread-with-notification/${threadId}`
|
|
5212
|
+
);
|
|
5213
|
+
if (response.ok) {
|
|
5214
|
+
const json = await response.json();
|
|
5215
|
+
return {
|
|
5216
|
+
thread: convertToThreadData(json.thread),
|
|
5217
|
+
inboxNotification: json.inboxNotification ? convertToInboxNotificationData(json.inboxNotification) : void 0
|
|
5218
|
+
};
|
|
5219
|
+
} else if (response.status === 404) {
|
|
5220
|
+
return;
|
|
5221
|
+
} else {
|
|
5222
|
+
throw new Error(`There was an error while getting thread ${threadId}.`);
|
|
5223
|
+
}
|
|
5224
|
+
}
|
|
5225
|
+
async function createThread({
|
|
5226
|
+
metadata,
|
|
5227
|
+
body,
|
|
5228
|
+
commentId,
|
|
5229
|
+
threadId
|
|
5230
|
+
}) {
|
|
5231
|
+
const thread = await fetchJson("/threads", {
|
|
5232
|
+
method: "POST",
|
|
5233
|
+
headers: {
|
|
5234
|
+
"Content-Type": "application/json"
|
|
5235
|
+
},
|
|
5236
|
+
body: JSON.stringify({
|
|
5237
|
+
id: threadId,
|
|
5238
|
+
comment: {
|
|
5239
|
+
id: commentId,
|
|
5240
|
+
body
|
|
5241
|
+
},
|
|
5242
|
+
metadata
|
|
5243
|
+
})
|
|
5244
|
+
});
|
|
5245
|
+
return convertToThreadData(thread);
|
|
5246
|
+
}
|
|
5247
|
+
async function editThreadMetadata({
|
|
5248
|
+
metadata,
|
|
5249
|
+
threadId
|
|
5250
|
+
}) {
|
|
5251
|
+
return await fetchJson(
|
|
5252
|
+
`/threads/${encodeURIComponent(threadId)}/metadata`,
|
|
5253
|
+
{
|
|
5254
|
+
method: "POST",
|
|
5255
|
+
headers: {
|
|
5256
|
+
"Content-Type": "application/json"
|
|
5257
|
+
},
|
|
5258
|
+
body: JSON.stringify(metadata)
|
|
5259
|
+
}
|
|
5260
|
+
);
|
|
5261
|
+
}
|
|
5262
|
+
async function createComment({
|
|
5263
|
+
threadId,
|
|
5264
|
+
commentId,
|
|
5265
|
+
body
|
|
5266
|
+
}) {
|
|
5267
|
+
const comment = await fetchJson(
|
|
5268
|
+
`/threads/${encodeURIComponent(threadId)}/comments`,
|
|
5269
|
+
{
|
|
5270
|
+
method: "POST",
|
|
5271
|
+
headers: {
|
|
5272
|
+
"Content-Type": "application/json"
|
|
5273
|
+
},
|
|
5274
|
+
body: JSON.stringify({
|
|
5275
|
+
id: commentId,
|
|
5276
|
+
body
|
|
5277
|
+
})
|
|
5278
|
+
}
|
|
5279
|
+
);
|
|
5280
|
+
return convertToCommentData(comment);
|
|
5281
|
+
}
|
|
5282
|
+
async function editComment({
|
|
5283
|
+
threadId,
|
|
5284
|
+
commentId,
|
|
5285
|
+
body
|
|
5286
|
+
}) {
|
|
5287
|
+
const comment = await fetchJson(
|
|
5288
|
+
`/threads/${encodeURIComponent(threadId)}/comments/${encodeURIComponent(
|
|
5289
|
+
commentId
|
|
5290
|
+
)}`,
|
|
5291
|
+
{
|
|
5292
|
+
method: "POST",
|
|
5293
|
+
headers: {
|
|
5294
|
+
"Content-Type": "application/json"
|
|
5295
|
+
},
|
|
5296
|
+
body: JSON.stringify({
|
|
5297
|
+
body
|
|
5298
|
+
})
|
|
5299
|
+
}
|
|
5300
|
+
);
|
|
5301
|
+
return convertToCommentData(comment);
|
|
5302
|
+
}
|
|
5303
|
+
async function deleteComment2({
|
|
5304
|
+
threadId,
|
|
5305
|
+
commentId
|
|
5306
|
+
}) {
|
|
5307
|
+
await fetchJson(
|
|
5308
|
+
`/threads/${encodeURIComponent(threadId)}/comments/${encodeURIComponent(
|
|
5309
|
+
commentId
|
|
5310
|
+
)}`,
|
|
5311
|
+
{
|
|
5312
|
+
method: "DELETE"
|
|
5313
|
+
}
|
|
5314
|
+
);
|
|
5315
|
+
}
|
|
5316
|
+
async function addReaction2({
|
|
5317
|
+
threadId,
|
|
5318
|
+
commentId,
|
|
5319
|
+
emoji
|
|
5320
|
+
}) {
|
|
5321
|
+
const reaction = await fetchJson(
|
|
5322
|
+
`/threads/${encodeURIComponent(threadId)}/comments/${encodeURIComponent(
|
|
5323
|
+
commentId
|
|
5324
|
+
)}/reactions`,
|
|
5325
|
+
{
|
|
5326
|
+
method: "POST",
|
|
5327
|
+
headers: {
|
|
5328
|
+
"Content-Type": "application/json"
|
|
5329
|
+
},
|
|
5330
|
+
body: JSON.stringify({ emoji })
|
|
5331
|
+
}
|
|
5332
|
+
);
|
|
5333
|
+
return convertToCommentUserReaction(reaction);
|
|
5334
|
+
}
|
|
5335
|
+
async function removeReaction2({
|
|
5336
|
+
threadId,
|
|
5337
|
+
commentId,
|
|
5338
|
+
emoji
|
|
5339
|
+
}) {
|
|
5340
|
+
await fetchJson(
|
|
5341
|
+
`/threads/${encodeURIComponent(threadId)}/comments/${encodeURIComponent(
|
|
5342
|
+
commentId
|
|
5343
|
+
)}/reactions/${encodeURIComponent(emoji)}`,
|
|
5344
|
+
{
|
|
5345
|
+
method: "DELETE"
|
|
5346
|
+
}
|
|
5347
|
+
);
|
|
5348
|
+
}
|
|
5349
|
+
return {
|
|
5350
|
+
getThreads,
|
|
5351
|
+
getThread,
|
|
5352
|
+
createThread,
|
|
5353
|
+
editThreadMetadata,
|
|
5354
|
+
createComment,
|
|
5355
|
+
editComment,
|
|
5356
|
+
deleteComment: deleteComment2,
|
|
5357
|
+
addReaction: addReaction2,
|
|
5358
|
+
removeReaction: removeReaction2
|
|
5359
|
+
};
|
|
5360
|
+
}
|
|
5361
|
+
var MARK_INBOX_NOTIFICATIONS_AS_READ_BATCH_DELAY2 = 50;
|
|
5151
5362
|
function createRoom(options, config) {
|
|
5152
5363
|
const initialPresence = typeof options.initialPresence === "function" ? options.initialPresence(config.roomId) : options.initialPresence;
|
|
5153
5364
|
const initialStorage = typeof options.initialStorage === "function" ? options.initialStorage(config.roomId) : options.initialStorage;
|
|
@@ -5209,7 +5420,7 @@ function createRoom(options, config) {
|
|
|
5209
5420
|
function onStatusDidChange(newStatus) {
|
|
5210
5421
|
const authValue = managedSocket.authValue;
|
|
5211
5422
|
if (authValue !== null) {
|
|
5212
|
-
const tokenKey = authValue
|
|
5423
|
+
const tokenKey = getAuthBearerHeaderFromAuthValue(authValue);
|
|
5213
5424
|
if (tokenKey !== lastTokenKey) {
|
|
5214
5425
|
lastTokenKey = tokenKey;
|
|
5215
5426
|
if (authValue.type === "secret") {
|
|
@@ -5312,7 +5523,9 @@ function createRoom(options, config) {
|
|
|
5312
5523
|
}
|
|
5313
5524
|
}
|
|
5314
5525
|
if (activeBatch) {
|
|
5315
|
-
|
|
5526
|
+
for (const op of ops) {
|
|
5527
|
+
activeBatch.ops.push(op);
|
|
5528
|
+
}
|
|
5316
5529
|
for (const [key, value] of storageUpdates) {
|
|
5317
5530
|
activeBatch.updates.storageUpdates.set(
|
|
5318
5531
|
key,
|
|
@@ -5346,8 +5559,6 @@ function createRoom(options, config) {
|
|
|
5346
5559
|
}
|
|
5347
5560
|
};
|
|
5348
5561
|
const eventHub = {
|
|
5349
|
-
connection: makeEventSource(),
|
|
5350
|
-
// Old/deprecated API
|
|
5351
5562
|
status: makeEventSource(),
|
|
5352
5563
|
// New/recommended API
|
|
5353
5564
|
lostConnection: makeEventSource(),
|
|
@@ -5363,22 +5574,38 @@ function createRoom(options, config) {
|
|
|
5363
5574
|
ydoc: makeEventSource(),
|
|
5364
5575
|
comments: makeEventSource()
|
|
5365
5576
|
};
|
|
5577
|
+
async function fetchClientApi(roomId, endpoint, authValue, options2, params) {
|
|
5578
|
+
const url = urljoin(
|
|
5579
|
+
config.baseUrl,
|
|
5580
|
+
`/v2/c/rooms/${encodeURIComponent(roomId)}${endpoint}`,
|
|
5581
|
+
params
|
|
5582
|
+
);
|
|
5583
|
+
const fetcher = config.polyfills?.fetch || /* istanbul ignore next */
|
|
5584
|
+
fetch;
|
|
5585
|
+
return await fetcher(url, {
|
|
5586
|
+
...options2,
|
|
5587
|
+
headers: {
|
|
5588
|
+
...options2?.headers,
|
|
5589
|
+
Authorization: `Bearer ${getAuthBearerHeaderFromAuthValue(authValue)}`
|
|
5590
|
+
}
|
|
5591
|
+
});
|
|
5592
|
+
}
|
|
5593
|
+
async function streamFetch(authValue, roomId) {
|
|
5594
|
+
return fetchClientApi(roomId, "/storage", authValue, {
|
|
5595
|
+
method: "GET",
|
|
5596
|
+
headers: {
|
|
5597
|
+
"Content-Type": "application/json"
|
|
5598
|
+
}
|
|
5599
|
+
});
|
|
5600
|
+
}
|
|
5366
5601
|
async function httpPostToRoom(endpoint, body) {
|
|
5367
5602
|
if (!managedSocket.authValue) {
|
|
5368
5603
|
throw new Error("Not authorized");
|
|
5369
5604
|
}
|
|
5370
|
-
|
|
5371
|
-
const url = new URL(
|
|
5372
|
-
`/v2/c/rooms/${encodeURIComponent(config.roomId)}${endpoint}`,
|
|
5373
|
-
config.baseUrl
|
|
5374
|
-
).toString();
|
|
5375
|
-
const fetcher = config.polyfills?.fetch || /* istanbul ignore next */
|
|
5376
|
-
fetch;
|
|
5377
|
-
return fetcher(url, {
|
|
5605
|
+
return fetchClientApi(config.roomId, endpoint, managedSocket.authValue, {
|
|
5378
5606
|
method: "POST",
|
|
5379
5607
|
headers: {
|
|
5380
|
-
"Content-Type": "application/json"
|
|
5381
|
-
Authorization: `Bearer ${authTokenOrPublicApiKey}`
|
|
5608
|
+
"Content-Type": "application/json"
|
|
5382
5609
|
},
|
|
5383
5610
|
body: JSON.stringify(body)
|
|
5384
5611
|
});
|
|
@@ -5419,9 +5646,7 @@ function createRoom(options, config) {
|
|
|
5419
5646
|
info: staticSession.userInfo,
|
|
5420
5647
|
presence: myPresence,
|
|
5421
5648
|
canWrite,
|
|
5422
|
-
canComment: canComment(dynamicSession.scopes)
|
|
5423
|
-
isReadOnly: !canWrite
|
|
5424
|
-
// Deprecated, kept for backward-compatibility
|
|
5649
|
+
canComment: canComment(dynamicSession.scopes)
|
|
5425
5650
|
};
|
|
5426
5651
|
}
|
|
5427
5652
|
}
|
|
@@ -5834,12 +6059,7 @@ function createRoom(options, config) {
|
|
|
5834
6059
|
break;
|
|
5835
6060
|
}
|
|
5836
6061
|
case 200 /* INITIAL_STORAGE_STATE */: {
|
|
5837
|
-
|
|
5838
|
-
createOrUpdateRootFromMessage(message, doNotBatchUpdates);
|
|
5839
|
-
applyAndSendOps(unacknowledgedOps, doNotBatchUpdates);
|
|
5840
|
-
_resolveStoragePromise?.();
|
|
5841
|
-
notifyStorageStatus();
|
|
5842
|
-
eventHub.storageDidLoad.notify();
|
|
6062
|
+
processInitialStorage(message);
|
|
5843
6063
|
break;
|
|
5844
6064
|
}
|
|
5845
6065
|
case 201 /* UPDATE_STORAGE */: {
|
|
@@ -5980,14 +6200,35 @@ ${Array.from(traces).join("\n\n")}`
|
|
|
5980
6200
|
flushNowOrSoon();
|
|
5981
6201
|
}
|
|
5982
6202
|
function dispatchOps(ops) {
|
|
5983
|
-
context.buffer
|
|
6203
|
+
const { storageOperations } = context.buffer;
|
|
6204
|
+
for (const op of ops) {
|
|
6205
|
+
storageOperations.push(op);
|
|
6206
|
+
}
|
|
5984
6207
|
flushNowOrSoon();
|
|
5985
6208
|
}
|
|
5986
6209
|
let _getStorage$ = null;
|
|
5987
6210
|
let _resolveStoragePromise = null;
|
|
5988
|
-
function
|
|
6211
|
+
function processInitialStorage(message) {
|
|
6212
|
+
const unacknowledgedOps = new Map(context.unacknowledgedOps);
|
|
6213
|
+
createOrUpdateRootFromMessage(message, doNotBatchUpdates);
|
|
6214
|
+
applyAndSendOps(unacknowledgedOps, doNotBatchUpdates);
|
|
6215
|
+
_resolveStoragePromise?.();
|
|
6216
|
+
notifyStorageStatus();
|
|
6217
|
+
eventHub.storageDidLoad.notify();
|
|
6218
|
+
}
|
|
6219
|
+
async function streamStorage() {
|
|
6220
|
+
if (!managedSocket.authValue) {
|
|
6221
|
+
return;
|
|
6222
|
+
}
|
|
6223
|
+
const result = await streamFetch(managedSocket.authValue, config.roomId);
|
|
6224
|
+
const items = await result.json();
|
|
6225
|
+
processInitialStorage({ type: 200 /* INITIAL_STORAGE_STATE */, items });
|
|
6226
|
+
}
|
|
6227
|
+
function refreshStorage(options2) {
|
|
5989
6228
|
const messages = context.buffer.messages;
|
|
5990
|
-
if (
|
|
6229
|
+
if (config.unstable_streamData) {
|
|
6230
|
+
void streamStorage();
|
|
6231
|
+
} else if (!messages.some((msg) => msg.type === 200 /* FETCH_STORAGE */)) {
|
|
5991
6232
|
messages.push({ type: 200 /* FETCH_STORAGE */ });
|
|
5992
6233
|
}
|
|
5993
6234
|
if (options2.flush) {
|
|
@@ -6165,13 +6406,86 @@ ${Array.from(traces).join("\n\n")}`
|
|
|
6165
6406
|
ydoc: eventHub.ydoc.observable,
|
|
6166
6407
|
comments: eventHub.comments.observable
|
|
6167
6408
|
};
|
|
6168
|
-
const commentsApi = createCommentsApi(
|
|
6169
|
-
|
|
6170
|
-
|
|
6409
|
+
const commentsApi = createCommentsApi(
|
|
6410
|
+
config.roomId,
|
|
6411
|
+
delegates.authenticate,
|
|
6412
|
+
fetchClientApi
|
|
6413
|
+
);
|
|
6414
|
+
async function fetchNotificationsJson(endpoint, options2) {
|
|
6415
|
+
const authValue = await delegates.authenticate();
|
|
6416
|
+
const response = await fetchClientApi(
|
|
6417
|
+
config.roomId,
|
|
6418
|
+
endpoint,
|
|
6419
|
+
authValue,
|
|
6420
|
+
options2
|
|
6421
|
+
);
|
|
6422
|
+
if (!response.ok) {
|
|
6423
|
+
if (response.status >= 400 && response.status < 600) {
|
|
6424
|
+
let error3;
|
|
6425
|
+
try {
|
|
6426
|
+
const errorBody = await response.json();
|
|
6427
|
+
error3 = new NotificationsApiError(
|
|
6428
|
+
errorBody.message,
|
|
6429
|
+
response.status,
|
|
6430
|
+
errorBody
|
|
6431
|
+
);
|
|
6432
|
+
} catch {
|
|
6433
|
+
error3 = new NotificationsApiError(
|
|
6434
|
+
response.statusText,
|
|
6435
|
+
response.status
|
|
6436
|
+
);
|
|
6437
|
+
}
|
|
6438
|
+
throw error3;
|
|
6439
|
+
}
|
|
6440
|
+
}
|
|
6441
|
+
let body;
|
|
6442
|
+
try {
|
|
6443
|
+
body = await response.json();
|
|
6444
|
+
} catch {
|
|
6445
|
+
body = {};
|
|
6446
|
+
}
|
|
6447
|
+
return body;
|
|
6448
|
+
}
|
|
6449
|
+
function getRoomNotificationSettings() {
|
|
6450
|
+
return fetchNotificationsJson(
|
|
6451
|
+
"/notification-settings"
|
|
6452
|
+
);
|
|
6453
|
+
}
|
|
6454
|
+
function updateRoomNotificationSettings(settings) {
|
|
6455
|
+
return fetchNotificationsJson(
|
|
6456
|
+
"/notification-settings",
|
|
6457
|
+
{
|
|
6458
|
+
method: "POST",
|
|
6459
|
+
body: JSON.stringify(settings),
|
|
6460
|
+
headers: {
|
|
6461
|
+
"Content-Type": "application/json"
|
|
6462
|
+
}
|
|
6463
|
+
}
|
|
6464
|
+
);
|
|
6465
|
+
}
|
|
6466
|
+
async function markInboxNotificationsAsRead(inboxNotificationIds) {
|
|
6467
|
+
await fetchNotificationsJson("/inbox-notifications/read", {
|
|
6468
|
+
method: "POST",
|
|
6469
|
+
headers: {
|
|
6470
|
+
"Content-Type": "application/json"
|
|
6471
|
+
},
|
|
6472
|
+
body: JSON.stringify({ inboxNotificationIds })
|
|
6473
|
+
});
|
|
6474
|
+
}
|
|
6475
|
+
const batchedMarkInboxNotificationsAsRead = new Batch(
|
|
6476
|
+
async (batchedInboxNotificationIds) => {
|
|
6477
|
+
const inboxNotificationIds = batchedInboxNotificationIds.flat();
|
|
6478
|
+
await markInboxNotificationsAsRead(inboxNotificationIds);
|
|
6479
|
+
return inboxNotificationIds;
|
|
6480
|
+
},
|
|
6481
|
+
{ delay: MARK_INBOX_NOTIFICATIONS_AS_READ_BATCH_DELAY2 }
|
|
6482
|
+
);
|
|
6483
|
+
async function markInboxNotificationAsRead(inboxNotificationId) {
|
|
6484
|
+
await batchedMarkInboxNotificationsAsRead.get(inboxNotificationId);
|
|
6485
|
+
}
|
|
6171
6486
|
return Object.defineProperty(
|
|
6172
6487
|
{
|
|
6173
|
-
|
|
6174
|
-
__internal: {
|
|
6488
|
+
[kInternal]: {
|
|
6175
6489
|
get presenceBuffer() {
|
|
6176
6490
|
return deepClone(context.buffer.presenceUpdates?.data ?? null);
|
|
6177
6491
|
},
|
|
@@ -6192,6 +6506,14 @@ ${Array.from(traces).join("\n\n")}`
|
|
|
6192
6506
|
// These exist only for our E2E testing app
|
|
6193
6507
|
explicitClose: (event) => managedSocket._privateSendMachineEvent({ type: "EXPLICIT_SOCKET_CLOSE", event }),
|
|
6194
6508
|
rawSend: (data) => managedSocket.send(data)
|
|
6509
|
+
},
|
|
6510
|
+
comments: {
|
|
6511
|
+
...commentsApi
|
|
6512
|
+
},
|
|
6513
|
+
notifications: {
|
|
6514
|
+
getRoomNotificationSettings,
|
|
6515
|
+
updateRoomNotificationSettings,
|
|
6516
|
+
markInboxNotificationAsRead
|
|
6195
6517
|
}
|
|
6196
6518
|
},
|
|
6197
6519
|
id: config.roomId,
|
|
@@ -6225,16 +6547,14 @@ ${Array.from(traces).join("\n\n")}`
|
|
|
6225
6547
|
events,
|
|
6226
6548
|
// Core
|
|
6227
6549
|
getStatus: () => managedSocket.getStatus(),
|
|
6228
|
-
getConnectionState: () => managedSocket.getLegacyStatus(),
|
|
6229
6550
|
getSelf: () => self.current,
|
|
6230
6551
|
// Presence
|
|
6231
6552
|
getPresence: () => context.myPresence.current,
|
|
6232
|
-
getOthers: () => context.others.current
|
|
6233
|
-
...commentsApi
|
|
6553
|
+
getOthers: () => context.others.current
|
|
6234
6554
|
},
|
|
6235
|
-
// Explictly make the
|
|
6555
|
+
// Explictly make the internal field non-enumerable, to avoid aggressive
|
|
6236
6556
|
// freezing when used with Immer
|
|
6237
|
-
|
|
6557
|
+
kInternal,
|
|
6238
6558
|
{ enumerable: false }
|
|
6239
6559
|
);
|
|
6240
6560
|
}
|
|
@@ -6280,12 +6600,6 @@ function makeClassicSubscribeFn(events) {
|
|
|
6280
6600
|
}
|
|
6281
6601
|
case "error":
|
|
6282
6602
|
return events.error.subscribe(callback);
|
|
6283
|
-
case "connection": {
|
|
6284
|
-
const cb = callback;
|
|
6285
|
-
return events.status.subscribe(
|
|
6286
|
-
(status) => cb(newToLegacyStatus(status))
|
|
6287
|
-
);
|
|
6288
|
-
}
|
|
6289
6603
|
case "status":
|
|
6290
6604
|
return events.status.subscribe(callback);
|
|
6291
6605
|
case "lost-connection":
|
|
@@ -6334,7 +6648,7 @@ function isRoomEventName(value) {
|
|
|
6334
6648
|
}
|
|
6335
6649
|
function makeAuthDelegateForRoom(roomId, authManager) {
|
|
6336
6650
|
return async () => {
|
|
6337
|
-
return authManager.getAuthValue("room:read", roomId);
|
|
6651
|
+
return authManager.getAuthValue({ requestedScope: "room:read", roomId });
|
|
6338
6652
|
};
|
|
6339
6653
|
}
|
|
6340
6654
|
function makeCreateSocketDelegateForRoom(roomId, baseUrl, WebSocketPolyfill) {
|
|
@@ -6361,6 +6675,470 @@ function makeCreateSocketDelegateForRoom(roomId, baseUrl, WebSocketPolyfill) {
|
|
|
6361
6675
|
};
|
|
6362
6676
|
}
|
|
6363
6677
|
|
|
6678
|
+
// src/store.ts
|
|
6679
|
+
function createClientStore() {
|
|
6680
|
+
const store = createStore({
|
|
6681
|
+
threads: {},
|
|
6682
|
+
queries: {},
|
|
6683
|
+
optimisticUpdates: [],
|
|
6684
|
+
inboxNotifications: {},
|
|
6685
|
+
notificationSettings: {}
|
|
6686
|
+
});
|
|
6687
|
+
return {
|
|
6688
|
+
...store,
|
|
6689
|
+
deleteThread(threadId) {
|
|
6690
|
+
store.set((state) => {
|
|
6691
|
+
return {
|
|
6692
|
+
...state,
|
|
6693
|
+
threads: deleteKeyImmutable(state.threads, threadId),
|
|
6694
|
+
inboxNotifications: Object.fromEntries(
|
|
6695
|
+
Object.entries(state.inboxNotifications).filter(
|
|
6696
|
+
([_id, notification]) => notification.kind === "thread" && notification.threadId === threadId
|
|
6697
|
+
)
|
|
6698
|
+
)
|
|
6699
|
+
};
|
|
6700
|
+
});
|
|
6701
|
+
},
|
|
6702
|
+
updateThreadAndNotification(thread, inboxNotification) {
|
|
6703
|
+
store.set((state) => {
|
|
6704
|
+
const existingThread = state.threads[thread.id];
|
|
6705
|
+
return {
|
|
6706
|
+
...state,
|
|
6707
|
+
threads: existingThread === void 0 || compareThreads(thread, existingThread) === 1 ? { ...state.threads, [thread.id]: thread } : state.threads,
|
|
6708
|
+
inboxNotifications: inboxNotification === void 0 ? state.inboxNotifications : {
|
|
6709
|
+
...state.inboxNotifications,
|
|
6710
|
+
[inboxNotification.id]: inboxNotification
|
|
6711
|
+
}
|
|
6712
|
+
};
|
|
6713
|
+
});
|
|
6714
|
+
},
|
|
6715
|
+
updateThreadsAndNotifications(threads, inboxNotifications, deletedThreads, deletedInboxNotifications, queryKey) {
|
|
6716
|
+
store.set((state) => ({
|
|
6717
|
+
...state,
|
|
6718
|
+
threads: applyThreadUpdates(state.threads, {
|
|
6719
|
+
newThreads: threads,
|
|
6720
|
+
deletedThreads
|
|
6721
|
+
}),
|
|
6722
|
+
inboxNotifications: applyNotificationsUpdates(
|
|
6723
|
+
state.inboxNotifications,
|
|
6724
|
+
{
|
|
6725
|
+
newInboxNotifications: inboxNotifications,
|
|
6726
|
+
deletedNotifications: deletedInboxNotifications
|
|
6727
|
+
}
|
|
6728
|
+
),
|
|
6729
|
+
queries: queryKey !== void 0 ? {
|
|
6730
|
+
...state.queries,
|
|
6731
|
+
[queryKey]: {
|
|
6732
|
+
isLoading: false
|
|
6733
|
+
}
|
|
6734
|
+
} : state.queries
|
|
6735
|
+
}));
|
|
6736
|
+
},
|
|
6737
|
+
updateRoomInboxNotificationSettings(roomId, settings, queryKey) {
|
|
6738
|
+
store.set((state) => ({
|
|
6739
|
+
...state,
|
|
6740
|
+
notificationSettings: {
|
|
6741
|
+
...state.notificationSettings,
|
|
6742
|
+
[roomId]: settings
|
|
6743
|
+
},
|
|
6744
|
+
queries: {
|
|
6745
|
+
...state.queries,
|
|
6746
|
+
[queryKey]: {
|
|
6747
|
+
isLoading: false
|
|
6748
|
+
}
|
|
6749
|
+
}
|
|
6750
|
+
}));
|
|
6751
|
+
},
|
|
6752
|
+
pushOptimisticUpdate(optimisticUpdate) {
|
|
6753
|
+
store.set((state) => ({
|
|
6754
|
+
...state,
|
|
6755
|
+
optimisticUpdates: [...state.optimisticUpdates, optimisticUpdate]
|
|
6756
|
+
}));
|
|
6757
|
+
},
|
|
6758
|
+
setQueryState(queryKey, queryState) {
|
|
6759
|
+
store.set((state) => ({
|
|
6760
|
+
...state,
|
|
6761
|
+
queries: {
|
|
6762
|
+
...state.queries,
|
|
6763
|
+
[queryKey]: queryState
|
|
6764
|
+
}
|
|
6765
|
+
}));
|
|
6766
|
+
}
|
|
6767
|
+
};
|
|
6768
|
+
}
|
|
6769
|
+
function deleteKeyImmutable(record, key) {
|
|
6770
|
+
if (Object.prototype.hasOwnProperty.call(record, key)) {
|
|
6771
|
+
const { [key]: _toDelete, ...rest } = record;
|
|
6772
|
+
return rest;
|
|
6773
|
+
}
|
|
6774
|
+
return record;
|
|
6775
|
+
}
|
|
6776
|
+
function compareThreads(thread1, thread2) {
|
|
6777
|
+
if (thread1.updatedAt && thread2.updatedAt) {
|
|
6778
|
+
return thread1.updatedAt > thread2.updatedAt ? 1 : thread1.updatedAt < thread2.updatedAt ? -1 : 0;
|
|
6779
|
+
} else if (thread1.updatedAt || thread2.updatedAt) {
|
|
6780
|
+
return thread1.updatedAt ? 1 : -1;
|
|
6781
|
+
}
|
|
6782
|
+
if (thread1.createdAt > thread2.createdAt) {
|
|
6783
|
+
return 1;
|
|
6784
|
+
} else if (thread1.createdAt < thread2.createdAt) {
|
|
6785
|
+
return -1;
|
|
6786
|
+
}
|
|
6787
|
+
return 0;
|
|
6788
|
+
}
|
|
6789
|
+
function applyOptimisticUpdates(state) {
|
|
6790
|
+
const result = {
|
|
6791
|
+
threads: {
|
|
6792
|
+
...state.threads
|
|
6793
|
+
},
|
|
6794
|
+
inboxNotifications: {
|
|
6795
|
+
...state.inboxNotifications
|
|
6796
|
+
},
|
|
6797
|
+
notificationSettings: {
|
|
6798
|
+
...state.notificationSettings
|
|
6799
|
+
}
|
|
6800
|
+
};
|
|
6801
|
+
for (const optimisticUpdate of state.optimisticUpdates) {
|
|
6802
|
+
switch (optimisticUpdate.type) {
|
|
6803
|
+
case "create-thread": {
|
|
6804
|
+
result.threads[optimisticUpdate.thread.id] = optimisticUpdate.thread;
|
|
6805
|
+
break;
|
|
6806
|
+
}
|
|
6807
|
+
case "edit-thread-metadata": {
|
|
6808
|
+
const thread = result.threads[optimisticUpdate.threadId];
|
|
6809
|
+
if (thread === void 0) {
|
|
6810
|
+
break;
|
|
6811
|
+
}
|
|
6812
|
+
if (thread.deletedAt !== void 0) {
|
|
6813
|
+
break;
|
|
6814
|
+
}
|
|
6815
|
+
if (thread.updatedAt !== void 0 && thread.updatedAt > optimisticUpdate.updatedAt) {
|
|
6816
|
+
break;
|
|
6817
|
+
}
|
|
6818
|
+
result.threads[thread.id] = {
|
|
6819
|
+
...thread,
|
|
6820
|
+
updatedAt: optimisticUpdate.updatedAt,
|
|
6821
|
+
metadata: {
|
|
6822
|
+
...thread.metadata,
|
|
6823
|
+
...optimisticUpdate.metadata
|
|
6824
|
+
}
|
|
6825
|
+
};
|
|
6826
|
+
break;
|
|
6827
|
+
}
|
|
6828
|
+
case "create-comment": {
|
|
6829
|
+
const thread = result.threads[optimisticUpdate.comment.threadId];
|
|
6830
|
+
if (thread === void 0) {
|
|
6831
|
+
break;
|
|
6832
|
+
}
|
|
6833
|
+
result.threads[thread.id] = upsertComment(
|
|
6834
|
+
thread,
|
|
6835
|
+
optimisticUpdate.comment
|
|
6836
|
+
);
|
|
6837
|
+
const inboxNotification = Object.values(result.inboxNotifications).find(
|
|
6838
|
+
(notification) => notification.kind === "thread" && notification.threadId === thread.id
|
|
6839
|
+
);
|
|
6840
|
+
if (inboxNotification === void 0) {
|
|
6841
|
+
break;
|
|
6842
|
+
}
|
|
6843
|
+
result.inboxNotifications[inboxNotification.id] = {
|
|
6844
|
+
...inboxNotification,
|
|
6845
|
+
notifiedAt: optimisticUpdate.comment.createdAt,
|
|
6846
|
+
readAt: optimisticUpdate.comment.createdAt
|
|
6847
|
+
};
|
|
6848
|
+
break;
|
|
6849
|
+
}
|
|
6850
|
+
case "edit-comment": {
|
|
6851
|
+
const thread = result.threads[optimisticUpdate.comment.threadId];
|
|
6852
|
+
if (thread === void 0) {
|
|
6853
|
+
break;
|
|
6854
|
+
}
|
|
6855
|
+
result.threads[thread.id] = upsertComment(
|
|
6856
|
+
thread,
|
|
6857
|
+
optimisticUpdate.comment
|
|
6858
|
+
);
|
|
6859
|
+
break;
|
|
6860
|
+
}
|
|
6861
|
+
case "delete-comment": {
|
|
6862
|
+
const thread = result.threads[optimisticUpdate.threadId];
|
|
6863
|
+
if (thread === void 0) {
|
|
6864
|
+
break;
|
|
6865
|
+
}
|
|
6866
|
+
result.threads[thread.id] = deleteComment(
|
|
6867
|
+
thread,
|
|
6868
|
+
optimisticUpdate.commentId,
|
|
6869
|
+
optimisticUpdate.deletedAt
|
|
6870
|
+
);
|
|
6871
|
+
break;
|
|
6872
|
+
}
|
|
6873
|
+
case "add-reaction": {
|
|
6874
|
+
const thread = result.threads[optimisticUpdate.threadId];
|
|
6875
|
+
if (thread === void 0) {
|
|
6876
|
+
break;
|
|
6877
|
+
}
|
|
6878
|
+
result.threads[thread.id] = addReaction(
|
|
6879
|
+
thread,
|
|
6880
|
+
optimisticUpdate.commentId,
|
|
6881
|
+
optimisticUpdate.reaction
|
|
6882
|
+
);
|
|
6883
|
+
break;
|
|
6884
|
+
}
|
|
6885
|
+
case "remove-reaction": {
|
|
6886
|
+
const thread = result.threads[optimisticUpdate.threadId];
|
|
6887
|
+
if (thread === void 0) {
|
|
6888
|
+
break;
|
|
6889
|
+
}
|
|
6890
|
+
result.threads[thread.id] = removeReaction(
|
|
6891
|
+
thread,
|
|
6892
|
+
optimisticUpdate.commentId,
|
|
6893
|
+
optimisticUpdate.emoji,
|
|
6894
|
+
optimisticUpdate.userId,
|
|
6895
|
+
optimisticUpdate.removedAt
|
|
6896
|
+
);
|
|
6897
|
+
break;
|
|
6898
|
+
}
|
|
6899
|
+
case "mark-inbox-notification-as-read": {
|
|
6900
|
+
result.inboxNotifications[optimisticUpdate.inboxNotificationId] = {
|
|
6901
|
+
...state.inboxNotifications[optimisticUpdate.inboxNotificationId],
|
|
6902
|
+
readAt: optimisticUpdate.readAt
|
|
6903
|
+
};
|
|
6904
|
+
break;
|
|
6905
|
+
}
|
|
6906
|
+
case "mark-inbox-notifications-as-read": {
|
|
6907
|
+
for (const id in result.inboxNotifications) {
|
|
6908
|
+
result.inboxNotifications[id] = {
|
|
6909
|
+
...result.inboxNotifications[id],
|
|
6910
|
+
readAt: optimisticUpdate.readAt
|
|
6911
|
+
};
|
|
6912
|
+
}
|
|
6913
|
+
break;
|
|
6914
|
+
}
|
|
6915
|
+
case "update-notification-settings": {
|
|
6916
|
+
result.notificationSettings[optimisticUpdate.roomId] = {
|
|
6917
|
+
...result.notificationSettings[optimisticUpdate.roomId],
|
|
6918
|
+
...optimisticUpdate.settings
|
|
6919
|
+
};
|
|
6920
|
+
}
|
|
6921
|
+
}
|
|
6922
|
+
}
|
|
6923
|
+
return result;
|
|
6924
|
+
}
|
|
6925
|
+
function applyThreadUpdates(existingThreads, updates) {
|
|
6926
|
+
const updatedThreads = { ...existingThreads };
|
|
6927
|
+
updates.newThreads.forEach((thread) => {
|
|
6928
|
+
const existingThread = updatedThreads[thread.id];
|
|
6929
|
+
if (existingThread) {
|
|
6930
|
+
const result = compareThreads(existingThread, thread);
|
|
6931
|
+
if (result === 1)
|
|
6932
|
+
return;
|
|
6933
|
+
}
|
|
6934
|
+
updatedThreads[thread.id] = thread;
|
|
6935
|
+
});
|
|
6936
|
+
updates.deletedThreads.forEach(({ id, deletedAt }) => {
|
|
6937
|
+
const existingThread = updatedThreads[id];
|
|
6938
|
+
if (existingThread === void 0)
|
|
6939
|
+
return;
|
|
6940
|
+
existingThread.deletedAt = deletedAt;
|
|
6941
|
+
existingThread.updatedAt = deletedAt;
|
|
6942
|
+
existingThread.comments = [];
|
|
6943
|
+
});
|
|
6944
|
+
return updatedThreads;
|
|
6945
|
+
}
|
|
6946
|
+
function applyNotificationsUpdates(existingInboxNotifications, updates) {
|
|
6947
|
+
const updatedInboxNotifications = { ...existingInboxNotifications };
|
|
6948
|
+
updates.newInboxNotifications.forEach((notification) => {
|
|
6949
|
+
const existingNotification = updatedInboxNotifications[notification.id];
|
|
6950
|
+
if (existingNotification) {
|
|
6951
|
+
const result = compareInboxNotifications(
|
|
6952
|
+
existingNotification,
|
|
6953
|
+
notification
|
|
6954
|
+
);
|
|
6955
|
+
if (result === 1)
|
|
6956
|
+
return;
|
|
6957
|
+
}
|
|
6958
|
+
updatedInboxNotifications[notification.id] = notification;
|
|
6959
|
+
});
|
|
6960
|
+
updates.deletedNotifications.forEach(
|
|
6961
|
+
({ id }) => delete updatedInboxNotifications[id]
|
|
6962
|
+
);
|
|
6963
|
+
return updatedInboxNotifications;
|
|
6964
|
+
}
|
|
6965
|
+
function compareInboxNotifications(inboxNotificationA, inboxNotificationB) {
|
|
6966
|
+
if (inboxNotificationA.notifiedAt > inboxNotificationB.notifiedAt) {
|
|
6967
|
+
return 1;
|
|
6968
|
+
} else if (inboxNotificationA.notifiedAt < inboxNotificationB.notifiedAt) {
|
|
6969
|
+
return -1;
|
|
6970
|
+
}
|
|
6971
|
+
if (inboxNotificationA.readAt && inboxNotificationB.readAt) {
|
|
6972
|
+
return inboxNotificationA.readAt > inboxNotificationB.readAt ? 1 : inboxNotificationA.readAt < inboxNotificationB.readAt ? -1 : 0;
|
|
6973
|
+
} else if (inboxNotificationA.readAt || inboxNotificationB.readAt) {
|
|
6974
|
+
return inboxNotificationA.readAt ? 1 : -1;
|
|
6975
|
+
}
|
|
6976
|
+
return 0;
|
|
6977
|
+
}
|
|
6978
|
+
function upsertComment(thread, comment) {
|
|
6979
|
+
if (thread.deletedAt !== void 0) {
|
|
6980
|
+
return thread;
|
|
6981
|
+
}
|
|
6982
|
+
if (comment.threadId !== thread.id) {
|
|
6983
|
+
warn(
|
|
6984
|
+
`Comment ${comment.id} does not belong to thread ${thread.id}`
|
|
6985
|
+
);
|
|
6986
|
+
return thread;
|
|
6987
|
+
}
|
|
6988
|
+
const existingComment = thread.comments.find(
|
|
6989
|
+
(existingComment2) => existingComment2.id === comment.id
|
|
6990
|
+
);
|
|
6991
|
+
if (existingComment === void 0) {
|
|
6992
|
+
const updatedAt = new Date(
|
|
6993
|
+
Math.max(thread.updatedAt?.getTime() || 0, comment.createdAt.getTime())
|
|
6994
|
+
);
|
|
6995
|
+
const updatedThread = {
|
|
6996
|
+
...thread,
|
|
6997
|
+
updatedAt,
|
|
6998
|
+
comments: [...thread.comments, comment]
|
|
6999
|
+
};
|
|
7000
|
+
return updatedThread;
|
|
7001
|
+
}
|
|
7002
|
+
if (existingComment.deletedAt !== void 0) {
|
|
7003
|
+
return thread;
|
|
7004
|
+
}
|
|
7005
|
+
if (existingComment.editedAt === void 0 || comment.editedAt === void 0 || existingComment.editedAt <= comment.editedAt) {
|
|
7006
|
+
const updatedComments = thread.comments.map(
|
|
7007
|
+
(existingComment2) => existingComment2.id === comment.id ? comment : existingComment2
|
|
7008
|
+
);
|
|
7009
|
+
const updatedThread = {
|
|
7010
|
+
...thread,
|
|
7011
|
+
updatedAt: new Date(
|
|
7012
|
+
Math.max(
|
|
7013
|
+
thread.updatedAt?.getTime() || 0,
|
|
7014
|
+
comment.editedAt?.getTime() || comment.createdAt.getTime()
|
|
7015
|
+
)
|
|
7016
|
+
),
|
|
7017
|
+
comments: updatedComments
|
|
7018
|
+
};
|
|
7019
|
+
return updatedThread;
|
|
7020
|
+
}
|
|
7021
|
+
return thread;
|
|
7022
|
+
}
|
|
7023
|
+
function deleteComment(thread, commentId, deletedAt) {
|
|
7024
|
+
if (thread.deletedAt !== void 0) {
|
|
7025
|
+
return thread;
|
|
7026
|
+
}
|
|
7027
|
+
const existingComment = thread.comments.find(
|
|
7028
|
+
(comment) => comment.id === commentId
|
|
7029
|
+
);
|
|
7030
|
+
if (existingComment === void 0) {
|
|
7031
|
+
return thread;
|
|
7032
|
+
}
|
|
7033
|
+
if (existingComment.deletedAt !== void 0) {
|
|
7034
|
+
return thread;
|
|
7035
|
+
}
|
|
7036
|
+
const updatedComments = thread.comments.map(
|
|
7037
|
+
(comment) => comment.id === commentId ? {
|
|
7038
|
+
...comment,
|
|
7039
|
+
deletedAt,
|
|
7040
|
+
body: void 0
|
|
7041
|
+
} : comment
|
|
7042
|
+
);
|
|
7043
|
+
if (!updatedComments.some((comment) => comment.deletedAt === void 0)) {
|
|
7044
|
+
return {
|
|
7045
|
+
...thread,
|
|
7046
|
+
deletedAt,
|
|
7047
|
+
updatedAt: deletedAt,
|
|
7048
|
+
comments: []
|
|
7049
|
+
};
|
|
7050
|
+
}
|
|
7051
|
+
return {
|
|
7052
|
+
...thread,
|
|
7053
|
+
updatedAt: deletedAt,
|
|
7054
|
+
comments: updatedComments
|
|
7055
|
+
};
|
|
7056
|
+
}
|
|
7057
|
+
function addReaction(thread, commentId, reaction) {
|
|
7058
|
+
if (thread.deletedAt !== void 0) {
|
|
7059
|
+
return thread;
|
|
7060
|
+
}
|
|
7061
|
+
const existingComment = thread.comments.find(
|
|
7062
|
+
(comment) => comment.id === commentId
|
|
7063
|
+
);
|
|
7064
|
+
if (existingComment === void 0) {
|
|
7065
|
+
return thread;
|
|
7066
|
+
}
|
|
7067
|
+
if (existingComment.deletedAt !== void 0) {
|
|
7068
|
+
return thread;
|
|
7069
|
+
}
|
|
7070
|
+
const updatedComments = thread.comments.map(
|
|
7071
|
+
(comment) => comment.id === commentId ? {
|
|
7072
|
+
...comment,
|
|
7073
|
+
reactions: upsertReaction(comment.reactions, reaction)
|
|
7074
|
+
} : comment
|
|
7075
|
+
);
|
|
7076
|
+
return {
|
|
7077
|
+
...thread,
|
|
7078
|
+
updatedAt: new Date(
|
|
7079
|
+
Math.max(reaction.createdAt.getTime(), thread.updatedAt?.getTime() || 0)
|
|
7080
|
+
),
|
|
7081
|
+
comments: updatedComments
|
|
7082
|
+
};
|
|
7083
|
+
}
|
|
7084
|
+
function removeReaction(thread, commentId, emoji, userId, removedAt) {
|
|
7085
|
+
if (thread.deletedAt !== void 0) {
|
|
7086
|
+
return thread;
|
|
7087
|
+
}
|
|
7088
|
+
const existingComment = thread.comments.find(
|
|
7089
|
+
(comment) => comment.id === commentId
|
|
7090
|
+
);
|
|
7091
|
+
if (existingComment === void 0) {
|
|
7092
|
+
return thread;
|
|
7093
|
+
}
|
|
7094
|
+
if (existingComment.deletedAt !== void 0) {
|
|
7095
|
+
return thread;
|
|
7096
|
+
}
|
|
7097
|
+
const updatedComments = thread.comments.map(
|
|
7098
|
+
(comment) => comment.id === commentId ? {
|
|
7099
|
+
...comment,
|
|
7100
|
+
reactions: comment.reactions.map(
|
|
7101
|
+
(reaction) => reaction.emoji === emoji ? {
|
|
7102
|
+
...reaction,
|
|
7103
|
+
users: reaction.users.filter((user) => user.id !== userId)
|
|
7104
|
+
} : reaction
|
|
7105
|
+
).filter((reaction) => reaction.users.length > 0)
|
|
7106
|
+
// Remove reactions with no users left
|
|
7107
|
+
} : comment
|
|
7108
|
+
);
|
|
7109
|
+
return {
|
|
7110
|
+
...thread,
|
|
7111
|
+
updatedAt: new Date(
|
|
7112
|
+
Math.max(removedAt.getTime(), thread.updatedAt?.getTime() || 0)
|
|
7113
|
+
),
|
|
7114
|
+
comments: updatedComments
|
|
7115
|
+
};
|
|
7116
|
+
}
|
|
7117
|
+
function upsertReaction(reactions, reaction) {
|
|
7118
|
+
const existingReaction = reactions.find(
|
|
7119
|
+
(existingReaction2) => existingReaction2.emoji === reaction.emoji
|
|
7120
|
+
);
|
|
7121
|
+
if (existingReaction === void 0) {
|
|
7122
|
+
return [
|
|
7123
|
+
...reactions,
|
|
7124
|
+
{
|
|
7125
|
+
emoji: reaction.emoji,
|
|
7126
|
+
createdAt: reaction.createdAt,
|
|
7127
|
+
users: [{ id: reaction.userId }]
|
|
7128
|
+
}
|
|
7129
|
+
];
|
|
7130
|
+
}
|
|
7131
|
+
if (existingReaction.users.some((user) => user.id === reaction.userId) === false) {
|
|
7132
|
+
return reactions.map(
|
|
7133
|
+
(existingReaction2) => existingReaction2.emoji === reaction.emoji ? {
|
|
7134
|
+
...existingReaction2,
|
|
7135
|
+
users: [...existingReaction2.users, { id: reaction.userId }]
|
|
7136
|
+
} : existingReaction2
|
|
7137
|
+
);
|
|
7138
|
+
}
|
|
7139
|
+
return reactions;
|
|
7140
|
+
}
|
|
7141
|
+
|
|
6364
7142
|
// src/client.ts
|
|
6365
7143
|
var MIN_THROTTLE = 16;
|
|
6366
7144
|
var MAX_THROTTLE = 1e3;
|
|
@@ -6370,16 +7148,22 @@ var MIN_LOST_CONNECTION_TIMEOUT = 200;
|
|
|
6370
7148
|
var RECOMMENDED_MIN_LOST_CONNECTION_TIMEOUT = 1e3;
|
|
6371
7149
|
var MAX_LOST_CONNECTION_TIMEOUT = 3e4;
|
|
6372
7150
|
var DEFAULT_LOST_CONNECTION_TIMEOUT = 5e3;
|
|
6373
|
-
|
|
6374
|
-
|
|
6375
|
-
|
|
6376
|
-
|
|
6377
|
-
|
|
6378
|
-
return clientOptions.baseUrl;
|
|
7151
|
+
var RESOLVE_USERS_BATCH_DELAY = 50;
|
|
7152
|
+
var RESOLVE_ROOMS_INFO_BATCH_DELAY = 50;
|
|
7153
|
+
function getBaseUrl(baseUrl) {
|
|
7154
|
+
if (typeof baseUrl === "string" && baseUrl.startsWith("http")) {
|
|
7155
|
+
return baseUrl;
|
|
6379
7156
|
} else {
|
|
6380
7157
|
return DEFAULT_BASE_URL;
|
|
6381
7158
|
}
|
|
6382
7159
|
}
|
|
7160
|
+
function getAuthBearerHeaderFromAuthValue(authValue) {
|
|
7161
|
+
if (authValue.type === "public") {
|
|
7162
|
+
return authValue.publicApiKey;
|
|
7163
|
+
} else {
|
|
7164
|
+
return authValue.token.raw;
|
|
7165
|
+
}
|
|
7166
|
+
}
|
|
6383
7167
|
function createClient(options) {
|
|
6384
7168
|
const clientOptions = options;
|
|
6385
7169
|
const throttleDelay = getThrottle(clientOptions.throttle ?? DEFAULT_THROTTLE);
|
|
@@ -6389,6 +7173,7 @@ function createClient(options) {
|
|
|
6389
7173
|
const backgroundKeepAliveTimeout = getBackgroundKeepAliveTimeout(
|
|
6390
7174
|
clientOptions.backgroundKeepAliveTimeout
|
|
6391
7175
|
);
|
|
7176
|
+
const baseUrl = getBaseUrl(clientOptions.baseUrl);
|
|
6392
7177
|
const authManager = createAuthManager(options);
|
|
6393
7178
|
const roomsById = /* @__PURE__ */ new Map();
|
|
6394
7179
|
function teardownRoom(room) {
|
|
@@ -6424,7 +7209,6 @@ function createClient(options) {
|
|
|
6424
7209
|
options2.initialPresence === null || options2.initialPresence === void 0,
|
|
6425
7210
|
"Please provide an initial presence value for the current user when entering the room."
|
|
6426
7211
|
);
|
|
6427
|
-
const baseUrl = getBaseUrlFromClientOptions(clientOptions);
|
|
6428
7212
|
const newRoom = createRoom(
|
|
6429
7213
|
{
|
|
6430
7214
|
initialPresence: options2.initialPresence ?? {},
|
|
@@ -6447,7 +7231,8 @@ function createClient(options) {
|
|
|
6447
7231
|
enableDebugLogging: clientOptions.enableDebugLogging,
|
|
6448
7232
|
unstable_batchedUpdates: options2?.unstable_batchedUpdates,
|
|
6449
7233
|
baseUrl,
|
|
6450
|
-
unstable_fallbackToHTTP: !!clientOptions.unstable_fallbackToHTTP
|
|
7234
|
+
unstable_fallbackToHTTP: !!clientOptions.unstable_fallbackToHTTP,
|
|
7235
|
+
unstable_streamData: !!clientOptions.unstable_streamData
|
|
6451
7236
|
}
|
|
6452
7237
|
);
|
|
6453
7238
|
const newRoomInfo = {
|
|
@@ -6457,7 +7242,7 @@ function createClient(options) {
|
|
|
6457
7242
|
roomsById.set(roomId, newRoomInfo);
|
|
6458
7243
|
setupDevTools(() => Array.from(roomsById.keys()));
|
|
6459
7244
|
linkDevTools(roomId, newRoom);
|
|
6460
|
-
const shouldConnect = options2.autoConnect ??
|
|
7245
|
+
const shouldConnect = options2.autoConnect ?? true;
|
|
6461
7246
|
if (shouldConnect) {
|
|
6462
7247
|
if (typeof atob === "undefined") {
|
|
6463
7248
|
if (clientOptions.polyfills?.atob === void 0) {
|
|
@@ -6479,58 +7264,454 @@ function createClient(options) {
|
|
|
6479
7264
|
const room = roomsById.get(roomId)?.room;
|
|
6480
7265
|
return room ? room : null;
|
|
6481
7266
|
}
|
|
6482
|
-
function forceLeave(roomId) {
|
|
6483
|
-
const unsubs = roomsById.get(roomId)?.unsubs ?? /* @__PURE__ */ new Set();
|
|
6484
|
-
for (const unsub of unsubs) {
|
|
6485
|
-
unsub();
|
|
7267
|
+
function forceLeave(roomId) {
|
|
7268
|
+
const unsubs = roomsById.get(roomId)?.unsubs ?? /* @__PURE__ */ new Set();
|
|
7269
|
+
for (const unsub of unsubs) {
|
|
7270
|
+
unsub();
|
|
7271
|
+
}
|
|
7272
|
+
}
|
|
7273
|
+
function logout() {
|
|
7274
|
+
authManager.reset();
|
|
7275
|
+
for (const { room } of roomsById.values()) {
|
|
7276
|
+
if (!isIdle(room.getStatus())) {
|
|
7277
|
+
room.reconnect();
|
|
7278
|
+
}
|
|
7279
|
+
}
|
|
7280
|
+
}
|
|
7281
|
+
const currentUserIdStore = createStore(null);
|
|
7282
|
+
const {
|
|
7283
|
+
getInboxNotifications,
|
|
7284
|
+
getUnreadInboxNotificationsCount,
|
|
7285
|
+
markAllInboxNotificationsAsRead,
|
|
7286
|
+
markInboxNotificationAsRead
|
|
7287
|
+
} = createNotificationsApi({
|
|
7288
|
+
baseUrl,
|
|
7289
|
+
fetcher: clientOptions.polyfills?.fetch || /* istanbul ignore next */
|
|
7290
|
+
fetch,
|
|
7291
|
+
authManager,
|
|
7292
|
+
currentUserIdStore
|
|
7293
|
+
});
|
|
7294
|
+
const cacheStore = createClientStore();
|
|
7295
|
+
const resolveUsers = clientOptions.resolveUsers;
|
|
7296
|
+
const warnIfNoResolveUsers = createDevelopmentWarning(
|
|
7297
|
+
() => !resolveUsers,
|
|
7298
|
+
"Set the resolveUsers option in createClient to specify user info."
|
|
7299
|
+
);
|
|
7300
|
+
const usersStore = createBatchStore(
|
|
7301
|
+
async (batchedUserIds) => {
|
|
7302
|
+
const userIds = batchedUserIds.flat();
|
|
7303
|
+
const users = await resolveUsers?.({ userIds });
|
|
7304
|
+
warnIfNoResolveUsers();
|
|
7305
|
+
return users ?? userIds.map(() => void 0);
|
|
7306
|
+
},
|
|
7307
|
+
{ delay: RESOLVE_USERS_BATCH_DELAY }
|
|
7308
|
+
);
|
|
7309
|
+
const resolveRoomsInfo = clientOptions.resolveRoomsInfo;
|
|
7310
|
+
const warnIfNoResolveRoomsInfo = createDevelopmentWarning(
|
|
7311
|
+
() => !resolveRoomsInfo,
|
|
7312
|
+
"Set the resolveRoomsInfo option in createClient to specify room info."
|
|
7313
|
+
);
|
|
7314
|
+
const roomsInfoStore = createBatchStore(
|
|
7315
|
+
async (batchedRoomIds) => {
|
|
7316
|
+
const roomIds = batchedRoomIds.flat();
|
|
7317
|
+
const roomsInfo = await resolveRoomsInfo?.({ roomIds });
|
|
7318
|
+
warnIfNoResolveRoomsInfo();
|
|
7319
|
+
return roomsInfo ?? roomIds.map(() => void 0);
|
|
7320
|
+
},
|
|
7321
|
+
{ delay: RESOLVE_ROOMS_INFO_BATCH_DELAY }
|
|
7322
|
+
);
|
|
7323
|
+
return Object.defineProperty(
|
|
7324
|
+
{
|
|
7325
|
+
logout,
|
|
7326
|
+
// Old, deprecated APIs
|
|
7327
|
+
enter,
|
|
7328
|
+
getRoom,
|
|
7329
|
+
leave: forceLeave,
|
|
7330
|
+
// New, preferred API
|
|
7331
|
+
enterRoom,
|
|
7332
|
+
// Internal
|
|
7333
|
+
[kInternal]: {
|
|
7334
|
+
notifications: {
|
|
7335
|
+
getInboxNotifications,
|
|
7336
|
+
getUnreadInboxNotificationsCount,
|
|
7337
|
+
markAllInboxNotificationsAsRead,
|
|
7338
|
+
markInboxNotificationAsRead
|
|
7339
|
+
},
|
|
7340
|
+
currentUserIdStore,
|
|
7341
|
+
resolveMentionSuggestions: clientOptions.resolveMentionSuggestions,
|
|
7342
|
+
cacheStore,
|
|
7343
|
+
usersStore,
|
|
7344
|
+
roomsInfoStore,
|
|
7345
|
+
getRoomIds() {
|
|
7346
|
+
return Array.from(roomsById.keys());
|
|
7347
|
+
}
|
|
7348
|
+
}
|
|
7349
|
+
},
|
|
7350
|
+
kInternal,
|
|
7351
|
+
{
|
|
7352
|
+
enumerable: false
|
|
7353
|
+
}
|
|
7354
|
+
);
|
|
7355
|
+
}
|
|
7356
|
+
var NotificationsApiError = class extends Error {
|
|
7357
|
+
constructor(message, status, details) {
|
|
7358
|
+
super(message);
|
|
7359
|
+
this.message = message;
|
|
7360
|
+
this.status = status;
|
|
7361
|
+
this.details = details;
|
|
7362
|
+
}
|
|
7363
|
+
};
|
|
7364
|
+
function checkBounds(option, value, min, max, recommendedMin) {
|
|
7365
|
+
if (typeof value !== "number" || value < min || max !== void 0 && value > max) {
|
|
7366
|
+
throw new Error(
|
|
7367
|
+
max !== void 0 ? `${option} should be between ${recommendedMin ?? min} and ${max}.` : `${option} should be at least ${recommendedMin ?? min}.`
|
|
7368
|
+
);
|
|
7369
|
+
}
|
|
7370
|
+
return value;
|
|
7371
|
+
}
|
|
7372
|
+
function getBackgroundKeepAliveTimeout(value) {
|
|
7373
|
+
if (value === void 0)
|
|
7374
|
+
return void 0;
|
|
7375
|
+
return checkBounds(
|
|
7376
|
+
"backgroundKeepAliveTimeout",
|
|
7377
|
+
value,
|
|
7378
|
+
MIN_BACKGROUND_KEEP_ALIVE_TIMEOUT
|
|
7379
|
+
);
|
|
7380
|
+
}
|
|
7381
|
+
function getThrottle(value) {
|
|
7382
|
+
return checkBounds("throttle", value, MIN_THROTTLE, MAX_THROTTLE);
|
|
7383
|
+
}
|
|
7384
|
+
function getLostConnectionTimeout(value) {
|
|
7385
|
+
return checkBounds(
|
|
7386
|
+
"lostConnectionTimeout",
|
|
7387
|
+
value,
|
|
7388
|
+
MIN_LOST_CONNECTION_TIMEOUT,
|
|
7389
|
+
MAX_LOST_CONNECTION_TIMEOUT,
|
|
7390
|
+
RECOMMENDED_MIN_LOST_CONNECTION_TIMEOUT
|
|
7391
|
+
);
|
|
7392
|
+
}
|
|
7393
|
+
function createDevelopmentWarning(condition, ...args) {
|
|
7394
|
+
let hasWarned = false;
|
|
7395
|
+
if (process.env.NODE_ENV !== "production") {
|
|
7396
|
+
return () => {
|
|
7397
|
+
if (!hasWarned && (typeof condition === "function" ? condition() : condition)) {
|
|
7398
|
+
warn(...args);
|
|
7399
|
+
hasWarned = true;
|
|
7400
|
+
}
|
|
7401
|
+
};
|
|
7402
|
+
} else {
|
|
7403
|
+
return () => {
|
|
7404
|
+
};
|
|
7405
|
+
}
|
|
7406
|
+
}
|
|
7407
|
+
|
|
7408
|
+
// src/comments/comment-body.ts
|
|
7409
|
+
function isCommentBodyParagraph(element) {
|
|
7410
|
+
return "type" in element && element.type === "mention";
|
|
7411
|
+
}
|
|
7412
|
+
function isCommentBodyText(element) {
|
|
7413
|
+
return "text" in element && typeof element.text === "string";
|
|
7414
|
+
}
|
|
7415
|
+
function isCommentBodyMention(element) {
|
|
7416
|
+
return "type" in element && element.type === "mention";
|
|
7417
|
+
}
|
|
7418
|
+
function isCommentBodyLink(element) {
|
|
7419
|
+
return "type" in element && element.type === "link";
|
|
7420
|
+
}
|
|
7421
|
+
var commentBodyElementsGuards = {
|
|
7422
|
+
paragraph: isCommentBodyParagraph,
|
|
7423
|
+
text: isCommentBodyText,
|
|
7424
|
+
link: isCommentBodyLink,
|
|
7425
|
+
mention: isCommentBodyMention
|
|
7426
|
+
};
|
|
7427
|
+
var commentBodyElementsTypes = {
|
|
7428
|
+
paragraph: "block",
|
|
7429
|
+
text: "inline",
|
|
7430
|
+
link: "inline",
|
|
7431
|
+
mention: "inline"
|
|
7432
|
+
};
|
|
7433
|
+
function traverseCommentBody(body, elementOrVisitor, possiblyVisitor) {
|
|
7434
|
+
if (!body || !body?.content) {
|
|
7435
|
+
return;
|
|
7436
|
+
}
|
|
7437
|
+
const element = typeof elementOrVisitor === "string" ? elementOrVisitor : void 0;
|
|
7438
|
+
const type = element ? commentBodyElementsTypes[element] : "all";
|
|
7439
|
+
const guard = element ? commentBodyElementsGuards[element] : () => true;
|
|
7440
|
+
const visitor = typeof elementOrVisitor === "function" ? elementOrVisitor : possiblyVisitor;
|
|
7441
|
+
for (const block of body.content) {
|
|
7442
|
+
if (type === "all" || type === "block") {
|
|
7443
|
+
if (guard(block)) {
|
|
7444
|
+
visitor?.(block);
|
|
7445
|
+
}
|
|
7446
|
+
}
|
|
7447
|
+
if (type === "all" || type === "inline") {
|
|
7448
|
+
for (const inline of block.children) {
|
|
7449
|
+
if (guard(inline)) {
|
|
7450
|
+
visitor?.(inline);
|
|
7451
|
+
}
|
|
7452
|
+
}
|
|
7453
|
+
}
|
|
7454
|
+
}
|
|
7455
|
+
}
|
|
7456
|
+
function getMentionedIdsFromCommentBody(body) {
|
|
7457
|
+
const mentionedIds = /* @__PURE__ */ new Set();
|
|
7458
|
+
traverseCommentBody(
|
|
7459
|
+
body,
|
|
7460
|
+
"mention",
|
|
7461
|
+
(mention) => mentionedIds.add(mention.id)
|
|
7462
|
+
);
|
|
7463
|
+
return Array.from(mentionedIds);
|
|
7464
|
+
}
|
|
7465
|
+
async function resolveUsersInCommentBody(body, resolveUsers) {
|
|
7466
|
+
const resolvedUsers = /* @__PURE__ */ new Map();
|
|
7467
|
+
if (!resolveUsers) {
|
|
7468
|
+
return resolvedUsers;
|
|
7469
|
+
}
|
|
7470
|
+
const userIds = getMentionedIdsFromCommentBody(body);
|
|
7471
|
+
const users = await resolveUsers({
|
|
7472
|
+
userIds
|
|
7473
|
+
});
|
|
7474
|
+
for (const [index, userId] of userIds.entries()) {
|
|
7475
|
+
const user = users?.[index];
|
|
7476
|
+
if (user) {
|
|
7477
|
+
resolvedUsers.set(userId, user);
|
|
7478
|
+
}
|
|
7479
|
+
}
|
|
7480
|
+
return resolvedUsers;
|
|
7481
|
+
}
|
|
7482
|
+
var htmlEscapables = {
|
|
7483
|
+
"&": "&",
|
|
7484
|
+
"<": "<",
|
|
7485
|
+
">": ">",
|
|
7486
|
+
'"': """,
|
|
7487
|
+
"'": "'"
|
|
7488
|
+
};
|
|
7489
|
+
var htmlEscapablesRegex = new RegExp(
|
|
7490
|
+
Object.keys(htmlEscapables).map((entity) => `\\${entity}`).join("|"),
|
|
7491
|
+
"g"
|
|
7492
|
+
);
|
|
7493
|
+
function htmlSafe(value) {
|
|
7494
|
+
return new HtmlSafeString([String(value)], []);
|
|
7495
|
+
}
|
|
7496
|
+
function joinHtml(strings) {
|
|
7497
|
+
if (strings.length <= 0) {
|
|
7498
|
+
return new HtmlSafeString([""], []);
|
|
7499
|
+
}
|
|
7500
|
+
return new HtmlSafeString(
|
|
7501
|
+
["", ...Array(strings.length - 1).fill(""), ""],
|
|
7502
|
+
strings
|
|
7503
|
+
);
|
|
7504
|
+
}
|
|
7505
|
+
function escapeHtml(value) {
|
|
7506
|
+
if (value instanceof HtmlSafeString) {
|
|
7507
|
+
return value.toString();
|
|
7508
|
+
}
|
|
7509
|
+
if (Array.isArray(value)) {
|
|
7510
|
+
return joinHtml(value).toString();
|
|
7511
|
+
}
|
|
7512
|
+
return String(value).replace(
|
|
7513
|
+
htmlEscapablesRegex,
|
|
7514
|
+
(character) => htmlEscapables[character]
|
|
7515
|
+
);
|
|
7516
|
+
}
|
|
7517
|
+
var HtmlSafeString = class {
|
|
7518
|
+
constructor(strings, values) {
|
|
7519
|
+
this._strings = strings;
|
|
7520
|
+
this._values = values;
|
|
7521
|
+
}
|
|
7522
|
+
toString() {
|
|
7523
|
+
return this._strings.reduce((result, str, i) => {
|
|
7524
|
+
return result + escapeHtml(nn(this._values[i - 1])) + str;
|
|
7525
|
+
});
|
|
7526
|
+
}
|
|
7527
|
+
};
|
|
7528
|
+
function html(strings, ...values) {
|
|
7529
|
+
return new HtmlSafeString(strings, values);
|
|
7530
|
+
}
|
|
7531
|
+
var markdownEscapables = {
|
|
7532
|
+
_: "\\_",
|
|
7533
|
+
"*": "\\*",
|
|
7534
|
+
"#": "\\#",
|
|
7535
|
+
"`": "\\`",
|
|
7536
|
+
"~": "\\~",
|
|
7537
|
+
"!": "\\!",
|
|
7538
|
+
"|": "\\|",
|
|
7539
|
+
"(": "\\(",
|
|
7540
|
+
")": "\\)",
|
|
7541
|
+
"{": "\\{",
|
|
7542
|
+
"}": "\\}",
|
|
7543
|
+
"[": "\\[",
|
|
7544
|
+
"]": "\\]"
|
|
7545
|
+
};
|
|
7546
|
+
var markdownEscapablesRegex = new RegExp(
|
|
7547
|
+
Object.keys(markdownEscapables).map((entity) => `\\${entity}`).join("|"),
|
|
7548
|
+
"g"
|
|
7549
|
+
);
|
|
7550
|
+
function joinMarkdown(strings) {
|
|
7551
|
+
if (strings.length <= 0) {
|
|
7552
|
+
return new MarkdownSafeString([""], []);
|
|
7553
|
+
}
|
|
7554
|
+
return new MarkdownSafeString(
|
|
7555
|
+
["", ...Array(strings.length - 1).fill(""), ""],
|
|
7556
|
+
strings
|
|
7557
|
+
);
|
|
7558
|
+
}
|
|
7559
|
+
function escapeMarkdown(value) {
|
|
7560
|
+
if (value instanceof MarkdownSafeString) {
|
|
7561
|
+
return value.toString();
|
|
7562
|
+
}
|
|
7563
|
+
if (Array.isArray(value)) {
|
|
7564
|
+
return joinMarkdown(value).toString();
|
|
7565
|
+
}
|
|
7566
|
+
return String(value).replace(
|
|
7567
|
+
markdownEscapablesRegex,
|
|
7568
|
+
(character) => markdownEscapables[character]
|
|
7569
|
+
);
|
|
7570
|
+
}
|
|
7571
|
+
var MarkdownSafeString = class {
|
|
7572
|
+
constructor(strings, values) {
|
|
7573
|
+
this._strings = strings;
|
|
7574
|
+
this._values = values;
|
|
7575
|
+
}
|
|
7576
|
+
toString() {
|
|
7577
|
+
return this._strings.reduce((result, str, i) => {
|
|
7578
|
+
return result + escapeMarkdown(nn(this._values[i - 1])) + str;
|
|
7579
|
+
});
|
|
7580
|
+
}
|
|
7581
|
+
};
|
|
7582
|
+
function markdown(strings, ...values) {
|
|
7583
|
+
return new MarkdownSafeString(strings, values);
|
|
7584
|
+
}
|
|
7585
|
+
function toAbsoluteUrl(url) {
|
|
7586
|
+
if (url.startsWith("http://") || url.startsWith("https://")) {
|
|
7587
|
+
return url;
|
|
7588
|
+
} else if (url.startsWith("www.")) {
|
|
7589
|
+
return "https://" + url;
|
|
7590
|
+
}
|
|
7591
|
+
return;
|
|
7592
|
+
}
|
|
7593
|
+
var stringifyCommentBodyPlainElements = {
|
|
7594
|
+
paragraph: ({ children }) => children,
|
|
7595
|
+
text: ({ element }) => element.text,
|
|
7596
|
+
link: ({ element }) => element.url,
|
|
7597
|
+
mention: ({ element, user }) => {
|
|
7598
|
+
return `@${user?.name ?? element.id}`;
|
|
7599
|
+
}
|
|
7600
|
+
};
|
|
7601
|
+
var stringifyCommentBodyHtmlElements = {
|
|
7602
|
+
paragraph: ({ children }) => {
|
|
7603
|
+
return children ? html`<p>${htmlSafe(children)}</p>` : children;
|
|
7604
|
+
},
|
|
7605
|
+
text: ({ element }) => {
|
|
7606
|
+
let children = element.text;
|
|
7607
|
+
if (!children) {
|
|
7608
|
+
return children;
|
|
7609
|
+
}
|
|
7610
|
+
if (element.bold) {
|
|
7611
|
+
children = html`<strong>${children}</strong>`;
|
|
7612
|
+
}
|
|
7613
|
+
if (element.italic) {
|
|
7614
|
+
children = html`<em>${children}</em>`;
|
|
7615
|
+
}
|
|
7616
|
+
if (element.strikethrough) {
|
|
7617
|
+
children = html`<s>${children}</s>`;
|
|
7618
|
+
}
|
|
7619
|
+
if (element.code) {
|
|
7620
|
+
children = html`<code>${children}</code>`;
|
|
7621
|
+
}
|
|
7622
|
+
return children;
|
|
7623
|
+
},
|
|
7624
|
+
link: ({ element, href }) => {
|
|
7625
|
+
return html`<a href="${href}" target="_blank" rel="noopener noreferrer">${element.url}</a>`;
|
|
7626
|
+
},
|
|
7627
|
+
mention: ({ element, user }) => {
|
|
7628
|
+
return html`<span data-mention>@${user?.name ?? element.id}</span>`;
|
|
7629
|
+
}
|
|
7630
|
+
};
|
|
7631
|
+
var stringifyCommentBodyMarkdownElements = {
|
|
7632
|
+
paragraph: ({ children }) => {
|
|
7633
|
+
return children;
|
|
7634
|
+
},
|
|
7635
|
+
text: ({ element }) => {
|
|
7636
|
+
let children = element.text;
|
|
7637
|
+
if (!children) {
|
|
7638
|
+
return children;
|
|
6486
7639
|
}
|
|
6487
|
-
|
|
6488
|
-
|
|
6489
|
-
|
|
6490
|
-
|
|
6491
|
-
|
|
6492
|
-
|
|
6493
|
-
|
|
7640
|
+
if (element.bold) {
|
|
7641
|
+
children = markdown`**${children}**`;
|
|
7642
|
+
}
|
|
7643
|
+
if (element.italic) {
|
|
7644
|
+
children = markdown`_${children}_`;
|
|
7645
|
+
}
|
|
7646
|
+
if (element.strikethrough) {
|
|
7647
|
+
children = markdown`~~${children}~~`;
|
|
6494
7648
|
}
|
|
7649
|
+
if (element.code) {
|
|
7650
|
+
children = markdown`\`${children}\``;
|
|
7651
|
+
}
|
|
7652
|
+
return children;
|
|
7653
|
+
},
|
|
7654
|
+
link: ({ element, href }) => {
|
|
7655
|
+
return markdown`[${element.url}](${href})`;
|
|
7656
|
+
},
|
|
7657
|
+
mention: ({ element, user }) => {
|
|
7658
|
+
return markdown`@${user?.name ?? element.id}`;
|
|
6495
7659
|
}
|
|
6496
|
-
|
|
6497
|
-
|
|
6498
|
-
|
|
6499
|
-
|
|
6500
|
-
|
|
6501
|
-
|
|
6502
|
-
|
|
6503
|
-
enterRoom
|
|
7660
|
+
};
|
|
7661
|
+
async function stringifyCommentBody(body, options) {
|
|
7662
|
+
const format = options?.format ?? "plain";
|
|
7663
|
+
const separator = options?.separator ?? (format === "markdown" ? "\n\n" : "\n");
|
|
7664
|
+
const elements = {
|
|
7665
|
+
...format === "html" ? stringifyCommentBodyHtmlElements : format === "markdown" ? stringifyCommentBodyMarkdownElements : stringifyCommentBodyPlainElements,
|
|
7666
|
+
...options?.elements
|
|
6504
7667
|
};
|
|
6505
|
-
|
|
6506
|
-
|
|
6507
|
-
|
|
6508
|
-
throw new Error(
|
|
6509
|
-
max !== void 0 ? `${option} should be between ${recommendedMin ?? min} and ${max}.` : `${option} should be at least ${recommendedMin ?? min}.`
|
|
6510
|
-
);
|
|
6511
|
-
}
|
|
6512
|
-
return value;
|
|
6513
|
-
}
|
|
6514
|
-
function getBackgroundKeepAliveTimeout(value) {
|
|
6515
|
-
if (value === void 0)
|
|
6516
|
-
return void 0;
|
|
6517
|
-
return checkBounds(
|
|
6518
|
-
"backgroundKeepAliveTimeout",
|
|
6519
|
-
value,
|
|
6520
|
-
MIN_BACKGROUND_KEEP_ALIVE_TIMEOUT
|
|
6521
|
-
);
|
|
6522
|
-
}
|
|
6523
|
-
function getThrottle(value) {
|
|
6524
|
-
return checkBounds("throttle", value, MIN_THROTTLE, MAX_THROTTLE);
|
|
6525
|
-
}
|
|
6526
|
-
function getLostConnectionTimeout(value) {
|
|
6527
|
-
return checkBounds(
|
|
6528
|
-
"lostConnectionTimeout",
|
|
6529
|
-
value,
|
|
6530
|
-
MIN_LOST_CONNECTION_TIMEOUT,
|
|
6531
|
-
MAX_LOST_CONNECTION_TIMEOUT,
|
|
6532
|
-
RECOMMENDED_MIN_LOST_CONNECTION_TIMEOUT
|
|
7668
|
+
const resolvedUsers = await resolveUsersInCommentBody(
|
|
7669
|
+
body,
|
|
7670
|
+
options?.resolveUsers
|
|
6533
7671
|
);
|
|
7672
|
+
const blocks = body.content.flatMap((block, blockIndex) => {
|
|
7673
|
+
switch (block.type) {
|
|
7674
|
+
case "paragraph": {
|
|
7675
|
+
const inlines = block.children.flatMap((inline, inlineIndex) => {
|
|
7676
|
+
if (isCommentBodyMention(inline)) {
|
|
7677
|
+
return inline.id ? [
|
|
7678
|
+
elements.mention(
|
|
7679
|
+
{
|
|
7680
|
+
element: inline,
|
|
7681
|
+
user: resolvedUsers.get(inline.id)
|
|
7682
|
+
},
|
|
7683
|
+
inlineIndex
|
|
7684
|
+
)
|
|
7685
|
+
] : [];
|
|
7686
|
+
}
|
|
7687
|
+
if (isCommentBodyLink(inline)) {
|
|
7688
|
+
return [
|
|
7689
|
+
elements.link(
|
|
7690
|
+
{
|
|
7691
|
+
element: inline,
|
|
7692
|
+
href: toAbsoluteUrl(inline.url) ?? inline.url
|
|
7693
|
+
},
|
|
7694
|
+
inlineIndex
|
|
7695
|
+
)
|
|
7696
|
+
];
|
|
7697
|
+
}
|
|
7698
|
+
if (isCommentBodyText(inline)) {
|
|
7699
|
+
return [elements.text({ element: inline }, inlineIndex)];
|
|
7700
|
+
}
|
|
7701
|
+
return [];
|
|
7702
|
+
});
|
|
7703
|
+
return [
|
|
7704
|
+
elements.paragraph(
|
|
7705
|
+
{ element: block, children: inlines.join("") },
|
|
7706
|
+
blockIndex
|
|
7707
|
+
)
|
|
7708
|
+
];
|
|
7709
|
+
}
|
|
7710
|
+
default:
|
|
7711
|
+
return [];
|
|
7712
|
+
}
|
|
7713
|
+
});
|
|
7714
|
+
return blocks.join(separator);
|
|
6534
7715
|
}
|
|
6535
7716
|
|
|
6536
7717
|
// src/crdts/utils.ts
|
|
@@ -6864,161 +8045,6 @@ function legacy_patchImmutableNode(state, path, update) {
|
|
|
6864
8045
|
}
|
|
6865
8046
|
}
|
|
6866
8047
|
|
|
6867
|
-
// src/lib/shallow.ts
|
|
6868
|
-
function shallowArray(xs, ys) {
|
|
6869
|
-
if (xs.length !== ys.length) {
|
|
6870
|
-
return false;
|
|
6871
|
-
}
|
|
6872
|
-
for (let i = 0; i < xs.length; i++) {
|
|
6873
|
-
if (!Object.is(xs[i], ys[i])) {
|
|
6874
|
-
return false;
|
|
6875
|
-
}
|
|
6876
|
-
}
|
|
6877
|
-
return true;
|
|
6878
|
-
}
|
|
6879
|
-
function shallowObj(objA, objB) {
|
|
6880
|
-
if (typeof objA !== "object" || objA === null || typeof objB !== "object" || objB === null || Object.prototype.toString.call(objA) !== "[object Object]" || Object.prototype.toString.call(objB) !== "[object Object]") {
|
|
6881
|
-
return false;
|
|
6882
|
-
}
|
|
6883
|
-
const keysA = Object.keys(objA);
|
|
6884
|
-
if (keysA.length !== Object.keys(objB).length) {
|
|
6885
|
-
return false;
|
|
6886
|
-
}
|
|
6887
|
-
return keysA.every(
|
|
6888
|
-
(key) => Object.prototype.hasOwnProperty.call(objB, key) && Object.is(objA[key], objB[key])
|
|
6889
|
-
);
|
|
6890
|
-
}
|
|
6891
|
-
function shallow(a, b) {
|
|
6892
|
-
if (Object.is(a, b)) {
|
|
6893
|
-
return true;
|
|
6894
|
-
}
|
|
6895
|
-
const isArrayA = Array.isArray(a);
|
|
6896
|
-
const isArrayB = Array.isArray(b);
|
|
6897
|
-
if (isArrayA || isArrayB) {
|
|
6898
|
-
if (!isArrayA || !isArrayB) {
|
|
6899
|
-
return false;
|
|
6900
|
-
}
|
|
6901
|
-
return shallowArray(a, b);
|
|
6902
|
-
}
|
|
6903
|
-
return shallowObj(a, b);
|
|
6904
|
-
}
|
|
6905
|
-
|
|
6906
|
-
// src/lib/AsyncCache.ts
|
|
6907
|
-
var noop = () => {
|
|
6908
|
-
};
|
|
6909
|
-
function isShallowEqual(a, b) {
|
|
6910
|
-
if (a.isLoading !== b.isLoading || a.data === void 0 !== (b.data === void 0) || a.error === void 0 !== (b.error === void 0)) {
|
|
6911
|
-
return false;
|
|
6912
|
-
} else {
|
|
6913
|
-
return shallow(a.data, b.data) && shallow(a.error, b.error);
|
|
6914
|
-
}
|
|
6915
|
-
}
|
|
6916
|
-
function createCacheItem(key, asyncFunction, options) {
|
|
6917
|
-
const $asyncFunction = async () => asyncFunction(key);
|
|
6918
|
-
const context = {
|
|
6919
|
-
isInvalid: true
|
|
6920
|
-
};
|
|
6921
|
-
let state = { isLoading: false };
|
|
6922
|
-
let previousState = { isLoading: false };
|
|
6923
|
-
const eventSource2 = makeEventSource();
|
|
6924
|
-
function notify() {
|
|
6925
|
-
const isEqual = options?.isStateEqual ?? isShallowEqual;
|
|
6926
|
-
if (!isEqual(previousState, state)) {
|
|
6927
|
-
previousState = state;
|
|
6928
|
-
eventSource2.notify(state);
|
|
6929
|
-
}
|
|
6930
|
-
}
|
|
6931
|
-
async function resolve() {
|
|
6932
|
-
if (!context.promise) {
|
|
6933
|
-
return;
|
|
6934
|
-
}
|
|
6935
|
-
try {
|
|
6936
|
-
const data = await context.promise;
|
|
6937
|
-
context.isInvalid = false;
|
|
6938
|
-
state = {
|
|
6939
|
-
isLoading: false,
|
|
6940
|
-
data
|
|
6941
|
-
};
|
|
6942
|
-
} catch (error3) {
|
|
6943
|
-
state = {
|
|
6944
|
-
isLoading: false,
|
|
6945
|
-
data: state.data,
|
|
6946
|
-
error: error3
|
|
6947
|
-
};
|
|
6948
|
-
}
|
|
6949
|
-
context.promise = void 0;
|
|
6950
|
-
notify();
|
|
6951
|
-
}
|
|
6952
|
-
async function revalidate() {
|
|
6953
|
-
context.isInvalid = true;
|
|
6954
|
-
return get();
|
|
6955
|
-
}
|
|
6956
|
-
async function get() {
|
|
6957
|
-
if (context.isInvalid) {
|
|
6958
|
-
if (!context.promise) {
|
|
6959
|
-
context.isInvalid = true;
|
|
6960
|
-
context.promise = $asyncFunction();
|
|
6961
|
-
state = { isLoading: true, data: state.data };
|
|
6962
|
-
notify();
|
|
6963
|
-
}
|
|
6964
|
-
await resolve();
|
|
6965
|
-
}
|
|
6966
|
-
return getState();
|
|
6967
|
-
}
|
|
6968
|
-
function getState() {
|
|
6969
|
-
return state;
|
|
6970
|
-
}
|
|
6971
|
-
return {
|
|
6972
|
-
...eventSource2.observable,
|
|
6973
|
-
get,
|
|
6974
|
-
getState,
|
|
6975
|
-
revalidate
|
|
6976
|
-
};
|
|
6977
|
-
}
|
|
6978
|
-
function createAsyncCache(asyncFunction, options) {
|
|
6979
|
-
const cache = /* @__PURE__ */ new Map();
|
|
6980
|
-
function create(key) {
|
|
6981
|
-
let cacheItem = cache.get(key);
|
|
6982
|
-
if (cacheItem) {
|
|
6983
|
-
return cacheItem;
|
|
6984
|
-
}
|
|
6985
|
-
cacheItem = createCacheItem(key, asyncFunction, options);
|
|
6986
|
-
cache.set(key, cacheItem);
|
|
6987
|
-
return cacheItem;
|
|
6988
|
-
}
|
|
6989
|
-
function get(key) {
|
|
6990
|
-
return create(key).get();
|
|
6991
|
-
}
|
|
6992
|
-
function getState(key) {
|
|
6993
|
-
return cache.get(key)?.getState();
|
|
6994
|
-
}
|
|
6995
|
-
function revalidate(key) {
|
|
6996
|
-
return create(key).revalidate();
|
|
6997
|
-
}
|
|
6998
|
-
function subscribe(key, callback) {
|
|
6999
|
-
return create(key).subscribe(callback) ?? noop;
|
|
7000
|
-
}
|
|
7001
|
-
function subscribeOnce(key, callback) {
|
|
7002
|
-
return create(key).subscribeOnce(callback) ?? noop;
|
|
7003
|
-
}
|
|
7004
|
-
function has(key) {
|
|
7005
|
-
return cache.has(key);
|
|
7006
|
-
}
|
|
7007
|
-
function clear() {
|
|
7008
|
-
cache.clear();
|
|
7009
|
-
}
|
|
7010
|
-
return {
|
|
7011
|
-
create,
|
|
7012
|
-
get,
|
|
7013
|
-
getState,
|
|
7014
|
-
revalidate,
|
|
7015
|
-
subscribe,
|
|
7016
|
-
subscribeOnce,
|
|
7017
|
-
has,
|
|
7018
|
-
clear
|
|
7019
|
-
};
|
|
7020
|
-
}
|
|
7021
|
-
|
|
7022
8048
|
// src/lib/Poller.ts
|
|
7023
8049
|
function makePoller(callback) {
|
|
7024
8050
|
let context = {
|
|
@@ -7108,19 +8134,43 @@ function makePoller(callback) {
|
|
|
7108
8134
|
};
|
|
7109
8135
|
}
|
|
7110
8136
|
|
|
7111
|
-
// src/lib/
|
|
7112
|
-
function
|
|
7113
|
-
if (
|
|
7114
|
-
return
|
|
8137
|
+
// src/lib/shallow.ts
|
|
8138
|
+
function shallowArray(xs, ys) {
|
|
8139
|
+
if (xs.length !== ys.length) {
|
|
8140
|
+
return false;
|
|
7115
8141
|
}
|
|
7116
|
-
|
|
7117
|
-
(
|
|
7118
|
-
|
|
7119
|
-
|
|
7120
|
-
|
|
7121
|
-
|
|
8142
|
+
for (let i = 0; i < xs.length; i++) {
|
|
8143
|
+
if (!Object.is(xs[i], ys[i])) {
|
|
8144
|
+
return false;
|
|
8145
|
+
}
|
|
8146
|
+
}
|
|
8147
|
+
return true;
|
|
8148
|
+
}
|
|
8149
|
+
function shallowObj(objA, objB) {
|
|
8150
|
+
if (typeof objA !== "object" || objA === null || typeof objB !== "object" || objB === null || Object.prototype.toString.call(objA) !== "[object Object]" || Object.prototype.toString.call(objB) !== "[object Object]") {
|
|
8151
|
+
return false;
|
|
8152
|
+
}
|
|
8153
|
+
const keysA = Object.keys(objA);
|
|
8154
|
+
if (keysA.length !== Object.keys(objB).length) {
|
|
8155
|
+
return false;
|
|
8156
|
+
}
|
|
8157
|
+
return keysA.every(
|
|
8158
|
+
(key) => Object.prototype.hasOwnProperty.call(objB, key) && Object.is(objA[key], objB[key])
|
|
7122
8159
|
);
|
|
7123
|
-
|
|
8160
|
+
}
|
|
8161
|
+
function shallow(a, b) {
|
|
8162
|
+
if (Object.is(a, b)) {
|
|
8163
|
+
return true;
|
|
8164
|
+
}
|
|
8165
|
+
const isArrayA = Array.isArray(a);
|
|
8166
|
+
const isArrayB = Array.isArray(b);
|
|
8167
|
+
if (isArrayA || isArrayB) {
|
|
8168
|
+
if (!isArrayA || !isArrayB) {
|
|
8169
|
+
return false;
|
|
8170
|
+
}
|
|
8171
|
+
return shallowArray(a, b);
|
|
8172
|
+
}
|
|
8173
|
+
return shallowObj(a, b);
|
|
7124
8174
|
}
|
|
7125
8175
|
|
|
7126
8176
|
// src/index.ts
|
|
@@ -7132,9 +8182,13 @@ export {
|
|
|
7132
8182
|
LiveList,
|
|
7133
8183
|
LiveMap,
|
|
7134
8184
|
LiveObject,
|
|
8185
|
+
NotificationsApiError,
|
|
7135
8186
|
OpCode,
|
|
7136
8187
|
ServerMsgCode,
|
|
7137
8188
|
WebsocketCloseCodes,
|
|
8189
|
+
ackOp,
|
|
8190
|
+
addReaction,
|
|
8191
|
+
applyOptimisticUpdates,
|
|
7138
8192
|
asPos,
|
|
7139
8193
|
assert,
|
|
7140
8194
|
assertNever,
|
|
@@ -7143,10 +8197,10 @@ export {
|
|
|
7143
8197
|
fancy_console_exports as console,
|
|
7144
8198
|
convertToCommentData,
|
|
7145
8199
|
convertToCommentUserReaction,
|
|
8200
|
+
convertToInboxNotificationData,
|
|
7146
8201
|
convertToThreadData,
|
|
7147
|
-
createAsyncCache,
|
|
7148
8202
|
createClient,
|
|
7149
|
-
|
|
8203
|
+
deleteComment,
|
|
7150
8204
|
deprecate,
|
|
7151
8205
|
deprecateIf,
|
|
7152
8206
|
detectDupes,
|
|
@@ -7160,20 +8214,24 @@ export {
|
|
|
7160
8214
|
isLiveNode,
|
|
7161
8215
|
isPlainObject,
|
|
7162
8216
|
isRootCrdt,
|
|
8217
|
+
kInternal,
|
|
7163
8218
|
legacy_patchImmutableObject,
|
|
7164
8219
|
lsonToJson,
|
|
7165
8220
|
makeEventSource,
|
|
7166
8221
|
makePoller,
|
|
7167
8222
|
makePosition,
|
|
7168
8223
|
nn,
|
|
8224
|
+
objectToQuery,
|
|
7169
8225
|
patchLiveObjectKey,
|
|
7170
8226
|
raise,
|
|
8227
|
+
removeReaction,
|
|
7171
8228
|
shallow,
|
|
7172
8229
|
stringify,
|
|
7173
8230
|
stringifyCommentBody,
|
|
7174
8231
|
throwUsageError,
|
|
7175
8232
|
toPlainLson,
|
|
7176
8233
|
tryParseJson,
|
|
8234
|
+
upsertComment,
|
|
7177
8235
|
withTimeout
|
|
7178
8236
|
};
|
|
7179
8237
|
//# sourceMappingURL=index.mjs.map
|