@octaviaflow/flow-rules 0.1.0 → 0.2.0

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 (74) hide show
  1. package/dist/index.d.ts +6 -0
  2. package/dist/index.js +3010 -28
  3. package/package.json +14 -5
  4. package/dist/catalog/actions/console-log/config.js +0 -70
  5. package/dist/catalog/actions/console-log/index.js +0 -89
  6. package/dist/catalog/actions/delay/config.js +0 -79
  7. package/dist/catalog/actions/delay/index.js +0 -71
  8. package/dist/catalog/actions/delay/migrate.js +0 -38
  9. package/dist/catalog/actions/delay/types.js +0 -17
  10. package/dist/catalog/actions/http-request/config.js +0 -111
  11. package/dist/catalog/actions/http-request/index.js +0 -223
  12. package/dist/catalog/ai/ai-agent/index.js +0 -72
  13. package/dist/catalog/ai/idp-extract/index.js +0 -90
  14. package/dist/catalog/api/graphql-query/config.js +0 -31
  15. package/dist/catalog/api/graphql-query/index.js +0 -75
  16. package/dist/catalog/communication/email-send/config.js +0 -80
  17. package/dist/catalog/communication/email-send/index.js +0 -152
  18. package/dist/catalog/communication/google-chat/config.js +0 -28
  19. package/dist/catalog/communication/google-chat/index.js +0 -36
  20. package/dist/catalog/communication/slack-message/config.js +0 -36
  21. package/dist/catalog/communication/slack-message/index.js +0 -37
  22. package/dist/catalog/communication/teams-message/config.js +0 -29
  23. package/dist/catalog/communication/teams-message/index.js +0 -39
  24. package/dist/catalog/communication/webhook-call/config.js +0 -31
  25. package/dist/catalog/communication/webhook-call/index.js +0 -43
  26. package/dist/catalog/communication/whatsapp-send/config.js +0 -36
  27. package/dist/catalog/communication/whatsapp-send/index.js +0 -57
  28. package/dist/catalog/general/query/config.js +0 -257
  29. package/dist/catalog/general/query/index.js +0 -271
  30. package/dist/catalog/general/query/types.js +0 -82
  31. package/dist/catalog/general/transform/config.js +0 -95
  32. package/dist/catalog/general/transform/index.js +0 -63
  33. package/dist/catalog/index.js +0 -168
  34. package/dist/catalog/logic/condition/config.js +0 -93
  35. package/dist/catalog/logic/condition/index.js +0 -64
  36. package/dist/catalog/logic/for-each/config.js +0 -75
  37. package/dist/catalog/logic/for-each/index.js +0 -92
  38. package/dist/catalog/logic/for-each/pathOptions.js +0 -151
  39. package/dist/catalog/logic/group/index.js +0 -46
  40. package/dist/catalog/policies.js +0 -62
  41. package/dist/catalog/storage/csv-action/index.js +0 -38
  42. package/dist/catalog/storage/dropbox-action/index.js +0 -33
  43. package/dist/catalog/storage/excel-action/index.js +0 -32
  44. package/dist/catalog/storage/file-action/index.js +0 -119
  45. package/dist/catalog/storage/file-operation/config.js +0 -45
  46. package/dist/catalog/storage/file-operation/index.js +0 -111
  47. package/dist/catalog/storage/ftp-action/index.js +0 -33
  48. package/dist/catalog/storage/google-drive-action/index.js +0 -38
  49. package/dist/catalog/storage/json-action/index.js +0 -31
  50. package/dist/catalog/storage/onedrive-action/index.js +0 -33
  51. package/dist/catalog/storage/s3-action/index.js +0 -36
  52. package/dist/catalog/storage/storage-action/index.js +0 -72
  53. package/dist/catalog/storage/storageCapabilities.js +0 -207
  54. package/dist/catalog/storage/xml-action/index.js +0 -31
  55. package/dist/catalog/transforms/format/config.js +0 -19
  56. package/dist/catalog/transforms/format/index.js +0 -39
  57. package/dist/catalog/triggers/connector-trigger/index.js +0 -72
  58. package/dist/catalog/triggers/manual-trigger/config.js +0 -60
  59. package/dist/catalog/triggers/manual-trigger/index.js +0 -74
  60. package/dist/catalog/triggers/schedule-trigger/config.js +0 -42
  61. package/dist/catalog/triggers/schedule-trigger/index.js +0 -102
  62. package/dist/catalog/triggers/webhook-trigger/config.js +0 -27
  63. package/dist/catalog/triggers/webhook-trigger/index.js +0 -89
  64. package/dist/catalog/types.js +0 -135
  65. package/dist/catalog/utility/debug/config.js +0 -90
  66. package/dist/catalog/utility/debug/index.js +0 -38
  67. package/dist/catalog/utility/error/config.js +0 -25
  68. package/dist/catalog/utility/error/index.js +0 -46
  69. package/dist/catalog/utility/variables/config.js +0 -70
  70. package/dist/catalog/utility/variables/index.js +0 -40
  71. package/dist/catalog/workflow.js +0 -25
  72. package/dist/ids.js +0 -53
  73. package/dist/rules/nodeConfigStatus.js +0 -217
  74. package/dist/rules/workflowValidator.js +0 -358
