feat(editor): round-trip pinned_input and pinned_output through graphAdapter
This commit is contained in:
@@ -47,6 +47,8 @@ export interface GraphNode {
|
||||
position: { x: number; y: number };
|
||||
config: Record<string, unknown>;
|
||||
connection_id?: string | null;
|
||||
pinned_input?: unknown;
|
||||
pinned_output?: unknown;
|
||||
}
|
||||
|
||||
export interface GraphEdge {
|
||||
|
||||
@@ -164,3 +164,73 @@ describe("toGraph — schema-typed coercion on save", () => {
|
||||
expect(g.nodes[0].config.ratio).toBe(100);
|
||||
});
|
||||
});
|
||||
|
||||
describe("graphAdapter — pinned data round-trip", () => {
|
||||
it("fromGraph copies pinned_input and pinned_output into VcNodeData", () => {
|
||||
const g = {
|
||||
nodes: [
|
||||
{
|
||||
id: "n1", type_id: "http.response",
|
||||
position: { x: 0, y: 0 }, config: {},
|
||||
pinned_input: { a: 1 },
|
||||
},
|
||||
{
|
||||
id: "t1", type_id: "http.webhook",
|
||||
position: { x: 0, y: 0 }, config: {},
|
||||
pinned_output: [{ b: 1 }],
|
||||
},
|
||||
],
|
||||
edges: [],
|
||||
};
|
||||
const { nodes } = fromGraph(g);
|
||||
expect(nodes[0].data.pinnedInput).toEqual({ a: 1 });
|
||||
expect(nodes[0].data.pinnedOutput).toBeUndefined();
|
||||
expect(nodes[1].data.pinnedOutput).toEqual([{ b: 1 }]);
|
||||
expect(nodes[1].data.pinnedInput).toBeUndefined();
|
||||
});
|
||||
|
||||
it("toGraph copies pinnedInput and pinnedOutput back to graph JSON", () => {
|
||||
const g = toGraph(
|
||||
[{
|
||||
id: "n1", type: "vc",
|
||||
position: { x: 0, y: 0 },
|
||||
data: {
|
||||
typeId: "http.response", config: {},
|
||||
pinnedInput: { a: 1 },
|
||||
},
|
||||
}, {
|
||||
id: "t1", type: "vc",
|
||||
position: { x: 0, y: 0 },
|
||||
data: {
|
||||
typeId: "http.webhook", config: {},
|
||||
pinnedOutput: [{ b: 1 }],
|
||||
},
|
||||
}],
|
||||
[],
|
||||
[],
|
||||
);
|
||||
expect(g.nodes[0].pinned_input).toEqual({ a: 1 });
|
||||
expect(g.nodes[0].pinned_output).toBeUndefined();
|
||||
expect(g.nodes[1].pinned_output).toEqual([{ b: 1 }]);
|
||||
expect(g.nodes[1].pinned_input).toBeUndefined();
|
||||
});
|
||||
|
||||
it("null pin values are dropped rather than sent as null", () => {
|
||||
// toGraph should omit the field when it's null/undefined so the wire
|
||||
// payload stays compact and unchanged for nodes that never used pins.
|
||||
const g = toGraph(
|
||||
[{
|
||||
id: "n1", type: "vc",
|
||||
position: { x: 0, y: 0 },
|
||||
data: {
|
||||
typeId: "http.response", config: {},
|
||||
pinnedInput: null, pinnedOutput: null,
|
||||
},
|
||||
}],
|
||||
[],
|
||||
[],
|
||||
);
|
||||
expect(g.nodes[0].pinned_input).toBeUndefined();
|
||||
expect(g.nodes[0].pinned_output).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,20 +6,27 @@ export interface VcNodeData extends Record<string, unknown> {
|
||||
name?: string;
|
||||
config: Record<string, unknown>;
|
||||
connection_id?: string | null;
|
||||
pinnedInput?: unknown;
|
||||
pinnedOutput?: unknown;
|
||||
}
|
||||
|
||||
export function fromGraph(g: WorkflowGraph): { nodes: Node<VcNodeData>[]; edges: Edge[] } {
|
||||
const nodes: Node<VcNodeData>[] = g.nodes.map((n) => ({
|
||||
id: n.id,
|
||||
type: "vc",
|
||||
position: { x: n.position?.x ?? 0, y: n.position?.y ?? 0 },
|
||||
data: {
|
||||
const nodes: Node<VcNodeData>[] = g.nodes.map((n) => {
|
||||
const data: VcNodeData = {
|
||||
typeId: n.type_id,
|
||||
name: n.name,
|
||||
config: n.config ?? {},
|
||||
connection_id: n.connection_id ?? null,
|
||||
},
|
||||
}));
|
||||
};
|
||||
if (n.pinned_input !== undefined && n.pinned_input !== null) data.pinnedInput = n.pinned_input;
|
||||
if (n.pinned_output !== undefined && n.pinned_output !== null) data.pinnedOutput = n.pinned_output;
|
||||
return {
|
||||
id: n.id,
|
||||
type: "vc",
|
||||
position: { x: n.position?.x ?? 0, y: n.position?.y ?? 0 },
|
||||
data,
|
||||
};
|
||||
});
|
||||
const edges: Edge[] = g.edges.map((e) => ({
|
||||
id: `${e.from_node}:${e.from_port}->${e.to_node}:${e.to_port}`,
|
||||
source: e.from_node,
|
||||
@@ -47,6 +54,8 @@ export function toGraph(
|
||||
};
|
||||
if (n.data.name !== undefined) node.name = n.data.name;
|
||||
if (n.data.connection_id != null) node.connection_id = n.data.connection_id;
|
||||
if (n.data.pinnedInput !== undefined && n.data.pinnedInput !== null) node.pinned_input = n.data.pinnedInput;
|
||||
if (n.data.pinnedOutput !== undefined && n.data.pinnedOutput !== null) node.pinned_output = n.data.pinnedOutput;
|
||||
return node;
|
||||
});
|
||||
const gEdges: GraphEdge[] = edges.map((e) => ({
|
||||
|
||||
Reference in New Issue
Block a user