cxtms 1.9.13

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.
Files changed (215) hide show
  1. package/README.md +384 -0
  2. package/dist/cli.d.ts +6 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +4784 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/extractUtils.d.ts +11 -0
  7. package/dist/extractUtils.d.ts.map +1 -0
  8. package/dist/extractUtils.js +19 -0
  9. package/dist/extractUtils.js.map +1 -0
  10. package/dist/index.d.ts +7 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +11 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/types.d.ts +129 -0
  15. package/dist/types.d.ts.map +1 -0
  16. package/dist/types.js +6 -0
  17. package/dist/types.js.map +1 -0
  18. package/dist/utils/schemaLoader.d.ts +17 -0
  19. package/dist/utils/schemaLoader.d.ts.map +1 -0
  20. package/dist/utils/schemaLoader.js +134 -0
  21. package/dist/utils/schemaLoader.js.map +1 -0
  22. package/dist/validator.d.ts +72 -0
  23. package/dist/validator.d.ts.map +1 -0
  24. package/dist/validator.js +432 -0
  25. package/dist/validator.js.map +1 -0
  26. package/dist/workflowValidator.d.ts +103 -0
  27. package/dist/workflowValidator.d.ts.map +1 -0
  28. package/dist/workflowValidator.js +753 -0
  29. package/dist/workflowValidator.js.map +1 -0
  30. package/package.json +51 -0
  31. package/schemas/actions/all.json +27 -0
  32. package/schemas/actions/clipboard.json +46 -0
  33. package/schemas/actions/confirm.json +21 -0
  34. package/schemas/actions/consoleLog.json +16 -0
  35. package/schemas/actions/dialog.json +25 -0
  36. package/schemas/actions/fileDownload.json +16 -0
  37. package/schemas/actions/forEach.json +31 -0
  38. package/schemas/actions/if.json +12 -0
  39. package/schemas/actions/mutation.json +25 -0
  40. package/schemas/actions/navigate.json +18 -0
  41. package/schemas/actions/navigateBack.json +22 -0
  42. package/schemas/actions/navigateBackOrClose.json +21 -0
  43. package/schemas/actions/notification.json +19 -0
  44. package/schemas/actions/openBarcodeScanner.json +104 -0
  45. package/schemas/actions/query.json +32 -0
  46. package/schemas/actions/refresh.json +13 -0
  47. package/schemas/actions/resetDirtyState.json +22 -0
  48. package/schemas/actions/setFields.json +21 -0
  49. package/schemas/actions/setStore.json +13 -0
  50. package/schemas/actions/validateForm.json +15 -0
  51. package/schemas/actions/workflow.json +24 -0
  52. package/schemas/components/README.md +147 -0
  53. package/schemas/components/appComponent.json +58 -0
  54. package/schemas/components/barcodeScanner.json +69 -0
  55. package/schemas/components/button.json +123 -0
  56. package/schemas/components/calendar.json +489 -0
  57. package/schemas/components/card.json +176 -0
  58. package/schemas/components/collection.json +54 -0
  59. package/schemas/components/dataGrid.json +119 -0
  60. package/schemas/components/datasource.json +151 -0
  61. package/schemas/components/dropdown.json +57 -0
  62. package/schemas/components/field-collection.json +618 -0
  63. package/schemas/components/field.json +265 -0
  64. package/schemas/components/form.json +234 -0
  65. package/schemas/components/index.json +71 -0
  66. package/schemas/components/layout.json +69 -0
  67. package/schemas/components/module.json +167 -0
  68. package/schemas/components/navDropdown.json +36 -0
  69. package/schemas/components/navbar.json +78 -0
  70. package/schemas/components/navbarItem.json +28 -0
  71. package/schemas/components/navbarLink.json +36 -0
  72. package/schemas/components/row.json +31 -0
  73. package/schemas/components/slot.json +30 -0
  74. package/schemas/components/tab.json +34 -0
  75. package/schemas/components/tabs.json +35 -0
  76. package/schemas/components/timeline.json +172 -0
  77. package/schemas/components/timelineGrid.json +328 -0
  78. package/schemas/fields/README.md +66 -0
  79. package/schemas/fields/attachment.json +156 -0
  80. package/schemas/fields/autocomplete-googleplaces.json +130 -0
  81. package/schemas/fields/checkbox.json +82 -0
  82. package/schemas/fields/date.json +88 -0
  83. package/schemas/fields/datetime.json +75 -0
  84. package/schemas/fields/email.json +75 -0
  85. package/schemas/fields/index.json +53 -0
  86. package/schemas/fields/number.json +91 -0
  87. package/schemas/fields/password.json +70 -0
  88. package/schemas/fields/radio.json +94 -0
  89. package/schemas/fields/rangedatetime.json +56 -0
  90. package/schemas/fields/select-async.json +334 -0
  91. package/schemas/fields/select.json +115 -0
  92. package/schemas/fields/tel.json +79 -0
  93. package/schemas/fields/text.json +86 -0
  94. package/schemas/fields/textarea.json +95 -0
  95. package/schemas/fields/time.json +91 -0
  96. package/schemas/fields/url.json +74 -0
  97. package/schemas/schema.graphql +12248 -0
  98. package/schemas/schemas.json +610 -0
  99. package/schemas/workflows/activity.json +96 -0
  100. package/schemas/workflows/common/condition.json +48 -0
  101. package/schemas/workflows/common/expression.json +76 -0
  102. package/schemas/workflows/common/mapping.json +173 -0
  103. package/schemas/workflows/common/step.json +38 -0
  104. package/schemas/workflows/flow/aggregation.json +44 -0
  105. package/schemas/workflows/flow/entity.json +129 -0
  106. package/schemas/workflows/flow/state.json +105 -0
  107. package/schemas/workflows/flow/transition.json +143 -0
  108. package/schemas/workflows/input.json +122 -0
  109. package/schemas/workflows/output.json +61 -0
  110. package/schemas/workflows/schedule.json +26 -0
  111. package/schemas/workflows/tasks/accounting-transaction.json +95 -0
  112. package/schemas/workflows/tasks/action-event.json +65 -0
  113. package/schemas/workflows/tasks/all.json +152 -0
  114. package/schemas/workflows/tasks/appmodule.json +56 -0
  115. package/schemas/workflows/tasks/attachment.json +97 -0
  116. package/schemas/workflows/tasks/authentication.json +86 -0
  117. package/schemas/workflows/tasks/caching.json +68 -0
  118. package/schemas/workflows/tasks/charge.json +92 -0
  119. package/schemas/workflows/tasks/commodity.json +92 -0
  120. package/schemas/workflows/tasks/contact-address.json +72 -0
  121. package/schemas/workflows/tasks/contact-payment-method.json +72 -0
  122. package/schemas/workflows/tasks/contact.json +82 -0
  123. package/schemas/workflows/tasks/csv.json +81 -0
  124. package/schemas/workflows/tasks/document-render.json +105 -0
  125. package/schemas/workflows/tasks/document-send.json +84 -0
  126. package/schemas/workflows/tasks/edi.json +157 -0
  127. package/schemas/workflows/tasks/email-send.json +110 -0
  128. package/schemas/workflows/tasks/error.json +72 -0
  129. package/schemas/workflows/tasks/export.json +90 -0
  130. package/schemas/workflows/tasks/filetransfer.json +102 -0
  131. package/schemas/workflows/tasks/flow-transition.json +68 -0
  132. package/schemas/workflows/tasks/foreach.json +69 -0
  133. package/schemas/workflows/tasks/generic.json +47 -0
  134. package/schemas/workflows/tasks/graphql.json +78 -0
  135. package/schemas/workflows/tasks/httpRequest.json +161 -0
  136. package/schemas/workflows/tasks/import.json +64 -0
  137. package/schemas/workflows/tasks/inventory.json +67 -0
  138. package/schemas/workflows/tasks/job.json +88 -0
  139. package/schemas/workflows/tasks/log.json +73 -0
  140. package/schemas/workflows/tasks/map.json +58 -0
  141. package/schemas/workflows/tasks/movement.json +54 -0
  142. package/schemas/workflows/tasks/note.json +59 -0
  143. package/schemas/workflows/tasks/number.json +65 -0
  144. package/schemas/workflows/tasks/order-tracking-event.json +109 -0
  145. package/schemas/workflows/tasks/order.json +139 -0
  146. package/schemas/workflows/tasks/payment.json +85 -0
  147. package/schemas/workflows/tasks/pdf-document.json +60 -0
  148. package/schemas/workflows/tasks/postal-codes.json +92 -0
  149. package/schemas/workflows/tasks/resolve-timezone.json +65 -0
  150. package/schemas/workflows/tasks/setVariable.json +76 -0
  151. package/schemas/workflows/tasks/switch.json +75 -0
  152. package/schemas/workflows/tasks/template.json +73 -0
  153. package/schemas/workflows/tasks/tracking-event.json +137 -0
  154. package/schemas/workflows/tasks/transmission.json +185 -0
  155. package/schemas/workflows/tasks/unzip-file.json +68 -0
  156. package/schemas/workflows/tasks/user.json +70 -0
  157. package/schemas/workflows/tasks/validation.json +99 -0
  158. package/schemas/workflows/tasks/while.json +53 -0
  159. package/schemas/workflows/tasks/workflow-execute.json +82 -0
  160. package/schemas/workflows/trigger.json +90 -0
  161. package/schemas/workflows/variable.json +46 -0
  162. package/schemas/workflows/workflow.json +335 -0
  163. package/scripts/postinstall.js +291 -0
  164. package/scripts/setup-vscode.js +80 -0
  165. package/skills/cxtms-developer/SKILL.md +118 -0
  166. package/skills/cxtms-developer/ref-cli-auth.md +120 -0
  167. package/skills/cxtms-developer/ref-entity-accounting.md +180 -0
  168. package/skills/cxtms-developer/ref-entity-commodity.md +239 -0
  169. package/skills/cxtms-developer/ref-entity-contact.md +163 -0
  170. package/skills/cxtms-developer/ref-entity-geography.md +154 -0
  171. package/skills/cxtms-developer/ref-entity-job.md +77 -0
  172. package/skills/cxtms-developer/ref-entity-notification.md +85 -0
  173. package/skills/cxtms-developer/ref-entity-order-sub.md +160 -0
  174. package/skills/cxtms-developer/ref-entity-order.md +183 -0
  175. package/skills/cxtms-developer/ref-entity-organization.md +41 -0
  176. package/skills/cxtms-developer/ref-entity-rate.md +182 -0
  177. package/skills/cxtms-developer/ref-entity-shared.md +176 -0
  178. package/skills/cxtms-developer/ref-entity-warehouse.md +115 -0
  179. package/skills/cxtms-developer/ref-graphql-query.md +309 -0
  180. package/skills/cxtms-module-builder/SKILL.md +477 -0
  181. package/skills/cxtms-module-builder/ref-components-data.md +293 -0
  182. package/skills/cxtms-module-builder/ref-components-display.md +411 -0
  183. package/skills/cxtms-module-builder/ref-components-forms.md +369 -0
  184. package/skills/cxtms-module-builder/ref-components-interactive.md +317 -0
  185. package/skills/cxtms-module-builder/ref-components-layout.md +390 -0
  186. package/skills/cxtms-module-builder/ref-components-specialized.md +477 -0
  187. package/skills/cxtms-workflow-builder/SKILL.md +438 -0
  188. package/skills/cxtms-workflow-builder/ref-accounting.md +66 -0
  189. package/skills/cxtms-workflow-builder/ref-communication.md +169 -0
  190. package/skills/cxtms-workflow-builder/ref-entity.md +342 -0
  191. package/skills/cxtms-workflow-builder/ref-expressions-ncalc.md +128 -0
  192. package/skills/cxtms-workflow-builder/ref-expressions-template.md +161 -0
  193. package/skills/cxtms-workflow-builder/ref-filetransfer.md +80 -0
  194. package/skills/cxtms-workflow-builder/ref-flow.md +210 -0
  195. package/skills/cxtms-workflow-builder/ref-other.md +157 -0
  196. package/skills/cxtms-workflow-builder/ref-query.md +105 -0
  197. package/skills/cxtms-workflow-builder/ref-utilities.md +417 -0
  198. package/templates/module-configuration.yaml +44 -0
  199. package/templates/module-form.yaml +152 -0
  200. package/templates/module-grid.yaml +229 -0
  201. package/templates/module-select.yaml +139 -0
  202. package/templates/module.yaml +84 -0
  203. package/templates/workflow-api-tracking.yaml +189 -0
  204. package/templates/workflow-basic.yaml +76 -0
  205. package/templates/workflow-document.yaml +155 -0
  206. package/templates/workflow-entity-trigger.yaml +90 -0
  207. package/templates/workflow-ftp-edi.yaml +158 -0
  208. package/templates/workflow-ftp-tracking.yaml +161 -0
  209. package/templates/workflow-mcp-tool.yaml +112 -0
  210. package/templates/workflow-public-api.yaml +135 -0
  211. package/templates/workflow-scheduled-execute.yaml +75 -0
  212. package/templates/workflow-scheduled.yaml +125 -0
  213. package/templates/workflow-utility.yaml +96 -0
  214. package/templates/workflow-webhook.yaml +128 -0
  215. package/templates/workflow.yaml +140 -0