package/dist/index.js CHANGED
@@ -1,28 +1,3010 @@
1
- /**
2
- * @octaviaflow/flow-rules
3
- *
4
- * One definition of what a flow action accepts, and one definition of what
5
- * makes a flow valid.
6
- *
7
- * Both lived in `octaviaflow-ui` and were therefore reachable only from a
8
- * browser. That was fine while the editor was the only thing building flows.
9
- * It stopped being fine when an AI agent became a second author (DEV-391): an
10
- * agent that cannot read an action's input schema guesses at the config, and
11
- * an agent that cannot run the rules cannot tell whether what it built works.
12
- *
13
- * Copying either into Backend would have produced two rule sets that agree on
14
- * the day they are written — the same failure mode as a duplicated permission
15
- * predicate, and the copy that drifts would be the one the agent trusts. So
16
- * they live here, and both the editor and the server import them.
17
- *
18
- * NO React, and no imports from either consumer. The config PANELS stay in
19
- * octaviaflow-ui; this package is the data and the rules they are built on.
20
- */
21
- // ── The catalog: what an action is, and what it accepts ────────────────────
22
- export * from "./catalog/types";
23
- export { actionsRegistry, getAllActions, getActionById, getActionsByCategory, } from "./catalog/index";
24
- // ── The rules: what makes a flow valid (Flow Doctor's verdict) ─────────────
25
- export { validateNode, validateEdge, validateWorkflow, getNodeValidationStatus, getEdgeValidationStatus, } from "./rules/workflowValidator";
26
- export { getNodeConfigStatus, } from "./rules/nodeConfigStatus";
27
- // ── Ids, so a caller building a flow makes ones the editor recognises ──────
28
- export { generateWorkflowId, generateStepId, generateEdgeId, generateUUIDv4, } from "./ids";
1
+ // src/catalog/types.ts
2
+ var ActionCategory;
3
+ ((ActionCategory) => {
4
+ ActionCategory["Trigger"] = "trigger";
5
+ ActionCategory["Action"] = "action";
6
+ ActionCategory["Logic"] = "logic";
7
+ ActionCategory["Transform"] = "transform";
8
+ ActionCategory["AI"] = "ai";
9
+ ActionCategory["Database"] = "database";
10
+ ActionCategory["API"] = "api";
11
+ ActionCategory["Storage"] = "storage";
12
+ ActionCategory["FileStorage"] = "file_storage";
13
+ ActionCategory["Communication"] = "communication";
14
+ ActionCategory["CRM"] = "crm";
15
+ ActionCategory["Ecommerce"] = "ecommerce";
16
+ ActionCategory["Marketing"] = "marketing";
17
+ ActionCategory["Analytics"] = "analytics";
18
+ ActionCategory["Productivity"] = "productivity";
19
+ ActionCategory["Custom"] = "custom";
20
+ ActionCategory["Utility"] = "utility";
21
+ })(ActionCategory ||= {});
22
+ var ActionType;
23
+ ((ActionType) => {
24
+ ActionType["Schedule"] = "schedule";
25
+ ActionType["Webhook"] = "webhook";
26
+ ActionType["Manual"] = "manual";
27
+ ActionType["DataChange"] = "data_change";
28
+ ActionType["Event"] = "event";
29
+ ActionType["Read"] = "read";
30
+ ActionType["Write"] = "write";
31
+ ActionType["Update"] = "update";
32
+ ActionType["Delete"] = "delete";
33
+ ActionType["Query"] = "query";
34
+ ActionType["HTTPRequest"] = "http_request";
35
+ ActionType["GraphQLQuery"] = "graphql_query";
36
+ ActionType["Condition"] = "condition";
37
+ ActionType["ForEach"] = "for_each";
38
+ ActionType["Group"] = "group";
39
+ ActionType["Format"] = "format";
40
+ ActionType["AIAgent"] = "ai_agent";
41
+ ActionType["Embedding"] = "embedding";
42
+ ActionType["VectorSearch"] = "vector_search";
43
+ ActionType["ImageGeneration"] = "image_generation";
44
+ ActionType["ImageAnalysis"] = "image_analysis";
45
+ ActionType["SpeechToText"] = "speech_to_text";
46
+ ActionType["TextToSpeech"] = "text_to_speech";
47
+ ActionType["Transform"] = "transform";
48
+ ActionType["FileOperation"] = "file_operation";
49
+ ActionType["FileAction"] = "file_action";
50
+ ActionType["CsvAction"] = "csv_action";
51
+ ActionType["JsonAction"] = "json_action";
52
+ ActionType["XmlAction"] = "xml_action";
53
+ ActionType["ExcelAction"] = "excel_action";
54
+ ActionType["S3Action"] = "s3_action";
55
+ ActionType["FtpAction"] = "ftp_action";
56
+ ActionType["GoogleDriveAction"] = "google_drive_action";
57
+ ActionType["DropboxAction"] = "dropbox_action";
58
+ ActionType["OneDriveAction"] = "onedrive_action";
59
+ ActionType["StorageAction"] = "storage_action";
60
+ ActionType["EmailSend"] = "email_send";
61
+ ActionType["SlackMessage"] = "slack_message";
62
+ ActionType["WhatsappSend"] = "whatsapp_send";
63
+ ActionType["TeamsMessage"] = "teams_message";
64
+ ActionType["GoogleChat"] = "google_chat";
65
+ ActionType["WebhookCall"] = "webhook_call";
66
+ ActionType["Delay"] = "delay";
67
+ ActionType["Wait"] = "wait";
68
+ ActionType["Console"] = "console";
69
+ ActionType["Debug"] = "debug";
70
+ ActionType["Error"] = "error";
71
+ ActionType["CustomCode"] = "custom_code";
72
+ ActionType["CustomAction"] = "custom_action";
73
+ ActionType["IdpExtract"] = "idp_extract";
74
+ })(ActionType ||= {});
75
+ var ActionStatus;
76
+ ((ActionStatus) => {
77
+ ActionStatus["Stable"] = "stable";
78
+ ActionStatus["Beta"] = "beta";
79
+ ActionStatus["Alpha"] = "alpha";
80
+ ActionStatus["Experimental"] = "experimental";
81
+ ActionStatus["Deprecated"] = "deprecated";
82
+ })(ActionStatus ||= {});
83
+ var FieldType;
84
+ ((FieldType) => {
85
+ FieldType["String"] = "string";
86
+ FieldType["Number"] = "number";
87
+ FieldType["Boolean"] = "boolean";
88
+ FieldType["Date"] = "date";
89
+ FieldType["DateTime"] = "datetime";
90
+ FieldType["Array"] = "array";
91
+ FieldType["Object"] = "object";
92
+ FieldType["JSON"] = "json";
93
+ FieldType["File"] = "file";
94
+ FieldType["Image"] = "image";
95
+ FieldType["Select"] = "select";
96
+ FieldType["MultiSelect"] = "multi_select";
97
+ FieldType["Code"] = "code";
98
+ FieldType["Expression"] = "expression";
99
+ FieldType["Mapping"] = "mapping";
100
+ FieldType["Connection"] = "connection";
101
+ FieldType["Secret"] = "secret";
102
+ FieldType["Color"] = "color";
103
+ FieldType["URL"] = "url";
104
+ FieldType["Email"] = "email";
105
+ FieldType["Phone"] = "phone";
106
+ FieldType["RichText"] = "rich_text";
107
+ FieldType["Markdown"] = "markdown";
108
+ })(FieldType ||= {});
109
+ // src/ids.ts
110
+ function randomSuffix(length = 7) {
111
+ const bytes = new Uint8Array(length);
112
+ crypto.getRandomValues(bytes);
113
+ let out = "";
114
+ for (let i = 0;i < length; i++) {
115
+ out += (bytes[i] % 36).toString(36);
116
+ }
117
+ return out;
118
+ }
119
+ function generateUUIDv4() {
120
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
121
+ const r = crypto.getRandomValues(new Uint8Array(1))[0] % 16;
122
+ const v = c === "x" ? r : r & 3 | 8;
123
+ return v.toString(16);
124
+ });
125
+ }
126
+ function generateWorkflowId() {
127
+ return generateUUIDv4();
128
+ }
129
+ function generateStepId() {
130
+ return `node_${Date.now()}_${randomSuffix(7)}`;
131
+ }
132
+ function generateEdgeId(sourceId, targetId) {
133
+ return `edge_${sourceId}_${targetId}_${Date.now()}_${randomSuffix(7)}`;
134
+ }
135
+
136
+ // src/catalog/triggers/manual-trigger/index.ts
137
+ var manualTriggerDefinition = {
138
+ id: "manual_trigger",
139
+ name: "Manual Trigger",
140
+ description: "Manually trigger workflow with optional description",
141
+ category: "trigger" /* Trigger */,
142
+ type: "manual" /* Manual */,
143
+ tags: ["trigger", "manual", "built-in"],
144
+ status: "stable" /* Stable */,
145
+ icon: "PlayOutline",
146
+ color: "#0f62fe",
147
+ inputSchema: {
148
+ fields: [
149
+ {
150
+ key: "description",
151
+ label: "Description",
152
+ type: "string" /* String */,
153
+ description: "Optional description for this trigger (shown on node)",
154
+ placeholder: "e.g., Manual data sync, Testing workflow, etc.",
155
+ validation: {
156
+ required: false,
157
+ maxLength: 500
158
+ }
159
+ }
160
+ ]
161
+ },
162
+ outputSchema: {
163
+ type: "object",
164
+ properties: [
165
+ {
166
+ key: "triggeredAt",
167
+ type: "datetime" /* DateTime */,
168
+ description: "Timestamp when workflow was triggered"
169
+ },
170
+ {
171
+ key: "executionId",
172
+ type: "string" /* String */,
173
+ description: "Unique execution ID for this workflow run"
174
+ },
175
+ {
176
+ key: "description",
177
+ type: "string" /* String */,
178
+ description: "The description provided by the user (if any)"
179
+ }
180
+ ],
181
+ sampleOutput: {
182
+ triggeredAt: new Date().toISOString(),
183
+ executionId: `exec_${Date.now()}_${randomSuffix(9)}`,
184
+ description: "Manual data sync"
185
+ }
186
+ },
187
+ version: "1.0.0",
188
+ createdAt: "2025-01-01T00:00:00Z",
189
+ updatedAt: "2025-12-15T00:00:00Z",
190
+ createdBy: "system",
191
+ isOfficial: true,
192
+ testable: true
193
+ };
194
+
195
+ // src/catalog/triggers/schedule-trigger/index.ts
196
+ var scheduleTriggerDefinition = {
197
+ id: "schedule_trigger",
198
+ name: "Schedule Trigger",
199
+ description: "Trigger workflow on a schedule using cron or intervals",
200
+ category: "trigger" /* Trigger */,
201
+ type: "schedule" /* Schedule */,
202
+ tags: ["trigger", "schedule", "cron", "built-in"],
203
+ status: "stable" /* Stable */,
204
+ icon: "Time",
205
+ color: "#0f62fe",
206
+ inputSchema: {
207
+ fields: [
208
+ {
209
+ key: "scheduleType",
210
+ label: "Schedule Type",
211
+ type: "select" /* Select */,
212
+ description: "Type of schedule",
213
+ defaultValue: "interval",
214
+ options: [
215
+ { label: "Interval", value: "interval" },
216
+ { label: "Cron Expression", value: "cron" },
217
+ { label: "Specific Time", value: "specific" }
218
+ ],
219
+ validation: { required: true }
220
+ },
221
+ {
222
+ key: "interval",
223
+ label: "Interval",
224
+ type: "number" /* Number */,
225
+ description: "Interval value (used with interval type)",
226
+ validation: { required: false, min: 1 }
227
+ },
228
+ {
229
+ key: "intervalUnit",
230
+ label: "Interval Unit",
231
+ type: "select" /* Select */,
232
+ description: "Unit for interval (minutes, hours, days)",
233
+ defaultValue: "minutes",
234
+ options: [
235
+ { label: "Minutes", value: "minutes" },
236
+ { label: "Hours", value: "hours" },
237
+ { label: "Days", value: "days" },
238
+ { label: "Weeks", value: "weeks" }
239
+ ],
240
+ validation: { required: false }
241
+ },
242
+ {
243
+ key: "cronExpression",
244
+ label: "Cron Expression",
245
+ type: "string" /* String */,
246
+ description: "Cron expression (e.g., 0 0 * * * for daily at midnight)",
247
+ placeholder: "0 0 * * *",
248
+ validation: { required: false }
249
+ },
250
+ {
251
+ key: "timezone",
252
+ label: "Timezone",
253
+ type: "string" /* String */,
254
+ description: "Timezone for schedule (e.g., UTC, America/New_York)",
255
+ defaultValue: "UTC",
256
+ validation: { required: false }
257
+ }
258
+ ]
259
+ },
260
+ outputSchema: {
261
+ type: "object",
262
+ properties: [
263
+ {
264
+ key: "scheduledAt",
265
+ type: "datetime" /* DateTime */,
266
+ description: "When the schedule was triggered"
267
+ },
268
+ {
269
+ key: "nextRun",
270
+ type: "datetime" /* DateTime */,
271
+ description: "When the next run is scheduled"
272
+ },
273
+ {
274
+ key: "scheduleType",
275
+ type: "string" /* String */,
276
+ description: "Type of schedule that triggered"
277
+ }
278
+ ],
279
+ sampleOutput: {
280
+ scheduledAt: new Date().toISOString(),
281
+ nextRun: new Date(Date.now() + 3600000).toISOString(),
282
+ scheduleType: "interval"
283
+ }
284
+ },
285
+ version: "1.0.0",
286
+ createdAt: "2025-01-01T00:00:00Z",
287
+ updatedAt: "2025-12-15T00:00:00Z",
288
+ createdBy: "system",
289
+ isOfficial: true,
290
+ testable: true
291
+ };
292
+
293
+ // src/catalog/triggers/webhook-trigger/index.ts
294
+ var webhookTriggerDefinition = {
295
+ id: "webhook_trigger",
296
+ name: "Webhook Trigger",
297
+ description: "Trigger workflow via HTTP webhook",
298
+ category: "trigger" /* Trigger */,
299
+ type: "webhook" /* Webhook */,
300
+ tags: ["trigger", "webhook", "http", "built-in"],
301
+ status: "stable" /* Stable */,
302
+ icon: "WebhookAlt",
303
+ color: "#0f62fe",
304
+ inputSchema: {
305
+ fields: [
306
+ {
307
+ key: "webhookPath",
308
+ label: "Webhook Path",
309
+ type: "string" /* String */,
310
+ description: "Custom path for the webhook URL",
311
+ placeholder: "/my-webhook",
312
+ validation: { required: false }
313
+ },
314
+ {
315
+ key: "method",
316
+ label: "HTTP Method",
317
+ type: "select" /* Select */,
318
+ description: "Allowed HTTP methods",
319
+ defaultValue: "POST",
320
+ options: [
321
+ { label: "GET", value: "GET" },
322
+ { label: "POST", value: "POST" },
323
+ { label: "PUT", value: "PUT" },
324
+ { label: "PATCH", value: "PATCH" },
325
+ { label: "DELETE", value: "DELETE" }
326
+ ],
327
+ validation: { required: true }
328
+ },
329
+ {
330
+ key: "requireAuth",
331
+ label: "Require Authentication",
332
+ type: "boolean" /* Boolean */,
333
+ description: "Require API key or token for webhook",
334
+ defaultValue: true,
335
+ validation: { required: false }
336
+ }
337
+ ]
338
+ },
339
+ outputSchema: {
340
+ type: "object",
341
+ properties: [
342
+ {
343
+ key: "webhookUrl",
344
+ type: "url" /* URL */,
345
+ description: "The generated webhook URL"
346
+ },
347
+ {
348
+ key: "method",
349
+ type: "string" /* String */,
350
+ description: "HTTP method used"
351
+ },
352
+ {
353
+ key: "payload",
354
+ type: "json" /* JSON */,
355
+ description: "Request payload received"
356
+ },
357
+ {
358
+ key: "headers",
359
+ type: "object" /* Object */,
360
+ description: "Request headers"
361
+ }
362
+ ],
363
+ sampleOutput: {
364
+ webhookUrl: "https://api.example.com/webhooks/trigger-123",
365
+ method: "POST",
366
+ payload: { data: "example" },
367
+ headers: { "content-type": "application/json" }
368
+ }
369
+ },
370
+ version: "1.0.0",
371
+ createdAt: "2025-01-01T00:00:00Z",
372
+ updatedAt: "2025-12-15T00:00:00Z",
373
+ createdBy: "system",
374
+ isOfficial: true,
375
+ testable: true
376
+ };
377
+
378
+ // src/catalog/triggers/connector-trigger/index.ts
379
+ var connectorTriggerDefinition = {
380
+ id: "connector_trigger",
381
+ name: "Connector Trigger",
382
+ description: "Trigger workflow when a connector platform event occurs",
383
+ category: "trigger" /* Trigger */,
384
+ type: "event" /* Event */,
385
+ tags: ["trigger", "connector", "event", "built-in"],
386
+ status: "stable" /* Stable */,
387
+ icon: "Connect",
388
+ color: "#6929c4",
389
+ inputSchema: {
390
+ fields: [
391
+ {
392
+ key: "connectorInstanceId",
393
+ label: "Connector Instance",
394
+ type: "string" /* String */,
395
+ description: "The connected app instance to listen to",
396
+ validation: { required: true }
397
+ },
398
+ {
399
+ key: "events",
400
+ label: "Events",
401
+ type: "json" /* JSON */,
402
+ description: "Entity/operation pairs to subscribe to",
403
+ validation: { required: true }
404
+ }
405
+ ]
406
+ },
407
+ outputSchema: {
408
+ type: "object",
409
+ properties: [
410
+ {
411
+ key: "eventType",
412
+ type: "string" /* String */,
413
+ description: "The type of event that occurred"
414
+ },
415
+ {
416
+ key: "entity",
417
+ type: "string" /* String */,
418
+ description: "The entity that changed (e.g. Invoice)"
419
+ },
420
+ {
421
+ key: "operation",
422
+ type: "string" /* String */,
423
+ description: "The operation performed (e.g. Create)"
424
+ },
425
+ {
426
+ key: "payload",
427
+ type: "json" /* JSON */,
428
+ description: "The event payload from the connector"
429
+ }
430
+ ],
431
+ sampleOutput: {
432
+ eventType: "connector.event",
433
+ entity: "Invoice",
434
+ operation: "Create",
435
+ payload: { id: "123", amount: 500 }
436
+ }
437
+ },
438
+ version: "1.0.0",
439
+ createdAt: "2025-01-01T00:00:00Z",
440
+ updatedAt: "2025-12-15T00:00:00Z",
441
+ createdBy: "system",
442
+ isOfficial: true,
443
+ testable: false
444
+ };
445
+
446
+ // src/catalog/actions/http-request/index.ts
447
+ var httpRequestDefinition = {
448
+ id: "http_request",
449
+ name: "HTTP Request",
450
+ description: "Make HTTP requests to external APIs and services",
451
+ category: "api" /* API */,
452
+ type: "http_request" /* HTTPRequest */,
453
+ tags: ["api", "http", "request", "built-in"],
454
+ status: "stable" /* Stable */,
455
+ icon: "CloudUpload",
456
+ color: "#0043ce",
457
+ inputSchema: {
458
+ fields: [
459
+ {
460
+ key: "apiType",
461
+ label: "API Type",
462
+ type: "select" /* Select */,
463
+ description: "Type of API request to make",
464
+ defaultValue: "rest",
465
+ options: [
466
+ { label: "REST", value: "rest" },
467
+ { label: "GraphQL", value: "graphql" }
468
+ ],
469
+ validation: { required: true }
470
+ },
471
+ {
472
+ key: "method",
473
+ label: "Method",
474
+ type: "select" /* Select */,
475
+ description: "HTTP method to use (REST only)",
476
+ defaultValue: "GET",
477
+ options: [
478
+ { label: "GET", value: "GET" },
479
+ { label: "POST", value: "POST" },
480
+ { label: "PUT", value: "PUT" },
481
+ { label: "PATCH", value: "PATCH" },
482
+ { label: "DELETE", value: "DELETE" },
483
+ { label: "HEAD", value: "HEAD" },
484
+ { label: "OPTIONS", value: "OPTIONS" }
485
+ ],
486
+ validation: { required: false }
487
+ },
488
+ {
489
+ key: "url",
490
+ label: "URL",
491
+ type: "url" /* URL */,
492
+ description: "The URL to send the request to. Supports {{variable}} interpolation.",
493
+ placeholder: "https://api.example.com/endpoint",
494
+ validation: { required: true }
495
+ },
496
+ {
497
+ key: "headers",
498
+ label: "Headers",
499
+ type: "json" /* JSON */,
500
+ description: "HTTP headers (JSON object or key-value array). Supports {{variable}} interpolation.",
501
+ defaultValue: {},
502
+ validation: { required: false }
503
+ },
504
+ {
505
+ key: "body",
506
+ label: "Request Body",
507
+ type: "json" /* JSON */,
508
+ description: "Request body for POST/PUT/PATCH. Supports {{variable}} interpolation.",
509
+ validation: { required: false }
510
+ },
511
+ {
512
+ key: "graphqlQuery",
513
+ label: "GraphQL Query",
514
+ type: "string" /* String */,
515
+ description: "GraphQL query or mutation string (GraphQL only)",
516
+ validation: { required: false }
517
+ },
518
+ {
519
+ key: "graphqlVariables",
520
+ label: "GraphQL Variables",
521
+ type: "json" /* JSON */,
522
+ description: "GraphQL variables object. Supports {{variable}} interpolation.",
523
+ defaultValue: {},
524
+ validation: { required: false }
525
+ },
526
+ {
527
+ key: "auth",
528
+ label: "Authentication",
529
+ type: "json" /* JSON */,
530
+ description: 'Authentication config: { type: "none"|"basic"|"bearer"|"apikey", token?, username?, password?, apiKeyName?, apiKeyValue?, apiKeyLocation? }',
531
+ defaultValue: { type: "none" },
532
+ validation: { required: false }
533
+ },
534
+ {
535
+ key: "timeout",
536
+ label: "Timeout (ms)",
537
+ type: "number" /* Number */,
538
+ description: "Request timeout in milliseconds",
539
+ defaultValue: 30000,
540
+ validation: { required: false, min: 1000 }
541
+ },
542
+ {
543
+ key: "failOnError",
544
+ label: "Fail on non-2xx",
545
+ type: "boolean" /* Boolean */,
546
+ description: "If true, step fails when response status is not 2xx. Default: true.",
547
+ defaultValue: true,
548
+ validation: { required: false }
549
+ },
550
+ {
551
+ key: "responseType",
552
+ label: "Response Type",
553
+ type: "select" /* Select */,
554
+ description: "How to parse the response body. JSON tries to parse as JSON; Text returns raw text; Binary returns Uint8Array bytes plus fileName/contentType/size.",
555
+ defaultValue: "json",
556
+ options: [
557
+ { label: "JSON", value: "json" },
558
+ { label: "Text", value: "text" },
559
+ { label: "Binary", value: "binary" }
560
+ ],
561
+ validation: { required: false }
562
+ },
563
+ {
564
+ key: "expectedContentTypes",
565
+ label: "Expected Content-Types",
566
+ type: "json" /* JSON */,
567
+ description: 'Optional array of content-type prefixes (e.g. ["application/pdf"]). Logs a warning if the response content-type does not start with any of these.',
568
+ defaultValue: [],
569
+ validation: { required: false }
570
+ }
571
+ ]
572
+ },
573
+ outputSchema: {
574
+ type: "object",
575
+ properties: [
576
+ {
577
+ key: "status",
578
+ type: "number" /* Number */,
579
+ description: "HTTP status code"
580
+ },
581
+ {
582
+ key: "statusText",
583
+ type: "string" /* String */,
584
+ description: "HTTP status text"
585
+ },
586
+ {
587
+ key: "ok",
588
+ type: "boolean" /* Boolean */,
589
+ description: "True if status is 2xx"
590
+ },
591
+ {
592
+ key: "headers",
593
+ type: "object" /* Object */,
594
+ description: "Response headers"
595
+ },
596
+ {
597
+ key: "body",
598
+ type: "json" /* JSON */,
599
+ description: "Response body (parsed JSON or raw string)"
600
+ },
601
+ {
602
+ key: "duration",
603
+ type: "number" /* Number */,
604
+ description: "Request duration in milliseconds"
605
+ },
606
+ {
607
+ key: "graphqlErrors",
608
+ type: "json" /* JSON */,
609
+ description: "GraphQL errors array (GraphQL only, present when errors returned)"
610
+ },
611
+ {
612
+ key: "pages",
613
+ type: "number" /* Number */,
614
+ description: "Number of pages fetched (pagination only)"
615
+ },
616
+ {
617
+ key: "attempts",
618
+ type: "number" /* Number */,
619
+ description: "Total fetch attempts made (includes retries)"
620
+ },
621
+ {
622
+ key: "extracted",
623
+ type: "object" /* Object */,
624
+ description: "Named fields extracted from response body via dot-notation paths"
625
+ },
626
+ {
627
+ key: "fileName",
628
+ type: "string" /* String */,
629
+ description: "Derived file name (only present when Response Type is Binary). Sourced from Content-Disposition header or URL pathname."
630
+ },
631
+ {
632
+ key: "contentType",
633
+ type: "string" /* String */,
634
+ description: "Response content-type (only present when Response Type is Binary). Defaults to application/octet-stream when missing."
635
+ },
636
+ {
637
+ key: "size",
638
+ type: "number" /* Number */,
639
+ description: "Response body size in bytes (only present when Response Type is Binary)."
640
+ }
641
+ ],
642
+ sampleOutput: {
643
+ status: 200,
644
+ statusText: "OK",
645
+ ok: true,
646
+ headers: { "content-type": "application/json" },
647
+ body: { success: true, data: {} },
648
+ duration: 245,
649
+ attempts: 1,
650
+ extracted: {}
651
+ }
652
+ },
653
+ execution: {
654
+ timeout: 30000,
655
+ retryable: true
656
+ },
657
+ version: "1.0.0",
658
+ createdAt: "2025-01-01T00:00:00Z",
659
+ updatedAt: "2025-12-15T00:00:00Z",
660
+ createdBy: "system",
661
+ isOfficial: true,
662
+ testable: true
663
+ };
664
+
665
+ // src/catalog/actions/console-log/index.ts
666
+ var consoleLogDefinition = {
667
+ id: "console_log",
668
+ name: "Console Log",
669
+ description: "Log messages to the workflow console for debugging",
670
+ category: "utility" /* Utility */,
671
+ type: "console" /* Console */,
672
+ tags: ["utility", "logging", "debug", "built-in"],
673
+ status: "stable" /* Stable */,
674
+ icon: "Terminal",
675
+ color: "#525252",
676
+ inputSchema: {
677
+ fields: [
678
+ {
679
+ key: "message",
680
+ label: "Message",
681
+ type: "string" /* String */,
682
+ description: "Message to log",
683
+ placeholder: "e.g., Processing user data...",
684
+ validation: { required: true }
685
+ },
686
+ {
687
+ key: "level",
688
+ label: "Log Level",
689
+ type: "select" /* Select */,
690
+ description: "Log level for the message",
691
+ defaultValue: "info",
692
+ options: [
693
+ { label: "Info", value: "info" },
694
+ { label: "Warning", value: "warning" },
695
+ { label: "Error", value: "error" },
696
+ { label: "Debug", value: "debug" }
697
+ ],
698
+ validation: { required: true }
699
+ },
700
+ {
701
+ key: "data",
702
+ label: "Data",
703
+ type: "json" /* JSON */,
704
+ description: "Additional data to log",
705
+ validation: { required: false }
706
+ },
707
+ {
708
+ key: "includeInputData",
709
+ label: "Include previous step output",
710
+ type: "boolean" /* Boolean */,
711
+ description: 'When off, only the custom message prints — useful for summary "Done" logs that follow a ForEach.',
712
+ defaultValue: true,
713
+ validation: { required: false }
714
+ }
715
+ ]
716
+ },
717
+ outputSchema: {
718
+ type: "object",
719
+ properties: [
720
+ {
721
+ key: "logged",
722
+ type: "boolean" /* Boolean */,
723
+ description: "Whether the message was successfully logged"
724
+ },
725
+ {
726
+ key: "timestamp",
727
+ type: "datetime" /* DateTime */,
728
+ description: "Timestamp of the log entry"
729
+ },
730
+ {
731
+ key: "level",
732
+ type: "string" /* String */,
733
+ description: "Log level used"
734
+ }
735
+ ],
736
+ sampleOutput: {
737
+ logged: true,
738
+ timestamp: new Date().toISOString(),
739
+ level: "info"
740
+ }
741
+ },
742
+ version: "1.0.0",
743
+ createdAt: "2025-01-01T00:00:00Z",
744
+ updatedAt: "2025-12-15T00:00:00Z",
745
+ createdBy: "system",
746
+ isOfficial: true,
747
+ testable: true
748
+ };
749
+
750
+ // src/catalog/actions/delay/index.ts
751
+ var delayDefinition = {
752
+ id: "delay",
753
+ name: "Delay",
754
+ description: "Pause workflow execution for a specified duration",
755
+ category: "utility" /* Utility */,
756
+ type: "delay" /* Delay */,
757
+ tags: ["utility", "delay", "wait", "built-in"],
758
+ status: "stable" /* Stable */,
759
+ icon: "Timer",
760
+ color: "#8f8f8f",
761
+ inputSchema: {
762
+ fields: [
763
+ {
764
+ key: "duration",
765
+ label: "Duration (ms)",
766
+ type: "number" /* Number */,
767
+ description: "Duration to delay in milliseconds",
768
+ defaultValue: 1000,
769
+ validation: { required: true, min: 0 }
770
+ },
771
+ {
772
+ key: "unit",
773
+ label: "Unit",
774
+ type: "select" /* Select */,
775
+ description: "Time unit for the duration",
776
+ defaultValue: "milliseconds",
777
+ options: [
778
+ { label: "Milliseconds", value: "milliseconds" },
779
+ { label: "Seconds", value: "seconds" },
780
+ { label: "Minutes", value: "minutes" },
781
+ { label: "Hours", value: "hours" }
782
+ ],
783
+ validation: { required: true }
784
+ }
785
+ ]
786
+ },
787
+ outputSchema: {
788
+ type: "object",
789
+ properties: [
790
+ {
791
+ key: "delayedFor",
792
+ type: "number" /* Number */,
793
+ description: "Actual delay duration in milliseconds"
794
+ },
795
+ {
796
+ key: "completedAt",
797
+ type: "datetime" /* DateTime */,
798
+ description: "Timestamp when delay completed"
799
+ }
800
+ ],
801
+ sampleOutput: {
802
+ delayedFor: 1000,
803
+ completedAt: new Date().toISOString()
804
+ }
805
+ },
806
+ execution: {
807
+ timeout: 3600000
808
+ },
809
+ version: "1.0.0",
810
+ createdAt: "2025-01-01T00:00:00Z",
811
+ updatedAt: "2025-12-15T00:00:00Z",
812
+ createdBy: "system",
813
+ isOfficial: true,
814
+ testable: true
815
+ };
816
+
817
+ // src/catalog/logic/condition/index.ts
818
+ var conditionDefinition = {
819
+ id: "condition",
820
+ name: "Condition",
821
+ description: "Branch workflow execution based on conditions",
822
+ category: "logic" /* Logic */,
823
+ type: "condition" /* Condition */,
824
+ tags: ["logic", "condition", "branching", "built-in"],
825
+ status: "stable" /* Stable */,
826
+ icon: "DecisionTree",
827
+ color: "#f1c21b",
828
+ inputSchema: {
829
+ fields: [
830
+ {
831
+ key: "mode",
832
+ label: "Mode",
833
+ type: "string" /* String */,
834
+ description: "Authoring mode (visual builder).",
835
+ defaultValue: "visual",
836
+ validation: { required: true }
837
+ },
838
+ {
839
+ key: "filters",
840
+ label: "Condition Filters",
841
+ type: "array" /* Array */,
842
+ description: "Visual condition filters (field / operator / value rows)",
843
+ validation: { required: false }
844
+ }
845
+ ]
846
+ },
847
+ outputSchema: {
848
+ type: "object",
849
+ properties: [
850
+ {
851
+ key: "result",
852
+ type: "boolean" /* Boolean */,
853
+ description: "Result of the condition evaluation"
854
+ },
855
+ {
856
+ key: "branch",
857
+ type: "string" /* String */,
858
+ description: "Which branch was taken (true or false)"
859
+ }
860
+ ],
861
+ sampleOutput: {
862
+ result: true,
863
+ branch: "true"
864
+ }
865
+ },
866
+ version: "1.0.0",
867
+ createdAt: "2025-01-01T00:00:00Z",
868
+ updatedAt: "2025-12-15T00:00:00Z",
869
+ createdBy: "system",
870
+ isOfficial: true,
871
+ testable: true
872
+ };
873
+
874
+ // src/catalog/logic/for-each/index.ts
875
+ var forEachDefinition = {
876
+ id: "for_each",
877
+ name: "ForEach",
878
+ description: "Iterate over array items and execute actions for each",
879
+ category: "logic" /* Logic */,
880
+ type: "for_each" /* ForEach */,
881
+ tags: ["logic", "loop", "iteration", "array", "built-in"],
882
+ status: "stable" /* Stable */,
883
+ icon: "Repeat",
884
+ color: "#f1c21b",
885
+ inputSchema: {
886
+ fields: [
887
+ {
888
+ key: "arrayPath",
889
+ label: "Records in",
890
+ type: "expression" /* Expression */,
891
+ description: "Path to the array to iterate over",
892
+ placeholder: "e.g., Account, data.items",
893
+ validation: { required: false }
894
+ },
895
+ {
896
+ key: "itemVariable",
897
+ label: "Item Variable Name",
898
+ type: "string" /* String */,
899
+ description: "Name of the variable for each item",
900
+ defaultValue: "item",
901
+ validation: { required: true }
902
+ },
903
+ {
904
+ key: "indexVariable",
905
+ label: "Index Variable Name",
906
+ type: "string" /* String */,
907
+ description: "Name of the variable for the index",
908
+ defaultValue: "index",
909
+ validation: { required: false }
910
+ },
911
+ {
912
+ key: "batchSize",
913
+ label: "Batch Size",
914
+ type: "number" /* Number */,
915
+ description: "Number of items to process per batch (0 = all at once)",
916
+ defaultValue: 0,
917
+ validation: { required: false }
918
+ },
919
+ {
920
+ key: "continueOnError",
921
+ label: "Continue on Error",
922
+ type: "boolean" /* Boolean */,
923
+ description: "Whether to continue processing remaining items if one fails",
924
+ defaultValue: false,
925
+ validation: { required: false }
926
+ }
927
+ ]
928
+ },
929
+ outputSchema: {
930
+ type: "object",
931
+ properties: [
932
+ {
933
+ key: "itemsProcessed",
934
+ type: "number" /* Number */,
935
+ description: "Number of items processed"
936
+ },
937
+ {
938
+ key: "results",
939
+ type: "array" /* Array */,
940
+ description: "Results from each iteration"
941
+ }
942
+ ],
943
+ sampleOutput: {
944
+ itemsProcessed: 5,
945
+ results: [{ item: 1 }, { item: 2 }]
946
+ }
947
+ },
948
+ version: "1.0.0",
949
+ createdAt: "2025-01-01T00:00:00Z",
950
+ updatedAt: "2025-12-15T00:00:00Z",
951
+ createdBy: "system",
952
+ isOfficial: true,
953
+ testable: true
954
+ };
955
+
956
+ // src/catalog/logic/group/index.ts
957
+ var groupDefinition = {
958
+ id: "group",
959
+ name: "Group",
960
+ description: "Visually group a set of steps — drop nodes inside to nest them.",
961
+ category: "logic" /* Logic */,
962
+ type: "group" /* Group */,
963
+ tags: ["logic", "container", "subflow", "built-in"],
964
+ status: "stable" /* Stable */,
965
+ icon: "GroupObjects",
966
+ color: "#6f6f6f",
967
+ inputSchema: { fields: [] },
968
+ outputSchema: {
969
+ type: "object",
970
+ properties: [
971
+ {
972
+ key: "result",
973
+ type: "object",
974
+ description: "Aggregated output of the contained steps."
975
+ }
976
+ ]
977
+ },
978
+ version: "1.0.0",
979
+ createdAt: "2026-05-19T00:00:00Z",
980
+ updatedAt: "2026-05-19T00:00:00Z",
981
+ createdBy: "system",
982
+ isOfficial: true,
983
+ testable: false
984
+ };
985
+ // src/catalog/general/query/config.ts
986
+ var BuildQueryConfigDefaults = {
987
+ mode: "visual" /* Visual */,
988
+ queryType: "select" /* Select */,
989
+ timeout: 30000,
990
+ maxRows: 1000,
991
+ visualConfig: {
992
+ tables: [],
993
+ fields: [],
994
+ filters: undefined,
995
+ joins: [],
996
+ groupBy: [],
997
+ sort: [],
998
+ limit: 10,
999
+ offset: 0
1000
+ },
1001
+ sqlConfig: {
1002
+ sql: "",
1003
+ parameters: {}
1004
+ }
1005
+ };
1006
+
1007
+ // src/catalog/general/query/index.ts
1008
+ var queryDefinition = {
1009
+ id: "query",
1010
+ name: "Query",
1011
+ description: "Execute queries against connected databases, APIs, and CRMs",
1012
+ longDescription: "Create powerful queries using either a visual no-code builder or advanced SQL editor. Supports databases (PostgreSQL, MySQL, MongoDB, etc.), APIs (REST, GraphQL), and CRMs (Salesforce, HubSpot). Query results can be used as input for downstream actions.",
1013
+ category: "database" /* Database */,
1014
+ type: "query" /* Query */,
1015
+ tags: ["query", "database", "sql", "visual-builder", "no-code", "api", "crm", "built-in"],
1016
+ status: "stable" /* Stable */,
1017
+ icon: "QueryQueue",
1018
+ color: "#0043ce",
1019
+ inputSchema: {
1020
+ fields: [
1021
+ {
1022
+ key: "connectorId",
1023
+ label: "Select Connector",
1024
+ type: "connection" /* Connection */,
1025
+ description: "Choose a connected database, API, or CRM (storage connectors like Dropbox/Google Drive are not supported)",
1026
+ validation: { required: true },
1027
+ helpText: "Only queryable connectors are shown. File storage connectors have separate actions."
1028
+ },
1029
+ {
1030
+ key: "mode",
1031
+ label: "Query Mode",
1032
+ type: "select" /* Select */,
1033
+ description: "Choose between visual query builder or SQL editor",
1034
+ options: [
1035
+ {
1036
+ label: "Visual Builder (No-Code)",
1037
+ value: "visual" /* Visual */,
1038
+ description: "Build queries visually without writing code"
1039
+ },
1040
+ {
1041
+ label: "SQL Editor (Advanced)",
1042
+ value: "sql" /* SQL */,
1043
+ description: "Write raw SQL queries with syntax highlighting"
1044
+ }
1045
+ ],
1046
+ defaultValue: "visual" /* Visual */,
1047
+ validation: { required: true }
1048
+ },
1049
+ {
1050
+ key: "queryType",
1051
+ label: "Query Type",
1052
+ type: "select" /* Select */,
1053
+ description: "Type of query operation — the Query action reads data; use Transform to write",
1054
+ options: [
1055
+ { label: "SELECT (Read Data)", value: "select" /* Select */ }
1056
+ ],
1057
+ defaultValue: "select" /* Select */,
1058
+ validation: { required: true },
1059
+ conditional: [
1060
+ {
1061
+ field: "mode",
1062
+ operator: "==",
1063
+ value: "visual" /* Visual */,
1064
+ action: "show"
1065
+ }
1066
+ ]
1067
+ },
1068
+ {
1069
+ key: "visualConfig.tables",
1070
+ label: "Select Tables",
1071
+ type: "multi_select" /* MultiSelect */,
1072
+ description: "Choose one or more tables to query",
1073
+ validation: { required: true },
1074
+ conditional: [
1075
+ {
1076
+ field: "mode",
1077
+ operator: "==",
1078
+ value: "visual" /* Visual */,
1079
+ action: "show"
1080
+ }
1081
+ ],
1082
+ optionsSource: {
1083
+ type: "dynamic",
1084
+ dependsOn: ["connectorId"]
1085
+ }
1086
+ },
1087
+ {
1088
+ key: "visualConfig.fields",
1089
+ label: "Select Fields",
1090
+ type: "array" /* Array */,
1091
+ description: "Choose fields to include in the query result",
1092
+ validation: { required: true },
1093
+ conditional: [
1094
+ {
1095
+ field: "mode",
1096
+ operator: "==",
1097
+ value: "visual" /* Visual */,
1098
+ action: "show"
1099
+ }
1100
+ ]
1101
+ },
1102
+ {
1103
+ key: "visualConfig.limit",
1104
+ label: "Limit",
1105
+ type: "number" /* Number */,
1106
+ description: "Maximum number of rows to return",
1107
+ defaultValue: 10,
1108
+ validation: { required: false, min: 1, max: 1e4 },
1109
+ conditional: [
1110
+ {
1111
+ field: "mode",
1112
+ operator: "==",
1113
+ value: "visual" /* Visual */,
1114
+ action: "show"
1115
+ }
1116
+ ]
1117
+ },
1118
+ {
1119
+ key: "sqlConfig.sql",
1120
+ label: "SQL Query",
1121
+ type: "code" /* Code */,
1122
+ language: "sql",
1123
+ description: "Write your SQL query here",
1124
+ placeholder: "SELECT * FROM users WHERE status = 'active' LIMIT 100",
1125
+ validation: { required: true },
1126
+ conditional: [
1127
+ {
1128
+ field: "mode",
1129
+ operator: "==",
1130
+ value: "sql" /* SQL */,
1131
+ action: "show"
1132
+ }
1133
+ ]
1134
+ },
1135
+ {
1136
+ key: "sqlConfig.parameters",
1137
+ label: "Query Parameters",
1138
+ type: "json" /* JSON */,
1139
+ description: 'Parameters for parameterized queries (e.g., {"userId": 123})',
1140
+ validation: { required: false },
1141
+ advanced: true,
1142
+ conditional: [
1143
+ {
1144
+ field: "mode",
1145
+ operator: "==",
1146
+ value: "sql" /* SQL */,
1147
+ action: "show"
1148
+ }
1149
+ ]
1150
+ },
1151
+ {
1152
+ key: "timeout",
1153
+ label: "Query Timeout (ms)",
1154
+ type: "number" /* Number */,
1155
+ description: "Maximum time to wait for query execution",
1156
+ defaultValue: 30000,
1157
+ validation: { required: false, min: 1000, max: 300000 },
1158
+ advanced: true
1159
+ },
1160
+ {
1161
+ key: "maxRows",
1162
+ label: "Max Rows",
1163
+ type: "number" /* Number */,
1164
+ description: "Maximum number of rows to return",
1165
+ defaultValue: 1000,
1166
+ validation: { required: false, min: 1, max: 1e4 },
1167
+ advanced: true
1168
+ }
1169
+ ],
1170
+ groups: [
1171
+ {
1172
+ id: "connection",
1173
+ label: "Connection",
1174
+ description: "Select the data source to query",
1175
+ fields: ["connectorId"]
1176
+ },
1177
+ {
1178
+ id: "query_mode",
1179
+ label: "Query Configuration",
1180
+ description: "Configure how you want to build your query",
1181
+ fields: ["mode", "queryType"]
1182
+ },
1183
+ {
1184
+ id: "visual_builder",
1185
+ label: "Visual Query Builder",
1186
+ description: "Build your query visually without writing code",
1187
+ fields: ["visualConfig.tables", "visualConfig.fields", "visualConfig.limit"]
1188
+ },
1189
+ {
1190
+ id: "sql_editor",
1191
+ label: "SQL Editor",
1192
+ description: "Write raw SQL queries",
1193
+ fields: ["sqlConfig.sql", "sqlConfig.parameters"]
1194
+ },
1195
+ {
1196
+ id: "settings",
1197
+ label: "Advanced Settings",
1198
+ description: "Configure query execution settings",
1199
+ collapsed: true,
1200
+ fields: ["timeout", "maxRows"]
1201
+ }
1202
+ ]
1203
+ },
1204
+ outputSchema: {
1205
+ type: "object",
1206
+ properties: [
1207
+ {
1208
+ key: "data",
1209
+ type: "array" /* Array */,
1210
+ description: "Query result data as an array of objects",
1211
+ example: [{ id: 1, name: "John Doe", email: "john@example.com" }]
1212
+ },
1213
+ {
1214
+ key: "rowCount",
1215
+ type: "number" /* Number */,
1216
+ description: "Number of rows returned",
1217
+ example: 1
1218
+ },
1219
+ {
1220
+ key: "columns",
1221
+ type: "array" /* Array */,
1222
+ description: "Column names in the result set",
1223
+ example: ["id", "name", "email"]
1224
+ },
1225
+ {
1226
+ key: "executionTime",
1227
+ type: "number" /* Number */,
1228
+ description: "Query execution time in milliseconds",
1229
+ example: 45
1230
+ },
1231
+ {
1232
+ key: "generatedSQL",
1233
+ type: "string" /* String */,
1234
+ description: "The SQL query that was executed (for visual builder mode)",
1235
+ example: "SELECT id, name, email FROM users WHERE status = 'active' LIMIT 100"
1236
+ }
1237
+ ],
1238
+ sampleOutput: {
1239
+ data: [
1240
+ { id: 1, name: "John Doe", email: "john@example.com", status: "active" },
1241
+ { id: 2, name: "Jane Smith", email: "jane@example.com", status: "active" }
1242
+ ],
1243
+ rowCount: 2,
1244
+ columns: ["id", "name", "email", "status"],
1245
+ executionTime: 45,
1246
+ generatedSQL: "SELECT id, name, email, status FROM users WHERE status = 'active' LIMIT 100"
1247
+ }
1248
+ },
1249
+ execution: {
1250
+ timeout: 30000,
1251
+ retryable: true,
1252
+ requiresAuth: true
1253
+ },
1254
+ testable: true,
1255
+ version: "1.0.0",
1256
+ createdAt: "2025-01-19T00:00:00Z",
1257
+ updatedAt: "2025-01-19T00:00:00Z",
1258
+ createdBy: "system",
1259
+ isOfficial: true
1260
+ };
1261
+
1262
+ // src/catalog/general/transform/index.ts
1263
+ var transformDefinition = {
1264
+ id: "transform",
1265
+ name: "Transform",
1266
+ description: "Map and transform data between workflow steps using the visual field mapper",
1267
+ category: "transform" /* Transform */,
1268
+ type: "transform" /* Transform */,
1269
+ tags: ["transform", "mapping", "data", "reshape", "convert", "built-in"],
1270
+ status: "stable" /* Stable */,
1271
+ icon: "Transform",
1272
+ color: "#0043ce",
1273
+ inputSchema: {
1274
+ fields: [
1275
+ {
1276
+ key: "name",
1277
+ label: "Transform Name",
1278
+ type: "string" /* String */,
1279
+ description: "A descriptive name for this transform step",
1280
+ defaultValue: "Transform",
1281
+ validation: { required: false }
1282
+ },
1283
+ {
1284
+ key: "mappings",
1285
+ label: "Field Mappings",
1286
+ type: "array" /* Array */,
1287
+ description: "Map source fields from upstream nodes to target output fields",
1288
+ validation: { required: false }
1289
+ }
1290
+ ]
1291
+ },
1292
+ outputSchema: {
1293
+ type: "object",
1294
+ properties: [
1295
+ {
1296
+ key: "result",
1297
+ type: "json" /* JSON */,
1298
+ description: "Transformed data output"
1299
+ },
1300
+ {
1301
+ key: "mappedFieldCount",
1302
+ type: "number" /* Number */,
1303
+ description: "Number of fields that were mapped/transformed"
1304
+ }
1305
+ ],
1306
+ sampleOutput: {
1307
+ result: { name: "John Doe", email: "john@example.com", age: 30 },
1308
+ mappedFieldCount: 3
1309
+ },
1310
+ dynamic: true
1311
+ },
1312
+ version: "2.0.0",
1313
+ createdAt: "2025-01-01T00:00:00Z",
1314
+ updatedAt: "2026-02-13T00:00:00Z",
1315
+ createdBy: "system",
1316
+ isOfficial: true,
1317
+ testable: true
1318
+ };
1319
+
1320
+ // src/catalog/storage/csv-action/index.ts
1321
+ var csvActionDefinition = {
1322
+ id: "csv_action",
1323
+ name: "CSV",
1324
+ description: "Parse CSV files into structured records or generate CSV files from workflow data",
1325
+ category: "storage" /* Storage */,
1326
+ type: "csv_action" /* CsvAction */,
1327
+ tags: ["csv", "parse", "generate", "file", "format", "built-in"],
1328
+ status: "stable" /* Stable */,
1329
+ icon: "Document",
1330
+ color: "#198038",
1331
+ inputSchema: {
1332
+ fields: [
1333
+ { key: "operation", label: "Operation", type: "select" /* Select */, options: [{ label: "Parse (CSV → Records)", value: "parse" }, { label: "Generate (Records → CSV)", value: "generate" }], defaultValue: "parse", validation: { required: true } },
1334
+ { key: "content", label: "CSV Content", type: "string" /* String */, description: "Paste CSV content or use FX token from upstream step" },
1335
+ { key: "delimiter", label: "Delimiter", type: "select" /* Select */, options: [{ label: "Comma (,)", value: "," }, { label: "Semicolon (;)", value: ";" }, { label: "Tab", value: "\t" }, { label: "Pipe (|)", value: "|" }], defaultValue: "," },
1336
+ { key: "headerRow", label: "Header Row", type: "number" /* Number */, description: "Row number containing column headers (default: 1)", defaultValue: 1 },
1337
+ { key: "encoding", label: "Encoding", type: "select" /* Select */, options: [{ label: "UTF-8", value: "utf-8" }, { label: "Latin-1", value: "latin1" }, { label: "ASCII", value: "ascii" }], defaultValue: "utf-8" },
1338
+ { key: "includeHeader", label: "Include Header Row", type: "boolean" /* Boolean */, description: "Include column headers in generated CSV", defaultValue: true },
1339
+ { key: "fileName", label: "Output File Name", type: "string" /* String */, description: "Name for generated file (e.g. export.csv)", defaultValue: "export.csv" }
1340
+ ]
1341
+ },
1342
+ outputSchema: {
1343
+ type: "object",
1344
+ properties: [
1345
+ { key: "data", type: "array" /* Array */, description: "Parsed records (parse mode) — loop these with a ForEach. Generated CSV string in generate mode." },
1346
+ { key: "columns", type: "json" /* JSON */, description: "Column names" },
1347
+ { key: "rowCount", type: "number" /* Number */, description: "Number of records" }
1348
+ ],
1349
+ sampleOutput: { data: [{ id: 1, name: "Widget", price: 9.99 }], columns: ["id", "name", "price"], rowCount: 1 }
1350
+ },
1351
+ version: "1.0.0",
1352
+ createdAt: "2026-03-28T00:00:00Z",
1353
+ updatedAt: "2026-03-28T00:00:00Z",
1354
+ createdBy: "system",
1355
+ isOfficial: true,
1356
+ testable: false
1357
+ };
1358
+
1359
+ // src/catalog/storage/json-action/index.ts
1360
+ var jsonActionDefinition = {
1361
+ id: "json_action",
1362
+ name: "JSON",
1363
+ description: "Parse JSON/JSONL files into structured records or generate JSON from workflow data",
1364
+ category: "storage" /* Storage */,
1365
+ type: "json_action" /* JsonAction */,
1366
+ tags: ["json", "jsonl", "parse", "generate", "file", "format", "built-in"],
1367
+ status: "stable" /* Stable */,
1368
+ icon: "DataStructured",
1369
+ color: "#f1c21b",
1370
+ inputSchema: {
1371
+ fields: [
1372
+ { key: "operation", label: "Operation", type: "select" /* Select */, options: [{ label: "Parse (JSON → Records)", value: "parse" }, { label: "Generate (Records → JSON)", value: "generate" }], defaultValue: "parse", validation: { required: true } },
1373
+ { key: "format", label: "Format", type: "select" /* Select */, options: [{ label: "JSON (array)", value: "json" }, { label: "JSONL (one object per line)", value: "jsonl" }], defaultValue: "json" },
1374
+ { key: "content", label: "JSON Content", type: "string" /* String */, description: "Paste JSON content or use FX token from upstream step" },
1375
+ { key: "prettyPrint", label: "Pretty Print", type: "boolean" /* Boolean */, description: "Format output with indentation", defaultValue: true },
1376
+ { key: "fileName", label: "Output File Name", type: "string" /* String */, defaultValue: "export.json" }
1377
+ ]
1378
+ },
1379
+ outputSchema: {
1380
+ type: "object",
1381
+ properties: [
1382
+ { key: "data", type: "array" /* Array */, description: "Parsed records (parse mode) — loop these with a ForEach. Generated JSON string in generate mode." },
1383
+ { key: "columns", type: "json" /* JSON */, description: "Field names" },
1384
+ { key: "rowCount", type: "number" /* Number */, description: "Number of records" }
1385
+ ],
1386
+ sampleOutput: { data: [{ id: 1, name: "Widget" }], columns: ["id", "name"], rowCount: 1 }
1387
+ },
1388
+ version: "1.0.0",
1389
+ createdAt: "2026-03-28T00:00:00Z",
1390
+ updatedAt: "2026-03-28T00:00:00Z",
1391
+ createdBy: "system",
1392
+ isOfficial: true,
1393
+ testable: false
1394
+ };
1395
+
1396
+ // src/catalog/storage/xml-action/index.ts
1397
+ var xmlActionDefinition = {
1398
+ id: "xml_action",
1399
+ name: "XML",
1400
+ description: "Parse XML files into structured records or generate XML from workflow data",
1401
+ category: "storage" /* Storage */,
1402
+ type: "xml_action" /* XmlAction */,
1403
+ tags: ["xml", "parse", "generate", "file", "format", "built-in"],
1404
+ status: "beta" /* Beta */,
1405
+ icon: "Code",
1406
+ color: "#e65100",
1407
+ inputSchema: {
1408
+ fields: [
1409
+ { key: "operation", label: "Operation", type: "select" /* Select */, options: [{ label: "Parse (XML → Records)", value: "parse" }, { label: "Generate (Records → XML)", value: "generate" }], defaultValue: "parse", validation: { required: true } },
1410
+ { key: "content", label: "XML Content", type: "string" /* String */, description: "Paste XML or use FX token" },
1411
+ { key: "rootElement", label: "Root Element", type: "string" /* String */, description: "Root XML element name (for generate)", defaultValue: "data" },
1412
+ { key: "rowElement", label: "Row Element", type: "string" /* String */, description: "Element name per record (for generate)", defaultValue: "row" },
1413
+ { key: "fileName", label: "Output File Name", type: "string" /* String */, defaultValue: "export.xml" }
1414
+ ]
1415
+ },
1416
+ outputSchema: {
1417
+ type: "object",
1418
+ properties: [
1419
+ { key: "data", type: "array" /* Array */, description: "Parsed records (parse mode) — loop these with a ForEach. Generated XML string in generate mode." },
1420
+ { key: "columns", type: "json" /* JSON */, description: "Field names" },
1421
+ { key: "rowCount", type: "number" /* Number */, description: "Number of records" }
1422
+ ],
1423
+ sampleOutput: { data: [{ id: 1, name: "Widget" }], columns: ["id", "name"], rowCount: 1 }
1424
+ },
1425
+ version: "1.0.0",
1426
+ createdAt: "2026-03-28T00:00:00Z",
1427
+ updatedAt: "2026-03-28T00:00:00Z",
1428
+ createdBy: "system",
1429
+ isOfficial: true,
1430
+ testable: false
1431
+ };
1432
+
1433
+ // src/catalog/storage/excel-action/index.ts
1434
+ var excelActionDefinition = {
1435
+ id: "excel_action",
1436
+ name: "Excel",
1437
+ description: "Parse Excel (.xlsx) files into structured records or generate Excel files from workflow data",
1438
+ category: "storage" /* Storage */,
1439
+ type: "excel_action" /* ExcelAction */,
1440
+ tags: ["excel", "xlsx", "xls", "spreadsheet", "parse", "generate", "built-in"],
1441
+ status: "stable" /* Stable */,
1442
+ icon: "Spreadsheet",
1443
+ color: "#217346",
1444
+ inputSchema: {
1445
+ fields: [
1446
+ { key: "operation", label: "Operation", type: "select" /* Select */, options: [{ label: "Parse (Excel → Records)", value: "parse" }, { label: "Generate (Records → Excel)", value: "generate" }], defaultValue: "parse", validation: { required: true } },
1447
+ { key: "content", label: "Excel File", type: "string" /* String */, description: "S3 key of uploaded Excel file or FX token from upstream" },
1448
+ { key: "sheetName", label: "Sheet Name", type: "string" /* String */, description: "Name of sheet to read (default: first sheet)" },
1449
+ { key: "headerRow", label: "Header Row", type: "number" /* Number */, description: "Row number containing headers", defaultValue: 1 },
1450
+ { key: "fileName", label: "Output File Name", type: "string" /* String */, defaultValue: "export.xlsx" }
1451
+ ]
1452
+ },
1453
+ outputSchema: {
1454
+ type: "object",
1455
+ properties: [
1456
+ { key: "data", type: "array" /* Array */, description: "Parsed records (parse mode) — loop these with a ForEach. File metadata in generate mode." },
1457
+ { key: "columns", type: "json" /* JSON */, description: "Column names" },
1458
+ { key: "rowCount", type: "number" /* Number */, description: "Number of records" },
1459
+ { key: "s3Key", type: "string" /* String */, description: "S3 key of generated file" }
1460
+ ],
1461
+ sampleOutput: { data: [{ id: 1, name: "Widget" }], columns: ["id", "name"], rowCount: 1 }
1462
+ },
1463
+ version: "1.0.0",
1464
+ createdAt: "2026-03-28T00:00:00Z",
1465
+ updatedAt: "2026-03-28T00:00:00Z",
1466
+ createdBy: "system",
1467
+ isOfficial: true,
1468
+ testable: false
1469
+ };
1470
+
1471
+ // src/catalog/storage/s3-action/index.ts
1472
+ var s3ActionDefinition = {
1473
+ id: "s3_action",
1474
+ name: "AWS S3",
1475
+ description: "Upload, download, list, delete, or copy files in Amazon S3 buckets",
1476
+ category: "storage" /* Storage */,
1477
+ type: "s3_action" /* S3Action */,
1478
+ tags: ["s3", "aws", "storage", "cloud", "bucket", "upload", "download", "built-in"],
1479
+ status: "stable" /* Stable */,
1480
+ icon: "CloudUpload",
1481
+ color: "#569A31",
1482
+ inputSchema: {
1483
+ fields: [
1484
+ { key: "operation", label: "Operation", type: "select" /* Select */, options: [{ label: "List Files", value: "list" }, { label: "Upload File", value: "upload" }, { label: "Download File", value: "download" }, { label: "Delete File", value: "delete" }, { label: "Copy File", value: "copy" }, { label: "Move / Rename", value: "move" }, { label: "Get Signed URL", value: "presign" }], defaultValue: "download", validation: { required: true } },
1485
+ { key: "bucket", label: "Bucket Name", type: "string" /* String */, description: "S3 bucket name (defaults to the connector’s bucket)" },
1486
+ { key: "key", label: "Object Key (Path)", type: "string" /* String */, description: "S3 object key, e.g. data/reports/monthly.csv" },
1487
+ { key: "prefix", label: "Prefix (for List)", type: "string" /* String */, description: "Filter objects by prefix (folder path)" },
1488
+ { key: "content", label: "File Content (for Upload)", type: "string" /* String */, description: "Content to upload — use FX token from upstream step" },
1489
+ { key: "contentType", label: "Content Type", type: "string" /* String */, description: "MIME type (e.g. text/csv, application/json)", defaultValue: "application/octet-stream" },
1490
+ { key: "destBucket", label: "Destination Bucket (for Copy)", type: "string" /* String */ },
1491
+ { key: "destKey", label: "Destination Key (for Copy)", type: "string" /* String */ },
1492
+ { key: "expiresIn", label: "URL Expiry (seconds)", type: "number" /* Number */, description: "Presigned URL expiry time", defaultValue: 3600 },
1493
+ { key: "maxKeys", label: "Max Results (for List)", type: "number" /* Number */, defaultValue: 100 }
1494
+ ]
1495
+ },
1496
+ outputSchema: {
1497
+ type: "object",
1498
+ properties: [
1499
+ { key: "data", type: "json" /* JSON */, description: "Downloaded content, file list, or operation result" },
1500
+ { key: "key", type: "string" /* String */, description: "S3 object key" },
1501
+ { key: "url", type: "string" /* String */, description: "Presigned URL (for presign operation)" }
1502
+ ],
1503
+ sampleOutput: { data: "file content here", key: "data/reports/monthly.csv" }
1504
+ },
1505
+ version: "1.0.0",
1506
+ createdAt: "2026-03-28T00:00:00Z",
1507
+ updatedAt: "2026-03-28T00:00:00Z",
1508
+ createdBy: "system",
1509
+ isOfficial: true,
1510
+ testable: false
1511
+ };
1512
+
1513
+ // src/catalog/storage/ftp-action/index.ts
1514
+ var ftpActionDefinition = {
1515
+ id: "ftp_action",
1516
+ name: "FTP / SFTP",
1517
+ description: "Upload, download, list, delete, or move files on FTP/SFTP servers. Select a configured FTP connector, then pick files from the remote file explorer.",
1518
+ category: "storage" /* Storage */,
1519
+ type: "ftp_action" /* FtpAction */,
1520
+ tags: ["ftp", "sftp", "ftps", "file", "transfer", "server", "built-in"],
1521
+ status: "beta" /* Beta */,
1522
+ icon: "DataBackup",
1523
+ color: "#005d5d",
1524
+ inputSchema: {
1525
+ fields: [
1526
+ { key: "connector", label: "FTP / SFTP Connection", type: "connection" /* Connection */, description: "Select a configured FTP/SFTP connector from Integrations", validation: { required: true } },
1527
+ { key: "operation", label: "Operation", type: "select" /* Select */, options: [{ label: "Download File", value: "download" }, { label: "Upload File", value: "upload" }, { label: "List Files", value: "list" }, { label: "Delete File", value: "delete" }, { label: "Move / Rename", value: "move" }], defaultValue: "download", validation: { required: true } },
1528
+ { key: "remotePath", label: "Remote Path", type: "string" /* String */, description: "File or folder path on the server (use file explorer to browse)" },
1529
+ { key: "content", label: "File Content (Upload)", type: "string" /* String */, description: "Content to upload — use FX token from upstream step" },
1530
+ { key: "fileName", label: "File Name (Upload)", type: "string" /* String */, description: "Name for the uploaded file" },
1531
+ { key: "destPath", label: "Destination Path (Move)", type: "string" /* String */, description: "New path for moved/renamed file" },
1532
+ { key: "ifExists", label: "If File Exists", type: "select" /* Select */, options: [{ label: "Overwrite", value: "overwrite" }, { label: "Skip", value: "skip" }], defaultValue: "overwrite" }
1533
+ ]
1534
+ },
1535
+ outputSchema: {
1536
+ type: "object",
1537
+ properties: [
1538
+ { key: "data", type: "json" /* JSON */, description: "Downloaded content, file list, or result" },
1539
+ { key: "files", type: "json" /* JSON */, description: "List of files (for list op)" },
1540
+ { key: "success", type: "boolean" /* Boolean */, description: "Whether operation succeeded" }
1541
+ ],
1542
+ sampleOutput: { success: true, data: "file content here" }
1543
+ },
1544
+ version: "1.0.0",
1545
+ createdAt: "2026-03-29T00:00:00Z",
1546
+ updatedAt: "2026-03-29T00:00:00Z",
1547
+ createdBy: "system",
1548
+ isOfficial: true,
1549
+ testable: false
1550
+ };
1551
+
1552
+ // src/catalog/storage/google-drive-action/index.ts
1553
+ var googleDriveActionDefinition = {
1554
+ id: "google_drive_action",
1555
+ name: "Google Drive",
1556
+ description: "Upload, download, list, delete, move, copy, or share files in Google Drive",
1557
+ category: "storage" /* Storage */,
1558
+ type: "google_drive_action" /* GoogleDriveAction */,
1559
+ tags: ["google", "drive", "cloud", "storage", "upload", "download", "built-in"],
1560
+ status: "beta" /* Beta */,
1561
+ icon: "CloudUpload",
1562
+ color: "#4285F4",
1563
+ inputSchema: {
1564
+ fields: [
1565
+ { key: "connector", label: "Google Account", type: "connection" /* Connection */, description: "Select a connected Google Sheets connector (shares Drive access)", validation: { required: true } },
1566
+ { key: "operation", label: "Operation", type: "select" /* Select */, options: [{ label: "Upload File", value: "upload" }, { label: "Download File", value: "download" }, { label: "List Files", value: "list" }, { label: "Delete File", value: "delete" }, { label: "Move File", value: "move" }, { label: "Copy File", value: "copy" }, { label: "Share File", value: "share" }, { label: "Create Folder", value: "create_folder" }], defaultValue: "upload", validation: { required: true } },
1567
+ { key: "fileId", label: "File ID / Path", type: "string" /* String */, description: "Google Drive file ID (use file explorer to browse)" },
1568
+ { key: "folderId", label: "Folder ID", type: "string" /* String */, description: "Target folder (root if empty)" },
1569
+ { key: "fileName", label: "File Name", type: "string" /* String */ },
1570
+ { key: "content", label: "File Content (Upload)", type: "string" /* String */, description: "Content to upload — use FX token from upstream" },
1571
+ { key: "mimeType", label: "MIME Type", type: "string" /* String */, defaultValue: "application/octet-stream" },
1572
+ { key: "destFolderId", label: "Destination Folder (Move/Copy)", type: "string" /* String */ },
1573
+ { key: "shareEmail", label: "Share With Email", type: "string" /* String */ },
1574
+ { key: "shareRole", label: "Permission", type: "select" /* Select */, options: [{ label: "Viewer", value: "reader" }, { label: "Editor", value: "writer" }], defaultValue: "reader" },
1575
+ { key: "query", label: "Search Query (List)", type: "string" /* String */, description: "e.g. name contains 'report'" },
1576
+ { key: "pageSize", label: "Max Results", type: "number" /* Number */, defaultValue: 50 }
1577
+ ]
1578
+ },
1579
+ outputSchema: {
1580
+ type: "object",
1581
+ properties: [
1582
+ { key: "data", type: "json" /* JSON */, description: "File content, file list, or operation result" },
1583
+ { key: "fileId", type: "string" /* String */, description: "Google Drive file ID" },
1584
+ { key: "webViewLink", type: "string" /* String */, description: "Link to view file in browser" }
1585
+ ],
1586
+ sampleOutput: { fileId: "1abc...", webViewLink: "https://drive.google.com/file/d/1abc.../view" }
1587
+ },
1588
+ version: "1.0.0",
1589
+ createdAt: "2026-03-28T00:00:00Z",
1590
+ updatedAt: "2026-03-28T00:00:00Z",
1591
+ createdBy: "system",
1592
+ isOfficial: true,
1593
+ testable: false
1594
+ };
1595
+
1596
+ // src/catalog/storage/dropbox-action/index.ts
1597
+ var dropboxActionDefinition = {
1598
+ id: "dropbox_action",
1599
+ name: "Dropbox",
1600
+ description: "Upload, download, list, delete, move, or copy files in Dropbox",
1601
+ category: "storage" /* Storage */,
1602
+ type: "dropbox_action" /* DropboxAction */,
1603
+ tags: ["dropbox", "cloud", "storage", "upload", "download", "built-in"],
1604
+ status: "beta" /* Beta */,
1605
+ icon: "CloudUpload",
1606
+ color: "#0061FF",
1607
+ inputSchema: {
1608
+ fields: [
1609
+ { key: "connector", label: "Dropbox Account", type: "connection" /* Connection */, description: "Select a connected Dropbox account", validation: { required: true } },
1610
+ { key: "operation", label: "Operation", type: "select" /* Select */, options: [{ label: "Download File", value: "download" }, { label: "Upload File", value: "upload" }, { label: "List Files", value: "list" }, { label: "Delete", value: "delete" }, { label: "Move", value: "move" }, { label: "Copy", value: "copy" }, { label: "Create Folder", value: "create_folder" }, { label: "Get Shared Link", value: "shared_link" }], defaultValue: "download", validation: { required: true } },
1611
+ { key: "path", label: "File / Folder Path", type: "string" /* String */, description: "Path on Dropbox (use file explorer to browse)" },
1612
+ { key: "content", label: "File Content (Upload)", type: "string" /* String */, description: "Content to upload — use FX token from upstream" },
1613
+ { key: "fileName", label: "File Name (Upload)", type: "string" /* String */ },
1614
+ { key: "destPath", label: "Destination Path (Move/Copy)", type: "string" /* String */ },
1615
+ { key: "mode", label: "Upload Mode", type: "select" /* Select */, options: [{ label: "Add (fail if exists)", value: "add" }, { label: "Overwrite", value: "overwrite" }], defaultValue: "overwrite" }
1616
+ ]
1617
+ },
1618
+ outputSchema: {
1619
+ type: "object",
1620
+ properties: [
1621
+ { key: "data", type: "json" /* JSON */, description: "File content, list, or metadata" },
1622
+ { key: "path", type: "string" /* String */, description: "Dropbox file path" },
1623
+ { key: "sharedLink", type: "string" /* String */, description: "Shared link URL" }
1624
+ ],
1625
+ sampleOutput: { path: "/reports/monthly.csv", data: "content..." }
1626
+ },
1627
+ version: "1.0.0",
1628
+ createdAt: "2026-03-28T00:00:00Z",
1629
+ updatedAt: "2026-03-28T00:00:00Z",
1630
+ createdBy: "system",
1631
+ isOfficial: true,
1632
+ testable: false
1633
+ };
1634
+
1635
+ // src/catalog/storage/onedrive-action/index.ts
1636
+ var onedriveActionDefinition = {
1637
+ id: "onedrive_action",
1638
+ name: "OneDrive",
1639
+ description: "Upload, download, list, delete, move, or copy files in Microsoft OneDrive",
1640
+ category: "storage" /* Storage */,
1641
+ type: "onedrive_action" /* OneDriveAction */,
1642
+ tags: ["onedrive", "microsoft", "cloud", "storage", "built-in"],
1643
+ status: "beta" /* Beta */,
1644
+ icon: "CloudUpload",
1645
+ color: "#0078D4",
1646
+ inputSchema: {
1647
+ fields: [
1648
+ { key: "connector", label: "Microsoft Account", type: "connection" /* Connection */, description: "Select a connected Microsoft/OneDrive account", validation: { required: true } },
1649
+ { key: "operation", label: "Operation", type: "select" /* Select */, options: [{ label: "Download File", value: "download" }, { label: "Upload File", value: "upload" }, { label: "List Files", value: "list" }, { label: "Delete", value: "delete" }, { label: "Move", value: "move" }, { label: "Copy", value: "copy" }], defaultValue: "download", validation: { required: true } },
1650
+ { key: "path", label: "File / Folder Path", type: "string" /* String */, description: "Path on OneDrive (use file explorer to browse)" },
1651
+ { key: "itemId", label: "Item ID", type: "string" /* String */, description: "OneDrive item ID (alternative to path)" },
1652
+ { key: "content", label: "File Content (Upload)", type: "string" /* String */, description: "Content to upload — use FX token from upstream" },
1653
+ { key: "fileName", label: "File Name (Upload)", type: "string" /* String */ },
1654
+ { key: "destPath", label: "Destination Path (Move/Copy)", type: "string" /* String */ }
1655
+ ]
1656
+ },
1657
+ outputSchema: {
1658
+ type: "object",
1659
+ properties: [
1660
+ { key: "data", type: "json" /* JSON */, description: "File content, list, or metadata" },
1661
+ { key: "itemId", type: "string" /* String */, description: "OneDrive item ID" },
1662
+ { key: "webUrl", type: "string" /* String */, description: "Browser URL" }
1663
+ ],
1664
+ sampleOutput: { itemId: "abc123", webUrl: "https://onedrive.live.com/..." }
1665
+ },
1666
+ version: "1.0.0",
1667
+ createdAt: "2026-03-28T00:00:00Z",
1668
+ updatedAt: "2026-03-28T00:00:00Z",
1669
+ createdBy: "system",
1670
+ isOfficial: true,
1671
+ testable: false
1672
+ };
1673
+
1674
+ // src/catalog/storage/storage-action/index.ts
1675
+ var storageActionDefinition = {
1676
+ id: "storage_action",
1677
+ name: "Storage",
1678
+ description: "Browse, transfer, and manage files on any connected storage — cloud (Amazon S3, Google Drive, OneDrive, Dropbox, GCS, Azure Blob) or FTP/SFTP.",
1679
+ category: "storage" /* Storage */,
1680
+ type: "storage_action" /* StorageAction */,
1681
+ tags: ["storage", "files", "s3", "dropbox", "onedrive", "google drive", "ftp", "sftp", "upload", "download", "cloud", "built-in"],
1682
+ status: "stable" /* Stable */,
1683
+ icon: "CloudUpload",
1684
+ color: "#4F46E5",
1685
+ inputSchema: {
1686
+ fields: [
1687
+ { key: "connector", label: "Storage connector", type: "connection" /* Connection */, description: "Pick a connected storage connector — its provider drives the available operations.", validation: { required: true } },
1688
+ {
1689
+ key: "operation",
1690
+ label: "Operation",
1691
+ type: "select" /* Select */,
1692
+ options: [
1693
+ { label: "List files", value: "list" },
1694
+ { label: "Download file", value: "download" },
1695
+ { label: "Upload file", value: "upload" },
1696
+ { label: "Delete file", value: "delete" },
1697
+ { label: "Copy file", value: "copy" },
1698
+ { label: "Move / rename", value: "move" },
1699
+ { label: "Get signed URL", value: "presign" },
1700
+ { label: "Share", value: "share" },
1701
+ { label: "Create folder", value: "create_folder" },
1702
+ { label: "Transfer to another connector", value: "transfer" }
1703
+ ],
1704
+ defaultValue: "download",
1705
+ validation: { required: true }
1706
+ },
1707
+ { key: "path", label: "Path", type: "string" /* String */, description: "File or folder path — use the file browser in the panel." },
1708
+ { key: "destPath", label: "Destination path", type: "string" /* String */, description: "Target for copy / move." },
1709
+ { key: "content", label: "File content (for Upload)", type: "string" /* String */, description: "Content to upload — bind an FX token from an upstream step." }
1710
+ ]
1711
+ },
1712
+ outputSchema: {
1713
+ type: "object",
1714
+ properties: [
1715
+ { key: "operation", type: "string" /* String */, description: "The operation that ran" },
1716
+ { key: "data", type: "json" /* JSON */, description: "Operation result or downloaded content" },
1717
+ { key: "files", type: "json" /* JSON */, description: "Listing (for the List operation)" },
1718
+ { key: "path", type: "string" /* String */, description: "Affected file/folder path" },
1719
+ { key: "url", type: "string" /* String */, description: "Signed URL (for the Get signed URL operation)" }
1720
+ ],
1721
+ sampleOutput: {
1722
+ operation: "list",
1723
+ files: [
1724
+ { name: "report.csv", path: "/reports/report.csv", ext: "csv", mimeType: "text/csv", type: "file", size: 2048, modifiedAt: "2026-06-18T10:00:00Z" }
1725
+ ]
1726
+ }
1727
+ },
1728
+ version: "1.0.0",
1729
+ createdAt: "2026-06-05T00:00:00Z",
1730
+ updatedAt: "2026-06-05T00:00:00Z",
1731
+ createdBy: "system",
1732
+ isOfficial: true,
1733
+ testable: false
1734
+ };
1735
+
1736
+ // src/catalog/communication/email-send/index.ts
1737
+ var emailDefinition = {
1738
+ id: "email",
1739
+ name: "Email",
1740
+ description: "Send an email through any connected email service provider",
1741
+ category: "communication" /* Communication */,
1742
+ type: "email_send" /* EmailSend */,
1743
+ tags: ["communication", "email", "smtp", "sendgrid", "ses", "imap", "pop3", "built-in"],
1744
+ status: "stable" /* Stable */,
1745
+ icon: "Email",
1746
+ color: "#0043ce",
1747
+ inputSchema: {
1748
+ fields: [
1749
+ {
1750
+ key: "connection",
1751
+ label: "Email Service",
1752
+ type: "connection" /* Connection */,
1753
+ description: "Email service connection (SMTP, IMAP, SendGrid, AWS SES, etc.)",
1754
+ validation: { required: true }
1755
+ },
1756
+ {
1757
+ key: "operation",
1758
+ label: "Operation",
1759
+ type: "select" /* Select */,
1760
+ description: "Email operation — Send is the only operation available today",
1761
+ options: [
1762
+ { label: "Send", value: "send" }
1763
+ ],
1764
+ defaultValue: "send",
1765
+ validation: { required: true }
1766
+ },
1767
+ {
1768
+ key: "to",
1769
+ label: "To",
1770
+ type: "string" /* String */,
1771
+ description: "Recipient email address(es), comma-separated (for send operation)",
1772
+ validation: { required: false }
1773
+ },
1774
+ {
1775
+ key: "cc",
1776
+ label: "CC",
1777
+ type: "string" /* String */,
1778
+ description: "CC email address(es), comma-separated (for send operation)",
1779
+ validation: { required: false }
1780
+ },
1781
+ {
1782
+ key: "bcc",
1783
+ label: "BCC",
1784
+ type: "string" /* String */,
1785
+ description: "BCC email address(es), comma-separated (for send operation)",
1786
+ validation: { required: false }
1787
+ },
1788
+ {
1789
+ key: "subject",
1790
+ label: "Subject",
1791
+ type: "string" /* String */,
1792
+ description: "Email subject (for send operation)",
1793
+ validation: { required: false }
1794
+ },
1795
+ {
1796
+ key: "body",
1797
+ label: "Body",
1798
+ type: "string" /* String */,
1799
+ description: "Email body content (for send operation)",
1800
+ validation: { required: false }
1801
+ },
1802
+ {
1803
+ key: "isHtml",
1804
+ label: "Is HTML",
1805
+ type: "boolean" /* Boolean */,
1806
+ description: "Whether body is HTML content",
1807
+ defaultValue: false,
1808
+ validation: { required: false }
1809
+ },
1810
+ {
1811
+ key: "attachments",
1812
+ label: "Attachments",
1813
+ type: "array" /* Array */,
1814
+ description: "File attachments (URLs or file paths)",
1815
+ validation: { required: false }
1816
+ },
1817
+ {
1818
+ key: "folder",
1819
+ label: "Folder",
1820
+ type: "string" /* String */,
1821
+ description: "Email folder (Inbox, Sent, Drafts, etc.)",
1822
+ validation: { required: false }
1823
+ },
1824
+ {
1825
+ key: "query",
1826
+ label: "Search Query",
1827
+ type: "string" /* String */,
1828
+ description: "Search criteria (for search/read operations)",
1829
+ validation: { required: false }
1830
+ },
1831
+ {
1832
+ key: "limit",
1833
+ label: "Limit",
1834
+ type: "number" /* Number */,
1835
+ description: "Maximum number of emails to retrieve",
1836
+ defaultValue: 10,
1837
+ validation: { required: false }
1838
+ }
1839
+ ]
1840
+ },
1841
+ outputSchema: {
1842
+ type: "object",
1843
+ properties: [
1844
+ {
1845
+ key: "success",
1846
+ type: "boolean" /* Boolean */,
1847
+ description: "Whether operation was successful"
1848
+ },
1849
+ {
1850
+ key: "data",
1851
+ type: "json" /* JSON */,
1852
+ description: "Operation result data (emails, message ID, etc.)"
1853
+ },
1854
+ {
1855
+ key: "count",
1856
+ type: "number" /* Number */,
1857
+ description: "Number of emails affected/returned"
1858
+ },
1859
+ {
1860
+ key: "messageId",
1861
+ type: "string" /* String */,
1862
+ description: "Email message ID (for send operation)"
1863
+ }
1864
+ ],
1865
+ sampleOutput: {
1866
+ success: true,
1867
+ data: [{ id: "email_123", from: "sender@example.com", subject: "Test" }],
1868
+ count: 1,
1869
+ messageId: "msg_123456"
1870
+ }
1871
+ },
1872
+ version: "1.0.0",
1873
+ createdAt: "2025-01-01T00:00:00Z",
1874
+ updatedAt: "2025-12-15T00:00:00Z",
1875
+ createdBy: "system",
1876
+ isOfficial: true,
1877
+ testable: true
1878
+ };
1879
+
1880
+ // src/catalog/communication/slack-message/index.ts
1881
+ var slackMessageDefinition = {
1882
+ id: "slack_message",
1883
+ name: "Slack",
1884
+ description: "Send messages to Slack channels or users",
1885
+ category: "communication" /* Communication */,
1886
+ type: "slack_message" /* SlackMessage */,
1887
+ tags: ["communication", "slack", "chat", "built-in"],
1888
+ status: "stable" /* Stable */,
1889
+ icon: "brand:slack",
1890
+ color: "#4A154B",
1891
+ inputSchema: {
1892
+ fields: [
1893
+ { key: "connection", label: "Slack Workspace", type: "connection" /* Connection */, validation: { required: true } },
1894
+ { key: "channel", label: "Channel/User", type: "string" /* String */, validation: { required: true } },
1895
+ { key: "message", label: "Message", type: "string" /* String */, validation: { required: true } },
1896
+ { key: "blocks", label: "Blocks (JSON)", type: "json" /* JSON */, validation: { required: false } }
1897
+ ]
1898
+ },
1899
+ outputSchema: {
1900
+ type: "object",
1901
+ properties: [
1902
+ { key: "success", type: "boolean" /* Boolean */, description: "Whether message was sent" },
1903
+ { key: "timestamp", type: "string" /* String */, description: "Message timestamp" }
1904
+ ],
1905
+ sampleOutput: { success: true, timestamp: "1234567890.123456" }
1906
+ },
1907
+ version: "1.0.0",
1908
+ createdAt: "2025-01-01T00:00:00Z",
1909
+ updatedAt: "2025-12-15T00:00:00Z",
1910
+ createdBy: "system",
1911
+ isOfficial: true,
1912
+ testable: true
1913
+ };
1914
+
1915
+ // src/catalog/communication/whatsapp-send/index.ts
1916
+ var whatsappSendDefinition = {
1917
+ id: "whatsapp_send",
1918
+ name: "WhatsApp",
1919
+ description: "Send a WhatsApp message — an approved template, or freeform text inside the 24-hour reply window",
1920
+ category: "communication" /* Communication */,
1921
+ type: "whatsapp_send" /* WhatsappSend */,
1922
+ tags: ["communication", "whatsapp", "messaging", "template", "built-in"],
1923
+ status: "beta" /* Beta */,
1924
+ icon: "brand:whatsapp",
1925
+ color: "#25D366",
1926
+ inputSchema: {
1927
+ fields: [
1928
+ { key: "connection", label: "WhatsApp Connection", type: "connection" /* Connection */, validation: { required: true } },
1929
+ { key: "to", label: "To (phone number)", type: "string" /* String */, validation: { required: true } },
1930
+ { key: "mode", label: "Message Type", type: "select" /* Select */, validation: { required: true } },
1931
+ { key: "templateName", label: "Template", type: "string" /* String */, validation: { required: false } },
1932
+ { key: "templateLanguage", label: "Template Language", type: "string" /* String */, validation: { required: false } },
1933
+ { key: "templateVariables", label: "Template Variables", type: "json" /* JSON */, validation: { required: false } },
1934
+ { key: "text", label: "Message", type: "string" /* String */, validation: { required: false } }
1935
+ ]
1936
+ },
1937
+ outputSchema: {
1938
+ type: "object",
1939
+ properties: [
1940
+ { key: "ok", type: "boolean" /* Boolean */, description: "Whether WhatsApp accepted the message" },
1941
+ { key: "messageId", type: "string" /* String */, description: "WhatsApp message ID (wamid…)" },
1942
+ { key: "waId", type: "string" /* String */, description: "Recipient's resolved WhatsApp ID" },
1943
+ { key: "mode", type: "string" /* String */, description: "template | text" }
1944
+ ],
1945
+ sampleOutput: {
1946
+ ok: true,
1947
+ messageId: "wamid.HBgMOTE4ODAyODg1MTQ1FQIAERgSN0YxN0E5RkQ5MEQ4RkE5QzFEAA==",
1948
+ waId: "919876543210",
1949
+ mode: "template"
1950
+ }
1951
+ },
1952
+ version: "1.0.0",
1953
+ createdAt: "2026-07-30T00:00:00Z",
1954
+ updatedAt: "2026-07-30T00:00:00Z",
1955
+ createdBy: "system",
1956
+ isOfficial: true,
1957
+ testable: true
1958
+ };
1959
+
1960
+ // src/catalog/communication/teams-message/index.ts
1961
+ var teamsMessageDefinition = {
1962
+ id: "teams_message",
1963
+ name: "Teams",
1964
+ description: "Post messages to Microsoft Teams channels via OAuth 2.0",
1965
+ category: "communication" /* Communication */,
1966
+ type: "teams_message" /* TeamsMessage */,
1967
+ tags: ["communication", "teams", "microsoft", "chat", "built-in"],
1968
+ status: "stable" /* Stable */,
1969
+ icon: "brand:teams",
1970
+ color: "#4B53BC",
1971
+ inputSchema: {
1972
+ fields: [
1973
+ { key: "connection", label: "Teams Account", type: "connection" /* Connection */, validation: { required: true } },
1974
+ { key: "teamId", label: "Team", type: "string" /* String */, validation: { required: true } },
1975
+ { key: "channelId", label: "Channel", type: "string" /* String */, validation: { required: true } },
1976
+ { key: "title", label: "Subject", type: "string" /* String */, validation: { required: false } },
1977
+ { key: "message", label: "Message", type: "string" /* String */, validation: { required: true } }
1978
+ ]
1979
+ },
1980
+ outputSchema: {
1981
+ type: "object",
1982
+ properties: [
1983
+ { key: "ok", type: "boolean" /* Boolean */, description: "Whether the message was sent" },
1984
+ { key: "id", type: "string" /* String */, description: "Sent message id" },
1985
+ { key: "webUrl", type: "string" /* String */, description: "Deep link to the message" }
1986
+ ],
1987
+ sampleOutput: { ok: true, id: "1700000000000", webUrl: "https://teams.microsoft.com/l/message/..." }
1988
+ },
1989
+ version: "1.0.0",
1990
+ createdAt: "2025-01-01T00:00:00Z",
1991
+ updatedAt: "2025-12-15T00:00:00Z",
1992
+ createdBy: "system",
1993
+ isOfficial: true,
1994
+ testable: true
1995
+ };
1996
+
1997
+ // src/catalog/communication/google-chat/index.ts
1998
+ var googleChatDefinition = {
1999
+ id: "google_chat",
2000
+ name: "Google Chat",
2001
+ description: "Post a message to a Google Chat space (OAuth 2.0 — pick any space you belong to)",
2002
+ category: "communication" /* Communication */,
2003
+ type: "google_chat" /* GoogleChat */,
2004
+ tags: ["communication", "google", "chat", "webhook", "built-in"],
2005
+ status: "stable" /* Stable */,
2006
+ icon: "brand:google_chat",
2007
+ color: "#00AC47",
2008
+ inputSchema: {
2009
+ fields: [
2010
+ { key: "connection", label: "Google Chat Space", type: "connection" /* Connection */, validation: { required: true } },
2011
+ { key: "text", label: "Message", type: "string" /* String */, validation: { required: true } },
2012
+ { key: "threadKey", label: "Thread Key", type: "string" /* String */, validation: { required: false } }
2013
+ ]
2014
+ },
2015
+ outputSchema: {
2016
+ type: "object",
2017
+ properties: [
2018
+ { key: "ok", type: "boolean" /* Boolean */, description: "Whether the message was sent" },
2019
+ { key: "name", type: "string" /* String */, description: "Created message resource name" }
2020
+ ],
2021
+ sampleOutput: { ok: true, name: "spaces/AAAA/messages/BBBB" }
2022
+ },
2023
+ version: "1.0.0",
2024
+ createdAt: "2026-06-18T00:00:00Z",
2025
+ updatedAt: "2026-06-18T00:00:00Z",
2026
+ createdBy: "system",
2027
+ isOfficial: true,
2028
+ testable: true
2029
+ };
2030
+
2031
+ // src/catalog/communication/webhook-call/index.ts
2032
+ var webhookCallDefinition = {
2033
+ id: "webhook_call",
2034
+ name: "Webhook Call",
2035
+ description: "Call external webhooks with custom payloads",
2036
+ category: "communication" /* Communication */,
2037
+ type: "webhook_call" /* WebhookCall */,
2038
+ tags: ["communication", "webhook", "http", "built-in"],
2039
+ status: "stable" /* Stable */,
2040
+ icon: "Webhook",
2041
+ color: "#0043ce",
2042
+ inputSchema: {
2043
+ fields: [
2044
+ { key: "url", label: "Webhook URL", type: "url" /* URL */, validation: { required: true } },
2045
+ { key: "method", label: "Method", type: "select" /* Select */, options: [
2046
+ { label: "POST", value: "POST" },
2047
+ { label: "PUT", value: "PUT" },
2048
+ { label: "PATCH", value: "PATCH" },
2049
+ { label: "GET", value: "GET" }
2050
+ ], defaultValue: "POST", validation: { required: true } },
2051
+ { key: "payload", label: "Payload", type: "json" /* JSON */, validation: { required: false } },
2052
+ { key: "headers", label: "Headers", type: "json" /* JSON */, validation: { required: false } }
2053
+ ]
2054
+ },
2055
+ outputSchema: {
2056
+ type: "object",
2057
+ properties: [
2058
+ { key: "statusCode", type: "number" /* Number */, description: "HTTP status code" },
2059
+ { key: "response", type: "json" /* JSON */, description: "Response body" },
2060
+ { key: "success", type: "boolean" /* Boolean */, description: "Whether call succeeded" }
2061
+ ],
2062
+ sampleOutput: { statusCode: 200, response: {}, success: true }
2063
+ },
2064
+ version: "1.0.0",
2065
+ createdAt: "2025-01-01T00:00:00Z",
2066
+ updatedAt: "2025-12-15T00:00:00Z",
2067
+ createdBy: "system",
2068
+ isOfficial: true,
2069
+ testable: true
2070
+ };
2071
+
2072
+ // src/catalog/utility/debug/index.ts
2073
+ var debugDefinition = {
2074
+ id: "debug",
2075
+ name: "Debug",
2076
+ description: "Inspect, assert, watch, profile, or log workflow data at any point. Supports condition gating, sampling, and schema-drift detection.",
2077
+ category: "utility" /* Utility */,
2078
+ type: "debug" /* Debug */,
2079
+ tags: ["utility", "debug", "observability", "assert", "snapshot", "profile", "built-in"],
2080
+ status: "stable" /* Stable */,
2081
+ icon: "Debug",
2082
+ color: "#6929C4",
2083
+ inputSchema: { fields: [] },
2084
+ outputSchema: {
2085
+ type: "object",
2086
+ properties: [],
2087
+ sampleOutput: { debugged: true, mode: "log" }
2088
+ },
2089
+ version: "2.0.0",
2090
+ createdAt: "2025-01-01T00:00:00Z",
2091
+ updatedAt: "2026-05-02T00:00:00Z",
2092
+ createdBy: "system",
2093
+ isOfficial: true,
2094
+ testable: false
2095
+ };
2096
+
2097
+ // src/catalog/utility/error/index.ts
2098
+ var errorDefinition = {
2099
+ id: "error",
2100
+ name: "Error",
2101
+ description: "Throw an error to stop workflow execution",
2102
+ category: "utility" /* Utility */,
2103
+ type: "error" /* Error */,
2104
+ tags: ["utility", "error", "control", "built-in"],
2105
+ status: "stable" /* Stable */,
2106
+ icon: "ErrorFilled",
2107
+ color: "#da3742",
2108
+ inputSchema: {
2109
+ fields: [
2110
+ {
2111
+ key: "message",
2112
+ label: "Error Message",
2113
+ type: "string" /* String */,
2114
+ description: "Error message to throw",
2115
+ validation: { required: true }
2116
+ },
2117
+ {
2118
+ key: "code",
2119
+ label: "Error Code",
2120
+ type: "string" /* String */,
2121
+ description: "Error code",
2122
+ validation: { required: false }
2123
+ }
2124
+ ]
2125
+ },
2126
+ outputSchema: {
2127
+ type: "void",
2128
+ properties: [],
2129
+ sampleOutput: null
2130
+ },
2131
+ version: "1.0.0",
2132
+ createdAt: "2025-01-01T00:00:00Z",
2133
+ updatedAt: "2025-12-15T00:00:00Z",
2134
+ createdBy: "system",
2135
+ isOfficial: true,
2136
+ testable: true
2137
+ };
2138
+
2139
+ // src/catalog/utility/variables/index.ts
2140
+ var variablesDefinition = {
2141
+ id: "variables",
2142
+ name: "Variables",
2143
+ description: "Emit one or more typed user-defined values as a step output. Sources: literal, expression, prompt, secret, env.",
2144
+ category: "utility" /* Utility */,
2145
+ type: "write" /* Write */,
2146
+ tags: ["utility", "variables", "value", "expression", "built-in"],
2147
+ status: "stable" /* Stable */,
2148
+ icon: "Parameter",
2149
+ color: "#0F62FE",
2150
+ inputSchema: { fields: [] },
2151
+ outputSchema: {
2152
+ type: "object",
2153
+ properties: [],
2154
+ sampleOutput: {}
2155
+ },
2156
+ version: "1.0.0",
2157
+ createdAt: "2026-05-02T00:00:00Z",
2158
+ updatedAt: "2026-05-02T00:00:00Z",
2159
+ createdBy: "system",
2160
+ isOfficial: true,
2161
+ testable: false
2162
+ };
2163
+
2164
+ // src/catalog/api/graphql-query/index.ts
2165
+ var graphqlQueryDefinition = {
2166
+ id: "graphql_query",
2167
+ name: "GraphQL Query",
2168
+ description: "Execute GraphQL queries against GraphQL endpoints",
2169
+ category: "api" /* API */,
2170
+ type: "graphql_query" /* GraphQLQuery */,
2171
+ tags: ["api", "graphql", "query", "built-in"],
2172
+ status: "stable" /* Stable */,
2173
+ icon: "GraphQL",
2174
+ color: "#0043ce",
2175
+ inputSchema: {
2176
+ fields: [
2177
+ {
2178
+ key: "endpoint",
2179
+ label: "GraphQL Endpoint",
2180
+ type: "url" /* URL */,
2181
+ description: "GraphQL endpoint URL",
2182
+ validation: { required: true }
2183
+ },
2184
+ {
2185
+ key: "query",
2186
+ label: "Query",
2187
+ type: "code" /* Code */,
2188
+ description: "GraphQL query",
2189
+ language: "json",
2190
+ validation: { required: true }
2191
+ },
2192
+ {
2193
+ key: "variables",
2194
+ label: "Variables",
2195
+ type: "json" /* JSON */,
2196
+ description: "Query variables",
2197
+ validation: { required: false }
2198
+ },
2199
+ {
2200
+ key: "headers",
2201
+ label: "Headers",
2202
+ type: "json" /* JSON */,
2203
+ description: "HTTP headers",
2204
+ validation: { required: false }
2205
+ }
2206
+ ]
2207
+ },
2208
+ outputSchema: {
2209
+ type: "object",
2210
+ properties: [
2211
+ {
2212
+ key: "data",
2213
+ type: "json" /* JSON */,
2214
+ description: "Query result data"
2215
+ },
2216
+ {
2217
+ key: "errors",
2218
+ type: "array" /* Array */,
2219
+ description: "GraphQL errors"
2220
+ }
2221
+ ],
2222
+ sampleOutput: {
2223
+ data: { user: { id: "1", name: "John" } },
2224
+ errors: []
2225
+ }
2226
+ },
2227
+ version: "1.0.0",
2228
+ createdAt: "2025-01-01T00:00:00Z",
2229
+ updatedAt: "2025-12-15T00:00:00Z",
2230
+ createdBy: "system",
2231
+ isOfficial: true,
2232
+ testable: true
2233
+ };
2234
+
2235
+ // src/catalog/ai/ai-agent/index.ts
2236
+ var aiAgentDefinition = {
2237
+ id: "ai_agent",
2238
+ name: "AI Agent",
2239
+ description: "Run a reusable AI agent. Pick a saved agent from /ai/agents; optionally override model, temperature, or instructions per step.",
2240
+ category: "ai" /* AI */,
2241
+ type: "ai_agent" /* AIAgent */,
2242
+ tags: ["ai", "agent", "chat", "built-in"],
2243
+ status: "stable" /* Stable */,
2244
+ icon: "Bot",
2245
+ color: "#7c3aed",
2246
+ inputSchema: {
2247
+ fields: [
2248
+ {
2249
+ key: "agentId",
2250
+ label: "Agent",
2251
+ type: "string" /* String */,
2252
+ description: "Saved Agent public id (e.g. agt_xxx).",
2253
+ validation: { required: true }
2254
+ },
2255
+ {
2256
+ key: "input",
2257
+ label: "Input",
2258
+ type: "string" /* String */,
2259
+ description: "Chat agents: a string (template-supported via {{step.field}}). ETL agents: rows array. When blank, falls back to upstream step output."
2260
+ },
2261
+ {
2262
+ key: "overrides",
2263
+ label: "Overrides",
2264
+ type: "json" /* JSON */,
2265
+ description: "Optional per-step overrides of the agent’s own settings: model, temperature, maxTokens, topP, instructions and instructionsMode."
2266
+ }
2267
+ ]
2268
+ },
2269
+ outputSchema: {
2270
+ type: "object",
2271
+ properties: [
2272
+ { key: "text", type: "string" /* String */, description: "Agent response text (chat agents)" },
2273
+ { key: "rows", type: "json" /* JSON */, description: "Output rows (etl agents)" },
2274
+ { key: "usage", type: "json" /* JSON */, description: "Token usage + cost: tokensIn, tokensOut, latencyMs, costUsd" },
2275
+ { key: "model", type: "string" /* String */, description: "Model that produced the response" },
2276
+ { key: "agentVersion", type: "number" /* Number */, description: "Version of the agent definition that ran" }
2277
+ ],
2278
+ sampleOutput: {
2279
+ text: "Sure — happy to help. What would you like to know?",
2280
+ usage: { tokensIn: 42, tokensOut: 18, latencyMs: 612, costUsd: 0.000041 },
2281
+ model: "gpt-4o-mini",
2282
+ agentVersion: 3
2283
+ }
2284
+ },
2285
+ version: "1.0.0",
2286
+ createdAt: "2026-05-27T00:00:00Z",
2287
+ updatedAt: "2026-05-27T00:00:00Z",
2288
+ createdBy: "system",
2289
+ isOfficial: true,
2290
+ testable: true
2291
+ };
2292
+
2293
+ // src/catalog/ai/idp-extract/index.ts
2294
+ var idpExtractDefinition = {
2295
+ id: "idp_extract",
2296
+ name: "IDP",
2297
+ description: "Extract structured data from documents received from an upstream step. Configure the model provider, model, and the JSON Schema to extract.",
2298
+ category: "ai" /* AI */,
2299
+ type: "idp_extract" /* IdpExtract */,
2300
+ tags: ["ai", "idp", "document", "extract", "built-in"],
2301
+ status: "stable" /* Stable */,
2302
+ icon: "DocumentImport",
2303
+ color: "#0F62FE",
2304
+ inputSchema: {
2305
+ fields: [
2306
+ {
2307
+ key: "llmConnectorId",
2308
+ label: "Model provider (connector)",
2309
+ type: "select" /* Select */,
2310
+ description: "Connected AI provider (OpenAI, Anthropic, Gemini, …). Resolved at execution time.",
2311
+ validation: { required: true }
2312
+ },
2313
+ {
2314
+ key: "model",
2315
+ label: "Model",
2316
+ type: "select" /* Select */,
2317
+ description: "LLM available on the selected provider (e.g. gpt-4o, claude-3.5-sonnet, gemini-2.0-flash). Vision-capable models recommended.",
2318
+ validation: { required: true }
2319
+ },
2320
+ {
2321
+ key: "expectedSchema",
2322
+ label: "Output schema",
2323
+ type: "json" /* JSON */,
2324
+ description: "JSON Schema describing the fields to extract. The LLM is forced to emit JSON matching this shape.",
2325
+ validation: { required: false }
2326
+ },
2327
+ {
2328
+ key: "systemPromptOverride",
2329
+ label: "System prompt override",
2330
+ type: "string" /* String */,
2331
+ description: "Optional extra instructions appended to the extraction prompt."
2332
+ },
2333
+ {
2334
+ key: "strategy",
2335
+ label: "Strategy",
2336
+ type: "select" /* Select */,
2337
+ description: "vision-direct sends the file as an image to a vision LLM. auto picks based on PDF text content.",
2338
+ defaultValue: "vision-direct"
2339
+ }
2340
+ ]
2341
+ },
2342
+ outputSchema: {
2343
+ type: "object",
2344
+ properties: [
2345
+ { key: "state", type: "string" /* String */, description: "Aggregate state — completed | partial-success | failed." },
2346
+ {
2347
+ key: "pages",
2348
+ type: "array" /* Array */,
2349
+ description: "One row per file received from upstream: { fileName, data, confidence, audit, error? }"
2350
+ },
2351
+ {
2352
+ key: "totals",
2353
+ type: "object" /* Object */,
2354
+ description: "Summary { pages, completed, failed }"
2355
+ }
2356
+ ]
2357
+ },
2358
+ version: "2.0.0",
2359
+ createdAt: "2026-05-06T00:00:00Z",
2360
+ updatedAt: "2026-05-10T00:00:00Z",
2361
+ createdBy: "system"
2362
+ };
2363
+
2364
+ // src/catalog/index.ts
2365
+ var actionsRegistry = {
2366
+ ["trigger" /* Trigger */]: {
2367
+ manual_trigger: manualTriggerDefinition,
2368
+ schedule_trigger: scheduleTriggerDefinition,
2369
+ webhook_trigger: webhookTriggerDefinition,
2370
+ connector_trigger: connectorTriggerDefinition
2371
+ },
2372
+ ["action" /* Action */]: {
2373
+ http_request: httpRequestDefinition,
2374
+ console_log: consoleLogDefinition,
2375
+ delay: delayDefinition,
2376
+ query: queryDefinition,
2377
+ transform: transformDefinition
2378
+ },
2379
+ ["logic" /* Logic */]: {
2380
+ condition: conditionDefinition,
2381
+ for_each: forEachDefinition,
2382
+ group: groupDefinition
2383
+ },
2384
+ ["transform" /* Transform */]: {},
2385
+ ["database" /* Database */]: {},
2386
+ ["storage" /* Storage */]: {
2387
+ csv_action: csvActionDefinition,
2388
+ json_action: jsonActionDefinition,
2389
+ excel_action: excelActionDefinition,
2390
+ xml_action: xmlActionDefinition,
2391
+ storage_action: storageActionDefinition,
2392
+ s3_action: { ...s3ActionDefinition, deprecated: true, replacedBy: "storage_action" },
2393
+ ftp_action: { ...ftpActionDefinition, deprecated: true, replacedBy: "storage_action" },
2394
+ google_drive_action: { ...googleDriveActionDefinition, deprecated: true, replacedBy: "storage_action" },
2395
+ dropbox_action: { ...dropboxActionDefinition, deprecated: true, replacedBy: "storage_action" },
2396
+ onedrive_action: { ...onedriveActionDefinition, deprecated: true, replacedBy: "storage_action" }
2397
+ },
2398
+ ["communication" /* Communication */]: {
2399
+ email: emailDefinition,
2400
+ slack_message: slackMessageDefinition,
2401
+ whatsapp_send: whatsappSendDefinition,
2402
+ teams_message: teamsMessageDefinition,
2403
+ google_chat: googleChatDefinition,
2404
+ webhook_call: webhookCallDefinition
2405
+ },
2406
+ ["utility" /* Utility */]: {
2407
+ variables: variablesDefinition,
2408
+ debug: debugDefinition
2409
+ },
2410
+ ["ecommerce" /* Ecommerce */]: {},
2411
+ ["api" /* API */]: {},
2412
+ ["ai" /* AI */]: {
2413
+ ai_agent: aiAgentDefinition,
2414
+ idp_extract: idpExtractDefinition
2415
+ }
2416
+ };
2417
+ var getAllActions = () => {
2418
+ const allActions = [];
2419
+ for (const category of Object.values(actionsRegistry)) {
2420
+ allActions.push(...Object.values(category).filter((action) => action !== undefined));
2421
+ }
2422
+ return allActions;
2423
+ };
2424
+ var getActionById = (id) => {
2425
+ for (const category of Object.values(actionsRegistry)) {
2426
+ for (const action of Object.values(category)) {
2427
+ if (action.id === id) {
2428
+ return action;
2429
+ }
2430
+ }
2431
+ }
2432
+ return;
2433
+ };
2434
+ var getActionsByCategory = (category) => {
2435
+ const categoryActions = actionsRegistry[category];
2436
+ if (!categoryActions)
2437
+ return [];
2438
+ return Object.values(categoryActions);
2439
+ };
2440
+ // src/rules/nodeConfigStatus.ts
2441
+ var HIDDEN_STATUS_ACTIONS = new Set(["console_log"]);
2442
+ function isFieldFilled(value) {
2443
+ if (value === undefined || value === null)
2444
+ return false;
2445
+ if (typeof value === "string")
2446
+ return value.trim().length > 0;
2447
+ if (typeof value === "number")
2448
+ return true;
2449
+ if (typeof value === "boolean")
2450
+ return true;
2451
+ if (Array.isArray(value))
2452
+ return value.length > 0;
2453
+ if (typeof value === "object")
2454
+ return Object.keys(value).length > 0;
2455
+ return false;
2456
+ }
2457
+ function isSatisfiedOutOfBand(actionId, fieldKey, config) {
2458
+ if (actionId === "connector_trigger" && fieldKey === "events") {
2459
+ return Number(config.eventCount ?? 0) > 0;
2460
+ }
2461
+ if (MESSAGE_BODY_ACTIONS.has(actionId) && (fieldKey === "message" || fieldKey === "text")) {
2462
+ const text = config.text ?? config.message;
2463
+ if (typeof text === "string" && text.trim().length > 0)
2464
+ return true;
2465
+ return Array.isArray(config.blocks) && config.blocks.length > 0;
2466
+ }
2467
+ return false;
2468
+ }
2469
+ var MESSAGE_BODY_ACTIONS = new Set([
2470
+ "slack_message",
2471
+ "teams_message",
2472
+ "google_chat"
2473
+ ]);
2474
+ function getNestedValue(config, keyPath) {
2475
+ const parts = keyPath.split(".");
2476
+ let current = config;
2477
+ for (const part of parts) {
2478
+ if (current === null || current === undefined || typeof current !== "object") {
2479
+ return;
2480
+ }
2481
+ current = current[part];
2482
+ }
2483
+ return current;
2484
+ }
2485
+ function isFieldActive(field, config) {
2486
+ if (!field.conditional || field.conditional.length === 0) {
2487
+ return true;
2488
+ }
2489
+ return field.conditional.some((cond) => {
2490
+ if (cond.action !== "show" && cond.action !== "require") {
2491
+ return false;
2492
+ }
2493
+ const fieldValue = getNestedValue(config, cond.field);
2494
+ switch (cond.operator) {
2495
+ case "==":
2496
+ return fieldValue === cond.value;
2497
+ case "!=":
2498
+ return fieldValue !== cond.value;
2499
+ case ">":
2500
+ return fieldValue > cond.value;
2501
+ case "<":
2502
+ return fieldValue < cond.value;
2503
+ case ">=":
2504
+ return fieldValue >= cond.value;
2505
+ case "<=":
2506
+ return fieldValue <= cond.value;
2507
+ case "in":
2508
+ return Array.isArray(cond.value) && cond.value.includes(fieldValue);
2509
+ case "not_in":
2510
+ return Array.isArray(cond.value) && !cond.value.includes(fieldValue);
2511
+ case "contains":
2512
+ return typeof fieldValue === "string" && fieldValue.includes(cond.value);
2513
+ default:
2514
+ return false;
2515
+ }
2516
+ });
2517
+ }
2518
+ function getNodeConfigStatus(node) {
2519
+ if (HIDDEN_STATUS_ACTIONS.has(node.actionDefinitionId)) {
2520
+ return {
2521
+ status: "hidden",
2522
+ requiredTotal: 0,
2523
+ requiredFilled: 0,
2524
+ optionalTotal: 0,
2525
+ optionalFilled: 0,
2526
+ missingRequired: [],
2527
+ filledOptional: []
2528
+ };
2529
+ }
2530
+ const definition = getActionById(node.actionDefinitionId);
2531
+ if (!definition) {
2532
+ return {
2533
+ status: "unconfigured",
2534
+ requiredTotal: 0,
2535
+ requiredFilled: 0,
2536
+ optionalTotal: 0,
2537
+ optionalFilled: 0,
2538
+ missingRequired: [],
2539
+ filledOptional: []
2540
+ };
2541
+ }
2542
+ const fields = definition.inputSchema?.fields ?? [];
2543
+ const config = node.config ?? {};
2544
+ const activeFields = fields.filter((f) => !f.hidden && isFieldActive(f, config));
2545
+ const requiredFields = activeFields.filter((f) => f.validation?.required);
2546
+ const optionalFields = activeFields.filter((f) => !f.validation?.required);
2547
+ const missingRequired = [];
2548
+ let requiredFilled = 0;
2549
+ for (const field of requiredFields) {
2550
+ const value = getNestedValue(config, field.key);
2551
+ if (isFieldFilled(value)) {
2552
+ requiredFilled++;
2553
+ } else if (isFieldFilled(field.defaultValue)) {
2554
+ requiredFilled++;
2555
+ } else if (isSatisfiedOutOfBand(node.actionDefinitionId, field.key, config)) {
2556
+ requiredFilled++;
2557
+ } else {
2558
+ missingRequired.push(field.key);
2559
+ }
2560
+ }
2561
+ const filledOptional = [];
2562
+ let optionalFilled = 0;
2563
+ for (const field of optionalFields) {
2564
+ const value = getNestedValue(config, field.key);
2565
+ if (isFieldFilled(value)) {
2566
+ optionalFilled++;
2567
+ filledOptional.push(field.key);
2568
+ }
2569
+ }
2570
+ const requiredTotal = requiredFields.length;
2571
+ const optionalTotal = optionalFields.length;
2572
+ let status;
2573
+ if (requiredTotal === 0) {
2574
+ status = "valid";
2575
+ } else if (missingRequired.length === 0) {
2576
+ status = "valid";
2577
+ } else if (requiredFilled > 0 || optionalFilled > 0) {
2578
+ status = "warning";
2579
+ } else {
2580
+ status = "error";
2581
+ }
2582
+ return {
2583
+ status,
2584
+ requiredTotal,
2585
+ requiredFilled,
2586
+ optionalTotal,
2587
+ optionalFilled,
2588
+ missingRequired,
2589
+ filledOptional
2590
+ };
2591
+ }
2592
+
2593
+ // src/rules/workflowValidator.ts
2594
+ var nodeName = (n) => n.label || n.id;
2595
+ function validateNode(node, allNodes, allEdges) {
2596
+ const errors = [];
2597
+ if (!node.id || node.id.trim().length === 0) {
2598
+ errors.push({
2599
+ id: `node-${node.id}-id`,
2600
+ type: "node",
2601
+ severity: "error",
2602
+ message: "Node ID is required",
2603
+ nodeId: node.id
2604
+ });
2605
+ }
2606
+ if (!node.label || node.label.trim().length === 0) {
2607
+ errors.push({
2608
+ id: `node-${node.id}-label`,
2609
+ type: "node",
2610
+ severity: "error",
2611
+ message: "Node label is required",
2612
+ nodeId: node.id
2613
+ });
2614
+ }
2615
+ const cfg = getNodeConfigStatus(node);
2616
+ if (cfg.missingRequired.length > 0) {
2617
+ const fields = cfg.missingRequired.slice(0, 4).join(", ");
2618
+ const more = cfg.missingRequired.length > 4 ? ` +${cfg.missingRequired.length - 4} more` : "";
2619
+ errors.push({
2620
+ id: `node-${node.id}-config`,
2621
+ type: "node",
2622
+ severity: "error",
2623
+ message: `Missing required settings: ${fields}${more}. Open the step and fill them in.`,
2624
+ nodeId: node.id
2625
+ });
2626
+ }
2627
+ const hasOutput = allEdges.some((edge) => edge.source === node.id);
2628
+ if (!hasOutput && node.type === "trigger") {
2629
+ errors.push({
2630
+ id: `node-${node.id}-output`,
2631
+ type: "node",
2632
+ severity: "warning",
2633
+ message: `Trigger "${nodeName(node)}" has no outgoing connections`,
2634
+ nodeId: node.id
2635
+ });
2636
+ }
2637
+ return errors;
2638
+ }
2639
+ function validateEdge(edge, allNodes, allEdges = []) {
2640
+ const errors = [];
2641
+ const sourceNode = allNodes.find((n) => n.id === edge.source);
2642
+ if (!sourceNode) {
2643
+ errors.push({
2644
+ id: `edge-${edge.id}-source`,
2645
+ type: "edge",
2646
+ severity: "error",
2647
+ message: `Source node "${edge.source}" does not exist`,
2648
+ edgeId: edge.id
2649
+ });
2650
+ }
2651
+ const targetNode = allNodes.find((n) => n.id === edge.target);
2652
+ if (!targetNode) {
2653
+ errors.push({
2654
+ id: `edge-${edge.id}-target`,
2655
+ type: "edge",
2656
+ severity: "error",
2657
+ message: `Target node "${edge.target}" does not exist`,
2658
+ edgeId: edge.id
2659
+ });
2660
+ }
2661
+ if (edge.source === edge.target) {
2662
+ errors.push({
2663
+ id: `edge-${edge.id}-loop`,
2664
+ type: "edge",
2665
+ severity: "error",
2666
+ message: "Nodes cannot connect to themselves",
2667
+ edgeId: edge.id
2668
+ });
2669
+ }
2670
+ const key = (e) => `${e.source}|${e.sourceHandle ?? ""}→${e.target}|${e.targetHandle ?? ""}`;
2671
+ const myKey = key(edge);
2672
+ const firstIndex = allEdges.findIndex((e) => key(e) === myKey);
2673
+ const myIndex = allEdges.findIndex((e) => e.id === edge.id);
2674
+ if (firstIndex !== -1 && myIndex > firstIndex) {
2675
+ errors.push({
2676
+ id: `edge-${edge.id}-duplicate`,
2677
+ type: "edge",
2678
+ severity: "warning",
2679
+ message: `Duplicate connection between "${sourceNode ? nodeName(sourceNode) : edge.source}" and "${targetNode ? nodeName(targetNode) : edge.target}"`,
2680
+ edgeId: edge.id
2681
+ });
2682
+ }
2683
+ return errors;
2684
+ }
2685
+ function validateWorkflow(nodes, edges) {
2686
+ const allErrors = [];
2687
+ const hasTrigger = nodes.some((node) => node.type === "trigger");
2688
+ if (!hasTrigger) {
2689
+ allErrors.push({
2690
+ id: "workflow-trigger",
2691
+ type: "workflow",
2692
+ severity: "error",
2693
+ message: "Workflow must have at least one trigger node"
2694
+ });
2695
+ }
2696
+ const hasAction = nodes.some((node) => node.type === "action");
2697
+ if (!hasAction && nodes.length > 0) {
2698
+ allErrors.push({
2699
+ id: "workflow-action",
2700
+ type: "workflow",
2701
+ severity: "warning",
2702
+ message: "Workflow should have at least one action node"
2703
+ });
2704
+ }
2705
+ nodes.forEach((node) => {
2706
+ const nodeErrors = validateNode(node, nodes, edges);
2707
+ allErrors.push(...nodeErrors);
2708
+ });
2709
+ edges.forEach((edge) => {
2710
+ const edgeErrors = validateEdge(edge, nodes, edges);
2711
+ allErrors.push(...edgeErrors);
2712
+ });
2713
+ if (nodes.length > 0 && edges.length > 0) {
2714
+ const inDegree = new Map(nodes.map((n) => [n.id, 0]));
2715
+ const out = new Map;
2716
+ for (const e of edges) {
2717
+ if (e.source === e.target)
2718
+ continue;
2719
+ if (!inDegree.has(e.source) || !inDegree.has(e.target))
2720
+ continue;
2721
+ inDegree.set(e.target, (inDegree.get(e.target) ?? 0) + 1);
2722
+ const list = out.get(e.source);
2723
+ if (list)
2724
+ list.push(e.target);
2725
+ else
2726
+ out.set(e.source, [e.target]);
2727
+ }
2728
+ const queue = nodes.filter((n) => (inDegree.get(n.id) ?? 0) === 0).map((n) => n.id);
2729
+ let visited = 0;
2730
+ while (queue.length) {
2731
+ const cur = queue.shift();
2732
+ visited++;
2733
+ for (const next of out.get(cur) ?? []) {
2734
+ const d = (inDegree.get(next) ?? 1) - 1;
2735
+ inDegree.set(next, d);
2736
+ if (d === 0)
2737
+ queue.push(next);
2738
+ }
2739
+ }
2740
+ if (visited < nodes.length) {
2741
+ const stuck = nodes.filter((n) => (inDegree.get(n.id) ?? 0) > 0);
2742
+ const names = stuck.slice(0, 3).map(nodeName).join(", ");
2743
+ const more = stuck.length > 3 ? ` +${stuck.length - 3} more` : "";
2744
+ allErrors.push({
2745
+ id: "workflow-cycle",
2746
+ type: "workflow",
2747
+ severity: "error",
2748
+ message: `Circular connection detected involving: ${names}${more}. Break the loop — execution order is undefined inside a cycle.`,
2749
+ nodeId: stuck[0]?.id
2750
+ });
2751
+ }
2752
+ }
2753
+ const isTrigger = (n) => n.type === "trigger" || String(n.actionDefinitionId ?? "").endsWith("_trigger");
2754
+ const triggerIds = nodes.filter(isTrigger).map((n) => n.id);
2755
+ const adjacency = new Map;
2756
+ for (const e of edges) {
2757
+ const list = adjacency.get(e.source);
2758
+ if (list)
2759
+ list.push(e.target);
2760
+ else
2761
+ adjacency.set(e.source, [e.target]);
2762
+ }
2763
+ const reachable = new Set(triggerIds);
2764
+ const queue = [...triggerIds];
2765
+ while (queue.length) {
2766
+ const cur = queue.shift();
2767
+ for (const next of adjacency.get(cur) ?? []) {
2768
+ if (!reachable.has(next)) {
2769
+ reachable.add(next);
2770
+ queue.push(next);
2771
+ }
2772
+ }
2773
+ }
2774
+ let changed = true;
2775
+ while (changed) {
2776
+ changed = false;
2777
+ for (const n of nodes) {
2778
+ if (reachable.has(n.id)) {
2779
+ if (n.parentId && !reachable.has(n.parentId)) {
2780
+ reachable.add(n.parentId);
2781
+ changed = true;
2782
+ }
2783
+ } else if (n.parentId && reachable.has(n.parentId)) {
2784
+ reachable.add(n.id);
2785
+ changed = true;
2786
+ }
2787
+ }
2788
+ }
2789
+ nodes.forEach((node) => {
2790
+ if (isTrigger(node))
2791
+ return;
2792
+ const isConnected = edges.some((e) => e.source === node.id || e.target === node.id);
2793
+ const wontRun = triggerIds.length > 0 ? !reachable.has(node.id) : !isConnected;
2794
+ if (wontRun) {
2795
+ allErrors.push({
2796
+ id: `node-${node.id}-orphan`,
2797
+ type: "node",
2798
+ severity: "warning",
2799
+ message: isConnected ? `"${nodeName(node)}" isn't reachable from a trigger and won't run.` : `"${nodeName(node)}" isn't connected to a flow and won't run.`,
2800
+ nodeId: node.id
2801
+ });
2802
+ }
2803
+ });
2804
+ if (triggerIds.length > 1) {
2805
+ const parentOf = new Map(nodes.filter((n) => n.parentId).map((n) => [n.id, n.parentId]));
2806
+ const undirected = new Map;
2807
+ const link = (a, b) => {
2808
+ const la = undirected.get(a);
2809
+ if (la)
2810
+ la.push(b);
2811
+ else
2812
+ undirected.set(a, [b]);
2813
+ };
2814
+ for (const e of edges) {
2815
+ link(e.source, e.target);
2816
+ link(e.target, e.source);
2817
+ }
2818
+ for (const [child, parent] of parentOf) {
2819
+ link(child, parent);
2820
+ link(parent, child);
2821
+ }
2822
+ const seen = new Set;
2823
+ let flowsWithTrigger = 0;
2824
+ for (const t of triggerIds) {
2825
+ if (seen.has(t))
2826
+ continue;
2827
+ flowsWithTrigger++;
2828
+ const stack = [t];
2829
+ seen.add(t);
2830
+ while (stack.length) {
2831
+ const cur = stack.pop();
2832
+ for (const next of undirected.get(cur) ?? []) {
2833
+ if (!seen.has(next)) {
2834
+ seen.add(next);
2835
+ stack.push(next);
2836
+ }
2837
+ }
2838
+ }
2839
+ }
2840
+ if (flowsWithTrigger > 1) {
2841
+ allErrors.push({
2842
+ id: "workflow-multi-flow",
2843
+ type: "workflow",
2844
+ severity: "warning",
2845
+ message: `This canvas holds ${flowsWithTrigger} separate flows. Each trigger runs only its own flow — consider splitting them into separate flows for clarity.`
2846
+ });
2847
+ }
2848
+ }
2849
+ const errors = allErrors.filter((e) => e.severity === "error");
2850
+ const warnings = allErrors.filter((e) => e.severity === "warning");
2851
+ return {
2852
+ isValid: errors.length === 0,
2853
+ errors,
2854
+ warnings
2855
+ };
2856
+ }
2857
+ function getNodeValidationStatus(nodeId, validationResult) {
2858
+ const hasError = validationResult.errors.some((e) => e.nodeId === nodeId);
2859
+ if (hasError)
2860
+ return "error";
2861
+ const hasWarning = validationResult.warnings.some((e) => e.nodeId === nodeId);
2862
+ if (hasWarning)
2863
+ return "warning";
2864
+ return "valid";
2865
+ }
2866
+ function getEdgeValidationStatus(edgeId, validationResult) {
2867
+ const hasError = validationResult.errors.some((e) => e.edgeId === edgeId);
2868
+ if (hasError)
2869
+ return "error";
2870
+ const hasWarning = validationResult.warnings.some((e) => e.edgeId === edgeId);
2871
+ if (hasWarning)
2872
+ return "warning";
2873
+ return "valid";
2874
+ }
2875
+ // src/catalog/logic/condition/config.ts
2876
+ var CONDITION_OPERATORS = [
2877
+ { id: "equals", label: "Equals", needsValue: true },
2878
+ { id: "not_equals", label: "Not Equals", needsValue: true },
2879
+ { id: "greater_than", label: "Greater Than", needsValue: true },
2880
+ { id: "greater_than_equals", label: "Greater Than or Equals", needsValue: true },
2881
+ { id: "less_than", label: "Less Than", needsValue: true },
2882
+ { id: "less_than_equals", label: "Less Than or Equals", needsValue: true },
2883
+ { id: "like", label: "Like", needsValue: true },
2884
+ { id: "contains", label: "Contains", needsValue: true },
2885
+ { id: "starts_with", label: "Starts With", needsValue: true },
2886
+ { id: "ends_with", label: "Ends With", needsValue: true },
2887
+ { id: "is_null", label: "Is Null", needsValue: false },
2888
+ { id: "is_not_null", label: "Is Not Null", needsValue: false },
2889
+ { id: "is_empty", label: "Is Empty", needsValue: false }
2890
+ ];
2891
+ // src/catalog/logic/for-each/pathOptions.ts
2892
+ function inferSchemaFromSample(sample) {
2893
+ const properties = {};
2894
+ for (const [key, value] of Object.entries(sample)) {
2895
+ if (value === null || value === undefined) {
2896
+ properties[key] = { type: "string" };
2897
+ } else if (Array.isArray(value)) {
2898
+ if (value.length > 0 && typeof value[0] === "object" && value[0] !== null) {
2899
+ properties[key] = { type: "array", items: inferSchemaFromSample(value[0]) };
2900
+ } else {
2901
+ properties[key] = { type: "array" };
2902
+ }
2903
+ } else if (typeof value === "object") {
2904
+ properties[key] = inferSchemaFromSample(value);
2905
+ } else if (typeof value === "number") {
2906
+ properties[key] = { type: "number" };
2907
+ } else if (typeof value === "boolean") {
2908
+ properties[key] = { type: "boolean" };
2909
+ } else {
2910
+ properties[key] = { type: "string" };
2911
+ }
2912
+ }
2913
+ return { type: "object", properties };
2914
+ }
2915
+ function collectArrayPaths(schema, prefix, add, depth = 0) {
2916
+ if (!schema || typeof schema !== "object" || depth > 8)
2917
+ return;
2918
+ if (schema.type === "array") {
2919
+ if (prefix) {
2920
+ const itemsType = schema.items?.type;
2921
+ const label = itemsType === "object" ? "array of objects" : "array";
2922
+ add(prefix, `${prefix} (${label})`, `Iterate over "${prefix}"`);
2923
+ }
2924
+ if (schema.items) {
2925
+ collectArrayPaths(schema.items, prefix, add, depth + 1);
2926
+ }
2927
+ return;
2928
+ }
2929
+ if (schema.type === "object" && schema.properties) {
2930
+ for (const [key, child] of Object.entries(schema.properties)) {
2931
+ const next = prefix ? `${prefix}.${key}` : key;
2932
+ collectArrayPaths(child, next, add, depth + 1);
2933
+ }
2934
+ }
2935
+ }
2936
+ function collectArrayPathsFromSample(sample, prefix, add, depth = 0) {
2937
+ if (!sample || typeof sample !== "object" || depth > 8)
2938
+ return;
2939
+ if (Array.isArray(sample)) {
2940
+ if (prefix) {
2941
+ const itemsObj = sample.length > 0 && typeof sample[0] === "object" && sample[0] !== null;
2942
+ const label = itemsObj ? "array of objects" : "array";
2943
+ add(prefix, `${prefix} (${label})`, `Iterate over "${prefix}"`);
2944
+ }
2945
+ if (sample.length > 0) {
2946
+ collectArrayPathsFromSample(sample[0], prefix, add, depth + 1);
2947
+ }
2948
+ return;
2949
+ }
2950
+ for (const [key, value] of Object.entries(sample)) {
2951
+ const next = prefix ? `${prefix}.${key}` : key;
2952
+ collectArrayPathsFromSample(value, next, add, depth + 1);
2953
+ }
2954
+ }
2955
+ function buildPathOptions(upstreamNodes) {
2956
+ const paths = [];
2957
+ const seen = new Set;
2958
+ const add = (id, text, description) => {
2959
+ if (seen.has(id))
2960
+ return;
2961
+ seen.add(id);
2962
+ paths.push({ id, text, description });
2963
+ };
2964
+ if (upstreamNodes) {
2965
+ for (const node of upstreamNodes) {
2966
+ const label = node.label || node.type || "Upstream";
2967
+ const queryTable = node.config?.visualConfig?.tables?.[0];
2968
+ add("data", queryTable ? `${queryTable} (${label})` : `All records (${label})`, queryTable ? `Iterate over every ${queryTable} record` : "Iterate over every record from upstream");
2969
+ const schema = node.outputSchema || node.config?._outputSchema;
2970
+ if (schema)
2971
+ collectArrayPaths(schema, "", add);
2972
+ const output = node.executionData?.output;
2973
+ if (output) {
2974
+ const records = Array.isArray(output.data) ? output.data : Array.isArray(output) ? output : null;
2975
+ if (records && records.length > 0 && typeof records[0] === "object") {
2976
+ collectArrayPathsFromSample(records[0], "", add);
2977
+ }
2978
+ }
2979
+ }
2980
+ }
2981
+ if (paths.length === 0) {
2982
+ add("data", "data (upstream output)");
2983
+ }
2984
+ return paths;
2985
+ }
2986
+ export {
2987
+ ActionCategory,
2988
+ ActionStatus,
2989
+ ActionType,
2990
+ CONDITION_OPERATORS,
2991
+ FieldType,
2992
+ actionsRegistry,
2993
+ buildPathOptions,
2994
+ collectArrayPaths,
2995
+ collectArrayPathsFromSample,
2996
+ generateEdgeId,
2997
+ generateStepId,
2998
+ generateUUIDv4,
2999
+ generateWorkflowId,
3000
+ getActionById,
3001
+ getActionsByCategory,
3002
+ getAllActions,
3003
+ getEdgeValidationStatus,
3004
+ getNodeConfigStatus,
3005
+ getNodeValidationStatus,
3006
+ inferSchemaFromSample,
3007
+ validateEdge,
3008
+ validateNode,
3009
+ validateWorkflow
3010
+ };