@cxtms/cx-schema 1.7.3 → 1.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/skills/cx-core/SKILL.md +11 -115
- package/.claude/skills/cx-core/ref-cli-auth.md +87 -0
- package/.claude/skills/cx-module/SKILL.md +4 -21
- package/.claude/skills/cx-workflow/SKILL.md +8 -20
- package/.claude/skills/cx-workflow/{ref-expressions.md → ref-expressions-ncalc.md} +10 -146
- package/.claude/skills/cx-workflow/ref-expressions-template.md +148 -0
- package/package.json +1 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: cx-core
|
|
3
3
|
description: >
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
Provides shared CargoXplorer entity field reference — domain entities, field names, enums, and customValues patterns.
|
|
5
|
+
Use when the user asks about CX entity fields, enums, customValues, entity relationships, or needs domain reference for Orders, Contacts, Commodities, Jobs, etc.
|
|
6
6
|
argument-hint: <entity name or question about fields>
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -10,88 +10,7 @@ Shared domain reference for CargoXplorer entities. Used by `cx-workflow` and `cx
|
|
|
10
10
|
|
|
11
11
|
## CX Server Authentication & Management
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
### Authentication
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
# Login to a CX environment (OAuth2 + PKCE — opens browser)
|
|
19
|
-
npx cxtms login https://tms-v3-dev.usatrt.com
|
|
20
|
-
|
|
21
|
-
# Logout from current session
|
|
22
|
-
npx cxtms logout
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
The session is stored at `~/.cxtms/<project-dir>/.session.json`, scoped by project directory name. Each project gets its own server session. The CLI auto-refreshes expired tokens.
|
|
26
|
-
|
|
27
|
-
### PAT Tokens (alternative to OAuth)
|
|
28
|
-
|
|
29
|
-
For CI/CD or headless environments, use Personal Access Tokens instead of interactive OAuth:
|
|
30
|
-
|
|
31
|
-
```bash
|
|
32
|
-
# Check PAT status and setup instructions
|
|
33
|
-
npx cxtms pat setup
|
|
34
|
-
|
|
35
|
-
# Create a new PAT token (requires OAuth login first)
|
|
36
|
-
npx cxtms pat create "my-ci-token"
|
|
37
|
-
|
|
38
|
-
# List active PAT tokens
|
|
39
|
-
npx cxtms pat list
|
|
40
|
-
|
|
41
|
-
# Revoke a PAT token
|
|
42
|
-
npx cxtms pat revoke <tokenId>
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
After creating a PAT, add to `.env` in your project root:
|
|
46
|
-
```
|
|
47
|
-
CXTMS_AUTH=pat_xxxxx...
|
|
48
|
-
CXTMS_SERVER=https://tms-v3-dev.usatrt.com
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
When `CXTMS_AUTH` is set, the CLI skips OAuth and uses the PAT token directly. `CXTMS_SERVER` provides the server URL (or set `server` in `app.yaml`).
|
|
52
|
-
|
|
53
|
-
### Organization Management
|
|
54
|
-
|
|
55
|
-
```bash
|
|
56
|
-
# List organizations on the server
|
|
57
|
-
npx cxtms orgs list
|
|
58
|
-
|
|
59
|
-
# Select an organization interactively
|
|
60
|
-
npx cxtms orgs select
|
|
61
|
-
|
|
62
|
-
# Set active organization by ID
|
|
63
|
-
npx cxtms orgs use <orgId>
|
|
64
|
-
|
|
65
|
-
# Show current context (server, org, app)
|
|
66
|
-
npx cxtms orgs use
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
The active org is cached in the session file and used by all server commands. Override with `--org <id>`.
|
|
70
|
-
|
|
71
|
-
### Session Resolution
|
|
72
|
-
|
|
73
|
-
Server commands resolve the target session in this order:
|
|
74
|
-
1. `CXTMS_AUTH` env var → PAT token auth (with `CXTMS_SERVER` or `app.yaml` server field)
|
|
75
|
-
2. `~/.cxtms/<project-dir>/.session.json` → project-scoped OAuth session
|
|
76
|
-
3. Not logged in → error
|
|
77
|
-
|
|
78
|
-
### Publish
|
|
79
|
-
|
|
80
|
-
```bash
|
|
81
|
-
# Publish all modules and workflows from current project
|
|
82
|
-
npx cxtms publish
|
|
83
|
-
|
|
84
|
-
# Publish only a specific feature directory
|
|
85
|
-
npx cxtms publish --feature billing
|
|
86
|
-
npx cxtms publish billing
|
|
87
|
-
|
|
88
|
-
# Publish with explicit org ID
|
|
89
|
-
npx cxtms publish --org 42
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
Validates all YAML files first, then pushes modules and workflows to the server. Skips files with validation errors and reports results.
|
|
93
|
-
|
|
94
|
-
---
|
|
13
|
+
For CLI authentication, PAT tokens, org management, and publishing: see [ref-cli-auth.md](ref-cli-auth.md)
|
|
95
14
|
|
|
96
15
|
## Feature File Layout
|
|
97
16
|
|
|
@@ -112,40 +31,17 @@ Use `--feature <feature_name>` with `cxtms create` to automatically place files
|
|
|
112
31
|
|
|
113
32
|
## Entity Field Reference
|
|
114
33
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
!cat .claude/skills/cx-core/ref-entity-order.md
|
|
118
|
-
!cat .claude/skills/cx-core/ref-entity-contact.md
|
|
119
|
-
!cat .claude/skills/cx-core/ref-entity-commodity.md
|
|
120
|
-
!cat .claude/skills/cx-core/ref-entity-accounting.md
|
|
121
|
-
|
|
122
|
-
### Order Sub-Entities & Related
|
|
123
|
-
|
|
124
|
-
!cat .claude/skills/cx-core/ref-entity-order-sub.md
|
|
125
|
-
!cat .claude/skills/cx-core/ref-entity-job.md
|
|
126
|
-
|
|
127
|
-
### Pricing & Accounting Lookups
|
|
128
|
-
|
|
129
|
-
!cat .claude/skills/cx-core/ref-entity-rate.md
|
|
130
|
-
|
|
131
|
-
### Shared & Lookup Entities
|
|
132
|
-
|
|
133
|
-
!cat .claude/skills/cx-core/ref-entity-shared.md
|
|
134
|
-
!cat .claude/skills/cx-core/ref-entity-geography.md
|
|
135
|
-
|
|
136
|
-
### Warehouse & Inventory
|
|
137
|
-
|
|
138
|
-
!cat .claude/skills/cx-core/ref-entity-warehouse.md
|
|
34
|
+
Read the relevant entity reference file when needed for the current task. Do not load all files upfront.
|
|
139
35
|
|
|
140
36
|
| Category | Entities | Reference |
|
|
141
37
|
|----------|----------|-----------|
|
|
142
|
-
| **Primary** | Order, Contact, Commodity, AccountingTransaction | ref-entity-order
|
|
143
|
-
| **Order sub** | OrderEntity, TrackingEvent, EventDefinition, LinkedOrder, OrderDocument | ref-entity-order-sub.md |
|
|
144
|
-
| **Job** | Job, JobOrder, JobStatus | ref-entity-job.md |
|
|
145
|
-
| **Pricing** | Rate, Lane, Discount, AccountingItem, AccountingAccount, PaymentTerm | ref-entity-rate.md |
|
|
146
|
-
| **Shared** | Tag, Attachment, Division, EquipmentType, PackageType, Note/NoteThread | ref-entity-shared.md |
|
|
147
|
-
| **Geography** | Country, State, City, Port, Vessel, CustomCode, ModeOfTransportation | ref-entity-geography.md |
|
|
148
|
-
| **Warehouse** | InventoryItem, WarehouseLocation, CargoMovement (Order variant) | ref-entity-warehouse.md |
|
|
38
|
+
| **Primary** | Order, Contact, Commodity, AccountingTransaction | [ref-entity-order.md](ref-entity-order.md), [ref-entity-contact.md](ref-entity-contact.md), [ref-entity-commodity.md](ref-entity-commodity.md), [ref-entity-accounting.md](ref-entity-accounting.md) |
|
|
39
|
+
| **Order sub** | OrderEntity, TrackingEvent, EventDefinition, LinkedOrder, OrderDocument | [ref-entity-order-sub.md](ref-entity-order-sub.md) |
|
|
40
|
+
| **Job** | Job, JobOrder, JobStatus | [ref-entity-job.md](ref-entity-job.md) |
|
|
41
|
+
| **Pricing** | Rate, Lane, Discount, AccountingItem, AccountingAccount, PaymentTerm | [ref-entity-rate.md](ref-entity-rate.md) |
|
|
42
|
+
| **Shared** | Tag, Attachment, Division, EquipmentType, PackageType, Note/NoteThread | [ref-entity-shared.md](ref-entity-shared.md) |
|
|
43
|
+
| **Geography** | Country, State, City, Port, Vessel, CustomCode, ModeOfTransportation | [ref-entity-geography.md](ref-entity-geography.md) |
|
|
44
|
+
| **Warehouse** | InventoryItem, WarehouseLocation, CargoMovement (Order variant) | [ref-entity-warehouse.md](ref-entity-warehouse.md) |
|
|
149
45
|
|
|
150
46
|
## CustomValues Pattern
|
|
151
47
|
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# CX Server Authentication & Management
|
|
2
|
+
|
|
3
|
+
## Contents
|
|
4
|
+
- Authentication (OAuth2 login/logout)
|
|
5
|
+
- PAT Tokens (CI/CD alternative to OAuth)
|
|
6
|
+
- Organization Management
|
|
7
|
+
- Session Resolution
|
|
8
|
+
- Publish (push modules and workflows to server)
|
|
9
|
+
|
|
10
|
+
## Authentication
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
# Login to a CX environment (OAuth2 + PKCE — opens browser)
|
|
14
|
+
npx cxtms login https://tms-v3-dev.usatrt.com
|
|
15
|
+
|
|
16
|
+
# Logout from current session
|
|
17
|
+
npx cxtms logout
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The session is stored at `~/.cxtms/<project-dir>/.session.json`, scoped by project directory name. Each project gets its own server session. The CLI auto-refreshes expired tokens.
|
|
21
|
+
|
|
22
|
+
## PAT Tokens (alternative to OAuth)
|
|
23
|
+
|
|
24
|
+
For CI/CD or headless environments, use Personal Access Tokens instead of interactive OAuth:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# Check PAT status and setup instructions
|
|
28
|
+
npx cxtms pat setup
|
|
29
|
+
|
|
30
|
+
# Create a new PAT token (requires OAuth login first)
|
|
31
|
+
npx cxtms pat create "my-ci-token"
|
|
32
|
+
|
|
33
|
+
# List active PAT tokens
|
|
34
|
+
npx cxtms pat list
|
|
35
|
+
|
|
36
|
+
# Revoke a PAT token
|
|
37
|
+
npx cxtms pat revoke <tokenId>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
After creating a PAT, add to `.env` in your project root:
|
|
41
|
+
```
|
|
42
|
+
CXTMS_AUTH=pat_xxxxx...
|
|
43
|
+
CXTMS_SERVER=https://tms-v3-dev.usatrt.com
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
When `CXTMS_AUTH` is set, the CLI skips OAuth and uses the PAT token directly. `CXTMS_SERVER` provides the server URL (or set `server` in `app.yaml`).
|
|
47
|
+
|
|
48
|
+
## Organization Management
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# List organizations on the server
|
|
52
|
+
npx cxtms orgs list
|
|
53
|
+
|
|
54
|
+
# Select an organization interactively
|
|
55
|
+
npx cxtms orgs select
|
|
56
|
+
|
|
57
|
+
# Set active organization by ID
|
|
58
|
+
npx cxtms orgs use <orgId>
|
|
59
|
+
|
|
60
|
+
# Show current context (server, org, app)
|
|
61
|
+
npx cxtms orgs use
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The active org is cached in the session file and used by all server commands. Override with `--org <id>`.
|
|
65
|
+
|
|
66
|
+
## Session Resolution
|
|
67
|
+
|
|
68
|
+
Server commands resolve the target session in this order:
|
|
69
|
+
1. `CXTMS_AUTH` env var → PAT token auth (with `CXTMS_SERVER` or `app.yaml` server field)
|
|
70
|
+
2. `~/.cxtms/<project-dir>/.session.json` → project-scoped OAuth session
|
|
71
|
+
3. Not logged in → error
|
|
72
|
+
|
|
73
|
+
## Publish
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# Publish all modules and workflows from current project
|
|
77
|
+
npx cxtms publish
|
|
78
|
+
|
|
79
|
+
# Publish only a specific feature directory
|
|
80
|
+
npx cxtms publish --feature billing
|
|
81
|
+
npx cxtms publish billing
|
|
82
|
+
|
|
83
|
+
# Publish with explicit org ID
|
|
84
|
+
npx cxtms publish --org 42
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Validates all YAML files first, then pushes modules and workflows to the server. Skips files with validation errors and reports results.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: cx-module
|
|
3
3
|
description: >
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
Generates schema-valid CargoXplorer app module YAML files (UI screens, forms, grids, routes).
|
|
5
|
+
Use when the user asks to create, modify, or fix a module YAML file, references *-module.yaml files, or asks about UI components/forms/grids/routes in a CX project.
|
|
6
|
+
Not for workflow YAML files, TypeScript code, or non-YAML tasks.
|
|
7
7
|
argument-hint: <description of what to build>
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -400,24 +400,7 @@ Reusable select components (e.g., `Countries/Select`, `Ports/Select`) follow thi
|
|
|
400
400
|
|
|
401
401
|
## Server Module Commands
|
|
402
402
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
```bash
|
|
406
|
-
# Deploy a module YAML to the server (creates or updates)
|
|
407
|
-
npx cxtms appmodule deploy modules/my-module.yaml
|
|
408
|
-
|
|
409
|
-
# Deploy with explicit org ID
|
|
410
|
-
npx cxtms appmodule deploy modules/my-module.yaml --org 42
|
|
411
|
-
|
|
412
|
-
# Undeploy an app module by UUID
|
|
413
|
-
npx cxtms appmodule undeploy <appModuleId>
|
|
414
|
-
|
|
415
|
-
# Publish all modules and workflows (validates first)
|
|
416
|
-
npx cxtms publish
|
|
417
|
-
npx cxtms publish --feature billing
|
|
418
|
-
```
|
|
419
|
-
|
|
420
|
-
Deploy reads `module.appModuleId` from the YAML, queries the server, and creates or updates accordingly. Requires an active session (`cxtms login` or PAT token — see cx-core skill).
|
|
403
|
+
Deploy, undeploy, and publish commands are listed in the CLI section at the top of this file. For authentication setup (login, PAT tokens, org management): see [cx-core/ref-cli-auth.md](.claude/skills/cx-core/ref-cli-auth.md)
|
|
421
404
|
|
|
422
405
|
---
|
|
423
406
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: cx-workflow
|
|
3
3
|
description: >
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
Generates schema-valid CargoXplorer workflow YAML files (standard process and Flow state machine workflows).
|
|
5
|
+
Use when the user asks to create, modify, or fix a workflow YAML file, references workflow/*.yaml files, or asks about workflow tasks/triggers/activities in a CX project.
|
|
6
|
+
Not for module YAML files, TypeScript code, or non-YAML tasks.
|
|
7
7
|
argument-hint: <description of what to build>
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -191,7 +191,8 @@ events: # Workflow-level event handlers
|
|
|
191
191
|
|
|
192
192
|
## Variable References (quick summary)
|
|
193
193
|
|
|
194
|
-
For
|
|
194
|
+
For template expressions and value directives: see [ref-expressions-template.md](.claude/skills/cx-workflow/ref-expressions-template.md)
|
|
195
|
+
For NCalc conditions and functions: see [ref-expressions-ncalc.md](.claude/skills/cx-workflow/ref-expressions-ncalc.md)
|
|
195
196
|
|
|
196
197
|
**`{{ path }}`** — in step inputs. Single `{{ }}` returns raw object. Multiple returns string interpolation.
|
|
197
198
|
**`[variable]`** — in conditions and `expression:` directives. NCalc syntax.
|
|
@@ -294,7 +295,8 @@ Implicit variable: `iteration` (zero-based).
|
|
|
294
295
|
|
|
295
296
|
| Reference | Load |
|
|
296
297
|
|-----------|------|
|
|
297
|
-
| Expressions &
|
|
298
|
+
| Template Expressions & Value Directives | `!cat .claude/skills/cx-workflow/ref-expressions-template.md` |
|
|
299
|
+
| NCalc Expressions & Functions | `!cat .claude/skills/cx-workflow/ref-expressions-ncalc.md` |
|
|
298
300
|
| Flow Workflows (state machines) | `!cat .claude/skills/cx-workflow/ref-flow.md` |
|
|
299
301
|
|
|
300
302
|
## Dynamic Schema Access (load on demand)
|
|
@@ -318,21 +320,7 @@ Implicit variable: `iteration` (zero-based).
|
|
|
318
320
|
|
|
319
321
|
## Server Workflow Commands
|
|
320
322
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
```bash
|
|
324
|
-
# Push a workflow YAML to the server (creates or updates)
|
|
325
|
-
npx cxtms workflow deploy workflows/my-workflow.yaml
|
|
326
|
-
|
|
327
|
-
# Delete a workflow by UUID
|
|
328
|
-
npx cxtms workflow undeploy <workflowId>
|
|
329
|
-
|
|
330
|
-
# Publish all modules and workflows (validates first)
|
|
331
|
-
npx cxtms publish
|
|
332
|
-
npx cxtms publish --feature billing
|
|
333
|
-
```
|
|
334
|
-
|
|
335
|
-
Deploy reads `workflow.workflowId` from the YAML, queries the server, and creates or updates accordingly. Requires an active session (`cxtms login` or PAT token — see cx-core skill).
|
|
323
|
+
Deploy, undeploy, and publish commands are listed in the CLI section at the top of this file. For authentication setup (login, PAT tokens, org management): see [cx-core/ref-cli-auth.md](.claude/skills/cx-core/ref-cli-auth.md)
|
|
336
324
|
|
|
337
325
|
### Execute
|
|
338
326
|
|
|
@@ -1,131 +1,16 @@
|
|
|
1
|
-
#
|
|
1
|
+
# NCalc Expressions & Functions
|
|
2
2
|
|
|
3
3
|
## Contents
|
|
4
|
-
-
|
|
5
|
-
-
|
|
6
|
-
-
|
|
4
|
+
- NCalc expression syntax `[variable]` (in conditions and expression directives)
|
|
5
|
+
- Operators (comparison, logical, arithmetic, ternary, membership)
|
|
6
|
+
- Iterator variables (`[each.*]` and `[item.*]`)
|
|
7
|
+
- Collection functions (any, all, count, sum, first, last, distinct, groupBy, join, etc.)
|
|
8
|
+
- String functions (isNullOrEmpty, length, lower, upper, replace, format, base64, etc.)
|
|
9
|
+
- Date functions (now, parseDate, addDays, formatDate, dateFromUnix, etc.)
|
|
10
|
+
- Math functions (Abs, Ceiling, Floor, Round, Min, Max, etc.)
|
|
11
|
+
- Domain functions (convertWeight, convertDimension)
|
|
7
12
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
## Template Expressions: `{{ path }}` (in step inputs)
|
|
11
|
-
|
|
12
|
-
Used in step `inputs` values. Resolves variable paths from scoped variables.
|
|
13
|
-
|
|
14
|
-
```yaml
|
|
15
|
-
inputs:
|
|
16
|
-
orderId: "{{ inputs.orderId }}" # Simple reference
|
|
17
|
-
url: "{{ chopinConfig.baseUrl }}/api/v1" # String interpolation
|
|
18
|
-
order: "{{ Data.GetOrder.order }}" # Raw object (single {{ }})
|
|
19
|
-
name: "Order {{ Data.GetOrder.order.orderNumber }}" # String interpolation (multiple)
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
**Key behavior**: A single `{{ path }}` returns the **raw object** (preserving type). Multiple `{{ }}` in a string returns string interpolation (each resolved value is `.ToString()`).
|
|
23
|
-
|
|
24
|
-
### Type Converters (prefix in {{ }})
|
|
25
|
-
|
|
26
|
-
```yaml
|
|
27
|
-
organizationId: "{{ int organizationId }}"
|
|
28
|
-
amount: "{{ decimal totalAmount }}"
|
|
29
|
-
isActive: "{{ bool isActive }}"
|
|
30
|
-
flag: "{{ boolOrFalse someFlag }}" # null -> false
|
|
31
|
-
flagOn: "{{ boolOrTrue someFlag }}" # null -> true
|
|
32
|
-
notes: "{{ emptyIfNull notes }}" # null -> ""
|
|
33
|
-
notes: "{{ nullIfEmpty notes }}" # "" or whitespace -> null
|
|
34
|
-
config: "{{ fromJson configJsonString }}" # JSON string -> dict/array
|
|
35
|
-
payload: "{{ toJson someObject }}" # object -> JSON string
|
|
36
|
-
name: "{{ trim value }}"
|
|
37
|
-
search: "{{ luceneString query }}" # escape & quote for Lucene
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
| Converter | Returns | Null handling |
|
|
41
|
-
|-----------|---------|---------------|
|
|
42
|
-
| `string` | `string` | null. Reads `Stream` to string if value is Stream |
|
|
43
|
-
| `int` | `int` | Throws on null |
|
|
44
|
-
| `decimal` | `decimal` | Throws on null |
|
|
45
|
-
| `bool` | `bool` | Throws on null |
|
|
46
|
-
| `boolOrFalse` | `bool` | `false` if null |
|
|
47
|
-
| `boolOrTrue` | `bool` | `true` if null |
|
|
48
|
-
| `datetime` | `DateTime` | Throws on null |
|
|
49
|
-
| `emptyIfNull` | same type | `""` if null, `0` for int?, `0m` for decimal? |
|
|
50
|
-
| `nullIfEmpty` | same type | `null` if empty/whitespace string or empty collection |
|
|
51
|
-
| `luceneString` | `string` | null |
|
|
52
|
-
| `transliterate` | `string` | null (Unicode -> ASCII via Unidecode) |
|
|
53
|
-
| `transliterateUa` | `string` | null (Ukrainian-specific rules) |
|
|
54
|
-
| `fromJson` | `dict` or `array` | null. Empty string -> empty dict |
|
|
55
|
-
| `toJson` | `string` | `""` if null |
|
|
56
|
-
| `trim` | `string` | null |
|
|
57
|
-
|
|
58
|
-
### Value Directives (in YAML input mappings)
|
|
59
|
-
|
|
60
|
-
**`expression`** -- Evaluate NCalc expression as a value:
|
|
61
|
-
```yaml
|
|
62
|
-
amount:
|
|
63
|
-
expression: "[price] * [quantity]"
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
**`coalesce`** -- First non-null value from a list:
|
|
67
|
-
```yaml
|
|
68
|
-
displayName:
|
|
69
|
-
coalesce:
|
|
70
|
-
- "{{ customer.name? }}"
|
|
71
|
-
- "{{ customer.email? }}"
|
|
72
|
-
- "Unknown"
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
**`foreach`** (value context) -- Transform collections inline:
|
|
76
|
-
```yaml
|
|
77
|
-
commodities:
|
|
78
|
-
foreach: "sourceCommodities"
|
|
79
|
-
item: "item" # default: "item"
|
|
80
|
-
conditions: "[item.isActive] = true" # optional NCalc filter per item
|
|
81
|
-
continueOnError: false # optional, skip errors
|
|
82
|
-
mapping: # dict -> List<dict>, string -> List<object>
|
|
83
|
-
name: "{{ item.name }}"
|
|
84
|
-
quantity: "{{ item.qty }}"
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
**`switch`** (value context) -- Value-based switch (case-insensitive match):
|
|
88
|
-
```yaml
|
|
89
|
-
perLb:
|
|
90
|
-
switch: "{{ contact.commissionTier }}"
|
|
91
|
-
cases:
|
|
92
|
-
"tier1": "{{ rate.customValues.commission_per_lb_tier1 }}"
|
|
93
|
-
"tier2": "{{ rate.customValues.commission_per_lb_tier2 }}"
|
|
94
|
-
default: "0"
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
**`extends`** -- Extend/merge an existing object or array:
|
|
98
|
-
```yaml
|
|
99
|
-
orderData:
|
|
100
|
-
extends: "{{ existingOrder }}" # base object or array
|
|
101
|
-
defaultIfNull: {} # fallback if extends is null
|
|
102
|
-
mapping: # dict: merge overrides. array: append items
|
|
103
|
-
status: "Updated"
|
|
104
|
-
notes: "{{ newNotes }}"
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
**`$raw`** -- Prevent template parsing (pass as-is):
|
|
108
|
-
```yaml
|
|
109
|
-
template:
|
|
110
|
-
$raw: "This {{ won't }} be parsed"
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
**`$eval`** -- Parse JSON string then evaluate as template:
|
|
114
|
-
```yaml
|
|
115
|
-
dynamicConfig:
|
|
116
|
-
$eval: "{{ configJsonString }}"
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
**`decrypt`** / **`encrypt`** -- AES-CBC encryption (optional key/IV, has defaults):
|
|
120
|
-
```yaml
|
|
121
|
-
apiKey:
|
|
122
|
-
decrypt:
|
|
123
|
-
encryptedValue: "{{ encryptedApiKey }}"
|
|
124
|
-
key: "{{ encryptionKey }}" # optional Base64 AES key
|
|
125
|
-
initializationVector: "{{ iv }}" # optional Base64 IV
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
---
|
|
13
|
+
For template expressions `{{ path }}` used in step inputs, see [ref-expressions-template.md](ref-expressions-template.md).
|
|
129
14
|
|
|
130
15
|
## NCalc Expressions: `[variable]` (in conditions and expression directives)
|
|
131
16
|
|
|
@@ -224,24 +109,3 @@ Custom: `ceiling([value])` -- same as `Ceiling` but handles type conversion to d
|
|
|
224
109
|
|----------|-------------|
|
|
225
110
|
| `convertWeight([weight], 'Kg', 'Lb')` | Weight unit conversion. Returns `decimal` rounded to 5 places |
|
|
226
111
|
| `convertDimension([length], 'Cm', 'In')` | Dimension unit conversion. Returns `decimal` rounded to 3 places |
|
|
227
|
-
|
|
228
|
-
---
|
|
229
|
-
|
|
230
|
-
## Property Path Syntax (in collection, mapping, variable paths)
|
|
231
|
-
|
|
232
|
-
Used in `collection:` (foreach), `mapping:` (outputs), and variable resolution.
|
|
233
|
-
|
|
234
|
-
| Pattern | Description | Example |
|
|
235
|
-
|---------|-------------|---------|
|
|
236
|
-
| `a.b.c` | Dot-separated nested path | `order.customer.name` |
|
|
237
|
-
| `prop?` | Optional access (null if missing) | `order.customer?.name?` |
|
|
238
|
-
| `list[0]` | Array index | `items[0]` |
|
|
239
|
-
| `list[^1]` | Index from end (last item) | `items[^1]` |
|
|
240
|
-
| `list[*]` | Flatten/wildcard (all items) | `containers[*].commodities` |
|
|
241
|
-
| `list[**]` | Recursive flatten (all depths) | `containerCommodities[**]` |
|
|
242
|
-
| `list[-1]` | Depth filter (leaves only) | `tree[**][-1]` |
|
|
243
|
-
| `list[condition]` | Filter by condition | `items[status=Active]` |
|
|
244
|
-
| `dict['key']` | Dictionary key access | `customValues['myField']` |
|
|
245
|
-
| `list[*].{f1 f2}` | Field selector (projection) | `items[*].{name description}` |
|
|
246
|
-
| `list[*].{alias:source}` | Field selector with alias | `items[*].{id:commodityId}` |
|
|
247
|
-
| `list[*].{alias:_.parent}` | Field selector referencing parent | `items[*].{parentId:_.orderId}` |
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# Template Expressions & Value Directives
|
|
2
|
+
|
|
3
|
+
## Contents
|
|
4
|
+
- Template expression syntax `{{ path }}` (in step inputs)
|
|
5
|
+
- Type converters (int, decimal, bool, fromJson, toJson, etc.)
|
|
6
|
+
- Value directives (expression, coalesce, foreach, switch, extends, $raw, $eval, encrypt/decrypt)
|
|
7
|
+
- Property path syntax (dot paths, array indexing, wildcards, filters, projections)
|
|
8
|
+
|
|
9
|
+
There are **two distinct syntaxes** for referencing variables, used in different contexts. This file covers **template expressions** used in step inputs. For NCalc conditions and functions, see [ref-expressions-ncalc.md](ref-expressions-ncalc.md).
|
|
10
|
+
|
|
11
|
+
## Template Expressions: `{{ path }}` (in step inputs)
|
|
12
|
+
|
|
13
|
+
Used in step `inputs` values. Resolves variable paths from scoped variables.
|
|
14
|
+
|
|
15
|
+
```yaml
|
|
16
|
+
inputs:
|
|
17
|
+
orderId: "{{ inputs.orderId }}" # Simple reference
|
|
18
|
+
url: "{{ chopinConfig.baseUrl }}/api/v1" # String interpolation
|
|
19
|
+
order: "{{ Data.GetOrder.order }}" # Raw object (single {{ }})
|
|
20
|
+
name: "Order {{ Data.GetOrder.order.orderNumber }}" # String interpolation (multiple)
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Key behavior**: A single `{{ path }}` returns the **raw object** (preserving type). Multiple `{{ }}` in a string returns string interpolation (each resolved value is `.ToString()`).
|
|
24
|
+
|
|
25
|
+
### Type Converters (prefix in {{ }})
|
|
26
|
+
|
|
27
|
+
```yaml
|
|
28
|
+
organizationId: "{{ int organizationId }}"
|
|
29
|
+
amount: "{{ decimal totalAmount }}"
|
|
30
|
+
isActive: "{{ bool isActive }}"
|
|
31
|
+
flag: "{{ boolOrFalse someFlag }}" # null -> false
|
|
32
|
+
flagOn: "{{ boolOrTrue someFlag }}" # null -> true
|
|
33
|
+
notes: "{{ emptyIfNull notes }}" # null -> ""
|
|
34
|
+
notes: "{{ nullIfEmpty notes }}" # "" or whitespace -> null
|
|
35
|
+
config: "{{ fromJson configJsonString }}" # JSON string -> dict/array
|
|
36
|
+
payload: "{{ toJson someObject }}" # object -> JSON string
|
|
37
|
+
name: "{{ trim value }}"
|
|
38
|
+
search: "{{ luceneString query }}" # escape & quote for Lucene
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
| Converter | Returns | Null handling |
|
|
42
|
+
|-----------|---------|---------------|
|
|
43
|
+
| `string` | `string` | null. Reads `Stream` to string if value is Stream |
|
|
44
|
+
| `int` | `int` | Throws on null |
|
|
45
|
+
| `decimal` | `decimal` | Throws on null |
|
|
46
|
+
| `bool` | `bool` | Throws on null |
|
|
47
|
+
| `boolOrFalse` | `bool` | `false` if null |
|
|
48
|
+
| `boolOrTrue` | `bool` | `true` if null |
|
|
49
|
+
| `datetime` | `DateTime` | Throws on null |
|
|
50
|
+
| `emptyIfNull` | same type | `""` if null, `0` for int?, `0m` for decimal? |
|
|
51
|
+
| `nullIfEmpty` | same type | `null` if empty/whitespace string or empty collection |
|
|
52
|
+
| `luceneString` | `string` | null |
|
|
53
|
+
| `transliterate` | `string` | null (Unicode -> ASCII via Unidecode) |
|
|
54
|
+
| `transliterateUa` | `string` | null (Ukrainian-specific rules) |
|
|
55
|
+
| `fromJson` | `dict` or `array` | null. Empty string -> empty dict |
|
|
56
|
+
| `toJson` | `string` | `""` if null |
|
|
57
|
+
| `trim` | `string` | null |
|
|
58
|
+
|
|
59
|
+
### Value Directives (in YAML input mappings)
|
|
60
|
+
|
|
61
|
+
**`expression`** -- Evaluate NCalc expression as a value:
|
|
62
|
+
```yaml
|
|
63
|
+
amount:
|
|
64
|
+
expression: "[price] * [quantity]"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**`coalesce`** -- First non-null value from a list:
|
|
68
|
+
```yaml
|
|
69
|
+
displayName:
|
|
70
|
+
coalesce:
|
|
71
|
+
- "{{ customer.name? }}"
|
|
72
|
+
- "{{ customer.email? }}"
|
|
73
|
+
- "Unknown"
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**`foreach`** (value context) -- Transform collections inline:
|
|
77
|
+
```yaml
|
|
78
|
+
commodities:
|
|
79
|
+
foreach: "sourceCommodities"
|
|
80
|
+
item: "item" # default: "item"
|
|
81
|
+
conditions: "[item.isActive] = true" # optional NCalc filter per item
|
|
82
|
+
continueOnError: false # optional, skip errors
|
|
83
|
+
mapping: # dict -> List<dict>, string -> List<object>
|
|
84
|
+
name: "{{ item.name }}"
|
|
85
|
+
quantity: "{{ item.qty }}"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**`switch`** (value context) -- Value-based switch (case-insensitive match):
|
|
89
|
+
```yaml
|
|
90
|
+
perLb:
|
|
91
|
+
switch: "{{ contact.commissionTier }}"
|
|
92
|
+
cases:
|
|
93
|
+
"tier1": "{{ rate.customValues.commission_per_lb_tier1 }}"
|
|
94
|
+
"tier2": "{{ rate.customValues.commission_per_lb_tier2 }}"
|
|
95
|
+
default: "0"
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**`extends`** -- Extend/merge an existing object or array:
|
|
99
|
+
```yaml
|
|
100
|
+
orderData:
|
|
101
|
+
extends: "{{ existingOrder }}" # base object or array
|
|
102
|
+
defaultIfNull: {} # fallback if extends is null
|
|
103
|
+
mapping: # dict: merge overrides. array: append items
|
|
104
|
+
status: "Updated"
|
|
105
|
+
notes: "{{ newNotes }}"
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**`$raw`** -- Prevent template parsing (pass as-is):
|
|
109
|
+
```yaml
|
|
110
|
+
template:
|
|
111
|
+
$raw: "This {{ won't }} be parsed"
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**`$eval`** -- Parse JSON string then evaluate as template:
|
|
115
|
+
```yaml
|
|
116
|
+
dynamicConfig:
|
|
117
|
+
$eval: "{{ configJsonString }}"
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**`decrypt`** / **`encrypt`** -- AES-CBC encryption (optional key/IV, has defaults):
|
|
121
|
+
```yaml
|
|
122
|
+
apiKey:
|
|
123
|
+
decrypt:
|
|
124
|
+
encryptedValue: "{{ encryptedApiKey }}"
|
|
125
|
+
key: "{{ encryptionKey }}" # optional Base64 AES key
|
|
126
|
+
initializationVector: "{{ iv }}" # optional Base64 IV
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Property Path Syntax (in collection, mapping, variable paths)
|
|
132
|
+
|
|
133
|
+
Used in `collection:` (foreach), `mapping:` (outputs), and variable resolution.
|
|
134
|
+
|
|
135
|
+
| Pattern | Description | Example |
|
|
136
|
+
|---------|-------------|---------|
|
|
137
|
+
| `a.b.c` | Dot-separated nested path | `order.customer.name` |
|
|
138
|
+
| `prop?` | Optional access (null if missing) | `order.customer?.name?` |
|
|
139
|
+
| `list[0]` | Array index | `items[0]` |
|
|
140
|
+
| `list[^1]` | Index from end (last item) | `items[^1]` |
|
|
141
|
+
| `list[*]` | Flatten/wildcard (all items) | `containers[*].commodities` |
|
|
142
|
+
| `list[**]` | Recursive flatten (all depths) | `containerCommodities[**]` |
|
|
143
|
+
| `list[-1]` | Depth filter (leaves only) | `tree[**][-1]` |
|
|
144
|
+
| `list[condition]` | Filter by condition | `items[status=Active]` |
|
|
145
|
+
| `dict['key']` | Dictionary key access | `customValues['myField']` |
|
|
146
|
+
| `list[*].{f1 f2}` | Field selector (projection) | `items[*].{name description}` |
|
|
147
|
+
| `list[*].{alias:source}` | Field selector with alias | `items[*].{id:commodityId}` |
|
|
148
|
+
| `list[*].{alias:_.parent}` | Field selector referencing parent | `items[*].{parentId:_.orderId}` |
|