@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.
@@ -1,8 +1,8 @@
1
1
  ---
2
2
  name: cx-core
3
3
  description: >
4
- Shared CargoXplorer entity field reference — domain entities, field names, enums, and customValues patterns.
5
- TRIGGER when: user asks about CX entity fields, enums, customValues, entity relationships, or needs domain reference for Orders, Contacts, Commodities, Jobs, etc.
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
- The CLI can authenticate against CX environments and manage server resources. Auth is required for push, delete, execute, logs, publish, and org commands.
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
- ### Primary Entities
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/contact/commodity/accounting.md |
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
- Generate schema-valid CargoXplorer app module YAML files (UI screens, forms, grids, routes).
5
- TRIGGER when: user asks to create, modify, or fix a module YAML file, or references *-module.yaml files, or asks about UI components/forms/grids/routes in a CX project.
6
- DO NOT TRIGGER when: working with workflow YAML files, general TypeScript/code changes, or non-YAML tasks.
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
- ### Deploy / Undeploy
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
- Generate schema-valid CargoXplorer workflow YAML files (standard process and Flow state machine workflows).
5
- TRIGGER when: user asks to create, modify, or fix a workflow YAML file, or references workflow/*.yaml files, or asks about workflow tasks/triggers/activities in a CX project.
6
- DO NOT TRIGGER when: working with module YAML files, general TypeScript/code changes, or non-YAML tasks.
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 full reference: `!cat .claude/skills/cx-workflow/ref-expressions.md`
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 & Functions | `!cat .claude/skills/cx-workflow/ref-expressions.md` |
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
- ### Deploy / Undeploy
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
- # Variable References & Expressions
1
+ # NCalc Expressions & Functions
2
2
 
3
3
  ## Contents
4
- - Template Expressions: `{{ path }}` (in step inputs)
5
- - NCalc Expressions: `[variable]` (in conditions and expression directives)
6
- - Property Path Syntax (in collection, mapping, variable paths)
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
- There are **two distinct syntaxes** for referencing variables, used in different contexts.
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}` |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cxtms/cx-schema",
3
- "version": "1.7.3",
3
+ "version": "1.7.5",
4
4
  "description": "Schema validation package for CargoXplorer YAML modules",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",