Node Creation API Integration
The studio app has been updated to integrate with the central backend API for creating and persisting process nodes. This document explains the implementation and API structure.
Overview
When users add nodes to the canvas in the studio app (via sidebar, drag-and-drop, or hover actions), the frontend now automatically saves them to the backend database using the central API.
Backend API
Endpoint
POST /v1/api/process/{processId}/node
Request Structure
{
nodeType: string; // e.g., "MANUAL_TRIGGER", "HUMAN_TASK"
name: string; // Display name for the node
description?: string; // Optional description
position: { // Canvas position
x: number;
y: number;
};
configuration?: Record<string, any>; // Node-specific config
metadata?: Record<string, any>; // Additional metadata
}
Response Structure
{
statusCode: number; // 201 for success
status: string; // "Success"
message: string; // Success/error message
data: {
id: string; // Generated database ID
processId: string; // Process this node belongs to
nodeType: string; // Node type
name: string; // Node name
description?: string; // Description
position: { x: number; y: number };
configuration: Record<string, any>;
metadata: Record<string, any>;
createdAt: string; // ISO timestamp
updatedAt: string; // ISO timestamp
};
error: string | null; // Error message if any
}
Frontend Implementation
API Proxy
The studio app uses a Next.js API route as a proxy to forward requests to the central backend:
// apps/studio/app/api/process/[processId]/node/route.ts
export async function POST(req: NextRequest, context: RouteContext) {
const { params } = routeContextSchema.parse(context);
const body = await req.json();
const response = await forwardRequestToCentralApp(
`/v1/api/process/${params.processId}/node`,
{
method: 'POST',
body: JSON.stringify(body),
}
);
return NextResponse.json(await response.json());
}
Node Creation Methods
The frontend supports three ways to create nodes, all of which integrate with the backend:
1. Sidebar Node Addition
const handleSidebarNodeAdd = useCallback((nodeType: string, position: { x: number; y: number }) => {
const newNode = {
id: `${nodeType}-${Date.now()}`,
type: nodeType,
position,
data: {
label: nodeType.replace('_', ' '),
nodeType: nodeType
},
};
// Add to React Flow immediately for responsiveness
setNodes((nds) => nds.concat(newNode));
// Save to backend
const payload = {
nodeType: newNode.type,
name: newNode.data.label,
description: `A ${newNode.type.replace('_', ' ').toLowerCase()} node`,
position: newNode.position,
configuration: {},
metadata: { id: newNode.id },
};
fetch(`/api/process/${processId}/node`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
})
.then(res => res.json())
.then(body => {
if (body.statusCode === 201 && !body.error) {
// Update with backend-generated ID
setNodes((nds) =>
nds.map((node) => {
if (node.id === newNode.id) {
return {
...node,
id: body.data.id,
position: body.data.position,
data: {
...node.data,
label: body.data.name,
},
};
}
return node;
})
);
}
});
}, []);
2. Drag-and-Drop Node Addition
Similar to sidebar addition but triggered by dropping elements from the palette.
3. Hover-based Node Addition
Allows users to add nodes by hovering over existing nodes and selecting connection points.
Key Features
Real-time Sync
- Nodes are added to the canvas immediately for responsiveness
- Backend IDs replace temporary frontend IDs after successful save
- Position and properties are synced with the backend response
Error Handling
- Network errors are handled gracefully with user notifications
- Backend validation errors are displayed to the user
- Failed saves don't break the frontend state
Validation
- DTO validation on the backend ensures data integrity
- NodeFactory validation ensures node types are supported
- Frontend validates start node uniqueness
Data Storage
- Configuration and metadata are stored in the database
dataJSON field - Proper field mapping between frontend and backend structures
- Support for future extension of node properties
Node Types Supported
The following node types are currently supported:
MANUAL_TRIGGER- Manual workflow triggersHUMAN_TASK- Tasks requiring human interventionUSER_TASK- User-assigned tasksEXCLUSIVE_GATEWAY- Decision points in workflows
Database Schema
Nodes are stored in the ProcessNode table with the following structure:
id(UUID) - Primary keyprocessId(UUID) - Foreign key to ProcessnodeId(String) - Unique node identifiertype(NodeType enum) - Node typename(String) - Display namedescription(Text) - Optional descriptionposition(JSON) - Canvas coordinatesdata(JSON) - Configuration and metadatacreatedAt/updatedAt- Timestamps
Error Scenarios
Common error scenarios and their handling:
- Invalid Node Type: Backend validates against supported node types
- Missing Required Fields: DTO validation ensures all required fields are present
- Network Failure: Frontend shows error toast and maintains local state
- Authentication Issues: Proper error messages guide user to re-authenticate
- Process Not Found: Backend validates process existence before creating nodes
Process ID Handling
Dynamic Process ID Resolution
The studio app now dynamically extracts process IDs from URL parameters:
// In /process/[id] routes
const params = useParams();
const processId = extractProcessId(params); // Validates UUID format
// Process validation with error handling
const result = await validateProcessAccess(processId);
if (!result.valid) {
// Show appropriate error message to user
}
Process Validation
Before creating nodes, the frontend validates:
- URL Format: Ensures process ID is a valid UUID
- Process Existence: Verifies the process exists in the database
- Access Permissions: Confirms user has permission to view/edit the process
- Foreign Key Constraints: Prevents database errors when creating nodes
Error Handling
Common scenarios and responses:
- Invalid UUID: Shows "Invalid process ID format" message
- Process Not Found: Shows "Process not found" with navigation options
- Access Denied: Shows "Permission denied" message
- Network Error: Shows "Connection error" with retry options
Future Enhancements
Planned improvements include:
- Real-time collaboration with WebSocket updates
- Undo/redo functionality with operation history
- Advanced node validation rules
- Bulk node operations
- Node templates and presets
- Automatic process creation for new workflows
- Process sharing and collaboration features