@cxtms/cx-schema 1.7.4 → 1.7.6
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 +1 -1
- package/.claude/skills/cx-module/SKILL.md +1 -1
- package/.claude/skills/cx-workflow/SKILL.md +5 -3
- 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,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: cx-core
|
|
3
3
|
description: >
|
|
4
|
-
Provides shared
|
|
4
|
+
Provides shared CXTMS entity field reference — domain entities, field names, enums, and customValues patterns.
|
|
5
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
|
---
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: cx-module
|
|
3
3
|
description: >
|
|
4
|
-
|
|
4
|
+
Works with CXTMS app module YAML files — creates, modifies, fixes, validates, and deploys UI screens, forms, grids, and routes.
|
|
5
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
6
|
Not for workflow YAML files, TypeScript code, or non-YAML tasks.
|
|
7
7
|
argument-hint: <description of what to build>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: cx-workflow
|
|
3
3
|
description: >
|
|
4
|
-
|
|
4
|
+
Works with CXTMS workflow YAML files — creates, modifies, fixes, validates, and deploys standard process and Flow state machine workflows.
|
|
5
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
6
|
Not for module YAML files, TypeScript code, or non-YAML tasks.
|
|
7
7
|
argument-hint: <description of what to build>
|
|
@@ -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)
|
|
@@ -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}` |
|