@liveblocks/react-flow 3.17.0 → 3.18.0-rc2
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 +2 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -20
- package/dist/index.d.ts +8 -20
- package/dist/index.js +2 -3
- package/dist/index.js.map +1 -1
- package/dist/{flow.cjs → lib/flow.cjs} +33 -41
- package/dist/lib/flow.cjs.map +1 -0
- package/dist/{flow.js → lib/flow.js} +26 -34
- package/dist/lib/flow.js.map +1 -0
- package/dist/lib/shared.cjs +77 -0
- package/dist/lib/shared.cjs.map +1 -0
- package/dist/lib/shared.js +68 -0
- package/dist/lib/shared.js.map +1 -0
- package/dist/{version.cjs → lib/version.cjs} +1 -1
- package/dist/lib/version.cjs.map +1 -0
- package/dist/{version.js → lib/version.js} +1 -1
- package/dist/lib/version.js.map +1 -0
- package/dist/node.cjs +151 -0
- package/dist/node.cjs.map +1 -0
- package/dist/node.d.cts +99 -0
- package/dist/node.d.ts +99 -0
- package/dist/node.js +149 -0
- package/dist/node.js.map +1 -0
- package/package.json +25 -5
- package/dist/constants.cjs +0 -35
- package/dist/constants.cjs.map +0 -1
- package/dist/constants.js +0 -31
- package/dist/constants.js.map +0 -1
- package/dist/flow.cjs.map +0 -1
- package/dist/flow.js.map +0 -1
- package/dist/helpers.cjs +0 -35
- package/dist/helpers.cjs.map +0 -1
- package/dist/helpers.js +0 -30
- package/dist/helpers.js.map +0 -1
- package/dist/version.cjs.map +0 -1
- package/dist/version.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const PKG_NAME = "@liveblocks/react-flow";
|
|
4
|
-
const PKG_VERSION = typeof "3.
|
|
4
|
+
const PKG_VERSION = typeof "3.18.0-rc2" === "string" && "3.18.0-rc2";
|
|
5
5
|
const PKG_FORMAT = typeof TSUP_FORMAT === "string" && TSUP_FORMAT;
|
|
6
6
|
|
|
7
7
|
exports.PKG_FORMAT = PKG_FORMAT;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.cjs","sources":["../../src/lib/version.ts"],"sourcesContent":["declare const __VERSION__: string;\ndeclare const TSUP_FORMAT: string;\n\nexport const PKG_NAME = \"@liveblocks/react-flow\";\nexport const PKG_VERSION = typeof __VERSION__ === \"string\" && __VERSION__;\nexport const PKG_FORMAT = typeof TSUP_FORMAT === \"string\" && TSUP_FORMAT;\n"],"names":[],"mappings":";;AAGO,MAAM,QAAW,GAAA,yBAAA;AACX,MAAA,WAAA,GAAc,OAAO,YAAA,KAAgB,QAAY,IAAA,aAAA;AACjD,MAAA,UAAA,GAAa,OAAO,WAAA,KAAgB,QAAY,IAAA;;;;;;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const PKG_NAME = "@liveblocks/react-flow";
|
|
2
|
-
const PKG_VERSION = typeof "3.
|
|
2
|
+
const PKG_VERSION = typeof "3.18.0-rc2" === "string" && "3.18.0-rc2";
|
|
3
3
|
const PKG_FORMAT = typeof TSUP_FORMAT === "string" && TSUP_FORMAT;
|
|
4
4
|
|
|
5
5
|
export { PKG_FORMAT, PKG_NAME, PKG_VERSION };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.js","sources":["../../src/lib/version.ts"],"sourcesContent":["declare const __VERSION__: string;\ndeclare const TSUP_FORMAT: string;\n\nexport const PKG_NAME = \"@liveblocks/react-flow\";\nexport const PKG_VERSION = typeof __VERSION__ === \"string\" && __VERSION__;\nexport const PKG_FORMAT = typeof TSUP_FORMAT === \"string\" && TSUP_FORMAT;\n"],"names":[],"mappings":"AAGO,MAAM,QAAW,GAAA,yBAAA;AACX,MAAA,WAAA,GAAc,OAAO,YAAA,KAAgB,QAAY,IAAA,aAAA;AACjD,MAAA,UAAA,GAAa,OAAO,WAAA,KAAgB,QAAY,IAAA;;;;"}
|
package/dist/node.cjs
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var core = require('@liveblocks/core');
|
|
4
|
+
var shared = require('./lib/shared.cjs');
|
|
5
|
+
|
|
6
|
+
async function mutateFlow(options, callback) {
|
|
7
|
+
const { client, roomId } = options;
|
|
8
|
+
const storageKey = options.storageKey ?? shared.DEFAULT_STORAGE_KEY;
|
|
9
|
+
const getNodeSyncConfig = shared.buildNodeConfigCache(options.nodes?.sync);
|
|
10
|
+
const getEdgeSyncConfig = shared.buildEdgeConfigCache(options.edges?.sync);
|
|
11
|
+
const nodeListCache = /* @__PURE__ */ new WeakMap();
|
|
12
|
+
const edgeListCache = /* @__PURE__ */ new WeakMap();
|
|
13
|
+
await client.mutateStorage(roomId, async ({ root }) => {
|
|
14
|
+
let flow = root.get(storageKey);
|
|
15
|
+
if (!flow) {
|
|
16
|
+
const newFlow = new core.LiveObject({
|
|
17
|
+
nodes: new core.LiveMap(),
|
|
18
|
+
edges: new core.LiveMap()
|
|
19
|
+
});
|
|
20
|
+
root.set(storageKey, newFlow);
|
|
21
|
+
flow = newFlow;
|
|
22
|
+
}
|
|
23
|
+
const nodesLiveMap = flow.get("nodes");
|
|
24
|
+
const edgesLiveMap = flow.get("edges");
|
|
25
|
+
function getNodes() {
|
|
26
|
+
const nodeMap = nodesLiveMap.toJSON();
|
|
27
|
+
if (!nodeListCache.has(nodeMap)) {
|
|
28
|
+
nodeListCache.set(nodeMap, Object.values(nodeMap));
|
|
29
|
+
}
|
|
30
|
+
return nodeListCache.get(nodeMap);
|
|
31
|
+
}
|
|
32
|
+
function getEdges() {
|
|
33
|
+
const edgeMap = edgesLiveMap.toJSON();
|
|
34
|
+
if (!edgeListCache.has(edgeMap)) {
|
|
35
|
+
edgeListCache.set(edgeMap, Object.values(edgeMap));
|
|
36
|
+
}
|
|
37
|
+
return edgeListCache.get(edgeMap);
|
|
38
|
+
}
|
|
39
|
+
function getNode(id) {
|
|
40
|
+
return nodesLiveMap.get(id)?.toJSON();
|
|
41
|
+
}
|
|
42
|
+
function getEdge(id) {
|
|
43
|
+
return edgesLiveMap.get(id)?.toJSON();
|
|
44
|
+
}
|
|
45
|
+
function upsertNode(id, newNode) {
|
|
46
|
+
const existing = nodesLiveMap.get(id);
|
|
47
|
+
const syncConfig = getNodeSyncConfig(newNode.type);
|
|
48
|
+
if (!existing) {
|
|
49
|
+
nodesLiveMap.set(id, shared.toLiveblocksInternalNode(newNode, syncConfig));
|
|
50
|
+
} else {
|
|
51
|
+
existing.reconcile(newNode, syncConfig);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function upsertEdge(id, newEdge) {
|
|
55
|
+
const existing = edgesLiveMap.get(id);
|
|
56
|
+
const syncConfig = getEdgeSyncConfig(newEdge.type);
|
|
57
|
+
if (!existing) {
|
|
58
|
+
edgesLiveMap.set(id, shared.toLiveblocksInternalEdge(newEdge, syncConfig));
|
|
59
|
+
} else {
|
|
60
|
+
existing.reconcile(newEdge, syncConfig);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const mutableFlow = {
|
|
64
|
+
get nodes() {
|
|
65
|
+
return getNodes();
|
|
66
|
+
},
|
|
67
|
+
get edges() {
|
|
68
|
+
return getEdges();
|
|
69
|
+
},
|
|
70
|
+
toJSON() {
|
|
71
|
+
return { nodes: getNodes(), edges: getEdges() };
|
|
72
|
+
},
|
|
73
|
+
getNode,
|
|
74
|
+
getEdge,
|
|
75
|
+
addNode(node) {
|
|
76
|
+
upsertNode(node.id, node);
|
|
77
|
+
},
|
|
78
|
+
addNodes(nodes) {
|
|
79
|
+
for (const node of nodes) {
|
|
80
|
+
mutableFlow.addNode(node);
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
updateNode(id, partialOrUpdater) {
|
|
84
|
+
const oldNode = getNode(id);
|
|
85
|
+
if (!oldNode)
|
|
86
|
+
return;
|
|
87
|
+
let newNode;
|
|
88
|
+
if (typeof partialOrUpdater === "function") {
|
|
89
|
+
newNode = partialOrUpdater(oldNode);
|
|
90
|
+
} else {
|
|
91
|
+
newNode = { ...oldNode, ...partialOrUpdater };
|
|
92
|
+
}
|
|
93
|
+
return upsertNode(id, newNode);
|
|
94
|
+
},
|
|
95
|
+
updateNodeData(id, partialOrUpdater) {
|
|
96
|
+
return mutableFlow.updateNode(id, (node) => {
|
|
97
|
+
const currData = node.data ?? {};
|
|
98
|
+
const newData = typeof partialOrUpdater === "function" ? partialOrUpdater(currData) : { ...currData, ...partialOrUpdater };
|
|
99
|
+
return { ...node, data: newData };
|
|
100
|
+
});
|
|
101
|
+
},
|
|
102
|
+
removeNode(id) {
|
|
103
|
+
nodesLiveMap.delete(id);
|
|
104
|
+
},
|
|
105
|
+
removeNodes(ids) {
|
|
106
|
+
for (const id of ids) {
|
|
107
|
+
nodesLiveMap.delete(id);
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
addEdge(edge) {
|
|
111
|
+
upsertEdge(edge.id, edge);
|
|
112
|
+
},
|
|
113
|
+
addEdges(edges) {
|
|
114
|
+
for (const edge of edges) {
|
|
115
|
+
mutableFlow.addEdge(edge);
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
updateEdge(id, partialOrUpdater) {
|
|
119
|
+
const oldEdge = getEdge(id);
|
|
120
|
+
if (!oldEdge)
|
|
121
|
+
return;
|
|
122
|
+
let newEdge;
|
|
123
|
+
if (typeof partialOrUpdater === "function") {
|
|
124
|
+
newEdge = partialOrUpdater(oldEdge);
|
|
125
|
+
} else {
|
|
126
|
+
newEdge = { ...oldEdge, ...partialOrUpdater };
|
|
127
|
+
}
|
|
128
|
+
return upsertEdge(id, newEdge);
|
|
129
|
+
},
|
|
130
|
+
updateEdgeData(id, partialOrUpdater) {
|
|
131
|
+
return mutableFlow.updateEdge(id, (edge) => {
|
|
132
|
+
const currData = edge.data;
|
|
133
|
+
const newData = typeof partialOrUpdater === "function" ? partialOrUpdater(currData) : { ...currData, ...partialOrUpdater };
|
|
134
|
+
return { ...edge, data: newData };
|
|
135
|
+
});
|
|
136
|
+
},
|
|
137
|
+
removeEdge(id) {
|
|
138
|
+
edgesLiveMap.delete(id);
|
|
139
|
+
},
|
|
140
|
+
removeEdges(ids) {
|
|
141
|
+
for (const id of ids) {
|
|
142
|
+
edgesLiveMap.delete(id);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
await callback(mutableFlow);
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
exports.mutateFlow = mutateFlow;
|
|
151
|
+
//# sourceMappingURL=node.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node.cjs","sources":["../src/node.ts"],"sourcesContent":["import type { JsonObject, LsonObject } from \"@liveblocks/core\";\nimport { LiveMap, LiveObject } from \"@liveblocks/core\";\nimport type { BuiltInEdge, BuiltInNode, Edge, Node } from \"@xyflow/react\";\n\nimport {\n buildEdgeConfigCache,\n buildNodeConfigCache,\n DEFAULT_STORAGE_KEY,\n toLiveblocksInternalEdge,\n toLiveblocksInternalNode,\n} from \"./lib/shared\";\nimport type {\n EdgeSyncConfig,\n InternalLiveblocksFlow,\n NodeSyncConfig,\n} from \"./lib/types\";\n\n/**\n * A minimal interface for the Liveblocks Node client — just the\n * `mutateStorage` method we actually need. This avoids importing\n * `@liveblocks/node` as a dependency.\n */\ninterface ILiveblocksClient {\n mutateStorage(\n roomId: string,\n callback: (context: {\n root: LiveObject<LsonObject>;\n }) => void | Promise<void>\n ): Promise<void>;\n}\n\n/** Options for `mutateFlow()`. */\nexport interface MutateFlowOptions<\n N extends Node = BuiltInNode,\n E extends Edge = BuiltInEdge,\n> {\n client: ILiveblocksClient;\n roomId: string;\n storageKey?: string;\n nodes?: { sync?: NodeSyncConfig<N> };\n edges?: { sync?: EdgeSyncConfig<E> };\n}\n\nexport interface MutableFlow<N extends Node, E extends Edge> {\n /** The current list of nodes. */\n readonly nodes: readonly N[];\n /** The current list of edges. */\n readonly edges: readonly E[];\n /** Returns a plain object snapshot with `nodes` and `edges` arrays. */\n toJSON(): {\n nodes: readonly N[];\n edges: readonly E[];\n };\n\n /** Returns a single node by ID, or `undefined` if not found. */\n getNode(id: string): N | undefined;\n /** Returns a single edge by ID, or `undefined` if not found. */\n getEdge(id: string): E | undefined;\n\n /** Adds a node. If a node with the same ID already exists, it is replaced. */\n addNode(node: N): void;\n /** Adds multiple nodes. Existing nodes with the same IDs are replaced. */\n addNodes(nodes: N[]): void;\n /** Updates a node by merging a partial object. No-op if the node does not exist. */\n updateNode(id: string, partial: Partial<N>): void;\n /** Updates a node using an updater function. Always return a new object, never mutate in-place. No-op if the node does not exist. */\n updateNode(id: string, updater: (node: N) => N): void;\n /** Updates a node's `data` by merging a partial object. No-op if the node does not exist. */\n updateNodeData(id: string, partial: Partial<N[\"data\"]>): void;\n /** Updates a node's `data` using an updater function. Always return a new object, never mutate in-place. No-op if the node does not exist. */\n updateNodeData<D extends N[\"data\"]>(\n id: string,\n updater: (data: D) => D\n ): void;\n /** Removes a node by ID. */\n removeNode(id: string): void;\n /** Removes multiple nodes by ID. */\n removeNodes(ids: string[]): void;\n\n /** Adds an edge. If an edge with the same ID already exists, it is replaced. */\n addEdge(edge: E): void;\n /** Adds multiple edges. Existing edges with the same IDs are replaced. */\n addEdges(edges: E[]): void;\n /** Updates an edge by merging a partial object. No-op if the edge does not exist. */\n updateEdge(id: string, partial: Partial<E>): void;\n /** Updates an edge using an updater function. Always return a new object, never mutate in-place. No-op if the edge does not exist. */\n updateEdge(id: string, updater: (edge: E) => E): void;\n /** Updates an edge's `data` by merging a partial object. No-op if the edge does not exist. */\n updateEdgeData(id: string, partial: Partial<NonNullable<E[\"data\"]>>): void;\n /** Updates an edge's `data` using an updater function. Always return a new object, never mutate in-place. No-op if the edge does not exist. */\n updateEdgeData<D extends E[\"data\"]>(\n id: string,\n updater: (data: D) => D\n ): void;\n /** Removes an edge by ID. */\n removeEdge(id: string): void;\n /** Removes multiple edges by ID. */\n removeEdges(ids: string[]): void;\n}\n\n/**\n * Opens a flow (a collection of React Flow nodes and edges) for reading and\n * mutating, then automatically flushes all changes when the callback\n * completes.\n *\n * @example\n * ```ts\n * await mutateFlow({ client, roomId: \"my-room\" }, (flow) => {\n * flow.addNode({ id: \"1\", position: { x: 0, y: 0 }, data: {} });\n * flow.updateNodeData(\"1\", { label: \"Hello\" });\n * });\n * ```\n */\nexport async function mutateFlow<\n N extends Node = BuiltInNode,\n E extends Edge = BuiltInEdge,\n>(\n options: MutateFlowOptions<N, E>,\n callback: (flow: MutableFlow<N, E>) => void | Promise<void>\n): Promise<void> {\n const { client, roomId } = options;\n const storageKey = options.storageKey ?? DEFAULT_STORAGE_KEY;\n\n const getNodeSyncConfig = buildNodeConfigCache(options.nodes?.sync);\n const getEdgeSyncConfig = buildEdgeConfigCache(options.edges?.sync);\n\n const nodeListCache = new WeakMap<Record<string, N>, N[]>();\n const edgeListCache = new WeakMap<Record<string, E>, E[]>();\n\n await client.mutateStorage(roomId, async ({ root }) => {\n let flow = root.get(storageKey) as InternalLiveblocksFlow | undefined;\n if (!flow) {\n const newFlow = new LiveObject({\n nodes: new LiveMap(),\n edges: new LiveMap(),\n }) satisfies InternalLiveblocksFlow;\n root.set(storageKey, newFlow);\n flow = newFlow;\n }\n\n const nodesLiveMap = flow.get(\"nodes\");\n const edgesLiveMap = flow.get(\"edges\");\n\n function getNodes(): readonly N[] {\n const nodeMap = nodesLiveMap.toJSON() as unknown as Record<string, N>;\n if (!nodeListCache.has(nodeMap)) {\n // TODO (LB-3665): To support sub-nodes, this function will need to emit nodes\n // in topological order (parents before children), deferring any node with a\n // parentId until its parent has been emitted.\n nodeListCache.set(nodeMap, Object.values(nodeMap));\n }\n return nodeListCache.get(nodeMap)!;\n }\n\n function getEdges(): readonly E[] {\n const edgeMap = edgesLiveMap.toJSON() as unknown as Record<string, E>;\n if (!edgeListCache.has(edgeMap)) {\n edgeListCache.set(edgeMap, Object.values(edgeMap));\n }\n return edgeListCache.get(edgeMap)!;\n }\n\n function getNode(id: string) {\n return nodesLiveMap.get(id)?.toJSON() as N | undefined;\n }\n function getEdge(id: string) {\n return edgesLiveMap.get(id)?.toJSON() as E | undefined;\n }\n\n function upsertNode(id: string, newNode: N) {\n const existing = nodesLiveMap.get(id);\n const syncConfig = getNodeSyncConfig(newNode.type);\n if (!existing) {\n nodesLiveMap.set(id, toLiveblocksInternalNode(newNode, syncConfig));\n } else {\n existing.reconcile(newNode as unknown as JsonObject, syncConfig);\n }\n }\n\n function upsertEdge(id: string, newEdge: E) {\n const existing = edgesLiveMap.get(id);\n const syncConfig = getEdgeSyncConfig(newEdge.type);\n if (!existing) {\n edgesLiveMap.set(id, toLiveblocksInternalEdge(newEdge, syncConfig));\n } else {\n existing.reconcile(newEdge as unknown as JsonObject, syncConfig);\n }\n }\n\n const mutableFlow: MutableFlow<N, E> = {\n get nodes() {\n return getNodes();\n },\n get edges() {\n return getEdges();\n },\n toJSON() {\n return { nodes: getNodes(), edges: getEdges() };\n },\n getNode,\n getEdge,\n\n addNode(node: N) {\n upsertNode(node.id, node);\n },\n addNodes(nodes: N[]) {\n for (const node of nodes) {\n mutableFlow.addNode(node);\n }\n },\n updateNode(id: string, partialOrUpdater: Partial<N> | ((node: N) => N)) {\n const oldNode = getNode(id);\n if (!oldNode) return;\n\n let newNode: N;\n if (typeof partialOrUpdater === \"function\") {\n newNode = partialOrUpdater(oldNode);\n } else {\n newNode = { ...oldNode, ...partialOrUpdater };\n }\n return upsertNode(id, newNode);\n },\n updateNodeData(\n id: string,\n partialOrUpdater:\n | Partial<N[\"data\"]>\n | (<D extends N[\"data\"]>(data: D) => D)\n ) {\n return mutableFlow.updateNode(id, (node) => {\n const currData = node.data ?? ({} as N[\"data\"]);\n const newData =\n typeof partialOrUpdater === \"function\"\n ? partialOrUpdater(currData)\n : { ...currData, ...partialOrUpdater };\n return { ...node, data: newData };\n });\n },\n removeNode(id: string) {\n nodesLiveMap.delete(id);\n },\n removeNodes(ids: string[]) {\n for (const id of ids) {\n nodesLiveMap.delete(id);\n }\n },\n\n addEdge(edge: E) {\n upsertEdge(edge.id, edge);\n },\n addEdges(edges: E[]) {\n for (const edge of edges) {\n mutableFlow.addEdge(edge);\n }\n },\n updateEdge(id: string, partialOrUpdater: Partial<E> | ((edge: E) => E)) {\n const oldEdge = getEdge(id);\n if (!oldEdge) return;\n\n let newEdge: E;\n if (typeof partialOrUpdater === \"function\") {\n newEdge = partialOrUpdater(oldEdge);\n } else {\n newEdge = { ...oldEdge, ...partialOrUpdater };\n }\n return upsertEdge(id, newEdge);\n },\n updateEdgeData(\n id: string,\n partialOrUpdater:\n | Partial<NonNullable<E[\"data\"]>>\n | (<D extends E[\"data\"]>(data: D) => D)\n ) {\n return mutableFlow.updateEdge(id, (edge) => {\n const currData = edge.data;\n const newData =\n typeof partialOrUpdater === \"function\"\n ? partialOrUpdater(currData)\n : { ...currData, ...partialOrUpdater };\n return { ...edge, data: newData };\n });\n },\n removeEdge(id: string) {\n edgesLiveMap.delete(id);\n },\n removeEdges(ids: string[]) {\n for (const id of ids) {\n edgesLiveMap.delete(id);\n }\n },\n };\n\n await callback(mutableFlow);\n });\n}\n"],"names":["DEFAULT_STORAGE_KEY","buildNodeConfigCache","buildEdgeConfigCache","LiveObject","LiveMap","toLiveblocksInternalNode","toLiveblocksInternalEdge"],"mappings":"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"}
|
package/dist/node.d.cts
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { SyncConfig, LiveObject, LsonObject } from '@liveblocks/core';
|
|
2
|
+
import { Node, Edge, BuiltInNode, BuiltInEdge } from '@xyflow/react';
|
|
3
|
+
|
|
4
|
+
type InferNodeTypeLiterals<N> = N extends Node<any, infer T extends string> ? string extends T ? never : T : never;
|
|
5
|
+
type NodeTypeLiterals<N> = (string & {}) | "*" | InferNodeTypeLiterals<N>;
|
|
6
|
+
type InferEdgeTypeLiterals<E> = E extends Edge<any, infer T extends string> ? string extends T ? never : T : never;
|
|
7
|
+
type EdgeTypeLiterals<E> = (string & {}) | "*" | InferEdgeTypeLiterals<E>;
|
|
8
|
+
type NodeSyncConfig<N extends Node> = {
|
|
9
|
+
[key in NodeTypeLiterals<N>]?: SyncConfig;
|
|
10
|
+
};
|
|
11
|
+
type EdgeSyncConfig<E extends Edge> = {
|
|
12
|
+
[key in EdgeTypeLiterals<E>]?: SyncConfig;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* A minimal interface for the Liveblocks Node client — just the
|
|
17
|
+
* `mutateStorage` method we actually need. This avoids importing
|
|
18
|
+
* `@liveblocks/node` as a dependency.
|
|
19
|
+
*/
|
|
20
|
+
interface ILiveblocksClient {
|
|
21
|
+
mutateStorage(roomId: string, callback: (context: {
|
|
22
|
+
root: LiveObject<LsonObject>;
|
|
23
|
+
}) => void | Promise<void>): Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
/** Options for `mutateFlow()`. */
|
|
26
|
+
interface MutateFlowOptions<N extends Node = BuiltInNode, E extends Edge = BuiltInEdge> {
|
|
27
|
+
client: ILiveblocksClient;
|
|
28
|
+
roomId: string;
|
|
29
|
+
storageKey?: string;
|
|
30
|
+
nodes?: {
|
|
31
|
+
sync?: NodeSyncConfig<N>;
|
|
32
|
+
};
|
|
33
|
+
edges?: {
|
|
34
|
+
sync?: EdgeSyncConfig<E>;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
interface MutableFlow<N extends Node, E extends Edge> {
|
|
38
|
+
/** The current list of nodes. */
|
|
39
|
+
readonly nodes: readonly N[];
|
|
40
|
+
/** The current list of edges. */
|
|
41
|
+
readonly edges: readonly E[];
|
|
42
|
+
/** Returns a plain object snapshot with `nodes` and `edges` arrays. */
|
|
43
|
+
toJSON(): {
|
|
44
|
+
nodes: readonly N[];
|
|
45
|
+
edges: readonly E[];
|
|
46
|
+
};
|
|
47
|
+
/** Returns a single node by ID, or `undefined` if not found. */
|
|
48
|
+
getNode(id: string): N | undefined;
|
|
49
|
+
/** Returns a single edge by ID, or `undefined` if not found. */
|
|
50
|
+
getEdge(id: string): E | undefined;
|
|
51
|
+
/** Adds a node. If a node with the same ID already exists, it is replaced. */
|
|
52
|
+
addNode(node: N): void;
|
|
53
|
+
/** Adds multiple nodes. Existing nodes with the same IDs are replaced. */
|
|
54
|
+
addNodes(nodes: N[]): void;
|
|
55
|
+
/** Updates a node by merging a partial object. No-op if the node does not exist. */
|
|
56
|
+
updateNode(id: string, partial: Partial<N>): void;
|
|
57
|
+
/** Updates a node using an updater function. Always return a new object, never mutate in-place. No-op if the node does not exist. */
|
|
58
|
+
updateNode(id: string, updater: (node: N) => N): void;
|
|
59
|
+
/** Updates a node's `data` by merging a partial object. No-op if the node does not exist. */
|
|
60
|
+
updateNodeData(id: string, partial: Partial<N["data"]>): void;
|
|
61
|
+
/** Updates a node's `data` using an updater function. Always return a new object, never mutate in-place. No-op if the node does not exist. */
|
|
62
|
+
updateNodeData<D extends N["data"]>(id: string, updater: (data: D) => D): void;
|
|
63
|
+
/** Removes a node by ID. */
|
|
64
|
+
removeNode(id: string): void;
|
|
65
|
+
/** Removes multiple nodes by ID. */
|
|
66
|
+
removeNodes(ids: string[]): void;
|
|
67
|
+
/** Adds an edge. If an edge with the same ID already exists, it is replaced. */
|
|
68
|
+
addEdge(edge: E): void;
|
|
69
|
+
/** Adds multiple edges. Existing edges with the same IDs are replaced. */
|
|
70
|
+
addEdges(edges: E[]): void;
|
|
71
|
+
/** Updates an edge by merging a partial object. No-op if the edge does not exist. */
|
|
72
|
+
updateEdge(id: string, partial: Partial<E>): void;
|
|
73
|
+
/** Updates an edge using an updater function. Always return a new object, never mutate in-place. No-op if the edge does not exist. */
|
|
74
|
+
updateEdge(id: string, updater: (edge: E) => E): void;
|
|
75
|
+
/** Updates an edge's `data` by merging a partial object. No-op if the edge does not exist. */
|
|
76
|
+
updateEdgeData(id: string, partial: Partial<NonNullable<E["data"]>>): void;
|
|
77
|
+
/** Updates an edge's `data` using an updater function. Always return a new object, never mutate in-place. No-op if the edge does not exist. */
|
|
78
|
+
updateEdgeData<D extends E["data"]>(id: string, updater: (data: D) => D): void;
|
|
79
|
+
/** Removes an edge by ID. */
|
|
80
|
+
removeEdge(id: string): void;
|
|
81
|
+
/** Removes multiple edges by ID. */
|
|
82
|
+
removeEdges(ids: string[]): void;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Opens a flow (a collection of React Flow nodes and edges) for reading and
|
|
86
|
+
* mutating, then automatically flushes all changes when the callback
|
|
87
|
+
* completes.
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```ts
|
|
91
|
+
* await mutateFlow({ client, roomId: "my-room" }, (flow) => {
|
|
92
|
+
* flow.addNode({ id: "1", position: { x: 0, y: 0 }, data: {} });
|
|
93
|
+
* flow.updateNodeData("1", { label: "Hello" });
|
|
94
|
+
* });
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
declare function mutateFlow<N extends Node = BuiltInNode, E extends Edge = BuiltInEdge>(options: MutateFlowOptions<N, E>, callback: (flow: MutableFlow<N, E>) => void | Promise<void>): Promise<void>;
|
|
98
|
+
|
|
99
|
+
export { MutableFlow, MutateFlowOptions, mutateFlow };
|
package/dist/node.d.ts
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { SyncConfig, LiveObject, LsonObject } from '@liveblocks/core';
|
|
2
|
+
import { Node, Edge, BuiltInNode, BuiltInEdge } from '@xyflow/react';
|
|
3
|
+
|
|
4
|
+
type InferNodeTypeLiterals<N> = N extends Node<any, infer T extends string> ? string extends T ? never : T : never;
|
|
5
|
+
type NodeTypeLiterals<N> = (string & {}) | "*" | InferNodeTypeLiterals<N>;
|
|
6
|
+
type InferEdgeTypeLiterals<E> = E extends Edge<any, infer T extends string> ? string extends T ? never : T : never;
|
|
7
|
+
type EdgeTypeLiterals<E> = (string & {}) | "*" | InferEdgeTypeLiterals<E>;
|
|
8
|
+
type NodeSyncConfig<N extends Node> = {
|
|
9
|
+
[key in NodeTypeLiterals<N>]?: SyncConfig;
|
|
10
|
+
};
|
|
11
|
+
type EdgeSyncConfig<E extends Edge> = {
|
|
12
|
+
[key in EdgeTypeLiterals<E>]?: SyncConfig;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* A minimal interface for the Liveblocks Node client — just the
|
|
17
|
+
* `mutateStorage` method we actually need. This avoids importing
|
|
18
|
+
* `@liveblocks/node` as a dependency.
|
|
19
|
+
*/
|
|
20
|
+
interface ILiveblocksClient {
|
|
21
|
+
mutateStorage(roomId: string, callback: (context: {
|
|
22
|
+
root: LiveObject<LsonObject>;
|
|
23
|
+
}) => void | Promise<void>): Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
/** Options for `mutateFlow()`. */
|
|
26
|
+
interface MutateFlowOptions<N extends Node = BuiltInNode, E extends Edge = BuiltInEdge> {
|
|
27
|
+
client: ILiveblocksClient;
|
|
28
|
+
roomId: string;
|
|
29
|
+
storageKey?: string;
|
|
30
|
+
nodes?: {
|
|
31
|
+
sync?: NodeSyncConfig<N>;
|
|
32
|
+
};
|
|
33
|
+
edges?: {
|
|
34
|
+
sync?: EdgeSyncConfig<E>;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
interface MutableFlow<N extends Node, E extends Edge> {
|
|
38
|
+
/** The current list of nodes. */
|
|
39
|
+
readonly nodes: readonly N[];
|
|
40
|
+
/** The current list of edges. */
|
|
41
|
+
readonly edges: readonly E[];
|
|
42
|
+
/** Returns a plain object snapshot with `nodes` and `edges` arrays. */
|
|
43
|
+
toJSON(): {
|
|
44
|
+
nodes: readonly N[];
|
|
45
|
+
edges: readonly E[];
|
|
46
|
+
};
|
|
47
|
+
/** Returns a single node by ID, or `undefined` if not found. */
|
|
48
|
+
getNode(id: string): N | undefined;
|
|
49
|
+
/** Returns a single edge by ID, or `undefined` if not found. */
|
|
50
|
+
getEdge(id: string): E | undefined;
|
|
51
|
+
/** Adds a node. If a node with the same ID already exists, it is replaced. */
|
|
52
|
+
addNode(node: N): void;
|
|
53
|
+
/** Adds multiple nodes. Existing nodes with the same IDs are replaced. */
|
|
54
|
+
addNodes(nodes: N[]): void;
|
|
55
|
+
/** Updates a node by merging a partial object. No-op if the node does not exist. */
|
|
56
|
+
updateNode(id: string, partial: Partial<N>): void;
|
|
57
|
+
/** Updates a node using an updater function. Always return a new object, never mutate in-place. No-op if the node does not exist. */
|
|
58
|
+
updateNode(id: string, updater: (node: N) => N): void;
|
|
59
|
+
/** Updates a node's `data` by merging a partial object. No-op if the node does not exist. */
|
|
60
|
+
updateNodeData(id: string, partial: Partial<N["data"]>): void;
|
|
61
|
+
/** Updates a node's `data` using an updater function. Always return a new object, never mutate in-place. No-op if the node does not exist. */
|
|
62
|
+
updateNodeData<D extends N["data"]>(id: string, updater: (data: D) => D): void;
|
|
63
|
+
/** Removes a node by ID. */
|
|
64
|
+
removeNode(id: string): void;
|
|
65
|
+
/** Removes multiple nodes by ID. */
|
|
66
|
+
removeNodes(ids: string[]): void;
|
|
67
|
+
/** Adds an edge. If an edge with the same ID already exists, it is replaced. */
|
|
68
|
+
addEdge(edge: E): void;
|
|
69
|
+
/** Adds multiple edges. Existing edges with the same IDs are replaced. */
|
|
70
|
+
addEdges(edges: E[]): void;
|
|
71
|
+
/** Updates an edge by merging a partial object. No-op if the edge does not exist. */
|
|
72
|
+
updateEdge(id: string, partial: Partial<E>): void;
|
|
73
|
+
/** Updates an edge using an updater function. Always return a new object, never mutate in-place. No-op if the edge does not exist. */
|
|
74
|
+
updateEdge(id: string, updater: (edge: E) => E): void;
|
|
75
|
+
/** Updates an edge's `data` by merging a partial object. No-op if the edge does not exist. */
|
|
76
|
+
updateEdgeData(id: string, partial: Partial<NonNullable<E["data"]>>): void;
|
|
77
|
+
/** Updates an edge's `data` using an updater function. Always return a new object, never mutate in-place. No-op if the edge does not exist. */
|
|
78
|
+
updateEdgeData<D extends E["data"]>(id: string, updater: (data: D) => D): void;
|
|
79
|
+
/** Removes an edge by ID. */
|
|
80
|
+
removeEdge(id: string): void;
|
|
81
|
+
/** Removes multiple edges by ID. */
|
|
82
|
+
removeEdges(ids: string[]): void;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Opens a flow (a collection of React Flow nodes and edges) for reading and
|
|
86
|
+
* mutating, then automatically flushes all changes when the callback
|
|
87
|
+
* completes.
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```ts
|
|
91
|
+
* await mutateFlow({ client, roomId: "my-room" }, (flow) => {
|
|
92
|
+
* flow.addNode({ id: "1", position: { x: 0, y: 0 }, data: {} });
|
|
93
|
+
* flow.updateNodeData("1", { label: "Hello" });
|
|
94
|
+
* });
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
declare function mutateFlow<N extends Node = BuiltInNode, E extends Edge = BuiltInEdge>(options: MutateFlowOptions<N, E>, callback: (flow: MutableFlow<N, E>) => void | Promise<void>): Promise<void>;
|
|
98
|
+
|
|
99
|
+
export { MutableFlow, MutateFlowOptions, mutateFlow };
|
package/dist/node.js
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { LiveObject, LiveMap } from '@liveblocks/core';
|
|
2
|
+
import { DEFAULT_STORAGE_KEY, buildNodeConfigCache, buildEdgeConfigCache, toLiveblocksInternalNode, toLiveblocksInternalEdge } from './lib/shared.js';
|
|
3
|
+
|
|
4
|
+
async function mutateFlow(options, callback) {
|
|
5
|
+
const { client, roomId } = options;
|
|
6
|
+
const storageKey = options.storageKey ?? DEFAULT_STORAGE_KEY;
|
|
7
|
+
const getNodeSyncConfig = buildNodeConfigCache(options.nodes?.sync);
|
|
8
|
+
const getEdgeSyncConfig = buildEdgeConfigCache(options.edges?.sync);
|
|
9
|
+
const nodeListCache = /* @__PURE__ */ new WeakMap();
|
|
10
|
+
const edgeListCache = /* @__PURE__ */ new WeakMap();
|
|
11
|
+
await client.mutateStorage(roomId, async ({ root }) => {
|
|
12
|
+
let flow = root.get(storageKey);
|
|
13
|
+
if (!flow) {
|
|
14
|
+
const newFlow = new LiveObject({
|
|
15
|
+
nodes: new LiveMap(),
|
|
16
|
+
edges: new LiveMap()
|
|
17
|
+
});
|
|
18
|
+
root.set(storageKey, newFlow);
|
|
19
|
+
flow = newFlow;
|
|
20
|
+
}
|
|
21
|
+
const nodesLiveMap = flow.get("nodes");
|
|
22
|
+
const edgesLiveMap = flow.get("edges");
|
|
23
|
+
function getNodes() {
|
|
24
|
+
const nodeMap = nodesLiveMap.toJSON();
|
|
25
|
+
if (!nodeListCache.has(nodeMap)) {
|
|
26
|
+
nodeListCache.set(nodeMap, Object.values(nodeMap));
|
|
27
|
+
}
|
|
28
|
+
return nodeListCache.get(nodeMap);
|
|
29
|
+
}
|
|
30
|
+
function getEdges() {
|
|
31
|
+
const edgeMap = edgesLiveMap.toJSON();
|
|
32
|
+
if (!edgeListCache.has(edgeMap)) {
|
|
33
|
+
edgeListCache.set(edgeMap, Object.values(edgeMap));
|
|
34
|
+
}
|
|
35
|
+
return edgeListCache.get(edgeMap);
|
|
36
|
+
}
|
|
37
|
+
function getNode(id) {
|
|
38
|
+
return nodesLiveMap.get(id)?.toJSON();
|
|
39
|
+
}
|
|
40
|
+
function getEdge(id) {
|
|
41
|
+
return edgesLiveMap.get(id)?.toJSON();
|
|
42
|
+
}
|
|
43
|
+
function upsertNode(id, newNode) {
|
|
44
|
+
const existing = nodesLiveMap.get(id);
|
|
45
|
+
const syncConfig = getNodeSyncConfig(newNode.type);
|
|
46
|
+
if (!existing) {
|
|
47
|
+
nodesLiveMap.set(id, toLiveblocksInternalNode(newNode, syncConfig));
|
|
48
|
+
} else {
|
|
49
|
+
existing.reconcile(newNode, syncConfig);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function upsertEdge(id, newEdge) {
|
|
53
|
+
const existing = edgesLiveMap.get(id);
|
|
54
|
+
const syncConfig = getEdgeSyncConfig(newEdge.type);
|
|
55
|
+
if (!existing) {
|
|
56
|
+
edgesLiveMap.set(id, toLiveblocksInternalEdge(newEdge, syncConfig));
|
|
57
|
+
} else {
|
|
58
|
+
existing.reconcile(newEdge, syncConfig);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
const mutableFlow = {
|
|
62
|
+
get nodes() {
|
|
63
|
+
return getNodes();
|
|
64
|
+
},
|
|
65
|
+
get edges() {
|
|
66
|
+
return getEdges();
|
|
67
|
+
},
|
|
68
|
+
toJSON() {
|
|
69
|
+
return { nodes: getNodes(), edges: getEdges() };
|
|
70
|
+
},
|
|
71
|
+
getNode,
|
|
72
|
+
getEdge,
|
|
73
|
+
addNode(node) {
|
|
74
|
+
upsertNode(node.id, node);
|
|
75
|
+
},
|
|
76
|
+
addNodes(nodes) {
|
|
77
|
+
for (const node of nodes) {
|
|
78
|
+
mutableFlow.addNode(node);
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
updateNode(id, partialOrUpdater) {
|
|
82
|
+
const oldNode = getNode(id);
|
|
83
|
+
if (!oldNode)
|
|
84
|
+
return;
|
|
85
|
+
let newNode;
|
|
86
|
+
if (typeof partialOrUpdater === "function") {
|
|
87
|
+
newNode = partialOrUpdater(oldNode);
|
|
88
|
+
} else {
|
|
89
|
+
newNode = { ...oldNode, ...partialOrUpdater };
|
|
90
|
+
}
|
|
91
|
+
return upsertNode(id, newNode);
|
|
92
|
+
},
|
|
93
|
+
updateNodeData(id, partialOrUpdater) {
|
|
94
|
+
return mutableFlow.updateNode(id, (node) => {
|
|
95
|
+
const currData = node.data ?? {};
|
|
96
|
+
const newData = typeof partialOrUpdater === "function" ? partialOrUpdater(currData) : { ...currData, ...partialOrUpdater };
|
|
97
|
+
return { ...node, data: newData };
|
|
98
|
+
});
|
|
99
|
+
},
|
|
100
|
+
removeNode(id) {
|
|
101
|
+
nodesLiveMap.delete(id);
|
|
102
|
+
},
|
|
103
|
+
removeNodes(ids) {
|
|
104
|
+
for (const id of ids) {
|
|
105
|
+
nodesLiveMap.delete(id);
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
addEdge(edge) {
|
|
109
|
+
upsertEdge(edge.id, edge);
|
|
110
|
+
},
|
|
111
|
+
addEdges(edges) {
|
|
112
|
+
for (const edge of edges) {
|
|
113
|
+
mutableFlow.addEdge(edge);
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
updateEdge(id, partialOrUpdater) {
|
|
117
|
+
const oldEdge = getEdge(id);
|
|
118
|
+
if (!oldEdge)
|
|
119
|
+
return;
|
|
120
|
+
let newEdge;
|
|
121
|
+
if (typeof partialOrUpdater === "function") {
|
|
122
|
+
newEdge = partialOrUpdater(oldEdge);
|
|
123
|
+
} else {
|
|
124
|
+
newEdge = { ...oldEdge, ...partialOrUpdater };
|
|
125
|
+
}
|
|
126
|
+
return upsertEdge(id, newEdge);
|
|
127
|
+
},
|
|
128
|
+
updateEdgeData(id, partialOrUpdater) {
|
|
129
|
+
return mutableFlow.updateEdge(id, (edge) => {
|
|
130
|
+
const currData = edge.data;
|
|
131
|
+
const newData = typeof partialOrUpdater === "function" ? partialOrUpdater(currData) : { ...currData, ...partialOrUpdater };
|
|
132
|
+
return { ...edge, data: newData };
|
|
133
|
+
});
|
|
134
|
+
},
|
|
135
|
+
removeEdge(id) {
|
|
136
|
+
edgesLiveMap.delete(id);
|
|
137
|
+
},
|
|
138
|
+
removeEdges(ids) {
|
|
139
|
+
for (const id of ids) {
|
|
140
|
+
edgesLiveMap.delete(id);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
await callback(mutableFlow);
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export { mutateFlow };
|
|
149
|
+
//# sourceMappingURL=node.js.map
|
package/dist/node.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node.js","sources":["../src/node.ts"],"sourcesContent":["import type { JsonObject, LsonObject } from \"@liveblocks/core\";\nimport { LiveMap, LiveObject } from \"@liveblocks/core\";\nimport type { BuiltInEdge, BuiltInNode, Edge, Node } from \"@xyflow/react\";\n\nimport {\n buildEdgeConfigCache,\n buildNodeConfigCache,\n DEFAULT_STORAGE_KEY,\n toLiveblocksInternalEdge,\n toLiveblocksInternalNode,\n} from \"./lib/shared\";\nimport type {\n EdgeSyncConfig,\n InternalLiveblocksFlow,\n NodeSyncConfig,\n} from \"./lib/types\";\n\n/**\n * A minimal interface for the Liveblocks Node client — just the\n * `mutateStorage` method we actually need. This avoids importing\n * `@liveblocks/node` as a dependency.\n */\ninterface ILiveblocksClient {\n mutateStorage(\n roomId: string,\n callback: (context: {\n root: LiveObject<LsonObject>;\n }) => void | Promise<void>\n ): Promise<void>;\n}\n\n/** Options for `mutateFlow()`. */\nexport interface MutateFlowOptions<\n N extends Node = BuiltInNode,\n E extends Edge = BuiltInEdge,\n> {\n client: ILiveblocksClient;\n roomId: string;\n storageKey?: string;\n nodes?: { sync?: NodeSyncConfig<N> };\n edges?: { sync?: EdgeSyncConfig<E> };\n}\n\nexport interface MutableFlow<N extends Node, E extends Edge> {\n /** The current list of nodes. */\n readonly nodes: readonly N[];\n /** The current list of edges. */\n readonly edges: readonly E[];\n /** Returns a plain object snapshot with `nodes` and `edges` arrays. */\n toJSON(): {\n nodes: readonly N[];\n edges: readonly E[];\n };\n\n /** Returns a single node by ID, or `undefined` if not found. */\n getNode(id: string): N | undefined;\n /** Returns a single edge by ID, or `undefined` if not found. */\n getEdge(id: string): E | undefined;\n\n /** Adds a node. If a node with the same ID already exists, it is replaced. */\n addNode(node: N): void;\n /** Adds multiple nodes. Existing nodes with the same IDs are replaced. */\n addNodes(nodes: N[]): void;\n /** Updates a node by merging a partial object. No-op if the node does not exist. */\n updateNode(id: string, partial: Partial<N>): void;\n /** Updates a node using an updater function. Always return a new object, never mutate in-place. No-op if the node does not exist. */\n updateNode(id: string, updater: (node: N) => N): void;\n /** Updates a node's `data` by merging a partial object. No-op if the node does not exist. */\n updateNodeData(id: string, partial: Partial<N[\"data\"]>): void;\n /** Updates a node's `data` using an updater function. Always return a new object, never mutate in-place. No-op if the node does not exist. */\n updateNodeData<D extends N[\"data\"]>(\n id: string,\n updater: (data: D) => D\n ): void;\n /** Removes a node by ID. */\n removeNode(id: string): void;\n /** Removes multiple nodes by ID. */\n removeNodes(ids: string[]): void;\n\n /** Adds an edge. If an edge with the same ID already exists, it is replaced. */\n addEdge(edge: E): void;\n /** Adds multiple edges. Existing edges with the same IDs are replaced. */\n addEdges(edges: E[]): void;\n /** Updates an edge by merging a partial object. No-op if the edge does not exist. */\n updateEdge(id: string, partial: Partial<E>): void;\n /** Updates an edge using an updater function. Always return a new object, never mutate in-place. No-op if the edge does not exist. */\n updateEdge(id: string, updater: (edge: E) => E): void;\n /** Updates an edge's `data` by merging a partial object. No-op if the edge does not exist. */\n updateEdgeData(id: string, partial: Partial<NonNullable<E[\"data\"]>>): void;\n /** Updates an edge's `data` using an updater function. Always return a new object, never mutate in-place. No-op if the edge does not exist. */\n updateEdgeData<D extends E[\"data\"]>(\n id: string,\n updater: (data: D) => D\n ): void;\n /** Removes an edge by ID. */\n removeEdge(id: string): void;\n /** Removes multiple edges by ID. */\n removeEdges(ids: string[]): void;\n}\n\n/**\n * Opens a flow (a collection of React Flow nodes and edges) for reading and\n * mutating, then automatically flushes all changes when the callback\n * completes.\n *\n * @example\n * ```ts\n * await mutateFlow({ client, roomId: \"my-room\" }, (flow) => {\n * flow.addNode({ id: \"1\", position: { x: 0, y: 0 }, data: {} });\n * flow.updateNodeData(\"1\", { label: \"Hello\" });\n * });\n * ```\n */\nexport async function mutateFlow<\n N extends Node = BuiltInNode,\n E extends Edge = BuiltInEdge,\n>(\n options: MutateFlowOptions<N, E>,\n callback: (flow: MutableFlow<N, E>) => void | Promise<void>\n): Promise<void> {\n const { client, roomId } = options;\n const storageKey = options.storageKey ?? DEFAULT_STORAGE_KEY;\n\n const getNodeSyncConfig = buildNodeConfigCache(options.nodes?.sync);\n const getEdgeSyncConfig = buildEdgeConfigCache(options.edges?.sync);\n\n const nodeListCache = new WeakMap<Record<string, N>, N[]>();\n const edgeListCache = new WeakMap<Record<string, E>, E[]>();\n\n await client.mutateStorage(roomId, async ({ root }) => {\n let flow = root.get(storageKey) as InternalLiveblocksFlow | undefined;\n if (!flow) {\n const newFlow = new LiveObject({\n nodes: new LiveMap(),\n edges: new LiveMap(),\n }) satisfies InternalLiveblocksFlow;\n root.set(storageKey, newFlow);\n flow = newFlow;\n }\n\n const nodesLiveMap = flow.get(\"nodes\");\n const edgesLiveMap = flow.get(\"edges\");\n\n function getNodes(): readonly N[] {\n const nodeMap = nodesLiveMap.toJSON() as unknown as Record<string, N>;\n if (!nodeListCache.has(nodeMap)) {\n // TODO (LB-3665): To support sub-nodes, this function will need to emit nodes\n // in topological order (parents before children), deferring any node with a\n // parentId until its parent has been emitted.\n nodeListCache.set(nodeMap, Object.values(nodeMap));\n }\n return nodeListCache.get(nodeMap)!;\n }\n\n function getEdges(): readonly E[] {\n const edgeMap = edgesLiveMap.toJSON() as unknown as Record<string, E>;\n if (!edgeListCache.has(edgeMap)) {\n edgeListCache.set(edgeMap, Object.values(edgeMap));\n }\n return edgeListCache.get(edgeMap)!;\n }\n\n function getNode(id: string) {\n return nodesLiveMap.get(id)?.toJSON() as N | undefined;\n }\n function getEdge(id: string) {\n return edgesLiveMap.get(id)?.toJSON() as E | undefined;\n }\n\n function upsertNode(id: string, newNode: N) {\n const existing = nodesLiveMap.get(id);\n const syncConfig = getNodeSyncConfig(newNode.type);\n if (!existing) {\n nodesLiveMap.set(id, toLiveblocksInternalNode(newNode, syncConfig));\n } else {\n existing.reconcile(newNode as unknown as JsonObject, syncConfig);\n }\n }\n\n function upsertEdge(id: string, newEdge: E) {\n const existing = edgesLiveMap.get(id);\n const syncConfig = getEdgeSyncConfig(newEdge.type);\n if (!existing) {\n edgesLiveMap.set(id, toLiveblocksInternalEdge(newEdge, syncConfig));\n } else {\n existing.reconcile(newEdge as unknown as JsonObject, syncConfig);\n }\n }\n\n const mutableFlow: MutableFlow<N, E> = {\n get nodes() {\n return getNodes();\n },\n get edges() {\n return getEdges();\n },\n toJSON() {\n return { nodes: getNodes(), edges: getEdges() };\n },\n getNode,\n getEdge,\n\n addNode(node: N) {\n upsertNode(node.id, node);\n },\n addNodes(nodes: N[]) {\n for (const node of nodes) {\n mutableFlow.addNode(node);\n }\n },\n updateNode(id: string, partialOrUpdater: Partial<N> | ((node: N) => N)) {\n const oldNode = getNode(id);\n if (!oldNode) return;\n\n let newNode: N;\n if (typeof partialOrUpdater === \"function\") {\n newNode = partialOrUpdater(oldNode);\n } else {\n newNode = { ...oldNode, ...partialOrUpdater };\n }\n return upsertNode(id, newNode);\n },\n updateNodeData(\n id: string,\n partialOrUpdater:\n | Partial<N[\"data\"]>\n | (<D extends N[\"data\"]>(data: D) => D)\n ) {\n return mutableFlow.updateNode(id, (node) => {\n const currData = node.data ?? ({} as N[\"data\"]);\n const newData =\n typeof partialOrUpdater === \"function\"\n ? partialOrUpdater(currData)\n : { ...currData, ...partialOrUpdater };\n return { ...node, data: newData };\n });\n },\n removeNode(id: string) {\n nodesLiveMap.delete(id);\n },\n removeNodes(ids: string[]) {\n for (const id of ids) {\n nodesLiveMap.delete(id);\n }\n },\n\n addEdge(edge: E) {\n upsertEdge(edge.id, edge);\n },\n addEdges(edges: E[]) {\n for (const edge of edges) {\n mutableFlow.addEdge(edge);\n }\n },\n updateEdge(id: string, partialOrUpdater: Partial<E> | ((edge: E) => E)) {\n const oldEdge = getEdge(id);\n if (!oldEdge) return;\n\n let newEdge: E;\n if (typeof partialOrUpdater === \"function\") {\n newEdge = partialOrUpdater(oldEdge);\n } else {\n newEdge = { ...oldEdge, ...partialOrUpdater };\n }\n return upsertEdge(id, newEdge);\n },\n updateEdgeData(\n id: string,\n partialOrUpdater:\n | Partial<NonNullable<E[\"data\"]>>\n | (<D extends E[\"data\"]>(data: D) => D)\n ) {\n return mutableFlow.updateEdge(id, (edge) => {\n const currData = edge.data;\n const newData =\n typeof partialOrUpdater === \"function\"\n ? partialOrUpdater(currData)\n : { ...currData, ...partialOrUpdater };\n return { ...edge, data: newData };\n });\n },\n removeEdge(id: string) {\n edgesLiveMap.delete(id);\n },\n removeEdges(ids: string[]) {\n for (const id of ids) {\n edgesLiveMap.delete(id);\n }\n },\n };\n\n await callback(mutableFlow);\n });\n}\n"],"names":[],"mappings":"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"}
|