project-graph-mcp 2.2.4 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +81 -0
- package/CHANGELOG.md +57 -0
- package/README.md +9 -4
- package/package.json +6 -13
- package/src/compact/expand.js +2 -4
- package/src/core/graph-builder.js +2 -2
- package/src/core/parser.js +2 -2
- package/src/network/server.js +1 -2
- package/src/network/web-server.js +4 -1
- package/vendor/symbiote-node/CHANGELOG.md +31 -0
- package/vendor/symbiote-node/LICENSE +21 -0
- package/vendor/symbiote-node/README.md +206 -0
- package/vendor/symbiote-node/canvas/AutoLayout.js +725 -0
- package/vendor/symbiote-node/canvas/Breadcrumb/Breadcrumb.css.js +73 -0
- package/vendor/symbiote-node/canvas/Breadcrumb/Breadcrumb.js +93 -0
- package/vendor/symbiote-node/canvas/Breadcrumb/Breadcrumb.tpl.js +9 -0
- package/vendor/symbiote-node/canvas/CanvasConnectionRenderer.js +962 -0
- package/vendor/symbiote-node/canvas/ConnectionRenderer.js +1468 -0
- package/vendor/symbiote-node/canvas/FlowSimulator.js +323 -0
- package/vendor/symbiote-node/canvas/ForceLayout.js +189 -0
- package/vendor/symbiote-node/canvas/ForceWorker.js +1325 -0
- package/vendor/symbiote-node/canvas/GraphTabs/GraphTabs.css.js +97 -0
- package/vendor/symbiote-node/canvas/GraphTabs/GraphTabs.js +176 -0
- package/vendor/symbiote-node/canvas/GraphTabs/GraphTabs.tpl.js +12 -0
- package/vendor/symbiote-node/canvas/LODManager.js +88 -0
- package/vendor/symbiote-node/canvas/Minimap/Minimap.css.js +71 -0
- package/vendor/symbiote-node/canvas/Minimap/Minimap.js +207 -0
- package/vendor/symbiote-node/canvas/Minimap/Minimap.tpl.js +9 -0
- package/vendor/symbiote-node/canvas/NodeCanvas/NodeCanvas.css.js +261 -0
- package/vendor/symbiote-node/canvas/NodeCanvas/NodeCanvas.js +1840 -0
- package/vendor/symbiote-node/canvas/NodeCanvas/NodeCanvas.tpl.js +22 -0
- package/vendor/symbiote-node/canvas/NodeSearch/NodeSearch.css.js +97 -0
- package/vendor/symbiote-node/canvas/NodeSearch/NodeSearch.js +132 -0
- package/vendor/symbiote-node/canvas/NodeSearch/NodeSearch.tpl.js +21 -0
- package/vendor/symbiote-node/canvas/NodeViewManager.js +584 -0
- package/vendor/symbiote-node/canvas/PinExpansion.js +131 -0
- package/vendor/symbiote-node/canvas/PseudoConnection.js +80 -0
- package/vendor/symbiote-node/canvas/SubgraphManager.js +201 -0
- package/vendor/symbiote-node/canvas/SubgraphRouter.js +443 -0
- package/vendor/symbiote-node/canvas/ViewportActions.js +446 -0
- package/vendor/symbiote-node/core/Connection.js +45 -0
- package/vendor/symbiote-node/core/Editor.js +451 -0
- package/vendor/symbiote-node/core/Frame.js +31 -0
- package/vendor/symbiote-node/core/GraphMermaid.js +348 -0
- package/vendor/symbiote-node/core/GraphText.js +210 -0
- package/vendor/symbiote-node/core/Node.js +143 -0
- package/vendor/symbiote-node/core/Portal.js +104 -0
- package/vendor/symbiote-node/core/Socket.js +185 -0
- package/vendor/symbiote-node/core/SubgraphNode.js +125 -0
- package/vendor/symbiote-node/index.js +103 -0
- package/vendor/symbiote-node/inspector/InspectorPanel/InspectorPanel.css.js +361 -0
- package/vendor/symbiote-node/inspector/InspectorPanel/InspectorPanel.js +332 -0
- package/vendor/symbiote-node/inspector/InspectorPanel/InspectorPanel.tpl.js +96 -0
- package/vendor/symbiote-node/inspector/TemplatePreview/TemplatePreview.css.js +104 -0
- package/vendor/symbiote-node/inspector/TemplatePreview/TemplatePreview.js +133 -0
- package/vendor/symbiote-node/inspector/TemplatePreview/TemplatePreview.tpl.js +33 -0
- package/vendor/symbiote-node/interactions/ConnectFlow.js +307 -0
- package/vendor/symbiote-node/interactions/Drag.js +102 -0
- package/vendor/symbiote-node/interactions/Selector.js +132 -0
- package/vendor/symbiote-node/interactions/SnapGrid.js +65 -0
- package/vendor/symbiote-node/interactions/Zoom.js +140 -0
- package/vendor/symbiote-node/layout/ActionZone/ActionZone.css.js +88 -0
- package/vendor/symbiote-node/layout/ActionZone/ActionZone.js +254 -0
- package/vendor/symbiote-node/layout/ActionZone/ActionZone.tpl.js +11 -0
- package/vendor/symbiote-node/layout/Layout/Layout.css.js +88 -0
- package/vendor/symbiote-node/layout/Layout/Layout.js +622 -0
- package/vendor/symbiote-node/layout/Layout/Layout.tpl.js +25 -0
- package/vendor/symbiote-node/layout/LayoutNode/LayoutNode.css.js +293 -0
- package/vendor/symbiote-node/layout/LayoutNode/LayoutNode.js +467 -0
- package/vendor/symbiote-node/layout/LayoutNode/LayoutNode.tpl.js +33 -0
- package/vendor/symbiote-node/layout/LayoutPreview/LayoutPreview.css.js +46 -0
- package/vendor/symbiote-node/layout/LayoutPreview/LayoutPreview.js +102 -0
- package/vendor/symbiote-node/layout/LayoutPreview/LayoutPreview.tpl.js +6 -0
- package/vendor/symbiote-node/layout/LayoutRouter/LayoutRouter.js +156 -0
- package/vendor/symbiote-node/layout/LayoutRouter/routerSync.js +250 -0
- package/vendor/symbiote-node/layout/LayoutSidebar/LayoutSidebar.css.js +379 -0
- package/vendor/symbiote-node/layout/LayoutSidebar/LayoutSidebar.js +263 -0
- package/vendor/symbiote-node/layout/LayoutSidebar/LayoutSidebar.tpl.js +20 -0
- package/vendor/symbiote-node/layout/LayoutSidebar/SidebarSection.js +183 -0
- package/vendor/symbiote-node/layout/LayoutTree.js +246 -0
- package/vendor/symbiote-node/layout/PanelMenu/PanelMenu.css.js +43 -0
- package/vendor/symbiote-node/layout/PanelMenu/PanelMenu.js +89 -0
- package/vendor/symbiote-node/layout/PanelMenu/PanelMenu.tpl.js +14 -0
- package/vendor/symbiote-node/layout/index.js +16 -0
- package/vendor/symbiote-node/menu/ContextMenu/ContextMenu.css.js +61 -0
- package/vendor/symbiote-node/menu/ContextMenu/ContextMenu.js +79 -0
- package/vendor/symbiote-node/menu/ContextMenu/ContextMenu.tpl.js +19 -0
- package/vendor/symbiote-node/node/CtrlItem/CtrlItem.css.js +41 -0
- package/vendor/symbiote-node/node/CtrlItem/CtrlItem.js +24 -0
- package/vendor/symbiote-node/node/CtrlItem/CtrlItem.tpl.js +16 -0
- package/vendor/symbiote-node/node/GraphFrame/GraphFrame.css.js +65 -0
- package/vendor/symbiote-node/node/GraphFrame/GraphFrame.js +29 -0
- package/vendor/symbiote-node/node/GraphFrame/GraphFrame.tpl.js +13 -0
- package/vendor/symbiote-node/node/GraphNode/GraphNode.css.js +683 -0
- package/vendor/symbiote-node/node/GraphNode/GraphNode.js +92 -0
- package/vendor/symbiote-node/node/GraphNode/GraphNode.tpl.js +17 -0
- package/vendor/symbiote-node/node/NodeSocket/NodeSocket.js +25 -0
- package/vendor/symbiote-node/node/NodeSocket/NodeSocket.tpl.js +7 -0
- package/vendor/symbiote-node/node/PortItem/PortItem.css.js +90 -0
- package/vendor/symbiote-node/node/PortItem/PortItem.js +87 -0
- package/vendor/symbiote-node/node/PortItem/PortItem.tpl.js +10 -0
- package/vendor/symbiote-node/package.json +59 -0
- package/vendor/symbiote-node/palette/PaletteBrowser/PaletteBrowser.css.js +143 -0
- package/vendor/symbiote-node/palette/PaletteBrowser/PaletteBrowser.js +131 -0
- package/vendor/symbiote-node/palette/PaletteBrowser/PaletteBrowser.tpl.js +16 -0
- package/vendor/symbiote-node/plugins/History.js +384 -0
- package/vendor/symbiote-node/plugins/Readonly.js +59 -0
- package/vendor/symbiote-node/shapes/CircleShape.js +80 -0
- package/vendor/symbiote-node/shapes/CommentShape.js +35 -0
- package/vendor/symbiote-node/shapes/DiamondShape.js +115 -0
- package/vendor/symbiote-node/shapes/NodeShape.js +80 -0
- package/vendor/symbiote-node/shapes/PillShape.js +91 -0
- package/vendor/symbiote-node/shapes/RectShape.js +72 -0
- package/vendor/symbiote-node/shapes/SVGShape.js +494 -0
- package/vendor/symbiote-node/shapes/index.js +53 -0
- package/vendor/symbiote-node/themes/Palette.js +32 -0
- package/vendor/symbiote-node/themes/Skin.js +113 -0
- package/vendor/symbiote-node/themes/Theme.js +84 -0
- package/vendor/symbiote-node/themes/carbon.js +137 -0
- package/vendor/symbiote-node/themes/dark.js +137 -0
- package/vendor/symbiote-node/themes/ebook.js +138 -0
- package/vendor/symbiote-node/themes/grey.js +137 -0
- package/vendor/symbiote-node/themes/light.js +137 -0
- package/vendor/symbiote-node/themes/neon.js +138 -0
- package/vendor/symbiote-node/themes/pcb.js +273 -0
- package/vendor/symbiote-node/themes/synthwave.js +137 -0
- package/vendor/symbiote-node/toolbar/QuickToolbar/QuickToolbar.css.js +86 -0
- package/vendor/symbiote-node/toolbar/QuickToolbar/QuickToolbar.js +128 -0
- package/vendor/symbiote-node/toolbar/QuickToolbar/QuickToolbar.tpl.js +29 -0
- package/web/app.js +6 -5
- package/web/components/canvas-graph.js +1666 -0
- package/web/components/event-feed/CodeWidget.js +32 -0
- package/web/components/event-feed/EventWidget.js +97 -0
- package/web/components/event-feed/ListWidget.js +57 -0
- package/web/components/event-feed/MiniGraphWidget.js +69 -0
- package/web/dashboard.js +1 -1
- package/web/index.html +4 -0
- package/web/panels/ActionBoard/ActionBoard.js +1 -1
- package/web/panels/SettingsPanel/SettingsPanel.tpl.js +1 -1
- package/web/panels/code-viewer.js +50 -15
- package/web/panels/dep-graph.js +2712 -7
- package/web/panels/file-tree.js +5 -2
- package/web/panels/live-monitor.js +75 -3
- package/web/style.css +33 -0
- package/docs/img/explorer-compact.jpg +0 -0
- package/docs/img/explorer-expanded.jpg +0 -0
- package/src/.contextignore +0 -22
- package/src/.project-graph-cache.json +0 -1
- package/src/compact/.project-graph-cache.json +0 -1
- package/web/.project-graph-cache.json +0 -1
- package/web/panels/SettingsPanel/.project-graph-cache.json +0 -1
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Portal — Named Reroutes for wireless connections
|
|
3
|
+
*
|
|
4
|
+
* Provides virtual sender/receiver pairs that act as invisible
|
|
5
|
+
* connections. PortalManager tracks named channels and resolves
|
|
6
|
+
* portal connections during graph evaluation.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* const pm = new PortalManager();
|
|
10
|
+
* pm.addSender('channelA', node1, 'output');
|
|
11
|
+
* pm.addReceiver('channelA', node2, 'input');
|
|
12
|
+
* pm.getConnections(); // returns virtual connections
|
|
13
|
+
*
|
|
14
|
+
* @module symbiote-node/core/Portal
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* PortalManager — manages named reroute channels
|
|
19
|
+
*/
|
|
20
|
+
export class PortalManager {
|
|
21
|
+
/** @type {Map<string, { senders: Array<{nodeId: string, portKey: string}>, receivers: Array<{nodeId: string, portKey: string}> }>} */
|
|
22
|
+
#channels = new Map();
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Register a sender portal
|
|
26
|
+
* @param {string} channel - Named channel
|
|
27
|
+
* @param {string} nodeId - Source node ID
|
|
28
|
+
* @param {string} portKey - Output port key
|
|
29
|
+
*/
|
|
30
|
+
addSender(channel, nodeId, portKey) {
|
|
31
|
+
if (!this.#channels.has(channel)) {
|
|
32
|
+
this.#channels.set(channel, { senders: [], receivers: [] });
|
|
33
|
+
}
|
|
34
|
+
this.#channels.get(channel).senders.push({ nodeId, portKey });
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Register a receiver portal
|
|
39
|
+
* @param {string} channel - Named channel
|
|
40
|
+
* @param {string} nodeId - Target node ID
|
|
41
|
+
* @param {string} portKey - Input port key
|
|
42
|
+
*/
|
|
43
|
+
addReceiver(channel, nodeId, portKey) {
|
|
44
|
+
if (!this.#channels.has(channel)) {
|
|
45
|
+
this.#channels.set(channel, { senders: [], receivers: [] });
|
|
46
|
+
}
|
|
47
|
+
this.#channels.get(channel).receivers.push({ nodeId, portKey });
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Remove all portals for a node
|
|
52
|
+
* @param {string} nodeId
|
|
53
|
+
*/
|
|
54
|
+
removeNode(nodeId) {
|
|
55
|
+
for (const [, ch] of this.#channels) {
|
|
56
|
+
ch.senders = ch.senders.filter(s => s.nodeId !== nodeId);
|
|
57
|
+
ch.receivers = ch.receivers.filter(r => r.nodeId !== nodeId);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Get all virtual connections from portal channels
|
|
63
|
+
* @returns {Array<{ from: string, out: string, to: string, in: string, channel: string }>}
|
|
64
|
+
*/
|
|
65
|
+
getConnections() {
|
|
66
|
+
const result = [];
|
|
67
|
+
for (const [channel, ch] of this.#channels) {
|
|
68
|
+
for (const sender of ch.senders) {
|
|
69
|
+
for (const receiver of ch.receivers) {
|
|
70
|
+
result.push({
|
|
71
|
+
from: sender.nodeId,
|
|
72
|
+
out: sender.portKey,
|
|
73
|
+
to: receiver.nodeId,
|
|
74
|
+
in: receiver.portKey,
|
|
75
|
+
channel,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return result;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Get all channel names
|
|
85
|
+
* @returns {string[]}
|
|
86
|
+
*/
|
|
87
|
+
getChannels() {
|
|
88
|
+
return [...this.#channels.keys()];
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Get channel info
|
|
93
|
+
* @param {string} channel
|
|
94
|
+
* @returns {{ senders: Array, receivers: Array }|undefined}
|
|
95
|
+
*/
|
|
96
|
+
getChannel(channel) {
|
|
97
|
+
return this.#channels.get(channel);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** Clear all portals */
|
|
101
|
+
clear() {
|
|
102
|
+
this.#channels.clear();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Socket — typed port connector
|
|
3
|
+
*
|
|
4
|
+
* Defines the type and visual identity of a connection endpoint.
|
|
5
|
+
* Compatible with symbiote-node SocketTypes system.
|
|
6
|
+
*
|
|
7
|
+
* @module symbiote-node/core/Socket
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
let _uid = 0;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Generate unique ID with prefix
|
|
14
|
+
* @param {string} prefix
|
|
15
|
+
* @returns {string}
|
|
16
|
+
*/
|
|
17
|
+
export function uid(prefix = 'id') {
|
|
18
|
+
return `${prefix}_${(++_uid).toString(36)}_${Date.now().toString(36)}`;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Socket type — defines connection endpoint type
|
|
23
|
+
*/
|
|
24
|
+
export class Socket {
|
|
25
|
+
/**
|
|
26
|
+
* @param {string} name - Socket type name (e.g. 'number', 'string', 'any')
|
|
27
|
+
* @param {object} [options]
|
|
28
|
+
* @param {string} [options.color] - CSS color for visual
|
|
29
|
+
*/
|
|
30
|
+
constructor(name, options = {}) {
|
|
31
|
+
/** @type {string} */
|
|
32
|
+
this.name = name;
|
|
33
|
+
|
|
34
|
+
/** @type {string} */
|
|
35
|
+
this.color = options.color || 'var(--clr-3)';
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Check if this socket is compatible with another
|
|
40
|
+
* @param {Socket} other
|
|
41
|
+
* @returns {boolean}
|
|
42
|
+
*/
|
|
43
|
+
isCompatibleWith(other) {
|
|
44
|
+
if (this.name === 'any' || other.name === 'any') return true;
|
|
45
|
+
return this.name === other.name;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Port — represents an input or output endpoint on a node
|
|
51
|
+
*/
|
|
52
|
+
export class Port {
|
|
53
|
+
/**
|
|
54
|
+
* @param {Socket} socket - Socket type
|
|
55
|
+
* @param {string} [label] - Display label
|
|
56
|
+
* @param {boolean} [multipleConnections=false] - Allow multiple connections
|
|
57
|
+
*/
|
|
58
|
+
constructor(socket, label, multipleConnections = false) {
|
|
59
|
+
/** @type {string} */
|
|
60
|
+
this.id = uid('port');
|
|
61
|
+
|
|
62
|
+
/** @type {Socket} */
|
|
63
|
+
this.socket = socket;
|
|
64
|
+
|
|
65
|
+
/** @type {string|undefined} */
|
|
66
|
+
this.label = label;
|
|
67
|
+
|
|
68
|
+
/** @type {boolean} */
|
|
69
|
+
this.multipleConnections = multipleConnections;
|
|
70
|
+
|
|
71
|
+
/** @type {number} */
|
|
72
|
+
this.index = 0;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Input port — accepts incoming connections
|
|
78
|
+
*/
|
|
79
|
+
export class Input extends Port {
|
|
80
|
+
/**
|
|
81
|
+
* @param {Socket} socket
|
|
82
|
+
* @param {string} [label]
|
|
83
|
+
* @param {boolean} [multipleConnections=false]
|
|
84
|
+
*/
|
|
85
|
+
constructor(socket, label, multipleConnections = false) {
|
|
86
|
+
super(socket, label, multipleConnections);
|
|
87
|
+
|
|
88
|
+
/** @type {Control|null} */
|
|
89
|
+
this.control = null;
|
|
90
|
+
|
|
91
|
+
/** @type {boolean} */
|
|
92
|
+
this.showControl = true;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Add embedded control to this input
|
|
97
|
+
* @param {Control} control
|
|
98
|
+
*/
|
|
99
|
+
addControl(control) {
|
|
100
|
+
if (this.control) throw new Error('control already added for this input');
|
|
101
|
+
this.control = control;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Remove embedded control
|
|
106
|
+
*/
|
|
107
|
+
removeControl() {
|
|
108
|
+
this.control = null;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Output port — provides outgoing connections
|
|
114
|
+
*/
|
|
115
|
+
export class Output extends Port {
|
|
116
|
+
/**
|
|
117
|
+
* @param {Socket} socket
|
|
118
|
+
* @param {string} [label]
|
|
119
|
+
* @param {boolean} [multipleConnections=true]
|
|
120
|
+
*/
|
|
121
|
+
constructor(socket, label, multipleConnections = true) {
|
|
122
|
+
super(socket, label, multipleConnections);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Control — embeddable UI widget inside a node
|
|
128
|
+
*/
|
|
129
|
+
export class Control {
|
|
130
|
+
constructor() {
|
|
131
|
+
/** @type {string} */
|
|
132
|
+
this.id = uid('ctrl');
|
|
133
|
+
|
|
134
|
+
/** @type {number} */
|
|
135
|
+
this.index = 0;
|
|
136
|
+
|
|
137
|
+
/** @type {function|undefined} */
|
|
138
|
+
this._onChange = undefined;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* InputControl — text or number input widget
|
|
144
|
+
*/
|
|
145
|
+
export class InputControl extends Control {
|
|
146
|
+
/**
|
|
147
|
+
* @param {'text'|'number'|'textarea'|'select'|'boolean'} type
|
|
148
|
+
* @param {object} [options]
|
|
149
|
+
* @param {boolean} [options.readonly=false]
|
|
150
|
+
* @param {string|number|boolean} [options.initial]
|
|
151
|
+
* @param {string} [options.label] - Display label
|
|
152
|
+
* @param {string[]} [options.options] - Options for select type
|
|
153
|
+
* @param {function} [options.change] - Callback on value change
|
|
154
|
+
*/
|
|
155
|
+
constructor(type, options = {}) {
|
|
156
|
+
super();
|
|
157
|
+
|
|
158
|
+
/** @type {'text'|'number'|'textarea'|'select'|'boolean'} */
|
|
159
|
+
this.type = type;
|
|
160
|
+
|
|
161
|
+
/** @type {boolean} */
|
|
162
|
+
this.readonly = options.readonly || false;
|
|
163
|
+
|
|
164
|
+
/** @type {string|number|boolean|undefined} */
|
|
165
|
+
this.value = options.initial;
|
|
166
|
+
|
|
167
|
+
/** @type {string} */
|
|
168
|
+
this.label = options.label || '';
|
|
169
|
+
|
|
170
|
+
/** @type {string[]} */
|
|
171
|
+
this.options = options.options || [];
|
|
172
|
+
|
|
173
|
+
/** @type {function|undefined} */
|
|
174
|
+
this._onChange = options.change;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Set control value
|
|
179
|
+
* @param {string|number|boolean} value
|
|
180
|
+
*/
|
|
181
|
+
setValue(value) {
|
|
182
|
+
this.value = value;
|
|
183
|
+
if (this._onChange) this._onChange(value);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SubgraphNode — Node containing an embedded graph
|
|
3
|
+
*
|
|
4
|
+
* Extends Node with an inner NodeEditor that holds a sub-pipeline.
|
|
5
|
+
* Ports are auto-generated from exposed inner nodes.
|
|
6
|
+
* Supports drill-down navigation via SubgraphManager.
|
|
7
|
+
*
|
|
8
|
+
* @module symbiote-node/core/SubgraphNode
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { Node } from './Node.js';
|
|
12
|
+
import { NodeEditor } from './Editor.js';
|
|
13
|
+
import { Socket, Input, Output } from './Socket.js';
|
|
14
|
+
|
|
15
|
+
export class SubgraphNode extends Node {
|
|
16
|
+
/** @type {NodeEditor} */
|
|
17
|
+
innerEditor;
|
|
18
|
+
|
|
19
|
+
/** @type {Object<string, { x: number, y: number }>} */
|
|
20
|
+
innerPositions = {};
|
|
21
|
+
|
|
22
|
+
/** @type {{ panX: number, panY: number, zoom: number }} */
|
|
23
|
+
innerTransform = { panX: 0, panY: 0, zoom: 1 };
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @param {string} label - Display name
|
|
27
|
+
* @param {object} [options={}]
|
|
28
|
+
* @param {string} [options.category='subgraph']
|
|
29
|
+
* @param {string} [options.icon='account_tree']
|
|
30
|
+
*/
|
|
31
|
+
constructor(label, options = {}) {
|
|
32
|
+
super(label, {
|
|
33
|
+
type: 'subgraph',
|
|
34
|
+
category: options.category ?? 'subgraph',
|
|
35
|
+
icon: options.icon ?? 'account_tree',
|
|
36
|
+
shape: 'rect',
|
|
37
|
+
...options,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
this.innerEditor = new NodeEditor();
|
|
41
|
+
this._isSubgraph = true;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Sync external ports with inner graph exposed nodes.
|
|
46
|
+
* Inner nodes with `_exposed: 'input'` become subgraph inputs.
|
|
47
|
+
* Inner nodes with `_exposed: 'output'` become subgraph outputs.
|
|
48
|
+
*/
|
|
49
|
+
syncPorts() {
|
|
50
|
+
// Clear existing auto-ports (keep manually added ones)
|
|
51
|
+
for (const key of Object.keys(this.inputs)) {
|
|
52
|
+
if (key.startsWith('sg_')) this.removeInput(key);
|
|
53
|
+
}
|
|
54
|
+
for (const key of Object.keys(this.outputs)) {
|
|
55
|
+
if (key.startsWith('sg_')) this.removeOutput(key);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const anySocket = new Socket('any', { color: '#94a3b8' });
|
|
59
|
+
|
|
60
|
+
// Find exposed inner nodes
|
|
61
|
+
for (const innerNode of this.innerEditor.getNodes()) {
|
|
62
|
+
if (innerNode._exposed === 'input') {
|
|
63
|
+
for (const [key, output] of Object.entries(innerNode.outputs)) {
|
|
64
|
+
const portKey = `sg_${innerNode.id}_${key}`;
|
|
65
|
+
this.addInput(portKey, new Input(
|
|
66
|
+
output.socket ?? anySocket,
|
|
67
|
+
innerNode.label ?? key
|
|
68
|
+
));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (innerNode._exposed === 'output') {
|
|
72
|
+
for (const [key, input] of Object.entries(innerNode.inputs)) {
|
|
73
|
+
const portKey = `sg_${innerNode.id}_${key}`;
|
|
74
|
+
this.addOutput(portKey, new Output(
|
|
75
|
+
input.socket ?? anySocket,
|
|
76
|
+
innerNode.label ?? key
|
|
77
|
+
));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Get inner editor
|
|
85
|
+
* @returns {NodeEditor}
|
|
86
|
+
*/
|
|
87
|
+
getInnerEditor() {
|
|
88
|
+
return this.innerEditor;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Save inner node positions
|
|
93
|
+
* @param {Object<string, { x: number, y: number }>} positions
|
|
94
|
+
*/
|
|
95
|
+
setInnerPositions(positions) {
|
|
96
|
+
this.innerPositions = { ...positions };
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Save inner viewport transform
|
|
101
|
+
* @param {{ panX: number, panY: number, zoom: number }} transform
|
|
102
|
+
*/
|
|
103
|
+
setInnerTransform(transform) {
|
|
104
|
+
this.innerTransform = { ...transform };
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Serialize subgraph node including inner graph
|
|
109
|
+
* @returns {object}
|
|
110
|
+
*/
|
|
111
|
+
toJSON() {
|
|
112
|
+
return {
|
|
113
|
+
id: this.id,
|
|
114
|
+
type: 'subgraph',
|
|
115
|
+
label: this.label,
|
|
116
|
+
category: this.category,
|
|
117
|
+
innerGraph: this.innerEditor.toJSON(
|
|
118
|
+
Object.fromEntries(
|
|
119
|
+
Object.entries(this.innerPositions).map(([id, pos]) => [id, [pos.x, pos.y]])
|
|
120
|
+
)
|
|
121
|
+
),
|
|
122
|
+
innerTransform: this.innerTransform,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* symbiote-node — Node Graph Editor for Symbiote.js
|
|
3
|
+
*
|
|
4
|
+
* Public API for the library.
|
|
5
|
+
*
|
|
6
|
+
* @module symbiote-node
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// Core
|
|
10
|
+
export { NodeEditor } from './core/Editor.js';
|
|
11
|
+
export { Node } from './core/Node.js';
|
|
12
|
+
export { Connection } from './core/Connection.js';
|
|
13
|
+
export { Frame } from './core/Frame.js';
|
|
14
|
+
export { Socket, Port, Input, Output, Control, InputControl, uid } from './core/Socket.js';
|
|
15
|
+
export { editorToText, textToGraph, textToEditor } from './core/GraphText.js';
|
|
16
|
+
export { editorToMermaid, mermaidToGraph } from './core/GraphMermaid.js';
|
|
17
|
+
|
|
18
|
+
// Canvas
|
|
19
|
+
export { NodeCanvas } from './canvas/NodeCanvas/NodeCanvas.js';
|
|
20
|
+
|
|
21
|
+
// Node components
|
|
22
|
+
export { GraphNode } from './node/GraphNode/GraphNode.js';
|
|
23
|
+
export { NodeSocket } from './node/NodeSocket/NodeSocket.js';
|
|
24
|
+
|
|
25
|
+
// Interactions
|
|
26
|
+
export { Drag } from './interactions/Drag.js';
|
|
27
|
+
export { Zoom } from './interactions/Zoom.js';
|
|
28
|
+
export { Selector } from './interactions/Selector.js';
|
|
29
|
+
export { SnapGrid } from './interactions/SnapGrid.js';
|
|
30
|
+
export { ConnectFlow } from './interactions/ConnectFlow.js';
|
|
31
|
+
|
|
32
|
+
// Shapes
|
|
33
|
+
export { NodeShape, RectShape, PillShape, CircleShape, DiamondShape, CommentShape, getShape, registerShape, SVGShape, createSVGShape, SVG_PRESETS } from './shapes/index.js';
|
|
34
|
+
|
|
35
|
+
// Themes (unified)
|
|
36
|
+
export { applyTheme, extractTheme, DARK_DEFAULT, LIGHT_CLEAN, SYNTHWAVE, GREY_NEUTRAL, NEON_GLOW } from './themes/Theme.js';
|
|
37
|
+
|
|
38
|
+
// Palette (color-only)
|
|
39
|
+
export { applyPalette, DARK_PALETTE, LIGHT_PALETTE, SYNTHWAVE_PALETTE, GREY_PALETTE } from './themes/Palette.js';
|
|
40
|
+
|
|
41
|
+
// Skin (geometry-only)
|
|
42
|
+
export { applySkin, MODERN_SKIN, COMPACT_SKIN, ROUNDED_SKIN } from './themes/Skin.js';
|
|
43
|
+
|
|
44
|
+
// Plugins
|
|
45
|
+
export { Readonly } from './plugins/Readonly.js';
|
|
46
|
+
export { History } from './plugins/History.js';
|
|
47
|
+
|
|
48
|
+
// Toolbar
|
|
49
|
+
export { QuickToolbar } from './toolbar/QuickToolbar/QuickToolbar.js';
|
|
50
|
+
export { FlowSimulator } from './canvas/FlowSimulator.js';
|
|
51
|
+
|
|
52
|
+
// Inspector
|
|
53
|
+
export { InspectorPanel } from './inspector/InspectorPanel/InspectorPanel.js';
|
|
54
|
+
|
|
55
|
+
// Minimap
|
|
56
|
+
export { Minimap } from './canvas/Minimap/Minimap.js';
|
|
57
|
+
|
|
58
|
+
// Search
|
|
59
|
+
export { NodeSearch } from './canvas/NodeSearch/NodeSearch.js';
|
|
60
|
+
|
|
61
|
+
// Layout (panel workspace)
|
|
62
|
+
export { Layout } from './layout/Layout/Layout.js';
|
|
63
|
+
export { LayoutNode } from './layout/LayoutNode/LayoutNode.js';
|
|
64
|
+
export { LayoutSidebar } from './layout/LayoutSidebar/LayoutSidebar.js';
|
|
65
|
+
export * as LayoutTree from './layout/LayoutTree.js';
|
|
66
|
+
export {
|
|
67
|
+
navigate, updateParams, parseQuery, buildHash, buildQuery,
|
|
68
|
+
getRoute, setDefaultPanel,
|
|
69
|
+
} from './layout/LayoutRouter/LayoutRouter.js';
|
|
70
|
+
export { syncWithRouter } from './layout/LayoutRouter/routerSync.js';
|
|
71
|
+
|
|
72
|
+
// Auto Layout
|
|
73
|
+
export { computeAutoLayout, computeTreeLayout } from './canvas/AutoLayout.js';
|
|
74
|
+
|
|
75
|
+
// Portals (Named Reroutes)
|
|
76
|
+
export { PortalManager } from './core/Portal.js';
|
|
77
|
+
|
|
78
|
+
// Palette Browser
|
|
79
|
+
export { PaletteBrowser } from './palette/PaletteBrowser/PaletteBrowser.js';
|
|
80
|
+
|
|
81
|
+
// Tabs
|
|
82
|
+
export { GraphTabs } from './canvas/GraphTabs/GraphTabs.js';
|
|
83
|
+
|
|
84
|
+
// Subgraphs
|
|
85
|
+
export { SubgraphNode } from './core/SubgraphNode.js';
|
|
86
|
+
export { SubgraphManager } from './canvas/SubgraphManager.js';
|
|
87
|
+
export { SubgraphRouter } from './canvas/SubgraphRouter.js';
|
|
88
|
+
export { Breadcrumb } from './canvas/Breadcrumb/Breadcrumb.js';
|
|
89
|
+
|
|
90
|
+
// Canvas utilities
|
|
91
|
+
export { LODManager } from './canvas/LODManager.js';
|
|
92
|
+
export { PinExpansion } from './canvas/PinExpansion.js';
|
|
93
|
+
export { ForceLayout } from './canvas/ForceLayout.js';
|
|
94
|
+
|
|
95
|
+
// Additional themes (not in base Theme.js barrel)
|
|
96
|
+
export { CARBON, CARBON_PALETTE } from './themes/carbon.js';
|
|
97
|
+
export { PCB_DARK } from './themes/pcb.js';
|
|
98
|
+
export { EBOOK, EBOOK_PALETTE } from './themes/ebook.js';
|
|
99
|
+
export { NEON_PALETTE } from './themes/neon.js';
|
|
100
|
+
|
|
101
|
+
// Engine (server-side graph runtime)
|
|
102
|
+
// Usage: import * as Engine from 'symbiote-node/engine'
|
|
103
|
+
// Or: import { Graph, Executor } from 'symbiote-node/engine'
|