@cxtms/cx-schema 1.9.7 → 1.9.9
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/package.json
CHANGED
|
@@ -68,13 +68,52 @@
|
|
|
68
68
|
"properties": {
|
|
69
69
|
"foreach": {
|
|
70
70
|
"type": "string",
|
|
71
|
-
"description": "
|
|
71
|
+
"description": "Expression evaluating to array collection to iterate (e.g., 'stepName.result?.items?')"
|
|
72
|
+
},
|
|
73
|
+
"item": {
|
|
74
|
+
"type": "string",
|
|
75
|
+
"description": "Variable name for current item (default: 'item')"
|
|
76
|
+
},
|
|
77
|
+
"index": {
|
|
78
|
+
"type": "string",
|
|
79
|
+
"description": "Variable name for current index"
|
|
80
|
+
},
|
|
81
|
+
"conditions": {
|
|
82
|
+
"oneOf": [
|
|
83
|
+
{
|
|
84
|
+
"type": "string",
|
|
85
|
+
"description": "Single NCalc filter expression (e.g., '[item.isActive] = true')"
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"type": "array",
|
|
89
|
+
"items": {
|
|
90
|
+
"oneOf": [
|
|
91
|
+
{ "type": "string" },
|
|
92
|
+
{
|
|
93
|
+
"type": "object",
|
|
94
|
+
"properties": {
|
|
95
|
+
"expression": { "type": "string" }
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
]
|
|
99
|
+
},
|
|
100
|
+
"description": "Array of condition expressions (all must be true)"
|
|
101
|
+
}
|
|
102
|
+
],
|
|
103
|
+
"description": "Filter conditions — only items matching all conditions are included"
|
|
104
|
+
},
|
|
105
|
+
"continueOnError": {
|
|
106
|
+
"type": "boolean",
|
|
107
|
+
"description": "Skip items that cause errors and continue"
|
|
72
108
|
},
|
|
73
109
|
"mapping": {
|
|
74
110
|
"type": "object",
|
|
111
|
+
"description": "Object defining the output shape — each key maps to a template expression or nested value directive",
|
|
75
112
|
"additionalProperties": true
|
|
76
113
|
}
|
|
77
|
-
}
|
|
114
|
+
},
|
|
115
|
+
"required": ["foreach", "mapping"],
|
|
116
|
+
"additionalProperties": false
|
|
78
117
|
},
|
|
79
118
|
{
|
|
80
119
|
"type": "object",
|
|
@@ -145,6 +145,28 @@ transitions:
|
|
|
145
145
|
- **auto**: Automatic evaluation based on conditions; sorted by priority descending
|
|
146
146
|
- **event**: External event-driven; requires `eventName`
|
|
147
147
|
|
|
148
|
+
### Auto-Transitions and Cross-Entity Support
|
|
149
|
+
|
|
150
|
+
Auto-transitions can fire on related entities. For example, an Order status change can trigger a Commodity flow transition via the `OrderCommodities` join table.
|
|
151
|
+
|
|
152
|
+
```yaml
|
|
153
|
+
states:
|
|
154
|
+
- name: Pending
|
|
155
|
+
autoTransitions:
|
|
156
|
+
- to: InTransit
|
|
157
|
+
trigger:
|
|
158
|
+
entityType: Order
|
|
159
|
+
event: StatusChanged
|
|
160
|
+
conditions:
|
|
161
|
+
- "order.orderStatusName == 'Shipped'"
|
|
162
|
+
priority: 1
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**Cross-entity resolution:**
|
|
166
|
+
| Triggering Entity | Flow Entity | Resolution |
|
|
167
|
+
|-------------------|-------------|------------|
|
|
168
|
+
| Order | Commodity | Via `OrderCommodities` join table |
|
|
169
|
+
|
|
148
170
|
### From States
|
|
149
171
|
- Single state: `from: Draft`
|
|
150
172
|
- Multiple states: `from: [Draft, Submitted]`
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
| `Utilities/Template@1` | Handlebars template rendering |
|
|
13
13
|
| `Utilities/Import@1` | Import data |
|
|
14
14
|
| `Utilities/Export@1` | Export data |
|
|
15
|
-
| `Utilities/CsvParse@1` | Parse CSV content |
|
|
15
|
+
| `Utilities/CsvParse@1` | Parse CSV content (supports columns, distinct) |
|
|
16
|
+
| `Utilities/GroupBy@1` | Group collection by fields |
|
|
16
17
|
| `Utilities/MoveFile@1` | Move file |
|
|
17
18
|
| `Utilities/ValidateReCaptcha` | Validate reCAPTCHA |
|
|
18
19
|
| `Utilities/ValidateHMAC` | Validate HMAC signatures |
|
|
@@ -242,7 +243,19 @@ Renders a Handlebars template string with data.
|
|
|
242
243
|
|
|
243
244
|
## CsvParse@1
|
|
244
245
|
|
|
245
|
-
Parses CSV/TSV data from a URL (file://, http://, https://). Headers are trimmed of whitespace, BOM, and special characters
|
|
246
|
+
Parses CSV/TSV data from a URL (file://, http://, https://). Headers are trimmed of whitespace, BOM, and special characters and converted to camelCase. Blank rows are skipped.
|
|
247
|
+
|
|
248
|
+
**Inputs:**
|
|
249
|
+
|
|
250
|
+
| Input | Type | Required | Description |
|
|
251
|
+
|-------|------|----------|-------------|
|
|
252
|
+
| `url` | string | yes | URL to CSV file |
|
|
253
|
+
| `hasHeader` | bool | no | `true` (default). Whether first row has headers |
|
|
254
|
+
| `delimiter` | string | no | `,` (default). Field delimiter. Use `\t` for tab |
|
|
255
|
+
| `columns` | string[] | no | Explicit column names; overrides file header |
|
|
256
|
+
| `distinct` | string[] | no | Deduplicate by these fields; output projected to only these fields |
|
|
257
|
+
|
|
258
|
+
**Outputs:** `records` (array of dicts), `count` (int), `hasRecords` (boolean).
|
|
246
259
|
|
|
247
260
|
```yaml
|
|
248
261
|
- task: "Utilities/CsvParse@1"
|
|
@@ -253,36 +266,25 @@ Parses CSV/TSV data from a URL (file://, http://, https://). Headers are trimmed
|
|
|
253
266
|
outputs:
|
|
254
267
|
- name: rows
|
|
255
268
|
mapping: "records?"
|
|
256
|
-
- name: rowCount
|
|
257
|
-
mapping: "count?"
|
|
258
|
-
```
|
|
259
|
-
|
|
260
|
-
Tab-delimited with custom columns (e.g. GeoNames postal code files):
|
|
261
269
|
|
|
262
|
-
```yaml
|
|
263
270
|
- task: "Utilities/CsvParse@1"
|
|
264
271
|
name: ParsePostalCodes
|
|
265
272
|
inputs:
|
|
266
273
|
url: "{{ Data?.UnzipFiles?.filePath? }}"
|
|
267
274
|
delimiter: "\t"
|
|
268
|
-
columns:
|
|
269
|
-
- CountryCode
|
|
270
|
-
- Code
|
|
271
|
-
- PlaceName
|
|
272
|
-
- StateName
|
|
273
|
-
- StateCode
|
|
274
|
-
- AdminName2
|
|
275
|
-
- AdminCode2
|
|
276
|
-
- AdminName3
|
|
277
|
-
- AdminCode3
|
|
278
|
-
- Latitude
|
|
279
|
-
- Longitude
|
|
280
|
-
- Accuracy
|
|
275
|
+
columns: ["CountryCode", "Code", "PlaceName", "StateName", "StateCode"]
|
|
281
276
|
outputs:
|
|
282
277
|
- name: postalCodes
|
|
283
278
|
mapping: "records?"
|
|
284
|
-
|
|
285
|
-
|
|
279
|
+
|
|
280
|
+
- task: "Utilities/CsvParse@1"
|
|
281
|
+
name: ExtractDistinctStates
|
|
282
|
+
inputs:
|
|
283
|
+
url: "{{ fileUrl }}"
|
|
284
|
+
distinct: ["stateCode", "stateName", "countryCode"]
|
|
285
|
+
outputs:
|
|
286
|
+
- name: states
|
|
287
|
+
mapping: "records?"
|
|
286
288
|
```
|
|
287
289
|
|
|
288
290
|
## Export@1
|
|
@@ -328,3 +330,88 @@ Imports data from file content or URL. Supports `file://` URLs for local files (
|
|
|
328
330
|
```
|
|
329
331
|
|
|
330
332
|
**`file://` URL support**: Import, Order/Import, PostalCodes/Import, and Notes/Import all accept `file://` URLs via UrlStreamHelper. This enables pipeline patterns: HttpRequest (saveToFile) → UnzipFile → Import (file://).
|
|
333
|
+
|
|
334
|
+
---
|
|
335
|
+
|
|
336
|
+
## GroupBy@1
|
|
337
|
+
|
|
338
|
+
Groups a collection of dictionaries by one or more fields. Produces `{ key, values }` groups for batch processing.
|
|
339
|
+
|
|
340
|
+
**Inputs:**
|
|
341
|
+
|
|
342
|
+
| Input | Type | Required | Description |
|
|
343
|
+
|-------|------|----------|-------------|
|
|
344
|
+
| `collection` | List<Dictionary> | yes | Records to group |
|
|
345
|
+
| `by` | string[] | yes | Field names to group by (case-insensitive) |
|
|
346
|
+
|
|
347
|
+
**Outputs:** `items` (array of `{ key: {field: value, ...}, values: [...] }`), `count` (int).
|
|
348
|
+
|
|
349
|
+
```yaml
|
|
350
|
+
- task: "Utilities/GroupBy@1"
|
|
351
|
+
name: GroupByCustomer
|
|
352
|
+
inputs:
|
|
353
|
+
collection: "{{ Data?.ParseCsv?.records? }}"
|
|
354
|
+
by: ["customerId"]
|
|
355
|
+
outputs:
|
|
356
|
+
- name: groups
|
|
357
|
+
mapping: "items?"
|
|
358
|
+
- name: groupCount
|
|
359
|
+
mapping: "count?"
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
---
|
|
363
|
+
|
|
364
|
+
## Import Tasks
|
|
365
|
+
|
|
366
|
+
Import tasks handle bulk data ingestion. All support `file://` URLs for chaining with UnzipFile.
|
|
367
|
+
|
|
368
|
+
### Order/Import@1
|
|
369
|
+
|
|
370
|
+
Imports orders from CSV, JSON, or XLSX. Inputs: `organizationId` (auto-injected), `fileUrl`/`stream`/`orders` (one required), `fileType` (auto-detected), `options` (match-by, update behavior).
|
|
371
|
+
|
|
372
|
+
### States/Import@1
|
|
373
|
+
|
|
374
|
+
Imports US states/provinces. Inputs: `organizationId`, `fileUrl`/`stream`/`states`, `matchByFields`, `updateIfExists`. Deduplicates by match key.
|
|
375
|
+
|
|
376
|
+
### PostalCodes/Import@1
|
|
377
|
+
|
|
378
|
+
Imports postal/ZIP codes. Inputs: `organizationId`, `fileUrl`/`stream`/`postalCodes`, `matchByFields`. Match-key fields protected from overwrite.
|
|
379
|
+
|
|
380
|
+
### TrackingEvent/Import@1
|
|
381
|
+
|
|
382
|
+
Imports tracking events for an order. Inputs: `orderId`, `events`, `matchByFields` (default: `["eventDefinitionName", "eventDate"]`), `skipIfExists`, `createEventDefinitions`. Auto-links commodities via `CommodityId`.
|
|
383
|
+
|
|
384
|
+
```yaml
|
|
385
|
+
# Full ZIP-to-import pipeline
|
|
386
|
+
- task: "Utilities/HttpRequest@1"
|
|
387
|
+
name: Download
|
|
388
|
+
inputs:
|
|
389
|
+
url: "{{ downloadUrl }}"
|
|
390
|
+
method: GET
|
|
391
|
+
saveToFile: true
|
|
392
|
+
|
|
393
|
+
- task: "Utilities/UnzipFile@1"
|
|
394
|
+
name: Unzip
|
|
395
|
+
inputs:
|
|
396
|
+
filePath: "{{ Main?.Download?.result?.FilePath? }}"
|
|
397
|
+
filePattern: "*.csv"
|
|
398
|
+
|
|
399
|
+
- task: "Utilities/CsvParse@1"
|
|
400
|
+
name: Parse
|
|
401
|
+
inputs:
|
|
402
|
+
url: "file://{{ Main?.Unzip?.files?[0] }}"
|
|
403
|
+
distinct: ["stateCode", "stateName", "countryCode"]
|
|
404
|
+
|
|
405
|
+
- task: "States/Import@1"
|
|
406
|
+
name: ImportStates
|
|
407
|
+
inputs:
|
|
408
|
+
organizationId: "{{ organizationId }}"
|
|
409
|
+
states: "{{ Main?.Parse?.records? }}"
|
|
410
|
+
|
|
411
|
+
- task: "PostalCodes/Import@1"
|
|
412
|
+
name: ImportPostalCodes
|
|
413
|
+
inputs:
|
|
414
|
+
organizationId: "{{ organizationId }}"
|
|
415
|
+
fileUrl: "file://{{ Main?.Unzip?.files?[0] }}"
|
|
416
|
+
fileType: "csv"
|
|
417
|
+
```
|