Advanced Syntax
This guide covers advanced Phlow syntax including enhanced module patterns and code block support for complex workflows.
Enhanced Module Syntax
Automatic Transformation
Phlow now automatically transforms legacy module syntax to the new standardized format during processing. This ensures backward compatibility while encouraging the use of the new, more consistent syntax.
How It Works
When you write:
steps:
- log:
message: "Hello World"
level: info
Phlow automatically transforms it to:
steps:
- use: log
input:
message: "Hello World"
level: info
Transformation Rules
The transformation applies to:
- ✅ Properties in the root of
steps
arrays - ✅ Properties in the root of
then
blocks - ✅ Properties in the root of
else
blocks - ❌ Properties inside
payload
(ignored) - ❌ Properties inside existing
input
blocks (ignored) - ❌ Exclusive properties:
use
,to
,id
,label
,assert
,condition
,return
,payload
,input
,then
,else
Examples
Valid Transformations:
steps:
- log: # ✅ Transformed
message: "Step 1"
- condition:
assert: !phs true
then:
- cache: # ✅ Transformed
action: set
- use: postgres # ❌ Already correct format
input:
query: "SELECT 1"
else:
- log: # ✅ Transformed
message: "Step 2"
Ignored Cases:
steps:
- payload:
nested:
log: # ❌ Not transformed (inside payload)
message: "ignored"
- use: cache
input:
log: # ❌ Not transformed (inside input)
message: "ignored"
Advanced Code Blocks
Multi-line Code with !phs {}
You can now write complex, multi-line code blocks using curly braces. These blocks are automatically processed and unified into single lines.
Basic Example
Input:
- payload: !phs {
let user = main.user;
let age = user.age || 0;
let category = age >= 18 ? "adult" : "minor";
#{
name: user.name,
age: age,
category: category,
timestamp: new Date().toISOString()
}
}
Processed Output:
- payload: "{{ { let user = main.user; let age = user.age || 0; let category = age >= 18 ? \"adult\" : \"minor\"; { name: user.name, age: age, category: category, timestamp: new Date().toISOString() } } }}"
Complex Data Processing
- payload: !phs {
let orders = main.orders || [];
let processed = orders.map(order => {
let total = order.items.reduce((sum, item) =>
sum + (item.price * item.quantity), 0
);
let discount = order.customer?.tier === "premium" ? 0.1 : 0;
let finalTotal = total * (1 - discount);
return #{
id: order.id,
customerId: order.customer.id,
itemCount: order.items.length,
subtotal: total,
discount: total * discount,
total: finalTotal,
status: finalTotal > 0 ? "valid" : "invalid"
};
});
#{
orders: processed,
summary: {
total: processed.length,
valid: processed.filter(o => o.status === "valid").length,
totalRevenue: processed.reduce((sum, o) => sum + o.total, 0)
}
}
}
With Module Calls
- use: log
input:
level: "info"
message: !phs {
let stats = payload.summary;
let revenue = Math.round(stats.totalRevenue * 100) / 100;
`Processed ${stats.total} orders, ${stats.valid} valid, $${revenue} revenue`
}
Code Block Limitations
What You CAN Do:
- ✅ Variable declarations (
let
,const
) - ✅ Complex calculations and transformations
- ✅ Array and object manipulations
- ✅ Conditional expressions and ternary operators
- ✅ Method calls on existing objects
- ✅ Access to flow variables (
main
,payload
,steps
)
What You CANNOT Do:
- ❌ Function declarations (
function myFunc() {}
) - ❌ Class declarations (
class MyClass {}
) - ❌ Import statements (
import
orrequire
) - ❌ Async/await patterns
For Complex Functions, Use !import
:
complex-logic.phs:
function calculateTax(amount, state) {
const taxRates = {
"CA": 0.0875,
"NY": 0.08,
"TX": 0.0625
};
return amount * (taxRates[state] || 0.05);
}
function processOrder(order, state) {
let subtotal = order.items.reduce((sum, item) =>
sum + (item.price * item.quantity), 0
);
let tax = calculateTax(subtotal, state);
return {
subtotal: subtotal,
tax: tax,
total: subtotal + tax
};
}
// Export the main function
processOrder
main.phlow:
steps:
- payload: !import complex-logic.phs
- payload: !phs payload(main.order, main.state)
Best Practices
Module Syntax
- Consistent Style: Choose between
use
+input
or direct module syntax based on your team's preference - Mixed Usage: Both syntaxes can be used in the same flow without any issues
- Readability: The
use
+input
syntax provides clearer separation of concerns
Code Blocks
- Complex Logic: Use
!phs {}
blocks for data transformations and calculations - Single Responsibility: Keep code blocks focused on one specific task
- Documentation: Add comments for complex logic within code blocks
- Functions: Use
!import
for reusable functions and complex algorithms
Error Handling
- Validation: All transformations are validated with clear error messages
- Testing: Test flows with
--print
flag to verify transformations - Debugging: Use appropriate log levels for troubleshooting
Performance Impact
- Zero Runtime Cost: Transformations happen during processing, not execution
- Optimized Code: Code blocks are optimized and cached
- Backward Compatible: No performance penalty for legacy syntax
- Memory Efficient: Transformed code uses the same memory footprint
These features maintain Phlow's performance characteristics while providing enhanced developer experience and maintainability.