Skip to content

Commit eafe7cb

Browse files
committed
feat: add CALL NANOFLOW, GRANT/REVOKE nanoflow access, agentic skill, and proposal
1 parent 436a61e commit eafe7cb

32 files changed

Lines changed: 12015 additions & 10152 deletions
Lines changed: 325 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,325 @@
1+
# Mendix Nanoflow Skill
2+
3+
This skill provides comprehensive guidance for writing Mendix nanoflows in MDL (Mendix Definition Language) syntax.
4+
5+
## When to Use This Skill
6+
7+
Use this skill when:
8+
- Writing CREATE NANOFLOW statements
9+
- Debugging nanoflow syntax errors
10+
- Converting Studio Pro nanoflows to MDL
11+
- Understanding nanoflow vs microflow differences
12+
13+
## Nanoflow vs Microflow
14+
15+
Nanoflows execute **client-side** (browser or native app). They share the same flow structure as microflows but have important restrictions:
16+
17+
| Aspect | Nanoflow | Microflow |
18+
|--------|----------|-----------|
19+
| Execution | Client-side (browser/native) | Server-side |
20+
| Database | Client-side offline DB | Server-side DB |
21+
| Error handling | `$latestError` (String only) | Full error events |
22+
| ErrorEvent | **Forbidden** | Allowed |
23+
| Return types | No `Binary`, no `Float` | All types |
24+
| Concurrency | N/A | `AllowConcurrentExecution` |
25+
| Entity access | N/A | `ApplyEntityAccess` |
26+
| Calling nanoflows | `call nanoflow` | `call microflow` (not nanoflow) |
27+
| JavaScript actions | Allowed | Not allowed |
28+
29+
## Nanoflow Structure
30+
31+
**CRITICAL: All nanoflows MUST have JavaDoc-style documentation**
32+
33+
```mdl
34+
/**
35+
* Nanoflow description explaining what it does
36+
*
37+
* @param $Parameter1 Description of first parameter
38+
* @param $Parameter2 Description of second parameter
39+
* @returns Description of return value
40+
* @since 1.0.0
41+
* @author Team Name
42+
*/
43+
create nanoflow Module.NanoflowName (
44+
$Parameter1: type,
45+
$Parameter2: type
46+
)
47+
returns ReturnType
48+
[folder 'FolderPath']
49+
begin
50+
-- Nanoflow logic here
51+
return $value;
52+
end;
53+
/
54+
```
55+
56+
### Key Differences from Microflow Syntax
57+
58+
- Use `create nanoflow` (not `create microflow`)
59+
- No `as $ReturnVariable` — nanoflows do not support `ReturnVariableName`
60+
- No `AllowConcurrentExecution` option
61+
- Otherwise identical syntax: same parameters, return types, body, folder, comment
62+
63+
### Parameter Types
64+
65+
Same as microflows:
66+
67+
```mdl
68+
$Name: string
69+
$count: integer
70+
$Amount: decimal
71+
$IsActive: boolean
72+
$date: datetime
73+
$Customer: Module.Entity
74+
$ProductList: list of Module.Product
75+
$status: enum Module.OrderStatus
76+
```
77+
78+
### Allowed Return Types
79+
80+
```
81+
boolean, integer, decimal, string, datetime, enumeration, object, list, void
82+
```
83+
84+
**NOT allowed**: `Binary`, `Float`
85+
86+
## Allowed Actions
87+
88+
### Actions available in nanoflows
89+
90+
| Action | MDL Syntax | Notes |
91+
|--------|-----------|-------|
92+
| CreateVariable | `declare $var type = value;` | Same as microflow |
93+
| ChangeVariable | `set $var = value;` | Same as microflow |
94+
| CreateObject | `$var = create Module.Entity (...)` | Same as microflow |
95+
| ChangeObject | `change $var (...)` | Same as microflow |
96+
| CommitObject | `commit $var;` | Same as microflow |
97+
| DeleteObject | `delete $var;` | Same as microflow |
98+
| RollbackObject | `rollback $var;` | Same as microflow |
99+
| RetrieveAction | `retrieve $var from ...` | From client DB |
100+
| CreateList | `declare $list list of ... = empty;` | Same as microflow |
101+
| ChangeList | `change list ...` | Same as microflow |
102+
| ListOperation | `list operation ...` | Same as microflow |
103+
| AggregateList | `aggregate list ...` | Same as microflow |
104+
| ShowPage | `show page Module.Page(...)` | Same as microflow |
105+
| ClosePage | `close page;` | Same as microflow |
106+
| ShowMessage | `show message ...` | Same as microflow |
107+
| ValidationFeedback | `validation feedback ...` | Same as microflow |
108+
| LogMessage | `log info/warning/error ...` | Same as microflow |
109+
| CastAction | `cast ...` | Same as microflow |
110+
| CallMicroflow | `call microflow Module.Name(...)` | Calls server-side |
111+
| **CallNanoflow** | `call nanoflow Module.Name(...)` | **Nanoflow-only** |
112+
| IF/ELSE | `if ... then ... end if;` | Same as microflow |
113+
| LOOP | `loop $var in $list begin ... end loop;` | Same as microflow |
114+
| WHILE | `while condition begin ... end while;` | Same as microflow |
115+
116+
### Actions NOT available in nanoflows
117+
118+
These will cause validation errors if used:
119+
120+
| Action | Reason |
121+
|--------|--------|
122+
| `call java action` | Server-side JVM execution |
123+
| `rest call` / `send rest request` | Server-side HTTP |
124+
| `call external` | Server-side external calls |
125+
| `download file` | Server-side file streaming |
126+
| `generate document` | Server-side document generation |
127+
| `import xml` / `export xml` | Server-side XML processing |
128+
| `show home page` | Server-side navigation |
129+
| All workflow actions | Server-side workflow engine |
130+
| All metrics actions | Server-side telemetry |
131+
| `send email` | Server-side email |
132+
| `push to client` | Server-side push (nanoflows ARE client-side) |
133+
| `execute database query` | Server-side SQL |
134+
| `transform json` | Server-side JSON transform |
135+
136+
### ErrorEvent is Forbidden
137+
138+
Nanoflows cannot use `ErrorEvent`. Error handling uses `on error continue` or `on error { ... }` blocks on individual activities, with `$latestError` (String) as the only predefined error variable.
139+
140+
## Calling Nanoflows
141+
142+
### CALL NANOFLOW
143+
144+
```mdl
145+
-- Call with result
146+
$Result = call nanoflow Module.ValidateForm(Customer = $Customer);
147+
148+
-- Call without result (void nanoflow)
149+
call nanoflow Module.RefreshUI(Page = $CurrentPage);
150+
151+
-- Call with error handling
152+
$Result = call nanoflow Module.ProcessLocally(data = $data) on error continue;
153+
```
154+
155+
**Important**: Same parameter matching rules as microflows — parameter names must exactly match the target nanoflow's signature (without `$` prefix). Use `describe nanoflow Module.Name` to verify.
156+
157+
### Calling Microflows from Nanoflows
158+
159+
Nanoflows can call microflows (triggers server round-trip):
160+
161+
```mdl
162+
$ServerResult = call microflow Module.FetchFromServer(query = $query);
163+
```
164+
165+
### Calling Nanoflows from Microflows
166+
167+
Microflows **cannot** call nanoflows directly. Use `call nanoflow` only inside nanoflow bodies.
168+
169+
## Security: GRANT/REVOKE
170+
171+
Control which module roles can execute a nanoflow:
172+
173+
```mdl
174+
-- Grant execution permission
175+
grant execute on nanoflow Module.NanoflowName to Module.RoleName;
176+
177+
-- Grant to multiple roles
178+
grant execute on nanoflow Module.NanoflowName to Module.Role1, Module.Role2;
179+
180+
-- Revoke permission
181+
revoke execute on nanoflow Module.NanoflowName from Module.RoleName;
182+
```
183+
184+
**Note**: Nanoflow security is design-time only (AllowedModuleRoles). Unlike microflows, nanoflows do not have `ApplyEntityAccess`.
185+
186+
## Error Handling
187+
188+
### Predefined Variables
189+
190+
Nanoflows have only one predefined error variable:
191+
- `$latestError` — String (not an object like in microflows)
192+
193+
### Error Handling Patterns
194+
195+
```mdl
196+
-- On error continue
197+
call microflow Module.ServerAction() on error continue;
198+
if $latestError != empty then
199+
show message error 'Server call failed: ' + $latestError;
200+
end if;
201+
202+
-- Custom error handler
203+
$Result = call nanoflow Module.RiskyOperation() on error {
204+
log warning node 'NanoflowError' 'Operation failed: ' + $latestError;
205+
return $DefaultValue;
206+
};
207+
```
208+
209+
## Complete Example
210+
211+
```mdl
212+
/**
213+
* Validates a customer form before saving
214+
*
215+
* Runs client-side for immediate feedback. Calls server
216+
* microflow only if local validation passes.
217+
*
218+
* @param $Customer The customer object to validate
219+
* @returns true if validation passes
220+
* @since 1.2.0
221+
* @author SPAM Team
222+
*/
223+
create nanoflow Shop.NFV_ValidateCustomerForm (
224+
$Customer: Shop.Customer
225+
)
226+
returns boolean
227+
folder 'Customers/Validation'
228+
begin
229+
-- Validate required fields
230+
if $Customer/Name = empty or $Customer/Name = '' then
231+
validation feedback $Customer attribute Name message 'Name is required';
232+
return false;
233+
end if;
234+
235+
if $Customer/Email = empty or $Customer/Email = '' then
236+
validation feedback $Customer attribute Email message 'Email is required';
237+
return false;
238+
end if;
239+
240+
-- Server-side uniqueness check
241+
$IsUnique = call microflow Shop.ACT_CheckEmailUnique(Email = $Customer/Email)
242+
on error continue;
243+
244+
if $latestError != empty then
245+
show message warning 'Could not verify email uniqueness. Please try again.';
246+
return false;
247+
end if;
248+
249+
if not $IsUnique then
250+
validation feedback $Customer attribute Email message 'Email already exists';
251+
return false;
252+
end if;
253+
254+
return true;
255+
end;
256+
/
257+
```
258+
259+
## Naming Conventions
260+
261+
Follow the same conventions as microflows with nanoflow-specific prefixes:
262+
263+
| Prefix | Purpose | Example |
264+
|--------|---------|---------|
265+
| `NFV_` | Validation nanoflow | `NFV_ValidateOrder` |
266+
| `NFA_` | Action nanoflow | `NFA_ProcessLocally` |
267+
| `NFS_` | Sub-nanoflow (helper) | `NFS_FormatAddress` |
268+
| `DS_` | Data source nanoflow | `DS_GetActiveProducts` |
269+
| `ON_` | On-change handler | `ON_StatusChanged` |
270+
271+
## Validation Checklist
272+
273+
Before executing a nanoflow script, verify:
274+
275+
- [ ] Uses `create nanoflow` (not `create microflow`)
276+
- [ ] No `as $ReturnVariable` in return declaration
277+
- [ ] Return type is not `Binary` or `Float`
278+
- [ ] No microflow-only actions (Java, REST, workflow, import/export, etc.)
279+
- [ ] No `ErrorEvent` in flow body
280+
- [ ] All `call nanoflow` parameter names match target signature
281+
- [ ] Every flow path ends with `return`
282+
- [ ] No code after `return` statements
283+
- [ ] All entity/association names are fully qualified
284+
- [ ] Nanoflow ends with `/` separator
285+
286+
## Common Errors
287+
288+
| Error | Message | Fix |
289+
|-------|---------|-----|
290+
| CE0125 | Not supported in nanoflows | Remove microflow-only action |
291+
| CE6051 | Web and native activities mixed | Use only web OR native actions |
292+
| CW0701 | Deprecated list parameter | Set `UseListParameterByReference` to true |
293+
| Parse error | Binary/Float return type | Use allowed return type |
294+
295+
## Quick Reference
296+
297+
### Nanoflow Declaration
298+
```mdl
299+
create nanoflow Module.Name ($Param: type) returns ReturnType
300+
folder 'Path' begin ... end; /
301+
```
302+
303+
### Call Nanoflow (inside nanoflow body)
304+
```mdl
305+
$result = call nanoflow Module.Name(Param = $value);
306+
call nanoflow Module.Name(Param = $value) on error continue;
307+
```
308+
309+
### Security
310+
```mdl
311+
grant execute on nanoflow Module.Name to Module.Role;
312+
revoke execute on nanoflow Module.Name from Module.Role;
313+
```
314+
315+
### Error Handling
316+
```mdl
317+
call nanoflow ... on error continue;
318+
call nanoflow ... on error { log ...; return ...; };
319+
```
320+
321+
## Related Documentation
322+
323+
- [Write Microflows Skill](write-microflows.md) — Server-side microflow syntax
324+
- [MDL Syntax Guide](../../docs/02-features/mdl-syntax.md)
325+
- [Mendix Nanoflow Documentation](https://docs.mendix.com/refguide/nanoflows/)

0 commit comments

Comments
 (0)