Skip to content
This repository was archived by the owner on Jul 15, 2026. It is now read-only.

Commit 82cd912

Browse files
committed
Add 'Source-Agnostic Processing' feature to the homepage with detailed description #111
1 parent ff2616f commit 82cd912

2 files changed

Lines changed: 197 additions & 122 deletions

File tree

Lines changed: 183 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -1,203 +1,265 @@
11
---
22
sidebar_position: 3
33
title: Expressions Syntax
4-
description: Learn how to use expressions in FlowSynx workflows to reference outputs, variables, and nested data dynamically during workflow execution.
4+
description: FlowSynx expression system for dynamic access to variables, task outputs, nested data, arithmetic, conditionals, boolean logic, and functional aggregation.
55
---
66

77
# FlowSynx Expression Syntax
88

9-
FlowSynx supports a flexible **expression system** that allows you to reference **workflow outputs**, **variables**, and **nested properties** dynamically within workflow definitions.
10-
Expressions are resolved at runtime by the `ExpressionParser` engine.
9+
FlowSynx provides a powerful expression system for dynamically resolving **workflow variables**, **task outputs**, **nested properties**, **arithmetic**, **boolean logic**, **conditional (ternary) operations**, and **functional aggregations** at runtime.
10+
All expressions are evaluated by the `ExpressionParser`.
1111

12-
## Overview
13-
14-
Expressions are enclosed within the syntax:
12+
## Core Delimiter
1513

14+
Wrap any resolvable content in:
1615
```
1716
$[...]
1817
```
1918

20-
Anything inside `$[...]` is evaluated by the expression parser.
19+
If the entire value is a single `$[...]` block, the resolved object is returned directly (e.g. an array or JSON object). If embedded inside a larger string, the resolved value is converted to a string and concatenated.
20+
21+
## Data Sources
22+
23+
| Source | Syntax | Description |
24+
| ------ | ------ | ----------- |
25+
| Variables | `$[Variables('Key')]` | Workflow-level variable lookup (case-insensitive). |
26+
| Outputs | `$[Outputs('TaskName')]` | Output of a previously executed task (case-insensitive). |
2127

22-
You can use this syntax anywhere in your workflow — for example in **task parameters**, **paths**, or **input data** fields.
28+
Keys with spaces or special characters should use single quotes: `$[Variables('My Custom Key')]`.
2329

24-
## Expression Sources
30+
### Outputs as PluginContext
2531

26-
FlowSynx supports two main data sources inside expressions:
32+
The [`Outputs`](command:_github.copilot.openSymbolFromReferences?%5B%22%22%2C%5B%7B%22uri%22%3A%7B%22scheme%22%3A%22file%22%2C%22authority%22%3A%22%22%2C%22path%22%3A%22%2Fc%3A%2Fgithub%2Fflowsynx%2Fdocs%2Fdocs%2Freference%2Fflowsynx%2Fexpressions.mdx%22%2C%22query%22%3A%22%22%2C%22fragment%22%3A%22%22%7D%2C%22pos%22%3A%7B%22line%22%3A25%2C%22character%22%3A2%7D%7D%5D%2C%2203b219c3-6667-4007-919c-1aa2e2101390%22%5D "Go to definition") object provides access to the following properties:
2733

28-
| Source | Syntax Example | Description |
29-
| ------- | --------------- | ----------- |
30-
| **Variables** | `$[Variables('InputPath')]` | References workflow-level variables defined under `"Variables"` in the workflow JSON. |
31-
| **Outputs** | `$[Outputs('TaskName')]` | References the output of a previously executed task. |
34+
| Property | Description |
35+
| ---------------- | --------------------------------------------------------------------------- |
36+
| `Id` | The unique identifier of the plugin context. |
37+
| `SourceType` | The type of source that generated the output. |
38+
| `Format` | The format of the output, if applicable. |
39+
| `Metadata` | A dictionary containing metadata as key-value pairs. |
40+
| `RawData` | The raw binary data of the output, if available. |
41+
| `Content` | The string content of the output, if available. |
42+
| `StructuredData` | A list of dictionaries representing structured data, if applicable. |
3243

33-
Both can be used in nested or concatenated contexts.
44+
Keys with spaces or special characters should use single quotes: `$[Variables('My Custom Key')]`.
3445

35-
## Basic Examples
46+
#### Example
3647

37-
### Accessing Workflow Variables
48+
##### Accessing Metadata
49+
You can retrieve specific metadata values using dot notation:
3850

