@liveblocks/core 3.16.0-feeds1 → 3.16.0-flow2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +884 -1076
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +116 -258
- package/dist/index.d.ts +116 -258
- package/dist/index.js +811 -1003
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ var __export = (target, all) => {
|
|
|
6
6
|
|
|
7
7
|
// src/version.ts
|
|
8
8
|
var PKG_NAME = "@liveblocks/core";
|
|
9
|
-
var PKG_VERSION = "3.16.0-
|
|
9
|
+
var PKG_VERSION = "3.16.0-flow2";
|
|
10
10
|
var PKG_FORMAT = "esm";
|
|
11
11
|
|
|
12
12
|
// src/dupe-detection.ts
|
|
@@ -3219,26 +3219,10 @@ var ServerMsgCode = Object.freeze({
|
|
|
3219
3219
|
COMMENT_REACTION_ADDED: 405,
|
|
3220
3220
|
COMMENT_REACTION_REMOVED: 406,
|
|
3221
3221
|
COMMENT_METADATA_UPDATED: 409,
|
|
3222
|
-
// For Feeds
|
|
3223
|
-
FEEDS_LIST: 500,
|
|
3224
|
-
FEEDS_ADDED: 501,
|
|
3225
|
-
FEEDS_UPDATED: 502,
|
|
3226
|
-
FEED_DELETED: 503,
|
|
3227
|
-
FEED_MESSAGES_LIST: 504,
|
|
3228
|
-
FEED_MESSAGES_ADDED: 505,
|
|
3229
|
-
FEED_MESSAGES_UPDATED: 506,
|
|
3230
|
-
FEED_MESSAGES_DELETED: 507,
|
|
3231
|
-
FEED_REQUEST_FAILED: 508,
|
|
3232
3222
|
// Error codes
|
|
3233
3223
|
REJECT_STORAGE_OP: 299
|
|
3234
3224
|
// Sent if a mutation was not allowed on the server (i.e. due to permissions, limit exceeded, etc)
|
|
3235
3225
|
});
|
|
3236
|
-
var FeedRequestErrorCode = {
|
|
3237
|
-
INTERNAL: "INTERNAL",
|
|
3238
|
-
FEED_ALREADY_EXISTS: "FEED_ALREADY_EXISTS",
|
|
3239
|
-
FEED_NOT_FOUND: "FEED_NOT_FOUND",
|
|
3240
|
-
FEED_MESSAGE_NOT_FOUND: "FEED_MESSAGE_NOT_FOUND"
|
|
3241
|
-
};
|
|
3242
3226
|
|
|
3243
3227
|
// src/types/IWebSocket.ts
|
|
3244
3228
|
var WebsocketCloseCodes = /* @__PURE__ */ ((WebsocketCloseCodes2) => {
|
|
@@ -5202,7 +5186,6 @@ var Permission = /* @__PURE__ */ ((Permission2) => {
|
|
|
5202
5186
|
Permission2["PresenceWrite"] = "room:presence:write";
|
|
5203
5187
|
Permission2["CommentsWrite"] = "comments:write";
|
|
5204
5188
|
Permission2["CommentsRead"] = "comments:read";
|
|
5205
|
-
Permission2["FeedsWrite"] = "feeds:write";
|
|
5206
5189
|
return Permission2;
|
|
5207
5190
|
})(Permission || {});
|
|
5208
5191
|
function canWriteStorage(scopes) {
|
|
@@ -6319,7 +6302,6 @@ var AbstractCrdt = class {
|
|
|
6319
6302
|
}
|
|
6320
6303
|
/**
|
|
6321
6304
|
* @internal
|
|
6322
|
-
*
|
|
6323
6305
|
* Return an snapshot of this Live tree for use in DevTools.
|
|
6324
6306
|
*/
|
|
6325
6307
|
toTreeNode(key) {
|
|
@@ -6329,6 +6311,14 @@ var AbstractCrdt = class {
|
|
|
6329
6311
|
}
|
|
6330
6312
|
return this.#cachedTreeNode;
|
|
6331
6313
|
}
|
|
6314
|
+
/**
|
|
6315
|
+
* @private
|
|
6316
|
+
* Returns true if the cached immutable snapshot exists and is
|
|
6317
|
+
* reference-equal to the given value. Does not trigger a recompute.
|
|
6318
|
+
*/
|
|
6319
|
+
immutableIs(value) {
|
|
6320
|
+
return this.#cachedImmutable !== void 0 && this.#cachedImmutable === value;
|
|
6321
|
+
}
|
|
6332
6322
|
/**
|
|
6333
6323
|
* Return an immutable snapshot of this Live node and its children.
|
|
6334
6324
|
*/
|
|
@@ -7876,270 +7866,674 @@ var LiveMap = class _LiveMap extends AbstractCrdt {
|
|
|
7876
7866
|
}
|
|
7877
7867
|
};
|
|
7878
7868
|
|
|
7879
|
-
// src/
|
|
7880
|
-
|
|
7881
|
-
|
|
7882
|
-
|
|
7883
|
-
|
|
7884
|
-
|
|
7885
|
-
|
|
7886
|
-
|
|
7887
|
-
|
|
7888
|
-
|
|
7889
|
-
|
|
7890
|
-
|
|
7891
|
-
|
|
7892
|
-
|
|
7893
|
-
|
|
7894
|
-
|
|
7895
|
-
|
|
7896
|
-
|
|
7897
|
-
|
|
7898
|
-
|
|
7899
|
-
|
|
7900
|
-
|
|
7901
|
-
|
|
7902
|
-
|
|
7903
|
-
|
|
7904
|
-
|
|
7905
|
-
|
|
7906
|
-
|
|
7907
|
-
|
|
7908
|
-
|
|
7909
|
-
|
|
7910
|
-
|
|
7911
|
-
|
|
7912
|
-
|
|
7869
|
+
// src/lib/Json.ts
|
|
7870
|
+
function isJsonScalar(data) {
|
|
7871
|
+
return data === null || typeof data === "string" || typeof data === "number" || typeof data === "boolean";
|
|
7872
|
+
}
|
|
7873
|
+
function isJsonArray(data) {
|
|
7874
|
+
return Array.isArray(data);
|
|
7875
|
+
}
|
|
7876
|
+
function isJsonObject(data) {
|
|
7877
|
+
return !isJsonScalar(data) && !isJsonArray(data);
|
|
7878
|
+
}
|
|
7879
|
+
|
|
7880
|
+
// src/immutable.ts
|
|
7881
|
+
function lsonObjectToJson(obj) {
|
|
7882
|
+
const result = {};
|
|
7883
|
+
for (const key in obj) {
|
|
7884
|
+
const val = obj[key];
|
|
7885
|
+
if (val !== void 0) {
|
|
7886
|
+
result[key] = lsonToJson(val);
|
|
7887
|
+
}
|
|
7888
|
+
}
|
|
7889
|
+
return result;
|
|
7890
|
+
}
|
|
7891
|
+
function liveObjectToJson(liveObject) {
|
|
7892
|
+
return lsonObjectToJson(liveObject.toObject());
|
|
7893
|
+
}
|
|
7894
|
+
function liveMapToJson(map) {
|
|
7895
|
+
const result = {};
|
|
7896
|
+
for (const [key, value] of map.entries()) {
|
|
7897
|
+
result[key] = lsonToJson(value);
|
|
7898
|
+
}
|
|
7899
|
+
return result;
|
|
7900
|
+
}
|
|
7901
|
+
function lsonListToJson(value) {
|
|
7902
|
+
return value.map(lsonToJson);
|
|
7903
|
+
}
|
|
7904
|
+
function liveListToJson(value) {
|
|
7905
|
+
return lsonListToJson(value.toArray());
|
|
7906
|
+
}
|
|
7907
|
+
function lsonToJson(value) {
|
|
7908
|
+
if (value instanceof LiveObject) {
|
|
7909
|
+
return liveObjectToJson(value);
|
|
7910
|
+
} else if (value instanceof LiveList) {
|
|
7911
|
+
return liveListToJson(value);
|
|
7912
|
+
} else if (value instanceof LiveMap) {
|
|
7913
|
+
return liveMapToJson(value);
|
|
7914
|
+
} else if (value instanceof LiveRegister) {
|
|
7915
|
+
return value.data;
|
|
7916
|
+
}
|
|
7917
|
+
if (Array.isArray(value)) {
|
|
7918
|
+
return lsonListToJson(value);
|
|
7919
|
+
} else if (isPlainObject(value)) {
|
|
7920
|
+
return lsonObjectToJson(value);
|
|
7921
|
+
}
|
|
7922
|
+
return value;
|
|
7923
|
+
}
|
|
7924
|
+
function deepLiveify(value, config) {
|
|
7925
|
+
if (Array.isArray(value)) {
|
|
7926
|
+
return new LiveList(value.map((v) => deepLiveify(v, config)));
|
|
7927
|
+
} else if (isPlainObject(value)) {
|
|
7928
|
+
const init = {};
|
|
7929
|
+
const locals = {};
|
|
7930
|
+
for (const key in value) {
|
|
7931
|
+
const val = value[key];
|
|
7932
|
+
if (val === void 0) {
|
|
7933
|
+
continue;
|
|
7934
|
+
}
|
|
7935
|
+
const subConfig = isPlainObject(config) ? config[key] : config;
|
|
7936
|
+
if (subConfig === false) {
|
|
7937
|
+
locals[key] = val;
|
|
7938
|
+
} else if (subConfig === "atomic") {
|
|
7939
|
+
init[key] = val;
|
|
7913
7940
|
} else {
|
|
7914
|
-
|
|
7915
|
-
const children = parentToChildren.get(crdt.parentId);
|
|
7916
|
-
if (children !== void 0) {
|
|
7917
|
-
children.push(node);
|
|
7918
|
-
} else {
|
|
7919
|
-
parentToChildren.set(crdt.parentId, [node]);
|
|
7920
|
-
}
|
|
7941
|
+
init[key] = deepLiveify(val, subConfig);
|
|
7921
7942
|
}
|
|
7922
7943
|
}
|
|
7923
|
-
|
|
7924
|
-
|
|
7944
|
+
const lo = new LiveObject(init);
|
|
7945
|
+
for (const key in locals) {
|
|
7946
|
+
lo.setLocal(key, locals[key]);
|
|
7925
7947
|
}
|
|
7926
|
-
return
|
|
7948
|
+
return lo;
|
|
7949
|
+
} else {
|
|
7950
|
+
return value;
|
|
7927
7951
|
}
|
|
7928
|
-
|
|
7929
|
-
|
|
7930
|
-
|
|
7931
|
-
|
|
7932
|
-
|
|
7933
|
-
|
|
7934
|
-
|
|
7935
|
-
|
|
7952
|
+
}
|
|
7953
|
+
function deepLiveifyObject(obj, config) {
|
|
7954
|
+
return deepLiveify(obj, config);
|
|
7955
|
+
}
|
|
7956
|
+
function reconcile(live, json, config) {
|
|
7957
|
+
if (isLiveObject(live) && isPlainObject(json)) {
|
|
7958
|
+
return reconcileLiveObject(live, json, config);
|
|
7959
|
+
} else if (isLiveList(live) && Array.isArray(json)) {
|
|
7960
|
+
return reconcileLiveList(live, json, config);
|
|
7961
|
+
} else if (isLiveMap(live) && isPlainObject(json)) {
|
|
7962
|
+
return reconcileLiveMap(live, config);
|
|
7963
|
+
} else {
|
|
7964
|
+
return deepLiveify(json, config);
|
|
7936
7965
|
}
|
|
7937
|
-
|
|
7938
|
-
|
|
7939
|
-
|
|
7940
|
-
|
|
7941
|
-
|
|
7942
|
-
|
|
7943
|
-
|
|
7944
|
-
|
|
7966
|
+
}
|
|
7967
|
+
function reconcileLiveMap(_liveMap, _config) {
|
|
7968
|
+
throw new Error("Reconciling a LiveMap is not supported yet");
|
|
7969
|
+
}
|
|
7970
|
+
function reconcileLiveObject(liveObj, jsonObj, config) {
|
|
7971
|
+
const currentKeys = liveObj.keys();
|
|
7972
|
+
for (const key in jsonObj) {
|
|
7973
|
+
currentKeys.delete(key);
|
|
7974
|
+
const newVal = jsonObj[key];
|
|
7975
|
+
if (newVal === void 0) {
|
|
7976
|
+
liveObj.delete(key);
|
|
7977
|
+
continue;
|
|
7978
|
+
}
|
|
7979
|
+
const subConfig = isPlainObject(config) ? config[key] : config;
|
|
7980
|
+
if (subConfig === false) {
|
|
7981
|
+
liveObj.setLocal(key, newVal);
|
|
7982
|
+
} else if (subConfig === "atomic") {
|
|
7983
|
+
const curVal = liveObj.get(key);
|
|
7984
|
+
if (curVal !== newVal) {
|
|
7985
|
+
liveObj.set(key, newVal);
|
|
7986
|
+
}
|
|
7987
|
+
} else {
|
|
7988
|
+
const curVal = liveObj.get(key);
|
|
7989
|
+
if (curVal === void 0) {
|
|
7990
|
+
liveObj.set(key, deepLiveify(newVal, subConfig));
|
|
7991
|
+
} else if (isLiveStructure(curVal)) {
|
|
7992
|
+
const next = reconcile(curVal, newVal, subConfig);
|
|
7993
|
+
if (next !== curVal) {
|
|
7994
|
+
liveObj.set(key, next);
|
|
7995
|
+
}
|
|
7996
|
+
} else if (curVal !== newVal) {
|
|
7997
|
+
liveObj.set(key, deepLiveify(newVal, subConfig));
|
|
7945
7998
|
}
|
|
7946
7999
|
}
|
|
7947
|
-
this.#map = new Map(Object.entries(o));
|
|
7948
8000
|
}
|
|
7949
|
-
|
|
7950
|
-
|
|
7951
|
-
|
|
7952
|
-
|
|
7953
|
-
|
|
7954
|
-
|
|
7955
|
-
|
|
7956
|
-
|
|
7957
|
-
|
|
7958
|
-
|
|
7959
|
-
|
|
7960
|
-
|
|
7961
|
-
|
|
7962
|
-
|
|
7963
|
-
|
|
7964
|
-
if (isLiveNode(value)) {
|
|
7965
|
-
for (const childOp of value._toOps(this._id, key)) {
|
|
7966
|
-
ops.push(childOp);
|
|
7967
|
-
}
|
|
7968
|
-
} else {
|
|
7969
|
-
op.data[key] = value;
|
|
8001
|
+
for (const key of currentKeys) {
|
|
8002
|
+
liveObj.delete(key);
|
|
8003
|
+
}
|
|
8004
|
+
return liveObj;
|
|
8005
|
+
}
|
|
8006
|
+
function reconcileLiveList(liveList, jsonArr, config) {
|
|
8007
|
+
const curLen = liveList.length;
|
|
8008
|
+
const newLen = jsonArr.length;
|
|
8009
|
+
for (let i = 0; i < Math.min(curLen, newLen); i++) {
|
|
8010
|
+
const curVal = liveList.get(i);
|
|
8011
|
+
const newVal = jsonArr[i];
|
|
8012
|
+
if (isLiveStructure(curVal)) {
|
|
8013
|
+
const next = reconcile(curVal, newVal, config);
|
|
8014
|
+
if (next !== curVal) {
|
|
8015
|
+
liveList.set(i, next);
|
|
7970
8016
|
}
|
|
8017
|
+
} else if (curVal !== newVal) {
|
|
8018
|
+
liveList.set(i, deepLiveify(newVal, config));
|
|
7971
8019
|
}
|
|
7972
|
-
return ops;
|
|
7973
8020
|
}
|
|
7974
|
-
|
|
7975
|
-
|
|
7976
|
-
const liveObj = new _LiveObject(item.data);
|
|
7977
|
-
liveObj._attach(id, pool);
|
|
7978
|
-
return this._deserializeChildren(liveObj, parentToChildren, pool);
|
|
8021
|
+
for (let i = curLen; i < newLen; i++) {
|
|
8022
|
+
liveList.push(deepLiveify(jsonArr[i], config));
|
|
7979
8023
|
}
|
|
7980
|
-
|
|
7981
|
-
|
|
7982
|
-
|
|
7983
|
-
|
|
7984
|
-
|
|
8024
|
+
for (let i = curLen - 1; i >= newLen; i--) {
|
|
8025
|
+
liveList.delete(i);
|
|
8026
|
+
}
|
|
8027
|
+
return liveList;
|
|
8028
|
+
}
|
|
8029
|
+
function legacy_patchLiveList(liveList, prev, next) {
|
|
8030
|
+
let i = 0;
|
|
8031
|
+
let prevEnd = prev.length - 1;
|
|
8032
|
+
let nextEnd = next.length - 1;
|
|
8033
|
+
let prevNode = prev[0];
|
|
8034
|
+
let nextNode = next[0];
|
|
8035
|
+
outer: {
|
|
8036
|
+
while (prevNode === nextNode) {
|
|
8037
|
+
++i;
|
|
8038
|
+
if (i > prevEnd || i > nextEnd) {
|
|
8039
|
+
break outer;
|
|
8040
|
+
}
|
|
8041
|
+
prevNode = prev[i];
|
|
8042
|
+
nextNode = next[i];
|
|
7985
8043
|
}
|
|
7986
|
-
|
|
7987
|
-
|
|
7988
|
-
|
|
7989
|
-
|
|
7990
|
-
|
|
8044
|
+
prevNode = prev[prevEnd];
|
|
8045
|
+
nextNode = next[nextEnd];
|
|
8046
|
+
while (prevNode === nextNode) {
|
|
8047
|
+
prevEnd--;
|
|
8048
|
+
nextEnd--;
|
|
8049
|
+
if (i > prevEnd || i > nextEnd) {
|
|
8050
|
+
break outer;
|
|
7991
8051
|
}
|
|
7992
|
-
|
|
7993
|
-
|
|
8052
|
+
prevNode = prev[prevEnd];
|
|
8053
|
+
nextNode = next[nextEnd];
|
|
7994
8054
|
}
|
|
7995
|
-
return liveObj;
|
|
7996
8055
|
}
|
|
7997
|
-
|
|
7998
|
-
|
|
7999
|
-
|
|
8000
|
-
|
|
8001
|
-
|
|
8002
|
-
value._attach(pool.generateId(), pool);
|
|
8056
|
+
if (i > prevEnd) {
|
|
8057
|
+
if (i <= nextEnd) {
|
|
8058
|
+
while (i <= nextEnd) {
|
|
8059
|
+
liveList.insert(deepLiveify(next[i]), i);
|
|
8060
|
+
i++;
|
|
8003
8061
|
}
|
|
8004
8062
|
}
|
|
8005
|
-
}
|
|
8006
|
-
|
|
8007
|
-
|
|
8008
|
-
|
|
8009
|
-
|
|
8063
|
+
} else if (i > nextEnd) {
|
|
8064
|
+
let localI = i;
|
|
8065
|
+
while (localI <= prevEnd) {
|
|
8066
|
+
liveList.delete(i);
|
|
8067
|
+
localI++;
|
|
8010
8068
|
}
|
|
8011
|
-
|
|
8012
|
-
|
|
8013
|
-
|
|
8014
|
-
|
|
8015
|
-
|
|
8069
|
+
} else {
|
|
8070
|
+
while (i <= prevEnd && i <= nextEnd) {
|
|
8071
|
+
prevNode = prev[i];
|
|
8072
|
+
nextNode = next[i];
|
|
8073
|
+
const liveListNode = liveList.get(i);
|
|
8074
|
+
if (isLiveObject(liveListNode) && isPlainObject(prevNode) && isPlainObject(nextNode)) {
|
|
8075
|
+
legacy_patchLiveObject(liveListNode, prevNode, nextNode);
|
|
8076
|
+
} else {
|
|
8077
|
+
liveList.set(i, deepLiveify(nextNode));
|
|
8016
8078
|
}
|
|
8017
|
-
|
|
8079
|
+
i++;
|
|
8018
8080
|
}
|
|
8019
|
-
|
|
8020
|
-
|
|
8021
|
-
|
|
8022
|
-
} else if (this.#unackedOpsByKey.get(key) === opId) {
|
|
8023
|
-
this.#unackedOpsByKey.delete(key);
|
|
8024
|
-
return { modified: false };
|
|
8025
|
-
} else {
|
|
8026
|
-
return { modified: false };
|
|
8081
|
+
while (i <= nextEnd) {
|
|
8082
|
+
liveList.insert(deepLiveify(next[i]), i);
|
|
8083
|
+
i++;
|
|
8027
8084
|
}
|
|
8028
|
-
|
|
8029
|
-
|
|
8030
|
-
|
|
8031
|
-
|
|
8032
|
-
reverse = previousValue._toOps(thisId, key);
|
|
8033
|
-
previousValue._detach();
|
|
8034
|
-
} else if (previousValue === void 0) {
|
|
8035
|
-
reverse = [{ type: OpCode.DELETE_OBJECT_KEY, id: thisId, key }];
|
|
8036
|
-
} else {
|
|
8037
|
-
reverse = [
|
|
8038
|
-
{
|
|
8039
|
-
type: OpCode.UPDATE_OBJECT,
|
|
8040
|
-
id: thisId,
|
|
8041
|
-
data: { [key]: previousValue }
|
|
8042
|
-
}
|
|
8043
|
-
];
|
|
8044
|
-
}
|
|
8045
|
-
this.#map.set(key, child);
|
|
8046
|
-
this.invalidate();
|
|
8047
|
-
if (isLiveStructure(child)) {
|
|
8048
|
-
child._setParentLink(this, key);
|
|
8049
|
-
child._attach(id, this._pool);
|
|
8085
|
+
let localI = i;
|
|
8086
|
+
while (localI <= prevEnd) {
|
|
8087
|
+
liveList.delete(i);
|
|
8088
|
+
localI++;
|
|
8050
8089
|
}
|
|
8051
|
-
return {
|
|
8052
|
-
reverse,
|
|
8053
|
-
modified: {
|
|
8054
|
-
node: this,
|
|
8055
|
-
type: "LiveObject",
|
|
8056
|
-
updates: { [key]: { type: "update" } }
|
|
8057
|
-
}
|
|
8058
|
-
};
|
|
8059
8090
|
}
|
|
8060
|
-
|
|
8061
|
-
|
|
8062
|
-
|
|
8063
|
-
|
|
8064
|
-
|
|
8065
|
-
|
|
8066
|
-
|
|
8067
|
-
|
|
8068
|
-
|
|
8069
|
-
|
|
8070
|
-
|
|
8071
|
-
|
|
8072
|
-
child._detach();
|
|
8073
|
-
const storageUpdate = {
|
|
8074
|
-
node: this,
|
|
8075
|
-
type: "LiveObject",
|
|
8076
|
-
updates: {
|
|
8077
|
-
[parentKey]: { type: "delete" }
|
|
8078
|
-
}
|
|
8079
|
-
};
|
|
8080
|
-
return { modified: storageUpdate, reverse };
|
|
8091
|
+
}
|
|
8092
|
+
function legacy_patchLiveObjectKey(liveObject, key, prev, next) {
|
|
8093
|
+
if (process.env.NODE_ENV !== "production") {
|
|
8094
|
+
const nonSerializableValue = findNonSerializableValue(next);
|
|
8095
|
+
if (nonSerializableValue) {
|
|
8096
|
+
error2(
|
|
8097
|
+
`New state path: '${nonSerializableValue.path}' value: '${String(
|
|
8098
|
+
nonSerializableValue.value
|
|
8099
|
+
)}' is not serializable.
|
|
8100
|
+
Only serializable value can be synced with Liveblocks.`
|
|
8101
|
+
);
|
|
8102
|
+
return;
|
|
8081
8103
|
}
|
|
8082
|
-
return { modified: false };
|
|
8083
8104
|
}
|
|
8084
|
-
|
|
8085
|
-
|
|
8086
|
-
|
|
8087
|
-
|
|
8088
|
-
|
|
8089
|
-
|
|
8090
|
-
|
|
8105
|
+
const value = liveObject.get(key);
|
|
8106
|
+
if (next === void 0) {
|
|
8107
|
+
liveObject.delete(key);
|
|
8108
|
+
} else if (value === void 0) {
|
|
8109
|
+
liveObject.set(key, deepLiveify(next));
|
|
8110
|
+
} else if (prev === next) {
|
|
8111
|
+
return;
|
|
8112
|
+
} else if (isLiveList(value) && Array.isArray(prev) && Array.isArray(next)) {
|
|
8113
|
+
legacy_patchLiveList(value, prev, next);
|
|
8114
|
+
} else if (isLiveObject(value) && isPlainObject(prev) && isPlainObject(next)) {
|
|
8115
|
+
legacy_patchLiveObject(value, prev, next);
|
|
8116
|
+
} else {
|
|
8117
|
+
liveObject.set(key, deepLiveify(next));
|
|
8118
|
+
}
|
|
8119
|
+
}
|
|
8120
|
+
function legacy_patchLiveObject(root, prev, next) {
|
|
8121
|
+
const updates = {};
|
|
8122
|
+
for (const key in next) {
|
|
8123
|
+
legacy_patchLiveObjectKey(root, key, prev[key], next[key]);
|
|
8124
|
+
}
|
|
8125
|
+
for (const key in prev) {
|
|
8126
|
+
if (next[key] === void 0) {
|
|
8127
|
+
root.delete(key);
|
|
8091
8128
|
}
|
|
8092
8129
|
}
|
|
8093
|
-
|
|
8094
|
-
|
|
8095
|
-
|
|
8096
|
-
|
|
8097
|
-
|
|
8098
|
-
|
|
8130
|
+
if (Object.keys(updates).length > 0) {
|
|
8131
|
+
root.update(updates);
|
|
8132
|
+
}
|
|
8133
|
+
}
|
|
8134
|
+
function getParentsPath(node) {
|
|
8135
|
+
const path = [];
|
|
8136
|
+
while (node.parent.type === "HasParent") {
|
|
8137
|
+
if (isLiveList(node.parent.node)) {
|
|
8138
|
+
path.push(node.parent.node._indexOfPosition(node.parent.key));
|
|
8139
|
+
} else {
|
|
8140
|
+
path.push(node.parent.key);
|
|
8099
8141
|
}
|
|
8100
|
-
|
|
8142
|
+
node = node.parent.node;
|
|
8101
8143
|
}
|
|
8102
|
-
|
|
8103
|
-
|
|
8104
|
-
|
|
8105
|
-
|
|
8106
|
-
|
|
8107
|
-
|
|
8144
|
+
return path;
|
|
8145
|
+
}
|
|
8146
|
+
function legacy_patchImmutableObject(state, updates) {
|
|
8147
|
+
return updates.reduce(
|
|
8148
|
+
(state2, update) => legacy_patchImmutableObjectWithUpdate(state2, update),
|
|
8149
|
+
state
|
|
8150
|
+
);
|
|
8151
|
+
}
|
|
8152
|
+
function legacy_patchImmutableObjectWithUpdate(state, update) {
|
|
8153
|
+
const path = getParentsPath(update.node);
|
|
8154
|
+
return legacy_patchImmutableNode(state, path, update);
|
|
8155
|
+
}
|
|
8156
|
+
function legacy_patchImmutableNode(state, path, update) {
|
|
8157
|
+
const pathItem = path.pop();
|
|
8158
|
+
if (pathItem === void 0) {
|
|
8159
|
+
switch (update.type) {
|
|
8160
|
+
case "LiveObject": {
|
|
8161
|
+
if (!isJsonObject(state)) {
|
|
8162
|
+
throw new Error(
|
|
8163
|
+
"Internal: received update on LiveObject but state was not an object"
|
|
8164
|
+
);
|
|
8165
|
+
}
|
|
8166
|
+
const newState = Object.assign({}, state);
|
|
8167
|
+
for (const key in update.updates) {
|
|
8168
|
+
if (update.updates[key]?.type === "update") {
|
|
8169
|
+
const val = update.node.get(key);
|
|
8170
|
+
if (val !== void 0) {
|
|
8171
|
+
newState[key] = lsonToJson(val);
|
|
8172
|
+
}
|
|
8173
|
+
} else if (update.updates[key]?.type === "delete") {
|
|
8174
|
+
delete newState[key];
|
|
8175
|
+
}
|
|
8176
|
+
}
|
|
8177
|
+
return newState;
|
|
8178
|
+
}
|
|
8179
|
+
case "LiveList": {
|
|
8180
|
+
if (!Array.isArray(state)) {
|
|
8181
|
+
throw new Error(
|
|
8182
|
+
"Internal: received update on LiveList but state was not an array"
|
|
8183
|
+
);
|
|
8184
|
+
}
|
|
8185
|
+
let newState = state.map((x) => x);
|
|
8186
|
+
for (const listUpdate of update.updates) {
|
|
8187
|
+
if (listUpdate.type === "set") {
|
|
8188
|
+
newState = newState.map(
|
|
8189
|
+
(item, index) => index === listUpdate.index ? lsonToJson(listUpdate.item) : item
|
|
8190
|
+
);
|
|
8191
|
+
} else if (listUpdate.type === "insert") {
|
|
8192
|
+
if (listUpdate.index === newState.length) {
|
|
8193
|
+
newState.push(lsonToJson(listUpdate.item));
|
|
8194
|
+
} else {
|
|
8195
|
+
newState = [
|
|
8196
|
+
...newState.slice(0, listUpdate.index),
|
|
8197
|
+
lsonToJson(listUpdate.item),
|
|
8198
|
+
...newState.slice(listUpdate.index)
|
|
8199
|
+
];
|
|
8200
|
+
}
|
|
8201
|
+
} else if (listUpdate.type === "delete") {
|
|
8202
|
+
newState.splice(listUpdate.index, 1);
|
|
8203
|
+
} else if (listUpdate.type === "move") {
|
|
8204
|
+
if (listUpdate.previousIndex > listUpdate.index) {
|
|
8205
|
+
newState = [
|
|
8206
|
+
...newState.slice(0, listUpdate.index),
|
|
8207
|
+
lsonToJson(listUpdate.item),
|
|
8208
|
+
...newState.slice(listUpdate.index, listUpdate.previousIndex),
|
|
8209
|
+
...newState.slice(listUpdate.previousIndex + 1)
|
|
8210
|
+
];
|
|
8211
|
+
} else {
|
|
8212
|
+
newState = [
|
|
8213
|
+
...newState.slice(0, listUpdate.previousIndex),
|
|
8214
|
+
...newState.slice(
|
|
8215
|
+
listUpdate.previousIndex + 1,
|
|
8216
|
+
listUpdate.index + 1
|
|
8217
|
+
),
|
|
8218
|
+
lsonToJson(listUpdate.item),
|
|
8219
|
+
...newState.slice(listUpdate.index + 1)
|
|
8220
|
+
];
|
|
8221
|
+
}
|
|
8222
|
+
}
|
|
8223
|
+
}
|
|
8224
|
+
return newState;
|
|
8225
|
+
}
|
|
8226
|
+
case "LiveMap": {
|
|
8227
|
+
if (!isJsonObject(state)) {
|
|
8228
|
+
throw new Error(
|
|
8229
|
+
"Internal: received update on LiveMap but state was not an object"
|
|
8230
|
+
);
|
|
8231
|
+
}
|
|
8232
|
+
const newState = Object.assign({}, state);
|
|
8233
|
+
for (const key in update.updates) {
|
|
8234
|
+
if (update.updates[key]?.type === "update") {
|
|
8235
|
+
const value = update.node.get(key);
|
|
8236
|
+
if (value !== void 0) {
|
|
8237
|
+
newState[key] = lsonToJson(value);
|
|
8238
|
+
}
|
|
8239
|
+
} else if (update.updates[key]?.type === "delete") {
|
|
8240
|
+
delete newState[key];
|
|
8241
|
+
}
|
|
8242
|
+
}
|
|
8243
|
+
return newState;
|
|
8108
8244
|
}
|
|
8109
8245
|
}
|
|
8110
|
-
|
|
8111
|
-
|
|
8112
|
-
|
|
8113
|
-
|
|
8114
|
-
|
|
8115
|
-
|
|
8116
|
-
|
|
8246
|
+
}
|
|
8247
|
+
if (Array.isArray(state)) {
|
|
8248
|
+
const newArray = [...state];
|
|
8249
|
+
newArray[pathItem] = legacy_patchImmutableNode(
|
|
8250
|
+
state[pathItem],
|
|
8251
|
+
path,
|
|
8252
|
+
update
|
|
8253
|
+
);
|
|
8254
|
+
return newArray;
|
|
8255
|
+
} else if (isJsonObject(state)) {
|
|
8256
|
+
const node = state[pathItem];
|
|
8257
|
+
if (node === void 0) {
|
|
8258
|
+
return state;
|
|
8117
8259
|
} else {
|
|
8260
|
+
const stateAsObj = state;
|
|
8118
8261
|
return {
|
|
8119
|
-
|
|
8120
|
-
|
|
8262
|
+
...stateAsObj,
|
|
8263
|
+
[pathItem]: legacy_patchImmutableNode(node, path, update)
|
|
8121
8264
|
};
|
|
8122
8265
|
}
|
|
8266
|
+
} else {
|
|
8267
|
+
return state;
|
|
8123
8268
|
}
|
|
8124
|
-
|
|
8125
|
-
|
|
8126
|
-
|
|
8127
|
-
|
|
8128
|
-
|
|
8129
|
-
|
|
8130
|
-
|
|
8131
|
-
|
|
8132
|
-
|
|
8133
|
-
|
|
8134
|
-
|
|
8135
|
-
|
|
8136
|
-
|
|
8137
|
-
|
|
8138
|
-
|
|
8139
|
-
|
|
8140
|
-
|
|
8141
|
-
|
|
8142
|
-
|
|
8269
|
+
}
|
|
8270
|
+
|
|
8271
|
+
// src/crdts/LiveObject.ts
|
|
8272
|
+
var MAX_LIVE_OBJECT_SIZE = 128 * 1024;
|
|
8273
|
+
var LiveObject = class _LiveObject extends AbstractCrdt {
|
|
8274
|
+
#synced;
|
|
8275
|
+
#local = /* @__PURE__ */ new Map();
|
|
8276
|
+
/**
|
|
8277
|
+
* Tracks unacknowledged local changes per property to preserve optimistic
|
|
8278
|
+
* updates. Maps property keys to their pending operation IDs.
|
|
8279
|
+
*
|
|
8280
|
+
* INVARIANT: Only locally-generated opIds are ever stored here. Remote opIds
|
|
8281
|
+
* are only compared against (to detect ACKs), never stored.
|
|
8282
|
+
*
|
|
8283
|
+
* When a local change is made, the opId is stored here. When a remote op
|
|
8284
|
+
* arrives for the same key:
|
|
8285
|
+
* - If no entry exists → apply remote op
|
|
8286
|
+
* - If opId matches → it's an ACK, clear the entry
|
|
8287
|
+
* - If opId differs → ignore remote op to preserve optimistic update
|
|
8288
|
+
*/
|
|
8289
|
+
#unackedOpsByKey;
|
|
8290
|
+
/**
|
|
8291
|
+
* Enable or disable detection of too large LiveObjects.
|
|
8292
|
+
* When enabled, throws an error if LiveObject static data exceeds 128KB, which
|
|
8293
|
+
* is the maximum value the server will be able to accept.
|
|
8294
|
+
* By default, this behavior is disabled to avoid the runtime performance
|
|
8295
|
+
* overhead on every LiveObject.set() or LiveObject.update() call.
|
|
8296
|
+
*
|
|
8297
|
+
* @experimental
|
|
8298
|
+
*/
|
|
8299
|
+
static detectLargeObjects = false;
|
|
8300
|
+
static #buildRootAndParentToChildren(nodes) {
|
|
8301
|
+
const parentToChildren = /* @__PURE__ */ new Map();
|
|
8302
|
+
let root = null;
|
|
8303
|
+
for (const node of nodes) {
|
|
8304
|
+
if (isRootStorageNode(node)) {
|
|
8305
|
+
root = node[1];
|
|
8306
|
+
} else {
|
|
8307
|
+
const crdt = node[1];
|
|
8308
|
+
const children = parentToChildren.get(crdt.parentId);
|
|
8309
|
+
if (children !== void 0) {
|
|
8310
|
+
children.push(node);
|
|
8311
|
+
} else {
|
|
8312
|
+
parentToChildren.set(crdt.parentId, [node]);
|
|
8313
|
+
}
|
|
8314
|
+
}
|
|
8315
|
+
}
|
|
8316
|
+
if (root === null) {
|
|
8317
|
+
throw new Error("Root can't be null");
|
|
8318
|
+
}
|
|
8319
|
+
return [root, parentToChildren];
|
|
8320
|
+
}
|
|
8321
|
+
/** @private Do not use this API directly */
|
|
8322
|
+
static _fromItems(nodes, pool) {
|
|
8323
|
+
const [root, parentToChildren] = _LiveObject.#buildRootAndParentToChildren(nodes);
|
|
8324
|
+
return _LiveObject._deserialize(
|
|
8325
|
+
["root", root],
|
|
8326
|
+
parentToChildren,
|
|
8327
|
+
pool
|
|
8328
|
+
);
|
|
8329
|
+
}
|
|
8330
|
+
constructor(obj = {}) {
|
|
8331
|
+
super();
|
|
8332
|
+
this.#unackedOpsByKey = /* @__PURE__ */ new Map();
|
|
8333
|
+
const o = compactObject(obj);
|
|
8334
|
+
for (const key of Object.keys(o)) {
|
|
8335
|
+
const value = o[key];
|
|
8336
|
+
if (isLiveNode(value)) {
|
|
8337
|
+
value._setParentLink(this, key);
|
|
8338
|
+
}
|
|
8339
|
+
}
|
|
8340
|
+
this.#synced = new Map(Object.entries(o));
|
|
8341
|
+
}
|
|
8342
|
+
/** @internal */
|
|
8343
|
+
_toOps(parentId, parentKey) {
|
|
8344
|
+
if (this._id === void 0) {
|
|
8345
|
+
throw new Error("Cannot serialize item is not attached");
|
|
8346
|
+
}
|
|
8347
|
+
const ops = [];
|
|
8348
|
+
const op = {
|
|
8349
|
+
type: OpCode.CREATE_OBJECT,
|
|
8350
|
+
id: this._id,
|
|
8351
|
+
parentId,
|
|
8352
|
+
parentKey,
|
|
8353
|
+
data: {}
|
|
8354
|
+
};
|
|
8355
|
+
ops.push(op);
|
|
8356
|
+
for (const [key, value] of this.#synced) {
|
|
8357
|
+
if (isLiveNode(value)) {
|
|
8358
|
+
for (const childOp of value._toOps(this._id, key)) {
|
|
8359
|
+
ops.push(childOp);
|
|
8360
|
+
}
|
|
8361
|
+
} else {
|
|
8362
|
+
op.data[key] = value;
|
|
8363
|
+
}
|
|
8364
|
+
}
|
|
8365
|
+
return ops;
|
|
8366
|
+
}
|
|
8367
|
+
/** @internal */
|
|
8368
|
+
static _deserialize([id, item], parentToChildren, pool) {
|
|
8369
|
+
const liveObj = new _LiveObject(item.data);
|
|
8370
|
+
liveObj._attach(id, pool);
|
|
8371
|
+
return this._deserializeChildren(liveObj, parentToChildren, pool);
|
|
8372
|
+
}
|
|
8373
|
+
/** @internal */
|
|
8374
|
+
static _deserializeChildren(liveObj, parentToChildren, pool) {
|
|
8375
|
+
const children = parentToChildren.get(nn(liveObj._id));
|
|
8376
|
+
if (children === void 0) {
|
|
8377
|
+
return liveObj;
|
|
8378
|
+
}
|
|
8379
|
+
for (const node of children) {
|
|
8380
|
+
const child = deserializeToLson(node, parentToChildren, pool);
|
|
8381
|
+
const crdt = node[1];
|
|
8382
|
+
if (isLiveStructure(child)) {
|
|
8383
|
+
child._setParentLink(liveObj, crdt.parentKey);
|
|
8384
|
+
}
|
|
8385
|
+
liveObj.#synced.set(crdt.parentKey, child);
|
|
8386
|
+
liveObj.invalidate();
|
|
8387
|
+
}
|
|
8388
|
+
return liveObj;
|
|
8389
|
+
}
|
|
8390
|
+
/** @internal */
|
|
8391
|
+
_attach(id, pool) {
|
|
8392
|
+
super._attach(id, pool);
|
|
8393
|
+
for (const [_key, value] of this.#synced) {
|
|
8394
|
+
if (isLiveNode(value)) {
|
|
8395
|
+
value._attach(pool.generateId(), pool);
|
|
8396
|
+
}
|
|
8397
|
+
}
|
|
8398
|
+
}
|
|
8399
|
+
/** @internal */
|
|
8400
|
+
_attachChild(op, source) {
|
|
8401
|
+
if (this._pool === void 0) {
|
|
8402
|
+
throw new Error("Can't attach child if managed pool is not present");
|
|
8403
|
+
}
|
|
8404
|
+
const { id, opId, parentKey: key } = op;
|
|
8405
|
+
const child = creationOpToLson(op);
|
|
8406
|
+
if (this._pool.getNode(id) !== void 0) {
|
|
8407
|
+
if (this.#unackedOpsByKey.get(key) === opId) {
|
|
8408
|
+
this.#unackedOpsByKey.delete(key);
|
|
8409
|
+
}
|
|
8410
|
+
return { modified: false };
|
|
8411
|
+
}
|
|
8412
|
+
if (source === 0 /* LOCAL */) {
|
|
8413
|
+
this.#unackedOpsByKey.set(key, nn(opId));
|
|
8414
|
+
} else if (this.#unackedOpsByKey.get(key) === void 0) {
|
|
8415
|
+
} else if (this.#unackedOpsByKey.get(key) === opId) {
|
|
8416
|
+
this.#unackedOpsByKey.delete(key);
|
|
8417
|
+
return { modified: false };
|
|
8418
|
+
} else {
|
|
8419
|
+
return { modified: false };
|
|
8420
|
+
}
|
|
8421
|
+
const thisId = nn(this._id);
|
|
8422
|
+
const previousValue = this.#synced.get(key);
|
|
8423
|
+
let reverse;
|
|
8424
|
+
if (isLiveNode(previousValue)) {
|
|
8425
|
+
reverse = previousValue._toOps(thisId, key);
|
|
8426
|
+
previousValue._detach();
|
|
8427
|
+
} else if (previousValue === void 0) {
|
|
8428
|
+
reverse = [{ type: OpCode.DELETE_OBJECT_KEY, id: thisId, key }];
|
|
8429
|
+
} else {
|
|
8430
|
+
reverse = [
|
|
8431
|
+
{
|
|
8432
|
+
type: OpCode.UPDATE_OBJECT,
|
|
8433
|
+
id: thisId,
|
|
8434
|
+
data: { [key]: previousValue }
|
|
8435
|
+
}
|
|
8436
|
+
];
|
|
8437
|
+
}
|
|
8438
|
+
this.#local.delete(key);
|
|
8439
|
+
this.#synced.set(key, child);
|
|
8440
|
+
this.invalidate();
|
|
8441
|
+
if (isLiveStructure(child)) {
|
|
8442
|
+
child._setParentLink(this, key);
|
|
8443
|
+
child._attach(id, this._pool);
|
|
8444
|
+
}
|
|
8445
|
+
return {
|
|
8446
|
+
reverse,
|
|
8447
|
+
modified: {
|
|
8448
|
+
node: this,
|
|
8449
|
+
type: "LiveObject",
|
|
8450
|
+
updates: { [key]: { type: "update" } }
|
|
8451
|
+
}
|
|
8452
|
+
};
|
|
8453
|
+
}
|
|
8454
|
+
/** @internal */
|
|
8455
|
+
_detachChild(child) {
|
|
8456
|
+
if (child) {
|
|
8457
|
+
const id = nn(this._id);
|
|
8458
|
+
const parentKey = nn(child._parentKey);
|
|
8459
|
+
const reverse = child._toOps(id, parentKey);
|
|
8460
|
+
for (const [key, value] of this.#synced) {
|
|
8461
|
+
if (value === child) {
|
|
8462
|
+
this.#synced.delete(key);
|
|
8463
|
+
this.invalidate();
|
|
8464
|
+
}
|
|
8465
|
+
}
|
|
8466
|
+
child._detach();
|
|
8467
|
+
const storageUpdate = {
|
|
8468
|
+
node: this,
|
|
8469
|
+
type: "LiveObject",
|
|
8470
|
+
updates: {
|
|
8471
|
+
[parentKey]: { type: "delete" }
|
|
8472
|
+
}
|
|
8473
|
+
};
|
|
8474
|
+
return { modified: storageUpdate, reverse };
|
|
8475
|
+
}
|
|
8476
|
+
return { modified: false };
|
|
8477
|
+
}
|
|
8478
|
+
/** @internal */
|
|
8479
|
+
_detach() {
|
|
8480
|
+
super._detach();
|
|
8481
|
+
for (const value of this.#synced.values()) {
|
|
8482
|
+
if (isLiveNode(value)) {
|
|
8483
|
+
value._detach();
|
|
8484
|
+
}
|
|
8485
|
+
}
|
|
8486
|
+
}
|
|
8487
|
+
/** @internal */
|
|
8488
|
+
_apply(op, isLocal) {
|
|
8489
|
+
if (op.type === OpCode.UPDATE_OBJECT) {
|
|
8490
|
+
return this.#applyUpdate(op, isLocal);
|
|
8491
|
+
} else if (op.type === OpCode.DELETE_OBJECT_KEY) {
|
|
8492
|
+
return this.#applyDeleteObjectKey(op, isLocal);
|
|
8493
|
+
}
|
|
8494
|
+
return super._apply(op, isLocal);
|
|
8495
|
+
}
|
|
8496
|
+
/** @internal */
|
|
8497
|
+
_serialize() {
|
|
8498
|
+
const data = {};
|
|
8499
|
+
for (const [key, value] of this.#synced) {
|
|
8500
|
+
if (!isLiveNode(value)) {
|
|
8501
|
+
data[key] = value;
|
|
8502
|
+
}
|
|
8503
|
+
}
|
|
8504
|
+
if (this.parent.type === "HasParent" && this.parent.node._id) {
|
|
8505
|
+
return {
|
|
8506
|
+
type: CrdtType.OBJECT,
|
|
8507
|
+
parentId: this.parent.node._id,
|
|
8508
|
+
parentKey: this.parent.key,
|
|
8509
|
+
data
|
|
8510
|
+
};
|
|
8511
|
+
} else {
|
|
8512
|
+
return {
|
|
8513
|
+
type: CrdtType.OBJECT,
|
|
8514
|
+
data
|
|
8515
|
+
};
|
|
8516
|
+
}
|
|
8517
|
+
}
|
|
8518
|
+
#applyUpdate(op, isLocal) {
|
|
8519
|
+
let isModified = false;
|
|
8520
|
+
const id = nn(this._id);
|
|
8521
|
+
const reverse = [];
|
|
8522
|
+
const reverseUpdate = {
|
|
8523
|
+
type: OpCode.UPDATE_OBJECT,
|
|
8524
|
+
id,
|
|
8525
|
+
data: {}
|
|
8526
|
+
};
|
|
8527
|
+
for (const key in op.data) {
|
|
8528
|
+
const oldValue = this.#synced.get(key);
|
|
8529
|
+
if (isLiveNode(oldValue)) {
|
|
8530
|
+
for (const childOp of oldValue._toOps(id, key)) {
|
|
8531
|
+
reverse.push(childOp);
|
|
8532
|
+
}
|
|
8533
|
+
oldValue._detach();
|
|
8534
|
+
} else if (oldValue !== void 0) {
|
|
8535
|
+
reverseUpdate.data[key] = oldValue;
|
|
8536
|
+
} else if (oldValue === void 0) {
|
|
8143
8537
|
reverse.push({ type: OpCode.DELETE_OBJECT_KEY, id, key });
|
|
8144
8538
|
}
|
|
8145
8539
|
}
|
|
@@ -8159,13 +8553,14 @@ var LiveObject = class _LiveObject extends AbstractCrdt {
|
|
|
8159
8553
|
} else {
|
|
8160
8554
|
continue;
|
|
8161
8555
|
}
|
|
8162
|
-
const oldValue = this.#
|
|
8556
|
+
const oldValue = this.#synced.get(key);
|
|
8163
8557
|
if (isLiveNode(oldValue)) {
|
|
8164
8558
|
oldValue._detach();
|
|
8165
8559
|
}
|
|
8166
8560
|
isModified = true;
|
|
8167
8561
|
updateDelta[key] = { type: "update" };
|
|
8168
|
-
this.#
|
|
8562
|
+
this.#local.delete(key);
|
|
8563
|
+
this.#synced.set(key, value);
|
|
8169
8564
|
this.invalidate();
|
|
8170
8565
|
}
|
|
8171
8566
|
if (Object.keys(reverseUpdate.data).length !== 0) {
|
|
@@ -8182,7 +8577,7 @@ var LiveObject = class _LiveObject extends AbstractCrdt {
|
|
|
8182
8577
|
}
|
|
8183
8578
|
#applyDeleteObjectKey(op, isLocal) {
|
|
8184
8579
|
const key = op.key;
|
|
8185
|
-
const oldValue = this.#
|
|
8580
|
+
const oldValue = this.#synced.get(key);
|
|
8186
8581
|
if (oldValue === void 0) {
|
|
8187
8582
|
return { modified: false };
|
|
8188
8583
|
}
|
|
@@ -8203,7 +8598,8 @@ var LiveObject = class _LiveObject extends AbstractCrdt {
|
|
|
8203
8598
|
}
|
|
8204
8599
|
];
|
|
8205
8600
|
}
|
|
8206
|
-
this.#
|
|
8601
|
+
this.#local.delete(key);
|
|
8602
|
+
this.#synced.delete(key);
|
|
8207
8603
|
this.invalidate();
|
|
8208
8604
|
return {
|
|
8209
8605
|
modified: {
|
|
@@ -8216,11 +8612,23 @@ var LiveObject = class _LiveObject extends AbstractCrdt {
|
|
|
8216
8612
|
reverse
|
|
8217
8613
|
};
|
|
8218
8614
|
}
|
|
8615
|
+
/** @private */
|
|
8616
|
+
keys() {
|
|
8617
|
+
const result = new Set(this.#synced.keys());
|
|
8618
|
+
for (const key of this.#local.keys()) {
|
|
8619
|
+
result.add(key);
|
|
8620
|
+
}
|
|
8621
|
+
return result;
|
|
8622
|
+
}
|
|
8219
8623
|
/**
|
|
8220
8624
|
* Transform the LiveObject into a javascript object
|
|
8221
8625
|
*/
|
|
8222
8626
|
toObject() {
|
|
8223
|
-
|
|
8627
|
+
const result = Object.fromEntries(this.#synced);
|
|
8628
|
+
for (const [key, value] of this.#local) {
|
|
8629
|
+
result[key] = value;
|
|
8630
|
+
}
|
|
8631
|
+
return result;
|
|
8224
8632
|
}
|
|
8225
8633
|
/**
|
|
8226
8634
|
* Adds or updates a property with a specified key and a value.
|
|
@@ -8228,49 +8636,109 @@ var LiveObject = class _LiveObject extends AbstractCrdt {
|
|
|
8228
8636
|
* @param value The value of the property to add
|
|
8229
8637
|
*/
|
|
8230
8638
|
set(key, value) {
|
|
8231
|
-
this._pool?.assertStorageIsWritable();
|
|
8232
8639
|
this.update({ [key]: value });
|
|
8233
8640
|
}
|
|
8641
|
+
/**
|
|
8642
|
+
* @experimental
|
|
8643
|
+
*
|
|
8644
|
+
* Sets a local-only property that is not synchronized over the wire.
|
|
8645
|
+
* The value will be visible via get(), toObject(), and toImmutable() on
|
|
8646
|
+
* this client only. Other clients and the server will see `undefined`
|
|
8647
|
+
* for this key.
|
|
8648
|
+
*
|
|
8649
|
+
* Caveat: this method will not add changes to the undo/redo stack.
|
|
8650
|
+
*/
|
|
8651
|
+
setLocal(key, value) {
|
|
8652
|
+
this._pool?.assertStorageIsWritable();
|
|
8653
|
+
const deleteResult = this.#prepareDelete(key);
|
|
8654
|
+
this.#local.set(key, value);
|
|
8655
|
+
this.invalidate();
|
|
8656
|
+
if (this._pool !== void 0 && this._id !== void 0) {
|
|
8657
|
+
const ops = deleteResult?.[0] ?? [];
|
|
8658
|
+
const reverse = deleteResult?.[1] ?? [];
|
|
8659
|
+
const storageUpdates = deleteResult?.[2] ?? /* @__PURE__ */ new Map();
|
|
8660
|
+
const existing = storageUpdates.get(this._id);
|
|
8661
|
+
storageUpdates.set(this._id, {
|
|
8662
|
+
node: this,
|
|
8663
|
+
type: "LiveObject",
|
|
8664
|
+
updates: {
|
|
8665
|
+
...existing?.updates,
|
|
8666
|
+
[key]: { type: "update" }
|
|
8667
|
+
}
|
|
8668
|
+
});
|
|
8669
|
+
this._pool.dispatch(ops, reverse, storageUpdates);
|
|
8670
|
+
}
|
|
8671
|
+
}
|
|
8234
8672
|
/**
|
|
8235
8673
|
* Returns a specified property from the LiveObject.
|
|
8236
8674
|
* @param key The key of the property to get
|
|
8237
8675
|
*/
|
|
8238
8676
|
get(key) {
|
|
8239
|
-
return this.#
|
|
8677
|
+
return this.#local.has(key) ? this.#local.get(key) : this.#synced.get(key);
|
|
8240
8678
|
}
|
|
8241
8679
|
/**
|
|
8242
|
-
*
|
|
8243
|
-
*
|
|
8680
|
+
* Removes a synced key, returning the ops, reverse ops, and storage updates
|
|
8681
|
+
* needed to notify the pool. Returns null if the key doesn't exist in
|
|
8682
|
+
* #synced or pool/id are unavailable. Does NOT dispatch.
|
|
8244
8683
|
*/
|
|
8245
|
-
|
|
8684
|
+
#prepareDelete(key) {
|
|
8246
8685
|
this._pool?.assertStorageIsWritable();
|
|
8247
|
-
const
|
|
8248
|
-
|
|
8686
|
+
const k = key;
|
|
8687
|
+
if (this.#local.has(k) && !this.#synced.has(k)) {
|
|
8688
|
+
const oldValue2 = this.#local.get(k);
|
|
8689
|
+
this.#local.delete(k);
|
|
8690
|
+
this.invalidate();
|
|
8691
|
+
if (this._pool !== void 0 && this._id !== void 0) {
|
|
8692
|
+
const storageUpdates2 = /* @__PURE__ */ new Map();
|
|
8693
|
+
storageUpdates2.set(this._id, {
|
|
8694
|
+
node: this,
|
|
8695
|
+
type: "LiveObject",
|
|
8696
|
+
updates: {
|
|
8697
|
+
[k]: {
|
|
8698
|
+
type: "delete",
|
|
8699
|
+
deletedItem: oldValue2
|
|
8700
|
+
}
|
|
8701
|
+
}
|
|
8702
|
+
});
|
|
8703
|
+
return [[], [], storageUpdates2];
|
|
8704
|
+
}
|
|
8705
|
+
return null;
|
|
8706
|
+
}
|
|
8707
|
+
this.#local.delete(k);
|
|
8708
|
+
const oldValue = this.#synced.get(k);
|
|
8249
8709
|
if (oldValue === void 0) {
|
|
8250
|
-
return;
|
|
8710
|
+
return null;
|
|
8251
8711
|
}
|
|
8252
8712
|
if (this._pool === void 0 || this._id === void 0) {
|
|
8253
8713
|
if (isLiveNode(oldValue)) {
|
|
8254
8714
|
oldValue._detach();
|
|
8255
8715
|
}
|
|
8256
|
-
this.#
|
|
8716
|
+
this.#synced.delete(k);
|
|
8257
8717
|
this.invalidate();
|
|
8258
|
-
return;
|
|
8718
|
+
return null;
|
|
8259
8719
|
}
|
|
8720
|
+
const ops = [
|
|
8721
|
+
{
|
|
8722
|
+
type: OpCode.DELETE_OBJECT_KEY,
|
|
8723
|
+
key: k,
|
|
8724
|
+
id: this._id,
|
|
8725
|
+
opId: this._pool.generateOpId()
|
|
8726
|
+
}
|
|
8727
|
+
];
|
|
8260
8728
|
let reverse;
|
|
8261
8729
|
if (isLiveNode(oldValue)) {
|
|
8262
8730
|
oldValue._detach();
|
|
8263
|
-
reverse = oldValue._toOps(this._id,
|
|
8731
|
+
reverse = oldValue._toOps(this._id, k);
|
|
8264
8732
|
} else {
|
|
8265
8733
|
reverse = [
|
|
8266
8734
|
{
|
|
8267
8735
|
type: OpCode.UPDATE_OBJECT,
|
|
8268
|
-
data: { [
|
|
8736
|
+
data: { [k]: oldValue },
|
|
8269
8737
|
id: this._id
|
|
8270
8738
|
}
|
|
8271
8739
|
];
|
|
8272
8740
|
}
|
|
8273
|
-
this.#
|
|
8741
|
+
this.#synced.delete(k);
|
|
8274
8742
|
this.invalidate();
|
|
8275
8743
|
const storageUpdates = /* @__PURE__ */ new Map();
|
|
8276
8744
|
storageUpdates.set(this._id, {
|
|
@@ -8280,18 +8748,18 @@ var LiveObject = class _LiveObject extends AbstractCrdt {
|
|
|
8280
8748
|
[key]: { type: "delete", deletedItem: oldValue }
|
|
8281
8749
|
}
|
|
8282
8750
|
});
|
|
8283
|
-
|
|
8284
|
-
|
|
8285
|
-
|
|
8286
|
-
|
|
8287
|
-
|
|
8288
|
-
|
|
8289
|
-
|
|
8290
|
-
|
|
8291
|
-
|
|
8292
|
-
reverse,
|
|
8293
|
-
storageUpdates
|
|
8294
|
-
|
|
8751
|
+
return [ops, reverse, storageUpdates];
|
|
8752
|
+
}
|
|
8753
|
+
/**
|
|
8754
|
+
* Deletes a key from the LiveObject
|
|
8755
|
+
* @param key The key of the property to delete
|
|
8756
|
+
*/
|
|
8757
|
+
delete(key) {
|
|
8758
|
+
const result = this.#prepareDelete(key);
|
|
8759
|
+
if (result) {
|
|
8760
|
+
const [ops, reverse, storageUpdates] = result;
|
|
8761
|
+
this._pool?.dispatch(ops, reverse, storageUpdates);
|
|
8762
|
+
}
|
|
8295
8763
|
}
|
|
8296
8764
|
/**
|
|
8297
8765
|
* Adds or updates multiple properties at once with an object.
|
|
@@ -8301,7 +8769,7 @@ var LiveObject = class _LiveObject extends AbstractCrdt {
|
|
|
8301
8769
|
this._pool?.assertStorageIsWritable();
|
|
8302
8770
|
if (_LiveObject.detectLargeObjects) {
|
|
8303
8771
|
const data = {};
|
|
8304
|
-
for (const [key, value] of this.#
|
|
8772
|
+
for (const [key, value] of this.#synced) {
|
|
8305
8773
|
if (!isLiveNode(value)) {
|
|
8306
8774
|
data[key] = value;
|
|
8307
8775
|
}
|
|
@@ -8330,14 +8798,15 @@ var LiveObject = class _LiveObject extends AbstractCrdt {
|
|
|
8330
8798
|
if (newValue === void 0) {
|
|
8331
8799
|
continue;
|
|
8332
8800
|
}
|
|
8333
|
-
const oldValue = this.#
|
|
8801
|
+
const oldValue = this.#synced.get(key);
|
|
8334
8802
|
if (isLiveNode(oldValue)) {
|
|
8335
8803
|
oldValue._detach();
|
|
8336
8804
|
}
|
|
8337
8805
|
if (isLiveNode(newValue)) {
|
|
8338
8806
|
newValue._setParentLink(this, key);
|
|
8339
8807
|
}
|
|
8340
|
-
this.#
|
|
8808
|
+
this.#local.delete(key);
|
|
8809
|
+
this.#synced.set(key, newValue);
|
|
8341
8810
|
this.invalidate();
|
|
8342
8811
|
}
|
|
8343
8812
|
return;
|
|
@@ -8357,7 +8826,7 @@ var LiveObject = class _LiveObject extends AbstractCrdt {
|
|
|
8357
8826
|
if (newValue === void 0) {
|
|
8358
8827
|
continue;
|
|
8359
8828
|
}
|
|
8360
|
-
const oldValue = this.#
|
|
8829
|
+
const oldValue = this.#synced.get(key);
|
|
8361
8830
|
if (isLiveNode(oldValue)) {
|
|
8362
8831
|
for (const childOp of oldValue._toOps(this._id, key)) {
|
|
8363
8832
|
reverseOps.push(childOp);
|
|
@@ -8389,7 +8858,8 @@ var LiveObject = class _LiveObject extends AbstractCrdt {
|
|
|
8389
8858
|
updatedProps[key] = newValue;
|
|
8390
8859
|
this.#unackedOpsByKey.set(key, opId);
|
|
8391
8860
|
}
|
|
8392
|
-
this.#
|
|
8861
|
+
this.#local.delete(key);
|
|
8862
|
+
this.#synced.set(key, newValue);
|
|
8393
8863
|
this.invalidate();
|
|
8394
8864
|
updateDelta[key] = { type: "update" };
|
|
8395
8865
|
}
|
|
@@ -8412,6 +8882,19 @@ var LiveObject = class _LiveObject extends AbstractCrdt {
|
|
|
8412
8882
|
});
|
|
8413
8883
|
this._pool.dispatch(ops, reverseOps, storageUpdates);
|
|
8414
8884
|
}
|
|
8885
|
+
/**
|
|
8886
|
+
* Reconciles a LiveObject tree to match the given JSON object and sync
|
|
8887
|
+
* config. Only mutates keys that actually changed. Recursively reconciles
|
|
8888
|
+
* the entire Live tree below it.
|
|
8889
|
+
*/
|
|
8890
|
+
reconcile(jsonObj, config) {
|
|
8891
|
+
if (this.immutableIs(jsonObj)) return;
|
|
8892
|
+
if (!isPlainObject(jsonObj))
|
|
8893
|
+
throw new Error(
|
|
8894
|
+
"Reconciling the document root expects a plain object value"
|
|
8895
|
+
);
|
|
8896
|
+
reconcileLiveObject(this, jsonObj, config);
|
|
8897
|
+
}
|
|
8415
8898
|
toImmutable() {
|
|
8416
8899
|
return super.toImmutable();
|
|
8417
8900
|
}
|
|
@@ -8426,7 +8909,7 @@ var LiveObject = class _LiveObject extends AbstractCrdt {
|
|
|
8426
8909
|
type: "LiveObject",
|
|
8427
8910
|
id: nodeId,
|
|
8428
8911
|
key,
|
|
8429
|
-
payload: Array.from(this.#
|
|
8912
|
+
payload: Array.from(this.#synced.entries()).map(
|
|
8430
8913
|
([key2, value]) => isLiveNode(value) ? value.toTreeNode(key2) : { type: "Json", id: `${nodeId}:${key2}`, key: key2, payload: value }
|
|
8431
8914
|
)
|
|
8432
8915
|
};
|
|
@@ -8434,20 +8917,27 @@ var LiveObject = class _LiveObject extends AbstractCrdt {
|
|
|
8434
8917
|
/** @internal */
|
|
8435
8918
|
_toImmutable() {
|
|
8436
8919
|
const result = {};
|
|
8437
|
-
for (const [key, val] of this.#
|
|
8920
|
+
for (const [key, val] of this.#synced) {
|
|
8438
8921
|
result[key] = isLiveStructure(val) ? val.toImmutable() : val;
|
|
8439
8922
|
}
|
|
8923
|
+
for (const [key, val] of this.#local) {
|
|
8924
|
+
result[key] = val;
|
|
8925
|
+
}
|
|
8440
8926
|
return process.env.NODE_ENV === "production" ? result : Object.freeze(result);
|
|
8441
8927
|
}
|
|
8442
8928
|
clone() {
|
|
8443
|
-
|
|
8929
|
+
const cloned = new _LiveObject(
|
|
8444
8930
|
Object.fromEntries(
|
|
8445
|
-
Array.from(this.#
|
|
8931
|
+
Array.from(this.#synced).map(([key, value]) => [
|
|
8446
8932
|
key,
|
|
8447
8933
|
isLiveStructure(value) ? value.clone() : deepClone(value)
|
|
8448
8934
|
])
|
|
8449
8935
|
)
|
|
8450
8936
|
);
|
|
8937
|
+
for (const [key, value] of this.#local) {
|
|
8938
|
+
cloned.#local.set(key, deepClone(value));
|
|
8939
|
+
}
|
|
8940
|
+
return cloned;
|
|
8451
8941
|
}
|
|
8452
8942
|
};
|
|
8453
8943
|
|
|
@@ -8747,17 +9237,6 @@ var Deque = class {
|
|
|
8747
9237
|
}
|
|
8748
9238
|
};
|
|
8749
9239
|
|
|
8750
|
-
// src/lib/Json.ts
|
|
8751
|
-
function isJsonScalar(data) {
|
|
8752
|
-
return data === null || typeof data === "string" || typeof data === "number" || typeof data === "boolean";
|
|
8753
|
-
}
|
|
8754
|
-
function isJsonArray(data) {
|
|
8755
|
-
return Array.isArray(data);
|
|
8756
|
-
}
|
|
8757
|
-
function isJsonObject(data) {
|
|
8758
|
-
return !isJsonScalar(data) && !isJsonArray(data);
|
|
8759
|
-
}
|
|
8760
|
-
|
|
8761
9240
|
// src/lib/stopwatch.ts
|
|
8762
9241
|
function makeStopWatch() {
|
|
8763
9242
|
let startTime = 0;
|
|
@@ -8791,16 +9270,7 @@ var ClientMsgCode = Object.freeze({
|
|
|
8791
9270
|
UPDATE_STORAGE: 201,
|
|
8792
9271
|
// For Yjs support
|
|
8793
9272
|
FETCH_YDOC: 300,
|
|
8794
|
-
UPDATE_YDOC: 301
|
|
8795
|
-
// For Feeds
|
|
8796
|
-
FETCH_FEEDS: 510,
|
|
8797
|
-
FETCH_FEED_MESSAGES: 511,
|
|
8798
|
-
ADD_FEED: 512,
|
|
8799
|
-
UPDATE_FEED: 513,
|
|
8800
|
-
DELETE_FEED: 514,
|
|
8801
|
-
ADD_FEED_MESSAGE: 515,
|
|
8802
|
-
UPDATE_FEED_MESSAGE: 516,
|
|
8803
|
-
DELETE_FEED_MESSAGE: 517
|
|
9273
|
+
UPDATE_YDOC: 301
|
|
8804
9274
|
});
|
|
8805
9275
|
|
|
8806
9276
|
// src/refs/ManagedOthers.ts
|
|
@@ -9036,15 +9506,12 @@ function defaultMessageFromContext(context) {
|
|
|
9036
9506
|
return "Could not update notification settings";
|
|
9037
9507
|
case "LARGE_MESSAGE_ERROR":
|
|
9038
9508
|
return "Could not send large message";
|
|
9039
|
-
case "FEED_REQUEST_ERROR":
|
|
9040
|
-
return context.reason ?? "Feed request failed";
|
|
9041
9509
|
default:
|
|
9042
9510
|
return assertNever(context, "Unhandled case");
|
|
9043
9511
|
}
|
|
9044
9512
|
}
|
|
9045
9513
|
|
|
9046
9514
|
// src/room.ts
|
|
9047
|
-
var FEEDS_TIMEOUT = 5e3;
|
|
9048
9515
|
function makeIdFactory(connectionId) {
|
|
9049
9516
|
let count = 0;
|
|
9050
9517
|
return () => `${connectionId}:${count++}`;
|
|
@@ -9255,9 +9722,13 @@ function createRoom(options, config) {
|
|
|
9255
9722
|
}
|
|
9256
9723
|
context.activeBatch.reverseOps.pushLeft(reverse);
|
|
9257
9724
|
} else {
|
|
9258
|
-
|
|
9259
|
-
|
|
9260
|
-
|
|
9725
|
+
if (reverse.length > 0) {
|
|
9726
|
+
addToUndoStack(reverse);
|
|
9727
|
+
}
|
|
9728
|
+
if (ops.length > 0) {
|
|
9729
|
+
context.redoStack.length = 0;
|
|
9730
|
+
dispatchOps(ops);
|
|
9731
|
+
}
|
|
9261
9732
|
notify({ storageUpdates });
|
|
9262
9733
|
}
|
|
9263
9734
|
}
|
|
@@ -9279,7 +9750,6 @@ function createRoom(options, config) {
|
|
|
9279
9750
|
storageStatus: makeEventSource(),
|
|
9280
9751
|
ydoc: makeEventSource(),
|
|
9281
9752
|
comments: makeEventSource(),
|
|
9282
|
-
feeds: makeEventSource(),
|
|
9283
9753
|
roomWillDestroy: makeEventSource()
|
|
9284
9754
|
};
|
|
9285
9755
|
async function createTextMention(mentionId, mention) {
|
|
@@ -9367,19 +9837,20 @@ function createRoom(options, config) {
|
|
|
9367
9837
|
);
|
|
9368
9838
|
}
|
|
9369
9839
|
const canWrite = self.get()?.canWrite ?? true;
|
|
9370
|
-
const
|
|
9371
|
-
|
|
9372
|
-
|
|
9373
|
-
if (
|
|
9374
|
-
|
|
9375
|
-
|
|
9376
|
-
|
|
9377
|
-
|
|
9378
|
-
|
|
9840
|
+
const root = context.root;
|
|
9841
|
+
withoutHistory(() => {
|
|
9842
|
+
for (const key in context.initialStorage) {
|
|
9843
|
+
if (root.get(key) === void 0) {
|
|
9844
|
+
if (canWrite) {
|
|
9845
|
+
root.set(key, cloneLson(context.initialStorage[key]));
|
|
9846
|
+
} else {
|
|
9847
|
+
warn(
|
|
9848
|
+
`Attempted to populate missing storage key '${key}', but current user has no write access`
|
|
9849
|
+
);
|
|
9850
|
+
}
|
|
9379
9851
|
}
|
|
9380
9852
|
}
|
|
9381
|
-
}
|
|
9382
|
-
context.undoStack.length = stackSizeBefore;
|
|
9853
|
+
});
|
|
9383
9854
|
}
|
|
9384
9855
|
function _addToRealUndoStack(frames) {
|
|
9385
9856
|
if (context.undoStack.length >= 50) {
|
|
@@ -9700,9 +10171,6 @@ function createRoom(options, config) {
|
|
|
9700
10171
|
notify(result.updates);
|
|
9701
10172
|
sendMessages(messages);
|
|
9702
10173
|
}
|
|
9703
|
-
function isFeedRequestFailedMsg(msg) {
|
|
9704
|
-
return msg.type === ServerMsgCode.FEED_REQUEST_FAILED;
|
|
9705
|
-
}
|
|
9706
10174
|
function handleServerMessage(event) {
|
|
9707
10175
|
if (typeof event.data !== "string") {
|
|
9708
10176
|
return;
|
|
@@ -9816,94 +10284,6 @@ function createRoom(options, config) {
|
|
|
9816
10284
|
eventHub.comments.notify(message);
|
|
9817
10285
|
break;
|
|
9818
10286
|
}
|
|
9819
|
-
case ServerMsgCode.FEEDS_LIST: {
|
|
9820
|
-
const feedsListMsg = message;
|
|
9821
|
-
const pending = pendingFeedsRequests.get(feedsListMsg.requestId);
|
|
9822
|
-
if (pending) {
|
|
9823
|
-
pending.resolve({
|
|
9824
|
-
feeds: feedsListMsg.feeds,
|
|
9825
|
-
nextCursor: feedsListMsg.nextCursor
|
|
9826
|
-
});
|
|
9827
|
-
pendingFeedsRequests.delete(feedsListMsg.requestId);
|
|
9828
|
-
}
|
|
9829
|
-
eventHub.feeds.notify(feedsListMsg);
|
|
9830
|
-
break;
|
|
9831
|
-
}
|
|
9832
|
-
case ServerMsgCode.FEEDS_ADDED: {
|
|
9833
|
-
const feedsAddedMsg = message;
|
|
9834
|
-
eventHub.feeds.notify(feedsAddedMsg);
|
|
9835
|
-
tryResolvePendingFeedMutationsFromFeedsEvent(feedsAddedMsg);
|
|
9836
|
-
break;
|
|
9837
|
-
}
|
|
9838
|
-
case ServerMsgCode.FEEDS_UPDATED: {
|
|
9839
|
-
const feedsUpdatedMsg = message;
|
|
9840
|
-
eventHub.feeds.notify(feedsUpdatedMsg);
|
|
9841
|
-
tryResolvePendingFeedMutationsFromFeedsEvent(feedsUpdatedMsg);
|
|
9842
|
-
break;
|
|
9843
|
-
}
|
|
9844
|
-
case ServerMsgCode.FEED_DELETED: {
|
|
9845
|
-
eventHub.feeds.notify(message);
|
|
9846
|
-
tryResolvePendingFeedMutationsFromFeedsEvent(message);
|
|
9847
|
-
break;
|
|
9848
|
-
}
|
|
9849
|
-
case ServerMsgCode.FEED_MESSAGES_LIST: {
|
|
9850
|
-
const feedMsgsListMsg = message;
|
|
9851
|
-
const pending = pendingFeedMessagesRequests.get(
|
|
9852
|
-
feedMsgsListMsg.requestId
|
|
9853
|
-
);
|
|
9854
|
-
if (pending) {
|
|
9855
|
-
pending.resolve({
|
|
9856
|
-
messages: feedMsgsListMsg.messages,
|
|
9857
|
-
nextCursor: feedMsgsListMsg.nextCursor
|
|
9858
|
-
});
|
|
9859
|
-
pendingFeedMessagesRequests.delete(feedMsgsListMsg.requestId);
|
|
9860
|
-
}
|
|
9861
|
-
eventHub.feeds.notify(feedMsgsListMsg);
|
|
9862
|
-
break;
|
|
9863
|
-
}
|
|
9864
|
-
case ServerMsgCode.FEED_MESSAGES_ADDED: {
|
|
9865
|
-
const feedMsgsAddedMsg = message;
|
|
9866
|
-
eventHub.feeds.notify(feedMsgsAddedMsg);
|
|
9867
|
-
tryResolvePendingFeedMutationsFromFeedsEvent(feedMsgsAddedMsg);
|
|
9868
|
-
break;
|
|
9869
|
-
}
|
|
9870
|
-
case ServerMsgCode.FEED_MESSAGES_UPDATED: {
|
|
9871
|
-
const feedMsgsUpdatedMsg = message;
|
|
9872
|
-
eventHub.feeds.notify(feedMsgsUpdatedMsg);
|
|
9873
|
-
tryResolvePendingFeedMutationsFromFeedsEvent(feedMsgsUpdatedMsg);
|
|
9874
|
-
break;
|
|
9875
|
-
}
|
|
9876
|
-
case ServerMsgCode.FEED_MESSAGES_DELETED: {
|
|
9877
|
-
eventHub.feeds.notify(message);
|
|
9878
|
-
tryResolvePendingFeedMutationsFromFeedsEvent(message);
|
|
9879
|
-
break;
|
|
9880
|
-
}
|
|
9881
|
-
case ServerMsgCode.FEED_REQUEST_FAILED: {
|
|
9882
|
-
if (!isFeedRequestFailedMsg(message)) {
|
|
9883
|
-
break;
|
|
9884
|
-
}
|
|
9885
|
-
const { requestId, code, reason } = message;
|
|
9886
|
-
const err = new LiveblocksError(reason ?? "Feed request failed", {
|
|
9887
|
-
type: "FEED_REQUEST_ERROR",
|
|
9888
|
-
roomId,
|
|
9889
|
-
requestId,
|
|
9890
|
-
code,
|
|
9891
|
-
reason
|
|
9892
|
-
});
|
|
9893
|
-
if (pendingFeedMutations.has(requestId)) {
|
|
9894
|
-
settleFeedMutation(requestId, "error", err);
|
|
9895
|
-
} else if (pendingFeedsRequests.has(requestId)) {
|
|
9896
|
-
const pending = pendingFeedsRequests.get(requestId);
|
|
9897
|
-
pendingFeedsRequests.delete(requestId);
|
|
9898
|
-
pending?.reject(err);
|
|
9899
|
-
} else if (pendingFeedMessagesRequests.has(requestId)) {
|
|
9900
|
-
const pending = pendingFeedMessagesRequests.get(requestId);
|
|
9901
|
-
pendingFeedMessagesRequests.delete(requestId);
|
|
9902
|
-
pending?.reject(err);
|
|
9903
|
-
}
|
|
9904
|
-
eventHub.feeds.notify(message);
|
|
9905
|
-
break;
|
|
9906
|
-
}
|
|
9907
10287
|
case ServerMsgCode.STORAGE_STATE_V7:
|
|
9908
10288
|
// No longer used in V8
|
|
9909
10289
|
default:
|
|
@@ -10007,141 +10387,6 @@ function createRoom(options, config) {
|
|
|
10007
10387
|
}
|
|
10008
10388
|
let _getStorage$ = null;
|
|
10009
10389
|
let _resolveStoragePromise = null;
|
|
10010
|
-
const pendingFeedsRequests = /* @__PURE__ */ new Map();
|
|
10011
|
-
const pendingFeedMessagesRequests = /* @__PURE__ */ new Map();
|
|
10012
|
-
const pendingFeedMutations = /* @__PURE__ */ new Map();
|
|
10013
|
-
const pendingAddMessageFifoByFeed = /* @__PURE__ */ new Map();
|
|
10014
|
-
function settleFeedMutation(requestId, outcome, error3) {
|
|
10015
|
-
const pending = pendingFeedMutations.get(requestId);
|
|
10016
|
-
if (pending === void 0) {
|
|
10017
|
-
return;
|
|
10018
|
-
}
|
|
10019
|
-
clearTimeout(pending.timeoutId);
|
|
10020
|
-
pendingFeedMutations.delete(requestId);
|
|
10021
|
-
if (pending.kind === "add-message" && !pending.expectedClientMessageId) {
|
|
10022
|
-
const q = pendingAddMessageFifoByFeed.get(pending.feedId);
|
|
10023
|
-
if (q !== void 0) {
|
|
10024
|
-
const idx = q.indexOf(requestId);
|
|
10025
|
-
if (idx >= 0) {
|
|
10026
|
-
q.splice(idx, 1);
|
|
10027
|
-
}
|
|
10028
|
-
if (q.length === 0) {
|
|
10029
|
-
pendingAddMessageFifoByFeed.delete(pending.feedId);
|
|
10030
|
-
}
|
|
10031
|
-
}
|
|
10032
|
-
}
|
|
10033
|
-
if (outcome === "ok") {
|
|
10034
|
-
pending.resolve();
|
|
10035
|
-
} else {
|
|
10036
|
-
pending.reject(error3 ?? new Error("Feed mutation failed"));
|
|
10037
|
-
}
|
|
10038
|
-
}
|
|
10039
|
-
function registerFeedMutation(requestId, kind, feedId, options2) {
|
|
10040
|
-
const { promise, resolve, reject } = Promise_withResolvers();
|
|
10041
|
-
const timeoutId = setTimeout(() => {
|
|
10042
|
-
if (pendingFeedMutations.has(requestId)) {
|
|
10043
|
-
settleFeedMutation(
|
|
10044
|
-
requestId,
|
|
10045
|
-
"error",
|
|
10046
|
-
new Error("Feed mutation timeout")
|
|
10047
|
-
);
|
|
10048
|
-
}
|
|
10049
|
-
}, FEEDS_TIMEOUT);
|
|
10050
|
-
pendingFeedMutations.set(requestId, {
|
|
10051
|
-
resolve,
|
|
10052
|
-
reject,
|
|
10053
|
-
timeoutId,
|
|
10054
|
-
kind,
|
|
10055
|
-
feedId,
|
|
10056
|
-
messageId: options2?.messageId,
|
|
10057
|
-
expectedClientMessageId: options2?.expectedClientMessageId
|
|
10058
|
-
});
|
|
10059
|
-
if (kind === "add-message" && options2?.expectedClientMessageId === void 0) {
|
|
10060
|
-
const q = pendingAddMessageFifoByFeed.get(feedId) ?? [];
|
|
10061
|
-
q.push(requestId);
|
|
10062
|
-
pendingAddMessageFifoByFeed.set(feedId, q);
|
|
10063
|
-
}
|
|
10064
|
-
return promise;
|
|
10065
|
-
}
|
|
10066
|
-
function tryResolvePendingFeedMutationsFromFeedsEvent(message) {
|
|
10067
|
-
switch (message.type) {
|
|
10068
|
-
case ServerMsgCode.FEEDS_ADDED: {
|
|
10069
|
-
for (const feed of message.feeds) {
|
|
10070
|
-
for (const [requestId, pending] of [...pendingFeedMutations]) {
|
|
10071
|
-
if (pending.kind === "add-feed" && pending.feedId === feed.feedId) {
|
|
10072
|
-
settleFeedMutation(requestId, "ok");
|
|
10073
|
-
break;
|
|
10074
|
-
}
|
|
10075
|
-
}
|
|
10076
|
-
}
|
|
10077
|
-
break;
|
|
10078
|
-
}
|
|
10079
|
-
case ServerMsgCode.FEEDS_UPDATED: {
|
|
10080
|
-
for (const feed of message.feeds) {
|
|
10081
|
-
for (const [requestId, pending] of [...pendingFeedMutations]) {
|
|
10082
|
-
if (pending.kind === "update-feed" && pending.feedId === feed.feedId) {
|
|
10083
|
-
settleFeedMutation(requestId, "ok");
|
|
10084
|
-
}
|
|
10085
|
-
}
|
|
10086
|
-
}
|
|
10087
|
-
break;
|
|
10088
|
-
}
|
|
10089
|
-
case ServerMsgCode.FEED_DELETED: {
|
|
10090
|
-
for (const [requestId, pending] of [...pendingFeedMutations]) {
|
|
10091
|
-
if (pending.kind === "delete-feed" && pending.feedId === message.feedId) {
|
|
10092
|
-
settleFeedMutation(requestId, "ok");
|
|
10093
|
-
break;
|
|
10094
|
-
}
|
|
10095
|
-
}
|
|
10096
|
-
break;
|
|
10097
|
-
}
|
|
10098
|
-
case ServerMsgCode.FEED_MESSAGES_ADDED: {
|
|
10099
|
-
for (const m of message.messages) {
|
|
10100
|
-
let matched = false;
|
|
10101
|
-
for (const [requestId, pending] of [...pendingFeedMutations]) {
|
|
10102
|
-
if (pending.kind === "add-message" && pending.feedId === message.feedId && pending.expectedClientMessageId === m.id) {
|
|
10103
|
-
settleFeedMutation(requestId, "ok");
|
|
10104
|
-
matched = true;
|
|
10105
|
-
break;
|
|
10106
|
-
}
|
|
10107
|
-
}
|
|
10108
|
-
if (!matched) {
|
|
10109
|
-
const q = pendingAddMessageFifoByFeed.get(message.feedId);
|
|
10110
|
-
const headId = q?.[0];
|
|
10111
|
-
if (headId !== void 0) {
|
|
10112
|
-
const pending = pendingFeedMutations.get(headId);
|
|
10113
|
-
if (pending?.kind === "add-message" && pending.expectedClientMessageId === void 0) {
|
|
10114
|
-
settleFeedMutation(headId, "ok");
|
|
10115
|
-
}
|
|
10116
|
-
}
|
|
10117
|
-
}
|
|
10118
|
-
}
|
|
10119
|
-
break;
|
|
10120
|
-
}
|
|
10121
|
-
case ServerMsgCode.FEED_MESSAGES_UPDATED: {
|
|
10122
|
-
for (const m of message.messages) {
|
|
10123
|
-
for (const [requestId, pending] of [...pendingFeedMutations]) {
|
|
10124
|
-
if (pending.kind === "update-message" && pending.feedId === message.feedId && pending.messageId === m.id) {
|
|
10125
|
-
settleFeedMutation(requestId, "ok");
|
|
10126
|
-
}
|
|
10127
|
-
}
|
|
10128
|
-
}
|
|
10129
|
-
break;
|
|
10130
|
-
}
|
|
10131
|
-
case ServerMsgCode.FEED_MESSAGES_DELETED: {
|
|
10132
|
-
for (const mid of message.messageIds) {
|
|
10133
|
-
for (const [requestId, pending] of [...pendingFeedMutations]) {
|
|
10134
|
-
if (pending.kind === "delete-message" && pending.feedId === message.feedId && pending.messageId === mid) {
|
|
10135
|
-
settleFeedMutation(requestId, "ok");
|
|
10136
|
-
}
|
|
10137
|
-
}
|
|
10138
|
-
}
|
|
10139
|
-
break;
|
|
10140
|
-
}
|
|
10141
|
-
default:
|
|
10142
|
-
break;
|
|
10143
|
-
}
|
|
10144
|
-
}
|
|
10145
10390
|
function processInitialStorage(nodes) {
|
|
10146
10391
|
const unacknowledgedOps = new Map(context.unacknowledgedOps);
|
|
10147
10392
|
createOrUpdateRootFromMessage(nodes);
|
|
@@ -10213,138 +10458,6 @@ function createRoom(options, config) {
|
|
|
10213
10458
|
}
|
|
10214
10459
|
flushNowOrSoon();
|
|
10215
10460
|
}
|
|
10216
|
-
async function fetchFeeds(options2) {
|
|
10217
|
-
const requestId = nanoid();
|
|
10218
|
-
const { promise, resolve, reject } = Promise_withResolvers();
|
|
10219
|
-
pendingFeedsRequests.set(requestId, { resolve, reject });
|
|
10220
|
-
const message = {
|
|
10221
|
-
type: ClientMsgCode.FETCH_FEEDS,
|
|
10222
|
-
requestId,
|
|
10223
|
-
cursor: options2?.cursor,
|
|
10224
|
-
since: options2?.since,
|
|
10225
|
-
limit: options2?.limit,
|
|
10226
|
-
metadata: options2?.metadata
|
|
10227
|
-
};
|
|
10228
|
-
context.buffer.messages.push(message);
|
|
10229
|
-
flushNowOrSoon();
|
|
10230
|
-
setTimeout(() => {
|
|
10231
|
-
if (pendingFeedsRequests.has(requestId)) {
|
|
10232
|
-
pendingFeedsRequests.delete(requestId);
|
|
10233
|
-
reject(new Error("Feeds fetch timeout"));
|
|
10234
|
-
}
|
|
10235
|
-
}, FEEDS_TIMEOUT);
|
|
10236
|
-
return promise;
|
|
10237
|
-
}
|
|
10238
|
-
async function fetchFeedMessages(feedId, options2) {
|
|
10239
|
-
const requestId = nanoid();
|
|
10240
|
-
const { promise, resolve, reject } = Promise_withResolvers();
|
|
10241
|
-
pendingFeedMessagesRequests.set(requestId, { resolve, reject });
|
|
10242
|
-
const message = {
|
|
10243
|
-
type: ClientMsgCode.FETCH_FEED_MESSAGES,
|
|
10244
|
-
requestId,
|
|
10245
|
-
feedId,
|
|
10246
|
-
cursor: options2?.cursor,
|
|
10247
|
-
since: options2?.since,
|
|
10248
|
-
limit: options2?.limit
|
|
10249
|
-
};
|
|
10250
|
-
context.buffer.messages.push(message);
|
|
10251
|
-
flushNowOrSoon();
|
|
10252
|
-
setTimeout(() => {
|
|
10253
|
-
if (pendingFeedMessagesRequests.has(requestId)) {
|
|
10254
|
-
pendingFeedMessagesRequests.delete(requestId);
|
|
10255
|
-
reject(new Error("Feed messages fetch timeout"));
|
|
10256
|
-
}
|
|
10257
|
-
}, FEEDS_TIMEOUT);
|
|
10258
|
-
return promise;
|
|
10259
|
-
}
|
|
10260
|
-
function addFeed(feedId, options2) {
|
|
10261
|
-
const requestId = nanoid();
|
|
10262
|
-
const promise = registerFeedMutation(requestId, "add-feed", feedId);
|
|
10263
|
-
const message = {
|
|
10264
|
-
type: ClientMsgCode.ADD_FEED,
|
|
10265
|
-
requestId,
|
|
10266
|
-
feedId,
|
|
10267
|
-
metadata: options2?.metadata,
|
|
10268
|
-
createdAt: options2?.createdAt
|
|
10269
|
-
};
|
|
10270
|
-
context.buffer.messages.push(message);
|
|
10271
|
-
flushNowOrSoon();
|
|
10272
|
-
return promise;
|
|
10273
|
-
}
|
|
10274
|
-
function updateFeed(feedId, metadata) {
|
|
10275
|
-
const requestId = nanoid();
|
|
10276
|
-
const promise = registerFeedMutation(requestId, "update-feed", feedId);
|
|
10277
|
-
const message = {
|
|
10278
|
-
type: ClientMsgCode.UPDATE_FEED,
|
|
10279
|
-
requestId,
|
|
10280
|
-
feedId,
|
|
10281
|
-
metadata
|
|
10282
|
-
};
|
|
10283
|
-
context.buffer.messages.push(message);
|
|
10284
|
-
flushNowOrSoon();
|
|
10285
|
-
return promise;
|
|
10286
|
-
}
|
|
10287
|
-
function deleteFeed(feedId) {
|
|
10288
|
-
const requestId = nanoid();
|
|
10289
|
-
const promise = registerFeedMutation(requestId, "delete-feed", feedId);
|
|
10290
|
-
const message = {
|
|
10291
|
-
type: ClientMsgCode.DELETE_FEED,
|
|
10292
|
-
requestId,
|
|
10293
|
-
feedId
|
|
10294
|
-
};
|
|
10295
|
-
context.buffer.messages.push(message);
|
|
10296
|
-
flushNowOrSoon();
|
|
10297
|
-
return promise;
|
|
10298
|
-
}
|
|
10299
|
-
function addFeedMessage(feedId, data, options2) {
|
|
10300
|
-
const requestId = nanoid();
|
|
10301
|
-
const promise = registerFeedMutation(requestId, "add-message", feedId, {
|
|
10302
|
-
expectedClientMessageId: options2?.id
|
|
10303
|
-
});
|
|
10304
|
-
const message = {
|
|
10305
|
-
type: ClientMsgCode.ADD_FEED_MESSAGE,
|
|
10306
|
-
requestId,
|
|
10307
|
-
feedId,
|
|
10308
|
-
data,
|
|
10309
|
-
id: options2?.id,
|
|
10310
|
-
createdAt: options2?.createdAt
|
|
10311
|
-
};
|
|
10312
|
-
context.buffer.messages.push(message);
|
|
10313
|
-
flushNowOrSoon();
|
|
10314
|
-
return promise;
|
|
10315
|
-
}
|
|
10316
|
-
function updateFeedMessage(feedId, messageId, data, options2) {
|
|
10317
|
-
const requestId = nanoid();
|
|
10318
|
-
const promise = registerFeedMutation(requestId, "update-message", feedId, {
|
|
10319
|
-
messageId
|
|
10320
|
-
});
|
|
10321
|
-
const message = {
|
|
10322
|
-
type: ClientMsgCode.UPDATE_FEED_MESSAGE,
|
|
10323
|
-
requestId,
|
|
10324
|
-
feedId,
|
|
10325
|
-
messageId,
|
|
10326
|
-
data,
|
|
10327
|
-
updatedAt: options2?.updatedAt
|
|
10328
|
-
};
|
|
10329
|
-
context.buffer.messages.push(message);
|
|
10330
|
-
flushNowOrSoon();
|
|
10331
|
-
return promise;
|
|
10332
|
-
}
|
|
10333
|
-
function deleteFeedMessage(feedId, messageId) {
|
|
10334
|
-
const requestId = nanoid();
|
|
10335
|
-
const promise = registerFeedMutation(requestId, "delete-message", feedId, {
|
|
10336
|
-
messageId
|
|
10337
|
-
});
|
|
10338
|
-
const message = {
|
|
10339
|
-
type: ClientMsgCode.DELETE_FEED_MESSAGE,
|
|
10340
|
-
requestId,
|
|
10341
|
-
feedId,
|
|
10342
|
-
messageId
|
|
10343
|
-
};
|
|
10344
|
-
context.buffer.messages.push(message);
|
|
10345
|
-
flushNowOrSoon();
|
|
10346
|
-
return promise;
|
|
10347
|
-
}
|
|
10348
10461
|
function undo() {
|
|
10349
10462
|
if (context.activeBatch) {
|
|
10350
10463
|
throw new Error("undo is not allowed during a batch");
|
|
@@ -10430,6 +10543,16 @@ function createRoom(options, config) {
|
|
|
10430
10543
|
_addToRealUndoStack(Array.from(frames));
|
|
10431
10544
|
}
|
|
10432
10545
|
}
|
|
10546
|
+
function withoutHistory(fn) {
|
|
10547
|
+
const undoBefore = context.undoStack.length;
|
|
10548
|
+
const redoBefore = context.redoStack.length;
|
|
10549
|
+
try {
|
|
10550
|
+
return fn();
|
|
10551
|
+
} finally {
|
|
10552
|
+
context.undoStack.length = undoBefore;
|
|
10553
|
+
context.redoStack.length = redoBefore;
|
|
10554
|
+
}
|
|
10555
|
+
}
|
|
10433
10556
|
const syncSourceForStorage = config.createSyncSource();
|
|
10434
10557
|
function getStorageStatus() {
|
|
10435
10558
|
if (context.root === void 0) {
|
|
@@ -10487,7 +10610,6 @@ function createRoom(options, config) {
|
|
|
10487
10610
|
storageStatus: eventHub.storageStatus.observable,
|
|
10488
10611
|
ydoc: eventHub.ydoc.observable,
|
|
10489
10612
|
comments: eventHub.comments.observable,
|
|
10490
|
-
feeds: eventHub.feeds.observable,
|
|
10491
10613
|
roomWillDestroy: eventHub.roomWillDestroy.observable
|
|
10492
10614
|
};
|
|
10493
10615
|
async function getThreadsSince(options2) {
|
|
@@ -10697,19 +10819,13 @@ function createRoom(options, config) {
|
|
|
10697
10819
|
id: roomId,
|
|
10698
10820
|
subscribe: makeClassicSubscribeFn(
|
|
10699
10821
|
roomId,
|
|
10700
|
-
|
|
10822
|
+
events,
|
|
10701
10823
|
config.errorEventSource
|
|
10702
10824
|
),
|
|
10703
10825
|
connect: () => managedSocket.connect(),
|
|
10704
10826
|
reconnect: () => managedSocket.reconnect(),
|
|
10705
10827
|
disconnect: () => managedSocket.disconnect(),
|
|
10706
10828
|
destroy: () => {
|
|
10707
|
-
pendingFeedsRequests.forEach(
|
|
10708
|
-
(request) => request.reject(new Error("Room destroyed"))
|
|
10709
|
-
);
|
|
10710
|
-
pendingFeedMessagesRequests.forEach(
|
|
10711
|
-
(request) => request.reject(new Error("Room destroyed"))
|
|
10712
|
-
);
|
|
10713
10829
|
const { roomWillDestroy, ...eventsExceptDestroy } = eventHub;
|
|
10714
10830
|
for (const source of Object.values(eventsExceptDestroy)) {
|
|
10715
10831
|
source.dispose();
|
|
@@ -10735,17 +10851,12 @@ function createRoom(options, config) {
|
|
|
10735
10851
|
canRedo,
|
|
10736
10852
|
clear,
|
|
10737
10853
|
pause: pauseHistory,
|
|
10738
|
-
resume: resumeHistory
|
|
10854
|
+
resume: resumeHistory,
|
|
10855
|
+
[kInternal]: {
|
|
10856
|
+
withoutHistory
|
|
10857
|
+
}
|
|
10739
10858
|
},
|
|
10740
10859
|
fetchYDoc,
|
|
10741
|
-
fetchFeeds,
|
|
10742
|
-
fetchFeedMessages,
|
|
10743
|
-
addFeed,
|
|
10744
|
-
updateFeed,
|
|
10745
|
-
deleteFeed,
|
|
10746
|
-
addFeedMessage,
|
|
10747
|
-
updateFeedMessage,
|
|
10748
|
-
deleteFeedMessage,
|
|
10749
10860
|
getStorage,
|
|
10750
10861
|
getStorageSnapshot,
|
|
10751
10862
|
getStorageStatus,
|
|
@@ -11653,309 +11764,6 @@ function toPlainLson(lson) {
|
|
|
11653
11764
|
}
|
|
11654
11765
|
}
|
|
11655
11766
|
|
|
11656
|
-
// src/immutable.ts
|
|
11657
|
-
function lsonObjectToJson(obj) {
|
|
11658
|
-
const result = {};
|
|
11659
|
-
for (const key in obj) {
|
|
11660
|
-
const val = obj[key];
|
|
11661
|
-
if (val !== void 0) {
|
|
11662
|
-
result[key] = lsonToJson(val);
|
|
11663
|
-
}
|
|
11664
|
-
}
|
|
11665
|
-
return result;
|
|
11666
|
-
}
|
|
11667
|
-
function liveObjectToJson(liveObject) {
|
|
11668
|
-
return lsonObjectToJson(liveObject.toObject());
|
|
11669
|
-
}
|
|
11670
|
-
function liveMapToJson(map) {
|
|
11671
|
-
const result = {};
|
|
11672
|
-
for (const [key, value] of map.entries()) {
|
|
11673
|
-
result[key] = lsonToJson(value);
|
|
11674
|
-
}
|
|
11675
|
-
return result;
|
|
11676
|
-
}
|
|
11677
|
-
function lsonListToJson(value) {
|
|
11678
|
-
return value.map(lsonToJson);
|
|
11679
|
-
}
|
|
11680
|
-
function liveListToJson(value) {
|
|
11681
|
-
return lsonListToJson(value.toArray());
|
|
11682
|
-
}
|
|
11683
|
-
function lsonToJson(value) {
|
|
11684
|
-
if (value instanceof LiveObject) {
|
|
11685
|
-
return liveObjectToJson(value);
|
|
11686
|
-
} else if (value instanceof LiveList) {
|
|
11687
|
-
return liveListToJson(value);
|
|
11688
|
-
} else if (value instanceof LiveMap) {
|
|
11689
|
-
return liveMapToJson(value);
|
|
11690
|
-
} else if (value instanceof LiveRegister) {
|
|
11691
|
-
return value.data;
|
|
11692
|
-
}
|
|
11693
|
-
if (Array.isArray(value)) {
|
|
11694
|
-
return lsonListToJson(value);
|
|
11695
|
-
} else if (isPlainObject(value)) {
|
|
11696
|
-
return lsonObjectToJson(value);
|
|
11697
|
-
}
|
|
11698
|
-
return value;
|
|
11699
|
-
}
|
|
11700
|
-
function deepLiveify(value) {
|
|
11701
|
-
if (Array.isArray(value)) {
|
|
11702
|
-
return new LiveList(value.map(deepLiveify));
|
|
11703
|
-
} else if (isPlainObject(value)) {
|
|
11704
|
-
const init = {};
|
|
11705
|
-
for (const key in value) {
|
|
11706
|
-
const val = value[key];
|
|
11707
|
-
if (val === void 0) {
|
|
11708
|
-
continue;
|
|
11709
|
-
}
|
|
11710
|
-
init[key] = deepLiveify(val);
|
|
11711
|
-
}
|
|
11712
|
-
return new LiveObject(init);
|
|
11713
|
-
} else {
|
|
11714
|
-
return value;
|
|
11715
|
-
}
|
|
11716
|
-
}
|
|
11717
|
-
function patchLiveList(liveList, prev, next) {
|
|
11718
|
-
let i = 0;
|
|
11719
|
-
let prevEnd = prev.length - 1;
|
|
11720
|
-
let nextEnd = next.length - 1;
|
|
11721
|
-
let prevNode = prev[0];
|
|
11722
|
-
let nextNode = next[0];
|
|
11723
|
-
outer: {
|
|
11724
|
-
while (prevNode === nextNode) {
|
|
11725
|
-
++i;
|
|
11726
|
-
if (i > prevEnd || i > nextEnd) {
|
|
11727
|
-
break outer;
|
|
11728
|
-
}
|
|
11729
|
-
prevNode = prev[i];
|
|
11730
|
-
nextNode = next[i];
|
|
11731
|
-
}
|
|
11732
|
-
prevNode = prev[prevEnd];
|
|
11733
|
-
nextNode = next[nextEnd];
|
|
11734
|
-
while (prevNode === nextNode) {
|
|
11735
|
-
prevEnd--;
|
|
11736
|
-
nextEnd--;
|
|
11737
|
-
if (i > prevEnd || i > nextEnd) {
|
|
11738
|
-
break outer;
|
|
11739
|
-
}
|
|
11740
|
-
prevNode = prev[prevEnd];
|
|
11741
|
-
nextNode = next[nextEnd];
|
|
11742
|
-
}
|
|
11743
|
-
}
|
|
11744
|
-
if (i > prevEnd) {
|
|
11745
|
-
if (i <= nextEnd) {
|
|
11746
|
-
while (i <= nextEnd) {
|
|
11747
|
-
liveList.insert(deepLiveify(next[i]), i);
|
|
11748
|
-
i++;
|
|
11749
|
-
}
|
|
11750
|
-
}
|
|
11751
|
-
} else if (i > nextEnd) {
|
|
11752
|
-
let localI = i;
|
|
11753
|
-
while (localI <= prevEnd) {
|
|
11754
|
-
liveList.delete(i);
|
|
11755
|
-
localI++;
|
|
11756
|
-
}
|
|
11757
|
-
} else {
|
|
11758
|
-
while (i <= prevEnd && i <= nextEnd) {
|
|
11759
|
-
prevNode = prev[i];
|
|
11760
|
-
nextNode = next[i];
|
|
11761
|
-
const liveListNode = liveList.get(i);
|
|
11762
|
-
if (isLiveObject(liveListNode) && isPlainObject(prevNode) && isPlainObject(nextNode)) {
|
|
11763
|
-
patchLiveObject(liveListNode, prevNode, nextNode);
|
|
11764
|
-
} else {
|
|
11765
|
-
liveList.set(i, deepLiveify(nextNode));
|
|
11766
|
-
}
|
|
11767
|
-
i++;
|
|
11768
|
-
}
|
|
11769
|
-
while (i <= nextEnd) {
|
|
11770
|
-
liveList.insert(deepLiveify(next[i]), i);
|
|
11771
|
-
i++;
|
|
11772
|
-
}
|
|
11773
|
-
let localI = i;
|
|
11774
|
-
while (localI <= prevEnd) {
|
|
11775
|
-
liveList.delete(i);
|
|
11776
|
-
localI++;
|
|
11777
|
-
}
|
|
11778
|
-
}
|
|
11779
|
-
}
|
|
11780
|
-
function patchLiveObjectKey(liveObject, key, prev, next) {
|
|
11781
|
-
if (process.env.NODE_ENV !== "production") {
|
|
11782
|
-
const nonSerializableValue = findNonSerializableValue(next);
|
|
11783
|
-
if (nonSerializableValue) {
|
|
11784
|
-
error2(
|
|
11785
|
-
`New state path: '${nonSerializableValue.path}' value: '${String(
|
|
11786
|
-
nonSerializableValue.value
|
|
11787
|
-
)}' is not serializable.
|
|
11788
|
-
Only serializable value can be synced with Liveblocks.`
|
|
11789
|
-
);
|
|
11790
|
-
return;
|
|
11791
|
-
}
|
|
11792
|
-
}
|
|
11793
|
-
const value = liveObject.get(key);
|
|
11794
|
-
if (next === void 0) {
|
|
11795
|
-
liveObject.delete(key);
|
|
11796
|
-
} else if (value === void 0) {
|
|
11797
|
-
liveObject.set(key, deepLiveify(next));
|
|
11798
|
-
} else if (prev === next) {
|
|
11799
|
-
return;
|
|
11800
|
-
} else if (isLiveList(value) && Array.isArray(prev) && Array.isArray(next)) {
|
|
11801
|
-
patchLiveList(value, prev, next);
|
|
11802
|
-
} else if (isLiveObject(value) && isPlainObject(prev) && isPlainObject(next)) {
|
|
11803
|
-
patchLiveObject(value, prev, next);
|
|
11804
|
-
} else {
|
|
11805
|
-
liveObject.set(key, deepLiveify(next));
|
|
11806
|
-
}
|
|
11807
|
-
}
|
|
11808
|
-
function patchLiveObject(root, prev, next) {
|
|
11809
|
-
const updates = {};
|
|
11810
|
-
for (const key in next) {
|
|
11811
|
-
patchLiveObjectKey(root, key, prev[key], next[key]);
|
|
11812
|
-
}
|
|
11813
|
-
for (const key in prev) {
|
|
11814
|
-
if (next[key] === void 0) {
|
|
11815
|
-
root.delete(key);
|
|
11816
|
-
}
|
|
11817
|
-
}
|
|
11818
|
-
if (Object.keys(updates).length > 0) {
|
|
11819
|
-
root.update(updates);
|
|
11820
|
-
}
|
|
11821
|
-
}
|
|
11822
|
-
function getParentsPath(node) {
|
|
11823
|
-
const path = [];
|
|
11824
|
-
while (node.parent.type === "HasParent") {
|
|
11825
|
-
if (isLiveList(node.parent.node)) {
|
|
11826
|
-
path.push(node.parent.node._indexOfPosition(node.parent.key));
|
|
11827
|
-
} else {
|
|
11828
|
-
path.push(node.parent.key);
|
|
11829
|
-
}
|
|
11830
|
-
node = node.parent.node;
|
|
11831
|
-
}
|
|
11832
|
-
return path;
|
|
11833
|
-
}
|
|
11834
|
-
function legacy_patchImmutableObject(state, updates) {
|
|
11835
|
-
return updates.reduce(
|
|
11836
|
-
(state2, update) => legacy_patchImmutableObjectWithUpdate(state2, update),
|
|
11837
|
-
state
|
|
11838
|
-
);
|
|
11839
|
-
}
|
|
11840
|
-
function legacy_patchImmutableObjectWithUpdate(state, update) {
|
|
11841
|
-
const path = getParentsPath(update.node);
|
|
11842
|
-
return legacy_patchImmutableNode(state, path, update);
|
|
11843
|
-
}
|
|
11844
|
-
function legacy_patchImmutableNode(state, path, update) {
|
|
11845
|
-
const pathItem = path.pop();
|
|
11846
|
-
if (pathItem === void 0) {
|
|
11847
|
-
switch (update.type) {
|
|
11848
|
-
case "LiveObject": {
|
|
11849
|
-
if (!isJsonObject(state)) {
|
|
11850
|
-
throw new Error(
|
|
11851
|
-
"Internal: received update on LiveObject but state was not an object"
|
|
11852
|
-
);
|
|
11853
|
-
}
|
|
11854
|
-
const newState = Object.assign({}, state);
|
|
11855
|
-
for (const key in update.updates) {
|
|
11856
|
-
if (update.updates[key]?.type === "update") {
|
|
11857
|
-
const val = update.node.get(key);
|
|
11858
|
-
if (val !== void 0) {
|
|
11859
|
-
newState[key] = lsonToJson(val);
|
|
11860
|
-
}
|
|
11861
|
-
} else if (update.updates[key]?.type === "delete") {
|
|
11862
|
-
delete newState[key];
|
|
11863
|
-
}
|
|
11864
|
-
}
|
|
11865
|
-
return newState;
|
|
11866
|
-
}
|
|
11867
|
-
case "LiveList": {
|
|
11868
|
-
if (!Array.isArray(state)) {
|
|
11869
|
-
throw new Error(
|
|
11870
|
-
"Internal: received update on LiveList but state was not an array"
|
|
11871
|
-
);
|
|
11872
|
-
}
|
|
11873
|
-
let newState = state.map((x) => x);
|
|
11874
|
-
for (const listUpdate of update.updates) {
|
|
11875
|
-
if (listUpdate.type === "set") {
|
|
11876
|
-
newState = newState.map(
|
|
11877
|
-
(item, index) => index === listUpdate.index ? lsonToJson(listUpdate.item) : item
|
|
11878
|
-
);
|
|
11879
|
-
} else if (listUpdate.type === "insert") {
|
|
11880
|
-
if (listUpdate.index === newState.length) {
|
|
11881
|
-
newState.push(lsonToJson(listUpdate.item));
|
|
11882
|
-
} else {
|
|
11883
|
-
newState = [
|
|
11884
|
-
...newState.slice(0, listUpdate.index),
|
|
11885
|
-
lsonToJson(listUpdate.item),
|
|
11886
|
-
...newState.slice(listUpdate.index)
|
|
11887
|
-
];
|
|
11888
|
-
}
|
|
11889
|
-
} else if (listUpdate.type === "delete") {
|
|
11890
|
-
newState.splice(listUpdate.index, 1);
|
|
11891
|
-
} else if (listUpdate.type === "move") {
|
|
11892
|
-
if (listUpdate.previousIndex > listUpdate.index) {
|
|
11893
|
-
newState = [
|
|
11894
|
-
...newState.slice(0, listUpdate.index),
|
|
11895
|
-
lsonToJson(listUpdate.item),
|
|
11896
|
-
...newState.slice(listUpdate.index, listUpdate.previousIndex),
|
|
11897
|
-
...newState.slice(listUpdate.previousIndex + 1)
|
|
11898
|
-
];
|
|
11899
|
-
} else {
|
|
11900
|
-
newState = [
|
|
11901
|
-
...newState.slice(0, listUpdate.previousIndex),
|
|
11902
|
-
...newState.slice(
|
|
11903
|
-
listUpdate.previousIndex + 1,
|
|
11904
|
-
listUpdate.index + 1
|
|
11905
|
-
),
|
|
11906
|
-
lsonToJson(listUpdate.item),
|
|
11907
|
-
...newState.slice(listUpdate.index + 1)
|
|
11908
|
-
];
|
|
11909
|
-
}
|
|
11910
|
-
}
|
|
11911
|
-
}
|
|
11912
|
-
return newState;
|
|
11913
|
-
}
|
|
11914
|
-
case "LiveMap": {
|
|
11915
|
-
if (!isJsonObject(state)) {
|
|
11916
|
-
throw new Error(
|
|
11917
|
-
"Internal: received update on LiveMap but state was not an object"
|
|
11918
|
-
);
|
|
11919
|
-
}
|
|
11920
|
-
const newState = Object.assign({}, state);
|
|
11921
|
-
for (const key in update.updates) {
|
|
11922
|
-
if (update.updates[key]?.type === "update") {
|
|
11923
|
-
const value = update.node.get(key);
|
|
11924
|
-
if (value !== void 0) {
|
|
11925
|
-
newState[key] = lsonToJson(value);
|
|
11926
|
-
}
|
|
11927
|
-
} else if (update.updates[key]?.type === "delete") {
|
|
11928
|
-
delete newState[key];
|
|
11929
|
-
}
|
|
11930
|
-
}
|
|
11931
|
-
return newState;
|
|
11932
|
-
}
|
|
11933
|
-
}
|
|
11934
|
-
}
|
|
11935
|
-
if (Array.isArray(state)) {
|
|
11936
|
-
const newArray = [...state];
|
|
11937
|
-
newArray[pathItem] = legacy_patchImmutableNode(
|
|
11938
|
-
state[pathItem],
|
|
11939
|
-
path,
|
|
11940
|
-
update
|
|
11941
|
-
);
|
|
11942
|
-
return newArray;
|
|
11943
|
-
} else if (isJsonObject(state)) {
|
|
11944
|
-
const node = state[pathItem];
|
|
11945
|
-
if (node === void 0) {
|
|
11946
|
-
return state;
|
|
11947
|
-
} else {
|
|
11948
|
-
const stateAsObj = state;
|
|
11949
|
-
return {
|
|
11950
|
-
...stateAsObj,
|
|
11951
|
-
[pathItem]: legacy_patchImmutableNode(node, path, update)
|
|
11952
|
-
};
|
|
11953
|
-
}
|
|
11954
|
-
} else {
|
|
11955
|
-
return state;
|
|
11956
|
-
}
|
|
11957
|
-
}
|
|
11958
|
-
|
|
11959
11767
|
// src/lib/abortController.ts
|
|
11960
11768
|
function makeAbortController(externalSignal) {
|
|
11961
11769
|
const ctl = new AbortController();
|
|
@@ -12127,7 +11935,6 @@ export {
|
|
|
12127
11935
|
DefaultMap,
|
|
12128
11936
|
Deque,
|
|
12129
11937
|
DerivedSignal,
|
|
12130
|
-
FeedRequestErrorCode,
|
|
12131
11938
|
HttpError,
|
|
12132
11939
|
LiveList,
|
|
12133
11940
|
LiveMap,
|
|
@@ -12169,6 +11976,7 @@ export {
|
|
|
12169
11976
|
createManagedPool,
|
|
12170
11977
|
createNotificationSettings,
|
|
12171
11978
|
createThreadId,
|
|
11979
|
+
deepLiveifyObject,
|
|
12172
11980
|
defineAiTool,
|
|
12173
11981
|
deprecate,
|
|
12174
11982
|
deprecateIf,
|
|
@@ -12202,6 +12010,7 @@ export {
|
|
|
12202
12010
|
kInternal,
|
|
12203
12011
|
keys,
|
|
12204
12012
|
legacy_patchImmutableObject,
|
|
12013
|
+
legacy_patchLiveObjectKey,
|
|
12205
12014
|
lsonToJson,
|
|
12206
12015
|
makeAbortController,
|
|
12207
12016
|
makeEventSource,
|
|
@@ -12213,7 +12022,6 @@ export {
|
|
|
12213
12022
|
nn,
|
|
12214
12023
|
nodeStreamToCompactNodes,
|
|
12215
12024
|
objectToQuery,
|
|
12216
|
-
patchLiveObjectKey,
|
|
12217
12025
|
patchNotificationSettings,
|
|
12218
12026
|
raise,
|
|
12219
12027
|
resolveMentionsInCommentBody,
|