@@ -0,0 +1,417 @@
1
+ # Utilities Tasks Reference
2
+
3
+ ## Available Tasks
4
+
5
+ | Task | Description |
6
+ |------|-------------|
7
+ | `Utilities/SetVariable@1` | Set variables in workflow scope (activity + global) |
8
+ | `Utilities/Log@1` | Log all task variables to workflow logger |
9
+ | `Utilities/Error@1` | Throw a workflow error with message |
10
+ | `Utilities/HttpRequest@1` | HTTP request (GET/POST/PUT/PATCH/DELETE) |
11
+ | `Utilities/Map@1` | Map/extract variables from inputs |
12
+ | `Utilities/Template@1` | Handlebars template rendering |
13
+ | `Utilities/Import@1` | Import data |
14
+ | `Utilities/Export@1` | Export data |
15
+ | `Utilities/CsvParse@1` | Parse CSV content (supports columns, distinct) |
16
+ | `Utilities/GroupBy@1` | Group collection by fields |
17
+ | `Utilities/MoveFile@1` | Move file |
18
+ | `Utilities/ValidateReCaptcha` | Validate reCAPTCHA |
19
+ | `Utilities/ValidateHMAC` | Validate HMAC signatures |
20
+ | `Utilities/UnzipFile@1` | Extract files from ZIP archive (local path or URL) |
21
+ | `Utilities/ResolveTimezone@1` | Resolve IANA timezone and UTC offset from lat/lng coordinates |
22
+
23
+ ## UnzipFile@1
24
+
25
+ Extracts files from a ZIP archive. Accepts a local file path (from `saveToFile` or previous step) or a URL (`file://`, `http://`, `https://`). Files are extracted to a workflow-scoped temp directory with auto-cleanup.
26
+
27
+ ```yaml
28
+ - task: "Utilities/UnzipFile@1"
29
+ name: ExtractArchive
30
+ inputs:
31
+ filePath: "{{ Main?.DownloadArchive?.result?.FilePath? }}"
32
+ filePattern: "*.csv"
33
+ outputs:
34
+ - name: files
35
+ mapping: "Files?"
36
+ - name: count
37
+ mapping: "Count?"
38
+ ```
39
+
40
+ **Inputs:** `filePath` (string, local path) OR `fileUrl` (string, URL — `file://`, `http://`, `https://`). Optional: `filePattern` (glob pattern, e.g. `*.csv`, `data_*.json`).
41
+ **Outputs:** `Files` (string[] — full paths to extracted files), `Count` (int — number of matched files).
42
+ Provide one of `filePath` or `fileUrl`. Common pattern: HttpRequest with `saveToFile: true` → UnzipFile with `filePath`.
43
+
44
+ ```yaml
45
+ # Download + unzip + import pipeline
46
+ - task: "Utilities/HttpRequest@1"
47
+ name: Download
48
+ inputs:
49
+ url: "{{ downloadUrl }}"
50
+ method: GET
51
+ saveToFile: true
52
+ outputs:
53
+ - name: result
54
+ mapping: "response?"
55
+
56
+ - task: "Utilities/UnzipFile@1"
57
+ name: Unzip
58
+ inputs:
59
+ filePath: "{{ Main?.Download?.result?.FilePath? }}"
60
+ filePattern: "*.csv"
61
+ outputs:
62
+ - name: files
63
+ mapping: "Files?"
64
+
65
+ - task: foreach
66
+ name: ProcessFiles
67
+ collection: "Main?.Unzip?.files?"
68
+ steps:
69
+ - task: "Utilities/Import@1"
70
+ name: ImportFile
71
+ inputs:
72
+ fileUrl: "file://{{ item }}"
73
+ format: "csv"
74
+ ```
75
+
76
+ ---
77
+
78
+ ## ResolveTimezone@1
79
+
80
+ Resolves IANA timezone ID and current UTC offset from geographic coordinates using offline boundary lookup (GeoTimeZone).
81
+
82
+ ```yaml
83
+ - task: "Utilities/ResolveTimezone@1"
84
+ name: ResolveTimezone
85
+ inputs:
86
+ latitude: "{{ postalCode.location.y }}"
87
+ longitude: "{{ postalCode.location.x }}"
88
+ outputs:
89
+ - name: tz
90
+ mapping: "timezoneId?"
91
+ - name: offset
92
+ mapping: "utcOffset?"
93
+ ```
94
+
95
+ **Inputs:** `latitude` (double/string, required), `longitude` (double/string, required)
96
+ **Outputs:** `timezoneId` (string, e.g. `America/Chicago`), `utcOffset` (double, e.g. `-5`)
97
+ Throws `WorkflowRuntimeException` if lat/lng missing or unparseable.
98
+
99
+ ---
100
+
101
+ ## SetVariable@1
102
+
103
+ Sets variables directly into both activity and global scope. No outputs — the side effect IS the variable setting.
104
+
105
+ ```yaml
106
+ - task: "Utilities/SetVariable@1"
107
+ name: SetResult
108
+ inputs:
109
+ variables:
110
+ - name: processResult
111
+ value:
112
+ success: true
113
+ orderId: "{{ inputs.orderId }}"
114
+ - name: hasMore
115
+ value:
116
+ expression: "[offset] < [Data?.FetchPage?.result?.totalCount?]"
117
+ ```
118
+
119
+ Each variable entry has `name` (string) and `value` (any type, supports expression directives).
120
+
121
+ ## Log@1
122
+
123
+ Logs all task variables (everything in the step's scoped variables) to the workflow file logger.
124
+
125
+ ```yaml
126
+ - task: "Utilities/Log@1"
127
+ name: LogInfo
128
+ inputs:
129
+ message: "Processing order: {{ Data?.GetOrder?.order?.orderNumber? }}"
130
+ level: Information
131
+ ```
132
+
133
+ Levels: `Debug`, `Information`, `Warning`, `Error`.
134
+
135
+ ## Error@1
136
+
137
+ Throws a workflow error that halts execution (unless `continueOnError: true` on a parent step).
138
+
139
+ ```yaml
140
+ - task: "Utilities/Error@1"
141
+ name: ThrowValidationError
142
+ conditions:
143
+ - expression: "isNullOrEmpty([Data?.GetOrder?.order?]) = true"
144
+ inputs:
145
+ message: "Order not found: {{ inputs.orderId }}"
146
+ ```
147
+
148
+ ## HttpRequest@1
149
+
150
+ Performs HTTP requests to external APIs.
151
+
152
+ ```yaml
153
+ - task: "Utilities/HttpRequest@1"
154
+ name: CallApi
155
+ inputs:
156
+ url: "{{ apiBaseUrl }}/api/v1/orders"
157
+ method: POST
158
+ contentType: "application/json"
159
+ headers:
160
+ - name: "Authorization"
161
+ value: "Bearer {{ apiToken }}"
162
+ body:
163
+ orderId: "{{ inputs.orderId }}"
164
+ outputs:
165
+ - name: result
166
+ mapping: "response?.body?"
167
+ ```
168
+
169
+ **Response structure**: The task returns a `Dictionary<string, object>` (case-insensitive) with key `response`. The response contains `StatusCode`, `Headers`, and `Body` (PascalCase in C#, but access is case-insensitive). Use `response?.body?` to get the parsed body. You can drill deeper: `response?.body?.output?`, `response?.body?.items?[0]?`.
170
+
171
+ **Case sensitivity**: Variable paths go through `Dictionary<string, object>(StringComparer.OrdinalIgnoreCase)` — so `body` and `Body` both work. Convention: use lowercase `body`.
172
+
173
+ Response available at `ActivityName?.CallApi?.result?`.
174
+
175
+ **`saveToFile` mode**: When `saveToFile: true`, the response body is saved to a temp file instead of being returned in memory. The response object changes to `{ StatusCode, Headers, FilePath }`. Use this for large file downloads, then pass `FilePath` to downstream tasks like `UnzipFile` or `Import`.
176
+
177
+ ```yaml
178
+ - task: "Utilities/HttpRequest@1"
179
+ name: DownloadArchive
180
+ inputs:
181
+ url: "{{ downloadUrl }}"
182
+ method: GET
183
+ saveToFile: true
184
+ outputs:
185
+ - name: result
186
+ mapping: "response?"
187
+ # result.FilePath contains the temp file path
188
+ ```
189
+
190
+ **Action events**: When an HTTP request operates on a specific entity (e.g., sending parcel info for an order), enable `actionEvents` in the inputs so the system can track and notify about the request. Include `eventDataExt` with the entity ID to link the event to the entity.
191
+
192
+ ```yaml
193
+ - task: "Utilities/HttpRequest@1"
194
+ name: CallCarrierApi
195
+ inputs:
196
+ actionEvents:
197
+ enabled: true
198
+ eventName: "carrier.sendParcelInfo"
199
+ eventDataExt:
200
+ orderId: "{{ inputs.orderId }}"
201
+ url: "{{ carrierConfig?.baseUrl? }}/api/shipments"
202
+ method: POST
203
+ contentType: "application/json"
204
+ body:
205
+ trackingNumber: "{{ Data?.GetOrder?.order?.trackingNumber? }}"
206
+ outputs:
207
+ - name: result
208
+ mapping: "response?.body?"
209
+ ```
210
+
211
+ ## Map@1
212
+
213
+ Extracts/reshapes data from variables into new variables.
214
+
215
+ ```yaml
216
+ - task: "Utilities/Map@1"
217
+ name: MapData
218
+ inputs:
219
+ variables:
220
+ - name: orderNumber
221
+ value: "{{ Data?.GetOrder?.order?.orderNumber? }}"
222
+ - name: customerName
223
+ value: "{{ Data?.GetOrder?.order?.customer?.name? }}"
224
+ ```
225
+
226
+ ## Template@1
227
+
228
+ Renders a Handlebars template string with data.
229
+
230
+ ```yaml
231
+ - task: "Utilities/Template@1"
232
+ name: RenderMessage
233
+ inputs:
234
+ template: "Hello {{name}}, your order {{orderNumber}} is {{status}}."
235
+ data:
236
+ name: "{{ Data?.GetOrder?.order?.customer?.name? }}"
237
+ orderNumber: "{{ Data?.GetOrder?.order?.orderNumber? }}"
238
+ status: "{{ Data?.GetOrder?.order?.status? }}"
239
+ outputs:
240
+ - name: message
241
+ mapping: "result?"
242
+ ```
243
+
244
+ ## CsvParse@1
245
+
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).
259
+
260
+ ```yaml
261
+ - task: "Utilities/CsvParse@1"
262
+ name: ParseCsv
263
+ inputs:
264
+ url: "{{ Data?.DownloadFile?.filePath? }}"
265
+ hasHeader: true
266
+ outputs:
267
+ - name: rows
268
+ mapping: "records?"
269
+
270
+ - task: "Utilities/CsvParse@1"
271
+ name: ParsePostalCodes
272
+ inputs:
273
+ url: "{{ Data?.UnzipFiles?.filePath? }}"
274
+ delimiter: "\t"
275
+ columns: ["CountryCode", "Code", "PlaceName", "StateName", "StateCode"]
276
+ outputs:
277
+ - name: postalCodes
278
+ mapping: "records?"
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?"
288
+ ```
289
+
290
+ ## Export@1
291
+
292
+ Exports data to file format.
293
+
294
+ ```yaml
295
+ - task: "Utilities/Export@1"
296
+ name: ExportData
297
+ inputs:
298
+ data: "{{ Data?.GetOrders?.result?.items? }}"
299
+ format: "csv"
300
+ outputs:
301
+ - name: file
302
+ mapping: "file?"
303
+ ```
304
+
305
+ ## Import@1
306
+
307
+ Imports data from file content or URL. Supports `file://` URLs for local files (e.g. from UnzipFile output).
308
+
309
+ ```yaml
310
+ - task: "Utilities/Import@1"
311
+ name: ImportData
312
+ inputs:
313
+ content: "{{ fileContent }}"
314
+ format: "csv"
315
+ outputs:
316
+ - name: data
317
+ mapping: "data?"
318
+ ```
319
+
320
+ ```yaml
321
+ # Import from local file (e.g. extracted from ZIP)
322
+ - task: "Utilities/Import@1"
323
+ name: ImportLocalFile
324
+ inputs:
325
+ fileUrl: "file://{{ localFilePath }}"
326
+ format: "csv"
327
+ outputs:
328
+ - name: data
329
+ mapping: "data?"
330
+ ```
331
+
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
+ ```
@@ -0,0 +1,44 @@
1
+ # {{displayName}} Configuration Module
2
+ # Generated by cxtms create module --template configuration
3
+
4
+ module:
5
+ name: "{{displayNameNoSpaces}}"
6
+ appModuleId: "{{uuid}}"
7
+ displayName:
8
+ en-US: "{{displayName}}"
9
+ description:
10
+ en-US: "{{displayName}} configuration module"
11
+ application: System
12
+
13
+ components:
14
+ - name: Configurations/{{displayNameNoSpaces}}
15
+ displayName:
16
+ en-US: "{{displayName}} Config"
17
+ platforms:
18
+ - web
19
+ layout:
20
+ component: layout
21
+ name: {{displayNameNoSpaces}}ConfigLayout
22
+ props:
23
+ cols: 1
24
+ title:
25
+ en-US: "{{displayName}} Configuration"
26
+ icon: Create
27
+ permission: System/OrganizationConfigs/Update
28
+ children:
29
+ - component: field
30
+ name: customValues.enabled
31
+ props:
32
+ type: checkbox
33
+ label:
34
+ en-US: "Enable {{displayName}}"
35
+
36
+ configurations:
37
+ - configName: "apps.{{name}}"
38
+ displayName:
39
+ en-US: "{{displayName}}"
40
+ description:
41
+ en-US: "{{displayName}} configuration"
42
+ component: "Configurations/{{displayNameNoSpaces}}"
43
+ defaultValue:
44
+ enabled: false
@@ -0,0 +1,152 @@
1
+ # {{displayName}} Form Module
2
+ # Generated by cxtms create module --template form
3
+
4
+ module:
5
+ name: "{{displayNameNoSpaces}}"
6
+ appModuleId: "{{uuid}}"
7
+ displayName:
8
+ en-US: "{{displayName}}"
9
+ description:
10
+ en-US: "{{displayName}} module"
11
+ application: System
12
+ filePath: "{{fileName}}"
13
+
14
+ components:
15
+ - name: {{displayNameNoSpaces}}/Detail
16
+ displayName:
17
+ en-US: "{{displayName}} Detail"
18
+ platforms:
19
+ - web
20
+ layout:
21
+ component: form
22
+ name: {{name}}Form
23
+ props:
24
+ title:
25
+ en-US: "{{displayName}}"
26
+ toolbar:
27
+ - component: button
28
+ name: saveBtn
29
+ props:
30
+ label:
31
+ en-US: "Save"
32
+ icon: check
33
+ options:
34
+ type: submit
35
+ variant: primary
36
+ - component: button
37
+ name: cancelBtn
38
+ props:
39
+ label:
40
+ en-US: "Cancel"
41
+ icon: x
42
+ options:
43
+ variant: secondary
44
+ onClick:
45
+ - navigateBack:
46
+ fallback: "/{{name}}"
47
+ dirtyGuard:
48
+ enabled: true
49
+ title:
50
+ en-US: "Unsaved Changes"
51
+ message:
52
+ en-US: "You have unsaved changes. Are you sure you want to leave?"
53
+ confirmLabel:
54
+ en-US: "Leave"
55
+ cancelLabel:
56
+ en-US: "Stay"
57
+ queries:
58
+ - name: get{{displayNameNoSpaces}}
59
+ query:
60
+ command: |
61
+ query Get{{displayNameNoSpaces}}($organizationId: Int!, $id: Int!) {
62
+ {{name}}(organizationId: $organizationId, id: $id) {
63
+ id
64
+ name
65
+ description
66
+ }
67
+ }
68
+ variables:
69
+ organizationId: '\{{number organizationId}}'
70
+ id: '\{{number id}}'
71
+ initialValues:
72
+ fromQuery:
73
+ name: get{{displayNameNoSpaces}}
74
+ path: {{name}}
75
+ validationSchema:
76
+ name:
77
+ type: string
78
+ required: true
79
+ description:
80
+ type: string
81
+ onSubmit:
82
+ - mutation:
83
+ command: |
84
+ mutation Save{{displayNameNoSpaces}}($organizationId: Int!, $input: {{displayNameNoSpaces}}Input!) {
85
+ save{{displayNameNoSpaces}}(organizationId: $organizationId, input: $input) {
86
+ id
87
+ }
88
+ }
89
+ variables:
90
+ organizationId: '\{{number organizationId}}'
91
+ input: '\{{form}}'
92
+ onSuccess:
93
+ - notification:
94
+ message:
95
+ en-US: "{{displayName}} saved successfully"
96
+ type: success
97
+ - navigateBack:
98
+ fallback: "/{{name}}"
99
+ onError:
100
+ - notification:
101
+ message:
102
+ en-US: "Failed to save {{displayName}}"
103
+ type: error
104
+ children:
105
+ - component: field
106
+ name: name
107
+ props:
108
+ label:
109
+ en-US: "Name"
110
+ type: text
111
+ required: true
112
+ - component: field
113
+ name: description
114
+ props:
115
+ label:
116
+ en-US: "Description"
117
+ type: textarea
118
+
119
+ routes:
120
+ - name: detail
121
+ path: /{{name}}/:id
122
+ component: {{displayNameNoSpaces}}/Detail
123
+ props:
124
+ title:
125
+ en-US: "{{displayName}}"
126
+
127
+ entities:
128
+ - name: {{displayNameNoSpaces}}
129
+ entityKind: Other
130
+ displayName:
131
+ en-US: "{{displayName}}"
132
+ fields:
133
+ - name: name
134
+ displayName:
135
+ en-US: "Name"
136
+ fieldType: text
137
+ - name: description
138
+ displayName:
139
+ en-US: "Description"
140
+ fieldType: text
141
+
142
+ permissions:
143
+ - name: "{{displayNameNoSpaces}}/Read"
144
+ displayName:
145
+ en-US: "Read {{displayName}}"
146
+ roles:
147
+ - Admin
148
+ - name: "{{displayNameNoSpaces}}/Update"
149
+ displayName:
150
+ en-US: "Update {{displayName}}"
151
+ roles:
152
+ - Admin