39-
```jsonc
40-
"Parameters": {
41-
"Path": "$[Variables('InputPath')]"
42-
}
51+
```
52+
$[Outputs('TaskName').Metadata['Key']]
4353
```
4454

45-
If your workflow defines:
55+
##### Accessing Content
56+
To retrieve the content of the output:
4657

47-
```jsonc
48-
"Variables": {
49-
"InputPath": "s3://bucket/input"
50-
}
58+
```
59+
$[Outputs('TaskName').Content]
5160
```
5261

53-
The parser will replace `$[Variables('InputPath')]` with:
62+
##### Accessing Structured Data
63+
You can traverse the StructuredData property to access specific elements:
5464

5565
```
56-
s3://bucket/input
66+
$[Outputs('TaskName').StructuredData[0]['FieldName']]
5767
```
5868

59-
### Accessing Task Outputs
69+
##### Combining Properties
70+
You can combine multiple properties in expressions:
6071

61-
```jsonc
62-
"Parameters": {
63-
"Data": "$[Outputs('ExtractData')]"
64-
}
72+
```
73+
$[Outputs('TaskName').Id + ' - ' + Outputs('TaskName').SourceType]
74+
```
75+
76+
#### Notes on PluginContext
77+
- Metadata keys are case-insensitive.
78+
- RawData is a binary array and cannot be directly used in string concatenation. You may need to convert it to a string or process it separately.
79+
- StructuredData is a list of dictionaries, allowing traversal and dynamic access to nested fields.
80+
81+
#### Updated Examples
82+
Here are some updated examples reflecting the PluginContext structure:
83+
84+
```
85+
$[Outputs('Task').Id]
86+
$[Outputs('Task').Metadata['Category']]
87+
$[Outputs('Task').StructuredData[0]['Name']]
88+
$[Contains(Outputs('Task').Metadata, 'urgent')]
89+
$[Outputs('Task').Content == 'success' ? 'completed' : 'retry']
6590
```
6691

67-
This retrieves the **entire output** of a task named `ExtractData`.
92+
#### Error Handling for PluginContext
93+
- Accessing a non-existent property or key in Metadata or StructuredData will throw a FlowSynxException with the code ExpressionParserKeyNotFound.
94+
- Ensure that RawData and StructuredData are not null before accessing their contents.
6895

69-
## Nested Property Access
96+
This update ensures that the Outputs object is documented accurately as a PluginContext type, reflecting its properties and usage in expressions.
7097

71-
You can access **nested fields** or **array elements** inside objects and arrays using `.` (dot notation) or `[]` (indexers):
98+
## Nested Access
99+
100+
Use dot notation and indexers:
72101

73102
| Example | Meaning |
74-
| -------- | -------- |
75-
| `$[Outputs('ExtractData').Records[0].Id]` | Accesses the `Id` property of the first record in the `Records` array. |
76-
| `$[Outputs('Transform').Result.Data.Value]` | Accesses a deeply nested property. |
103+
| ------- | ------- |
104+
| `$[Outputs('Extract').Id]` | Record's `Id`. |
105+
| `$[Outputs('Transform').Content]` | Property traversal. |
106+
| `$[Outputs('Task').Metadata[Variables('Index')]]` | Dynamic index. |
77107

78-
These can be combined with variable lookups:
108+
Arrays are supported for `IList` and `JArray`. Properties are resolved case-insensitively (`JObject`, `JToken`, or CLR objects).
79109

80-
```jsonc
81-
"Parameters": {
82-
"Path": "$[Variables('BasePath')]/$[Outputs('Task1').FileName]"
83-
}
84-
```
110+
## Literal Values
85111

86-
If:
87-
```jsonc
88-
"Variables": { "BasePath": "/data/output" },
89-
"Outputs": { "Task1": { "FileName": "report.csv" } }
90-
```
112+
Inside expressions you can use:
113+
- Quoted strings: `'text'` or `"text"`
114+
- Numbers: `42`, `3.14`
115+
- Booleans: `true`, `false`
116+
- Null: `null`
117+
118+
Example: `$['static-value']`
119+
120+
## Functional Methods
121+
122+
Built-in case-insensitive aggregation and search functions:
123+
124+
| Function | Signature | Behavior |
125+
| -------- | --------- | -------- |
126+
| `Min` | `Min(arg1, arg2, collection, ...)` | Returns smallest numeric value (flattens enumerables). |
127+
| `Max` | `Max(...)` | Returns largest numeric value. |
128+
| `Sum` | `Sum(...)` | Sums all numeric values. |
129+
| `Avg` | `Avg(...)` | Arithmetic mean (0 if no numbers). |
130+
| `Count` | `Count(collection)` or `Count(arg1,arg2,...)` | If single enumerable → element count; otherwise number of arguments. |
131+
| `Contains` | `Contains(container, value)` | Case-insensitive search (strings, enumerables, or direct value comparison). |
132+
133+
Arguments can be:
134+
- Literals
135+
- Variable/output references
136+
- Nested expressions
137+
- Other functional calls
138+
139+
Examples:
91140

92-
Result:
93141
```
94-
/data/output/report.csv
142+
$[Sum(Variables('Prep').Values)]
143+
$[Avg(Variables('A').Numbers, Outputs('B').Content, 10)]
144+
$[Count(Variables('ListTask').Items)]
145+
$[Contains(Outputs('Meta').Metadata, 'critical')]
146+
$[Min(Variables('A').Values, Variables('B').Values)]
95147
```
96148

97-
## Expression Evaluation Rules
149+
## Arithmetic Expressions
98150

99-
The `ExpressionParser` engine follows these rules:
151+
You can perform arithmetic inside `$[...]` using operators: `+ - * / %` and parentheses.
100152

101-
1. **Single Expression**
102-
- If the expression is *entirely* a `$[...]` block, the value is returned directly as an object (not just a string).
103-
- Example: `$[Outputs('Task1')]` returns the full object produced by `Task1`.
153+
```
154+
$[(Variables('Calc').Base + Variables('Offset')) * 0.5]
155+
```
156+
157+
Resolution flow:
158+
1. Embedded `$[...]` segments inside the arithmetic are first resolved.
159+
2. `Variables(...)` / `Outputs(...)` inside arithmetic are replaced with their string value (missing values become `0` in arithmetic context).
160+
3. Expression is evaluated; numeric result returned as `double`.
161+
4. If evaluation fails, it falls back to literal/lookup interpretation.
104162

105-
2. **String Concatenation**
106-
- If the expression is embedded within a larger string, the resolved value is converted to a string and concatenated.
107-
- Example: `"File: $[Outputs('Task1').FileName]"``"File: result.csv"`.
163+
## Boolean Logic & Comparisons
108164

109-
3. **Nested Expressions**
110-
- Expressions can reference other expressions recursively.
111-
- Example: `$[Variables(Outputs('MetaTask').VariableKey)]`.
165+
Supported operators: `== != > < >= <= && || !`
112166

113-
4. **Case Insensitivity**
114-
- Keys and property names are resolved case-insensitively (`Outputs('task1')` = `Outputs('Task1')`).
167+
Examples:
115168

116-
5. **Unbalanced Brackets or Parentheses**
117-
- The parser detects and throws descriptive errors for unbalanced `[]` or `()` characters.
169+
```
170+
$[Variables('Mode') == 'fast']
171+
$[Variables('Stats').Errors > 0 && Variables('Stats').Warnings == 0]
172+
$[!Contains(Variables('Tags').All,'deprecated')]
173+
```
118174

119-
6. **Quoted Keys**
120-
- You can wrap keys in single quotes to include spaces or special characters:
121-
`$[Variables('My Custom Key')]`.
175+
Comparison semantics:
176+
- Equality is case-insensitive string comparison for `==` / `!=`.
177+
- Relational operators (`> < >= <=`) apply only if both sides convert to numbers.
122178

123-
## Supported Operations
179+
## Conditional (Ternary) Expressions
124180

125-
### 1. Variable Access
126181
```
127-
$[Variables('key')]
182+
$[Variables('Score').Value >= 90 ? 'excellent' : 'standard']
183+
$[Contains(Outputs('Meta').Metadata, 'urgent') ? Variables('UrgentPath') : Variables('NormalPath')]
128184
```
129185

130-
### 2. Output Access
186+
Format: `condition ? whenTrue : whenFalse`
187+
Condition can include logical or comparison operators.
188+
189+
## Recursive & Dynamic Keys
190+
191+
You can build dynamic keys or nested expressions:
192+
131193
```
132-
$[Outputs('taskName')]
194+
$[Variables(Outputs('Meta').Id)]
195+
$[Outputs(Variables('DynamicTask')).StructuredData]
133196
```
134197

135-
### 3. Nested Field Access
198+
Resolution is recursive: inner expressions resolve before outer structures.
199+
200+
## String Concatenation Example
201+
136202
```
137-
$[Outputs('task').data.results[1].value]
203+
"Path": "$[Variables('Base')]/$[Outputs('Export').Id]"
138204
```
139205

140-
### 4. Combined or Concatenated Strings
206+
If:
207+
141208
```
142-
"Path": "logs/$[Variables('RunId')]/$[Outputs('Extract').FileName]"
209+
Variables: { "Base": "/data/out" } Outputs: { "Export": { "Id": "report.csv" } }
143210
```
144211

145-
### 5. Recursive Expressions
212+
Result:
213+
146214
```
147-
$[Variables(Outputs('Metadata').DynamicKey)]
215+
/data/out/report.csv
148216
```
149217

150-
## Error Handling
218+
## Return Value Behavior
151219

152-
When an expression cannot be resolved, the parser throws a `FlowSynxException` with specific error codes.
220+
1. Whole expression only: `$[Outputs('Task')]` → returns the raw object (array, complex type, etc.).
221+
2. Embedded in text: `"File=$[Outputs('Task').Id]"` → string interpolation.
222+
3. Functions/Arithmetic: return numeric or boolean values directly if standalone.
153223

154-
| Error Code | Condition | Example |
155-
| ----------- | ---------- | -------- |
156-
| `ExpressionParserKeyNotFound` | Key or source (`Variables` / `Outputs`) is missing or invalid. | `$[Outputs('UnknownTask')]` |
157-
|| Unbalanced brackets or parentheses. | `$[Variables('Key'` |
224+
## Error Handling
158225

159-
## Example Use Case
226+
Parser throws `FlowSynxException` (code: `ExpressionParserKeyNotFound`) for:
227+
- Missing `Variables('key')` or `Outputs('key')`.
228+
- Unbalanced brackets `[...]` or parentheses `(...)`.
229+
- Invalid functional syntax (e.g. `Contains()` with argument count ≠ 2).
230+
- Malformed conditional expressions.
160231

161-
Here’s a real-world usage in a FlowSynx workflow task:
232+
In arithmetic-only contexts, missing lookups are coerced to `0` (to avoid failure). Direct lookup outside arithmetic still throws.
162233

163-
```jsonc
164-
{
165-
"Name": "SaveData",
166-
"Type": "FlowSynx.FileSystem",
167-
"Dependencies": ["ToCSV"],
168-
"Parameters": {
169-
"Operation": "write",
170-
"Path": "$[Variables('OutputDirectory')]/$[Outputs('ToCSV').FileName]",
171-
"Data": "$[Outputs('ToCSV').Content]",
172-
"Overwrite": true
173-
}
174-
}
175-
```
234+
## Examples
176235

177-
If:
178-
```jsonc
179-
"Variables": { "OutputDirectory": "/mnt/results" },
180-
"Outputs": { "ToCSV": { "FileName": "report.csv", "Content": "data" } }
181236
```
182-
183-
Then the evaluated parameters become:
184-
```jsonc
185-
{
186-
"Operation": "write",
187-
"Path": "/mnt/results/report.csv",
188-
"Data": "data",
189-
"Overwrite": true
190-
}
237+
$[Sum(Outputs('Collect').Content, 10, Variables('Bonus'))]
238+
$[Outputs('Metrics').Metadata[0] > 50 ? 'pass' : 'fail']
239+
$[Contains(Outputs('Tags').List, Variables('TargetTag')) && Variables('Stats').Count >= 5]
240+
$[Min(Outputs('A').Content, Outputs('B').Content)]
241+
$[Variables(Outputs('Resolver').Id)]
191242
```
192243

244+
245+
## Best Practices
246+
247+
- Use single quotes for keys with spaces: `$[Variables('My Key')]`.
248+
- Keep arithmetic numeric; non-numeric tokens cause literal fallback.
249+
- Prefer explicit parentheses for complex logic.
250+
- Avoid over-nesting; consider storing intermediate values in variables.
251+
193252
## Summary
194253

195-
FlowSynx Expressions allow:
196-
- Dynamic parameter substitution.
197-
- Flexible referencing of workflow data.
198-
- Safe and validated parsing with descriptive errors.
199-
- Recursive resolution for advanced workflow logic.
254+
FlowSynx Expressions support:
255+
- Dynamic access to variables and task outputs
256+
- Nested property and array traversal
257+
- Functional aggregation (Min/Max/Sum/Avg/Count/Contains)
258+
- Arithmetic and numeric evaluation
259+
- Boolean logic and conditional branching
260+
- Recursive and dynamic key resolution
261+
- Strong error signaling for invalid syntax
200262

201263
:::info
202-
You can use `$[Variables(...)]` and `$[Outputs(...)]` in *any* string field inside a FlowSynx workflow — the parser will automatically handle context-aware replacements.
264+
Expressions can be used in any string field in workflow definitions. Mix multiple `$[...]` segments freely; each is resolved independently and merged into the final string.
203265
:::

0 commit comments

Comments
 (0)