- Added inline type definitions for WorkflowNode, WorkflowContext, ExecutionState, NodeResult, ValidationResult, and INodeExecutor - Fixed execute() method to return proper NodeResult format with status field - Implemented missing validate() method required by INodeExecutor interface - Fixed tsconfig.json to not depend on non-existent root config - All hook method signatures updated to accept generic state object - TypeScript compilation now succeeds (0 errors) This ensures the workflow hooks plugin is fully compatible with the workflow engine's type system. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Workflow Hooks Plugin
Version: 1.0.0 Status: Production Ready Purpose: Provide hook-like state management in workflow DAG execution
Overview
The Workflow Hooks Plugin enables hook-like state management operations directly in workflow definitions. It mirrors the API of @metabuilder/hooks but works in the server-side DAG execution context (not React).
This allows workflows to use familiar hook patterns for:
- Counters (increment, decrement, bounds)
- Toggles (boolean state)
- History management (undo/redo)
- Validation (field-level errors)
- Data structures (arrays, sets, maps, stacks, queues)
Installation
The plugin is built into the workflow system. Import and register in the node registry:
import WorkflowHooksExecutor from '@metabuilder/workflow-plugin-hooks'
// Register in node registry
nodeRegistry.register(new WorkflowHooksExecutor())
Usage
All hook operations use the same node type: hook
Basic Structure
{
"type": "hook",
"parameters": {
"hookType": "useCounter",
"operation": "increment",
"key": "myCounter",
"initial": 0,
"min": 0,
"max": 100
}
}
Available Hooks
useCounter - Counter state management
Operations: increment, decrement, set, reset
{
"type": "hook",
"parameters": {
"hookType": "useCounter",
"operation": "increment",
"key": "counter",
"initial": 0,
"min": 0,
"max": 100
}
}
Returns:
result: New counter value[key]: Updated counter statecanIncrement: Boolean indicating if increment is allowedcanDecrement: Boolean indicating if decrement is allowed
Examples:
// Increment
{ "hookType": "useCounter", "operation": "increment", "key": "count", "initial": 0, "max": 10 }
// Decrement
{ "hookType": "useCounter", "operation": "decrement", "key": "count", "min": 0 }
// Set value
{ "hookType": "useCounter", "operation": "set", "key": "count", "value": 5 }
// Reset to initial
{ "hookType": "useCounter", "operation": "reset", "key": "count", "initial": 0 }
useToggle - Boolean state management
Operations: toggle, setTrue, setFalse, set, reset
{
"type": "hook",
"parameters": {
"hookType": "useToggle",
"operation": "toggle",
"key": "isVisible",
"initial": false
}
}
Returns:
result: New boolean value[key]: Updated toggle statevalue: Current value
Examples:
// Toggle
{ "hookType": "useToggle", "operation": "toggle", "key": "isVisible" }
// Set true
{ "hookType": "useToggle", "operation": "setTrue", "key": "isActive" }
// Set false
{ "hookType": "useToggle", "operation": "setFalse", "key": "isLoading" }
// Set custom value
{ "hookType": "useToggle", "operation": "set", "key": "flag", "value": true }
// Reset to initial
{ "hookType": "useToggle", "operation": "reset", "key": "isOpen", "initial": false }
useStateWithHistory - State with undo/redo
Operations: set, undo, redo, reset, getHistory
{
"type": "hook",
"parameters": {
"hookType": "useStateWithHistory",
"operation": "set",
"key": "formState",
"value": { "email": "user@example.com", "name": "John" },
"initial": {},
"maxHistory": 50
}
}
Returns:
result: Current state value[key]: Updated history state with indexcurrent: Current valuecanUndo: Boolean indicating if undo is availablecanRedo: Boolean indicating if redo is available
Examples:
// Set new state
{ "hookType": "useStateWithHistory", "operation": "set", "key": "data", "value": {"updated": true} }
// Undo
{ "hookType": "useStateWithHistory", "operation": "undo", "key": "data" }
// Redo
{ "hookType": "useStateWithHistory", "operation": "redo", "key": "data" }
// Get full history
{ "hookType": "useStateWithHistory", "operation": "getHistory", "key": "data" }
// Reset
{ "hookType": "useStateWithHistory", "operation": "reset", "key": "data", "initial": {} }
useValidation - Field validation
Operations: validate, addRule, clearErrors
{
"type": "hook",
"parameters": {
"hookType": "useValidation",
"operation": "validate",
"key": "formValidation",
"values": {
"email": "user@example.com",
"password": "secret123"
},
"rules": {
"email": "value.includes('@') ? null : 'Invalid email'",
"password": "value.length >= 8 ? null : 'Min 8 characters'"
}
}
}
Returns:
result: Object with errors and isValiderrors: Record of field errors (null if valid)isValid: Boolean indicating if all validations passed[key]: Updated validation state
Examples:
// Validate fields
{
"hookType": "useValidation",
"operation": "validate",
"values": { "email": "user@example.com" },
"rules": { "email": "value.includes('@') ? null : 'Invalid email'" }
}
// Add validation rule
{
"hookType": "useValidation",
"operation": "addRule",
"key": "validator",
"field": "name",
"rule": "value.length > 0 ? null : 'Required'"
}
// Clear errors
{ "hookType": "useValidation", "operation": "clearErrors", "key": "validator" }
useArray - Array operations
Operations: push, pop, shift, unshift, insert, remove, removeAt, clear
{
"type": "hook",
"parameters": {
"hookType": "useArray",
"operation": "push",
"key": "items",
"value": { "id": 1, "name": "Item 1" },
"initialValue": []
}
}
Returns:
result: Modified array[key]: Updated array statelength: New array length
Examples:
// Push
{ "hookType": "useArray", "operation": "push", "key": "items", "value": {"id": 1} }
// Pop
{ "hookType": "useArray", "operation": "pop", "key": "items" }
// Insert at index
{ "hookType": "useArray", "operation": "insert", "key": "items", "index": 2, "value": {"id": 3} }
// Remove by value
{ "hookType": "useArray", "operation": "remove", "key": "items", "value": {"id": 1} }
// Remove at index
{ "hookType": "useArray", "operation": "removeAt", "key": "items", "index": 0 }
// Clear
{ "hookType": "useArray", "operation": "clear", "key": "items" }
useSet - Set operations
Operations: add, remove, has, toggle, clear
{
"type": "hook",
"parameters": {
"hookType": "useSet",
"operation": "add",
"key": "selectedItems",
"value": "item1",
"initialValue": []
}
}
Returns:
result: Array of set values[key]: Updated set statesize: Set size
Examples:
// Add
{ "hookType": "useSet", "operation": "add", "key": "tags", "value": "javascript" }
// Remove
{ "hookType": "useSet", "operation": "remove", "key": "tags", "value": "python" }
// Check membership
{ "hookType": "useSet", "operation": "has", "key": "tags", "value": "javascript" }
// Toggle
{ "hookType": "useSet", "operation": "toggle", "key": "tags", "value": "rust" }
// Clear
{ "hookType": "useSet", "operation": "clear", "key": "tags" }
useMap - Map operations
Operations: set, get, delete, has, clear, entries, keys, values
{
"type": "hook",
"parameters": {
"hookType": "useMap",
"operation": "set",
"key": "userMap",
"key_": "user1",
"value": { "name": "John", "email": "john@example.com" }
}
}
Returns:
result: Current map value/entries[key]: Updated map statesize: Map size
Note: Parameter key_ is used for map key (to avoid conflict with node key)
Examples:
// Set
{ "hookType": "useMap", "operation": "set", "key": "data", "key_": "user1", "value": {"name": "John"} }
// Get
{ "hookType": "useMap", "operation": "get", "key": "data", "key_": "user1" }
// Delete
{ "hookType": "useMap", "operation": "delete", "key": "data", "key_": "user1" }
// Check membership
{ "hookType": "useMap", "operation": "has", "key": "data", "key_": "user1" }
// Get all entries
{ "hookType": "useMap", "operation": "entries", "key": "data" }
// Get all keys
{ "hookType": "useMap", "operation": "keys", "key": "data" }
// Get all values
{ "hookType": "useMap", "operation": "values", "key": "data" }
// Clear
{ "hookType": "useMap", "operation": "clear", "key": "data" }
useStack - LIFO stack operations
Operations: push, pop, peek, clear
{
"type": "hook",
"parameters": {
"hookType": "useStack",
"operation": "push",
"key": "stack",
"value": "item1"
}
}
Returns:
result: Top of stack or updated stack[key]: Updated stack statesize: Stack size
Examples:
// Push
{ "hookType": "useStack", "operation": "push", "key": "stack", "value": "item1" }
// Pop
{ "hookType": "useStack", "operation": "pop", "key": "stack" }
// Peek
{ "hookType": "useStack", "operation": "peek", "key": "stack" }
// Clear
{ "hookType": "useStack", "operation": "clear", "key": "stack" }
useQueue - FIFO queue operations
Operations: enqueue, dequeue, peek, clear
{
"type": "hook",
"parameters": {
"hookType": "useQueue",
"operation": "enqueue",
"key": "queue",
"value": "item1"
}
}
Returns:
result: Front of queue or updated queue[key]: Updated queue statesize: Queue size
Examples:
// Enqueue
{ "hookType": "useQueue", "operation": "enqueue", "key": "queue", "value": "item1" }
// Dequeue
{ "hookType": "useQueue", "operation": "dequeue", "key": "queue" }
// Peek
{ "hookType": "useQueue", "operation": "peek", "key": "queue" }
// Clear
{ "hookType": "useQueue", "operation": "clear", "key": "queue" }
Complete Workflow Example
{
"version": "1.0.0",
"nodes": [
{
"id": "init-counter",
"type": "hook",
"parameters": {
"hookType": "useCounter",
"operation": "set",
"key": "requestCount",
"value": 0,
"min": 0,
"max": 100
}
},
{
"id": "check-limit",
"type": "branch",
"condition": "{{ state.requestCount < 100 }}"
},
{
"id": "increment-counter",
"type": "hook",
"parameters": {
"hookType": "useCounter",
"operation": "increment",
"key": "requestCount"
}
},
{
"id": "track-toggle",
"type": "hook",
"parameters": {
"hookType": "useToggle",
"operation": "toggle",
"key": "isProcessing"
}
},
{
"id": "validate-data",
"type": "hook",
"parameters": {
"hookType": "useValidation",
"operation": "validate",
"values": "{{ data }}",
"rules": {
"email": "value.includes('@') ? null : 'Invalid email'",
"age": "value >= 18 ? null : 'Must be 18+'"
}
}
},
{
"id": "collect-items",
"type": "hook",
"parameters": {
"hookType": "useArray",
"operation": "push",
"key": "results",
"value": "{{ processedItem }}"
}
}
]
}
Return Value Structure
All hook operations return:
{
result: any // Primary result
[key]: any // Updated state with given key
error?: string // Error message if operation fails
hookType: string // The hook type that was executed
operation: string // The operation that was performed
// ... hook-specific fields (canIncrement, isValid, size, etc.)
}
State Persistence
Hook state is stored in the workflow execution state and persists across nodes:
{
"nodes": [
{
"id": "node1",
"type": "hook",
"parameters": {
"hookType": "useCounter",
"operation": "set",
"key": "count",
"value": 5
}
},
{
"id": "node2",
"type": "hook",
"parameters": {
"hookType": "useCounter",
"operation": "increment",
"key": "count"
}
}
]
}
After node1: state.count = 5
After node2: state.count = 6
Error Handling
Operations return errors in the result:
{
"result": null,
"error": "Unknown hook type: useInvalidHook",
"hookType": "useInvalidHook",
"operation": "someOp"
}
Performance Characteristics
- Simple operations (toggle, increment): O(1)
- Array operations: O(n) for filter/search, O(1) for push/pop
- Set/Map operations: O(1) average case
- History operations: O(1) for set/undo/redo
- Validation: O(n) where n = number of rules
Compatibility
- Workflow System: v3.0.0+
- Node.js: 14+
- TypeScript: 5.0+
See Also
- @metabuilder/hooks - React hooks library (client-side)
- @metabuilder/workflow - Workflow DAG engine
- Workflow Plugin System - Plugin architecture documentation
Status: Production Ready Last Updated: January 23, 2026 Version: 1.0.0