@octaviaflow/flow-rules 0.1.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.
- package/README.md +96 -0
- package/dist/catalog/actions/console-log/config.d.ts +58 -0
- package/dist/catalog/actions/console-log/config.js +70 -0
- package/dist/catalog/actions/console-log/index.d.ts +7 -0
- package/dist/catalog/actions/console-log/index.js +89 -0
- package/dist/catalog/actions/delay/config.d.ts +50 -0
- package/dist/catalog/actions/delay/config.js +79 -0
- package/dist/catalog/actions/delay/index.d.ts +7 -0
- package/dist/catalog/actions/delay/index.js +71 -0
- package/dist/catalog/actions/delay/migrate.d.ts +18 -0
- package/dist/catalog/actions/delay/migrate.js +38 -0
- package/dist/catalog/actions/delay/types.d.ts +58 -0
- package/dist/catalog/actions/delay/types.js +17 -0
- package/dist/catalog/actions/http-request/config.d.ts +114 -0
- package/dist/catalog/actions/http-request/config.js +111 -0
- package/dist/catalog/actions/http-request/index.d.ts +7 -0
- package/dist/catalog/actions/http-request/index.js +223 -0
- package/dist/catalog/ai/ai-agent/index.d.ts +12 -0
- package/dist/catalog/ai/ai-agent/index.js +72 -0
- package/dist/catalog/ai/idp-extract/index.d.ts +18 -0
- package/dist/catalog/ai/idp-extract/index.js +90 -0
- package/dist/catalog/api/graphql-query/config.d.ts +36 -0
- package/dist/catalog/api/graphql-query/config.js +31 -0
- package/dist/catalog/api/graphql-query/index.d.ts +7 -0
- package/dist/catalog/api/graphql-query/index.js +75 -0
- package/dist/catalog/communication/email-send/config.d.ts +80 -0
- package/dist/catalog/communication/email-send/config.js +80 -0
- package/dist/catalog/communication/email-send/index.d.ts +11 -0
- package/dist/catalog/communication/email-send/index.js +152 -0
- package/dist/catalog/communication/google-chat/config.d.ts +45 -0
- package/dist/catalog/communication/google-chat/config.js +28 -0
- package/dist/catalog/communication/google-chat/index.d.ts +5 -0
- package/dist/catalog/communication/google-chat/index.js +36 -0
- package/dist/catalog/communication/slack-message/config.d.ts +47 -0
- package/dist/catalog/communication/slack-message/config.js +36 -0
- package/dist/catalog/communication/slack-message/index.d.ts +5 -0
- package/dist/catalog/communication/slack-message/index.js +37 -0
- package/dist/catalog/communication/teams-message/config.d.ts +48 -0
- package/dist/catalog/communication/teams-message/config.js +29 -0
- package/dist/catalog/communication/teams-message/index.d.ts +5 -0
- package/dist/catalog/communication/teams-message/index.js +39 -0
- package/dist/catalog/communication/webhook-call/config.d.ts +36 -0
- package/dist/catalog/communication/webhook-call/config.js +31 -0
- package/dist/catalog/communication/webhook-call/index.d.ts +5 -0
- package/dist/catalog/communication/webhook-call/index.js +43 -0
- package/dist/catalog/communication/whatsapp-send/config.d.ts +23 -0
- package/dist/catalog/communication/whatsapp-send/config.js +36 -0
- package/dist/catalog/communication/whatsapp-send/index.d.ts +15 -0
- package/dist/catalog/communication/whatsapp-send/index.js +57 -0
- package/dist/catalog/general/query/config.d.ts +36 -0
- package/dist/catalog/general/query/config.js +257 -0
- package/dist/catalog/general/query/index.d.ts +11 -0
- package/dist/catalog/general/query/index.js +271 -0
- package/dist/catalog/general/query/types.d.ts +205 -0
- package/dist/catalog/general/query/types.js +82 -0
- package/dist/catalog/general/transform/config.d.ts +117 -0
- package/dist/catalog/general/transform/config.js +95 -0
- package/dist/catalog/general/transform/index.d.ts +8 -0
- package/dist/catalog/general/transform/index.js +63 -0
- package/dist/catalog/index.d.ts +57 -0
- package/dist/catalog/index.js +168 -0
- package/dist/catalog/logic/condition/config.d.ts +54 -0
- package/dist/catalog/logic/condition/config.js +93 -0
- package/dist/catalog/logic/condition/index.d.ts +7 -0
- package/dist/catalog/logic/condition/index.js +64 -0
- package/dist/catalog/logic/for-each/config.d.ts +100 -0
- package/dist/catalog/logic/for-each/config.js +75 -0
- package/dist/catalog/logic/for-each/index.d.ts +7 -0
- package/dist/catalog/logic/for-each/index.js +92 -0
- package/dist/catalog/logic/for-each/pathOptions.d.ts +62 -0
- package/dist/catalog/logic/for-each/pathOptions.js +151 -0
- package/dist/catalog/logic/group/index.d.ts +15 -0
- package/dist/catalog/logic/group/index.js +46 -0
- package/dist/catalog/policies.d.ts +75 -0
- package/dist/catalog/policies.js +62 -0
- package/dist/catalog/storage/csv-action/index.d.ts +2 -0
- package/dist/catalog/storage/csv-action/index.js +38 -0
- package/dist/catalog/storage/dropbox-action/index.d.ts +2 -0
- package/dist/catalog/storage/dropbox-action/index.js +33 -0
- package/dist/catalog/storage/excel-action/index.d.ts +2 -0
- package/dist/catalog/storage/excel-action/index.js +32 -0
- package/dist/catalog/storage/file-action/index.d.ts +2 -0
- package/dist/catalog/storage/file-action/index.js +119 -0
- package/dist/catalog/storage/file-operation/config.d.ts +48 -0
- package/dist/catalog/storage/file-operation/config.js +45 -0
- package/dist/catalog/storage/file-operation/index.d.ts +8 -0
- package/dist/catalog/storage/file-operation/index.js +111 -0
- package/dist/catalog/storage/ftp-action/index.d.ts +2 -0
- package/dist/catalog/storage/ftp-action/index.js +33 -0
- package/dist/catalog/storage/google-drive-action/index.d.ts +2 -0
- package/dist/catalog/storage/google-drive-action/index.js +38 -0
- package/dist/catalog/storage/json-action/index.d.ts +2 -0
- package/dist/catalog/storage/json-action/index.js +31 -0
- package/dist/catalog/storage/onedrive-action/index.d.ts +2 -0
- package/dist/catalog/storage/onedrive-action/index.js +33 -0
- package/dist/catalog/storage/s3-action/index.d.ts +2 -0
- package/dist/catalog/storage/s3-action/index.js +36 -0
- package/dist/catalog/storage/storage-action/index.d.ts +13 -0
- package/dist/catalog/storage/storage-action/index.js +72 -0
- package/dist/catalog/storage/storageCapabilities.d.ts +57 -0
- package/dist/catalog/storage/storageCapabilities.js +207 -0
- package/dist/catalog/storage/xml-action/index.d.ts +2 -0
- package/dist/catalog/storage/xml-action/index.js +31 -0
- package/dist/catalog/transforms/format/config.d.ts +23 -0
- package/dist/catalog/transforms/format/config.js +19 -0
- package/dist/catalog/transforms/format/index.d.ts +5 -0
- package/dist/catalog/transforms/format/index.js +39 -0
- package/dist/catalog/triggers/connector-trigger/index.d.ts +7 -0
- package/dist/catalog/triggers/connector-trigger/index.js +72 -0
- package/dist/catalog/triggers/manual-trigger/config.d.ts +40 -0
- package/dist/catalog/triggers/manual-trigger/config.js +60 -0
- package/dist/catalog/triggers/manual-trigger/index.d.ts +10 -0
- package/dist/catalog/triggers/manual-trigger/index.js +74 -0
- package/dist/catalog/triggers/schedule-trigger/config.d.ts +42 -0
- package/dist/catalog/triggers/schedule-trigger/config.js +42 -0
- package/dist/catalog/triggers/schedule-trigger/index.d.ts +7 -0
- package/dist/catalog/triggers/schedule-trigger/index.js +102 -0
- package/dist/catalog/triggers/webhook-trigger/config.d.ts +31 -0
- package/dist/catalog/triggers/webhook-trigger/config.js +27 -0
- package/dist/catalog/triggers/webhook-trigger/index.d.ts +7 -0
- package/dist/catalog/triggers/webhook-trigger/index.js +89 -0
- package/dist/catalog/types.d.ts +360 -0
- package/dist/catalog/types.js +135 -0
- package/dist/catalog/utility/debug/config.d.ts +72 -0
- package/dist/catalog/utility/debug/config.js +90 -0
- package/dist/catalog/utility/debug/index.d.ts +11 -0
- package/dist/catalog/utility/debug/index.js +38 -0
- package/dist/catalog/utility/error/config.d.ts +26 -0
- package/dist/catalog/utility/error/config.js +25 -0
- package/dist/catalog/utility/error/index.d.ts +7 -0
- package/dist/catalog/utility/error/index.js +46 -0
- package/dist/catalog/utility/variables/config.d.ts +76 -0
- package/dist/catalog/utility/variables/config.js +70 -0
- package/dist/catalog/utility/variables/index.d.ts +13 -0
- package/dist/catalog/utility/variables/index.js +40 -0
- package/dist/catalog/workflow.d.ts +308 -0
- package/dist/catalog/workflow.js +25 -0
- package/dist/ids.d.ts +31 -0
- package/dist/ids.js +53 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +28 -0
- package/dist/rules/nodeConfigStatus.d.ts +33 -0
- package/dist/rules/nodeConfigStatus.js +217 -0
- package/dist/rules/workflowValidator.d.ts +53 -0
- package/dist/rules/workflowValidator.js +358 -0
- package/package.json +41 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Actions Registry
|
|
3
|
+
*
|
|
4
|
+
* Central registry for all built-in actions
|
|
5
|
+
* Each action is self-contained with its own configuration, UI, and metadata
|
|
6
|
+
*/
|
|
7
|
+
import { ActionCategory } from './types';
|
|
8
|
+
// Trigger actions
|
|
9
|
+
import { manualTriggerDefinition } from './triggers/manual-trigger';
|
|
10
|
+
import { scheduleTriggerDefinition } from './triggers/schedule-trigger';
|
|
11
|
+
import { webhookTriggerDefinition } from './triggers/webhook-trigger';
|
|
12
|
+
import { connectorTriggerDefinition } from './triggers/connector-trigger';
|
|
13
|
+
// Action actions
|
|
14
|
+
import { httpRequestDefinition } from './actions/http-request';
|
|
15
|
+
import { consoleLogDefinition } from './actions/console-log';
|
|
16
|
+
import { delayDefinition } from './actions/delay';
|
|
17
|
+
// Logic actions
|
|
18
|
+
import { conditionDefinition } from './logic/condition';
|
|
19
|
+
import { forEachDefinition } from './logic/for-each';
|
|
20
|
+
import { groupDefinition } from './logic/group';
|
|
21
|
+
// Transform actions
|
|
22
|
+
// General actions (work across all platforms)
|
|
23
|
+
import { queryDefinition } from './general/query';
|
|
24
|
+
import { transformDefinition } from './general/transform';
|
|
25
|
+
// `data_replication` was removed — it now lives as its own platform
|
|
26
|
+
//. Workflows
|
|
27
|
+
// that referenced it will fail with `unknown_action_type`; there is
|
|
28
|
+
// no in-place migration by design.
|
|
29
|
+
// Storage / File actions
|
|
30
|
+
import { csvActionDefinition } from './storage/csv-action';
|
|
31
|
+
import { jsonActionDefinition } from './storage/json-action';
|
|
32
|
+
import { xmlActionDefinition } from './storage/xml-action';
|
|
33
|
+
import { excelActionDefinition } from './storage/excel-action';
|
|
34
|
+
import { s3ActionDefinition } from './storage/s3-action';
|
|
35
|
+
import { ftpActionDefinition } from './storage/ftp-action';
|
|
36
|
+
import { googleDriveActionDefinition } from './storage/google-drive-action';
|
|
37
|
+
import { dropboxActionDefinition } from './storage/dropbox-action';
|
|
38
|
+
import { onedriveActionDefinition } from './storage/onedrive-action';
|
|
39
|
+
import { storageActionDefinition } from './storage/storage-action';
|
|
40
|
+
// Communication actions
|
|
41
|
+
import { emailDefinition } from './communication/email-send';
|
|
42
|
+
import { slackMessageDefinition } from './communication/slack-message';
|
|
43
|
+
import { whatsappSendDefinition } from './communication/whatsapp-send';
|
|
44
|
+
import { teamsMessageDefinition } from './communication/teams-message';
|
|
45
|
+
import { googleChatDefinition } from './communication/google-chat';
|
|
46
|
+
import { webhookCallDefinition } from './communication/webhook-call';
|
|
47
|
+
// Utility actions
|
|
48
|
+
import { debugDefinition } from './utility/debug';
|
|
49
|
+
import { errorDefinition } from './utility/error';
|
|
50
|
+
import { variablesDefinition } from './utility/variables';
|
|
51
|
+
// API actions
|
|
52
|
+
import { graphqlQueryDefinition } from './api/graphql-query';
|
|
53
|
+
// AI actions
|
|
54
|
+
//
|
|
55
|
+
// The only generic AI workflow action is `ai_agent` — a first-class Agent
|
|
56
|
+
// reference (DEV-85, see the platform documentation).
|
|
57
|
+
// The legacy `llm_chat` action was removed in DEV-93; any workflows that
|
|
58
|
+
// referenced it fail with `unknown_action_type` (no migration, per user direction).
|
|
59
|
+
//
|
|
60
|
+
// Other removals (DEV-14 reshape):
|
|
61
|
+
// - llm_completion, classification, sentiment, summarization, translation,
|
|
62
|
+
// extraction, ml_inference — prompt-template wrappers with no engine impl.
|
|
63
|
+
// - embedding, vector_search — replaced by the Knowledge Bases app (DEV-16).
|
|
64
|
+
// - image_analysis, image_generation, speech_to_text, text_to_speech —
|
|
65
|
+
// niche; users hit the provider through HTTP Request.
|
|
66
|
+
//
|
|
67
|
+
// Document parsing belongs to the IDP app,
|
|
68
|
+
// not a workflow action — except for `idp_extract` which orchestrates the IDP
|
|
69
|
+
// service from inside a workflow.
|
|
70
|
+
import { aiAgentDefinition } from './ai/ai-agent';
|
|
71
|
+
import { idpExtractDefinition } from './ai/idp-extract';
|
|
72
|
+
/**
|
|
73
|
+
* Registry of all available actions
|
|
74
|
+
* Organized by category for easy lookup and management
|
|
75
|
+
*/
|
|
76
|
+
export const actionsRegistry = {
|
|
77
|
+
[ActionCategory.Trigger]: {
|
|
78
|
+
manual_trigger: manualTriggerDefinition,
|
|
79
|
+
schedule_trigger: scheduleTriggerDefinition,
|
|
80
|
+
webhook_trigger: webhookTriggerDefinition,
|
|
81
|
+
connector_trigger: connectorTriggerDefinition,
|
|
82
|
+
},
|
|
83
|
+
[ActionCategory.Action]: {
|
|
84
|
+
http_request: httpRequestDefinition,
|
|
85
|
+
console_log: consoleLogDefinition,
|
|
86
|
+
delay: delayDefinition,
|
|
87
|
+
query: queryDefinition,
|
|
88
|
+
transform: transformDefinition,
|
|
89
|
+
},
|
|
90
|
+
[ActionCategory.Logic]: {
|
|
91
|
+
condition: conditionDefinition,
|
|
92
|
+
for_each: forEachDefinition,
|
|
93
|
+
group: groupDefinition,
|
|
94
|
+
},
|
|
95
|
+
[ActionCategory.Transform]: {
|
|
96
|
+
// Format action will be added when implemented
|
|
97
|
+
},
|
|
98
|
+
[ActionCategory.Database]: {},
|
|
99
|
+
[ActionCategory.Storage]: {
|
|
100
|
+
csv_action: csvActionDefinition,
|
|
101
|
+
json_action: jsonActionDefinition,
|
|
102
|
+
excel_action: excelActionDefinition,
|
|
103
|
+
xml_action: xmlActionDefinition,
|
|
104
|
+
// Unified Cloud Storage action — the one users add. The five per-provider
|
|
105
|
+
// actions below are kept registered (so existing nodes still resolve +
|
|
106
|
+
// edit + execute) but marked deprecated → hidden from the add-palette.
|
|
107
|
+
storage_action: storageActionDefinition,
|
|
108
|
+
s3_action: { ...s3ActionDefinition, deprecated: true, replacedBy: 'storage_action' },
|
|
109
|
+
ftp_action: { ...ftpActionDefinition, deprecated: true, replacedBy: 'storage_action' },
|
|
110
|
+
google_drive_action: { ...googleDriveActionDefinition, deprecated: true, replacedBy: 'storage_action' },
|
|
111
|
+
dropbox_action: { ...dropboxActionDefinition, deprecated: true, replacedBy: 'storage_action' },
|
|
112
|
+
onedrive_action: { ...onedriveActionDefinition, deprecated: true, replacedBy: 'storage_action' },
|
|
113
|
+
},
|
|
114
|
+
[ActionCategory.Communication]: {
|
|
115
|
+
email: emailDefinition,
|
|
116
|
+
slack_message: slackMessageDefinition,
|
|
117
|
+
whatsapp_send: whatsappSendDefinition,
|
|
118
|
+
teams_message: teamsMessageDefinition,
|
|
119
|
+
google_chat: googleChatDefinition,
|
|
120
|
+
webhook_call: webhookCallDefinition,
|
|
121
|
+
},
|
|
122
|
+
[ActionCategory.Utility]: {
|
|
123
|
+
variables: variablesDefinition,
|
|
124
|
+
debug: debugDefinition,
|
|
125
|
+
},
|
|
126
|
+
[ActionCategory.Ecommerce]: {},
|
|
127
|
+
[ActionCategory.API]: {
|
|
128
|
+
// GraphQL action will be added when implemented
|
|
129
|
+
},
|
|
130
|
+
[ActionCategory.AI]: {
|
|
131
|
+
ai_agent: aiAgentDefinition,
|
|
132
|
+
idp_extract: idpExtractDefinition,
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
/**
|
|
136
|
+
* Get all actions as a flat array
|
|
137
|
+
*/
|
|
138
|
+
export const getAllActions = () => {
|
|
139
|
+
const allActions = [];
|
|
140
|
+
for (const category of Object.values(actionsRegistry)) {
|
|
141
|
+
allActions.push(...Object.values(category).filter((action) => action !== undefined));
|
|
142
|
+
}
|
|
143
|
+
return allActions;
|
|
144
|
+
};
|
|
145
|
+
/**
|
|
146
|
+
* Get action by ID
|
|
147
|
+
*/
|
|
148
|
+
export const getActionById = (id) => {
|
|
149
|
+
for (const category of Object.values(actionsRegistry)) {
|
|
150
|
+
for (const action of Object.values(category)) {
|
|
151
|
+
if (action.id === id) {
|
|
152
|
+
return action;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return undefined;
|
|
157
|
+
};
|
|
158
|
+
/**
|
|
159
|
+
* Get actions by category
|
|
160
|
+
*/
|
|
161
|
+
export const getActionsByCategory = (category) => {
|
|
162
|
+
const categoryActions = actionsRegistry[category];
|
|
163
|
+
if (!categoryActions)
|
|
164
|
+
return [];
|
|
165
|
+
return Object.values(categoryActions);
|
|
166
|
+
};
|
|
167
|
+
// Export individual action definitions for direct imports
|
|
168
|
+
export { csvActionDefinition, jsonActionDefinition, xmlActionDefinition, excelActionDefinition, s3ActionDefinition, ftpActionDefinition, googleDriveActionDefinition, dropboxActionDefinition, onedriveActionDefinition, manualTriggerDefinition, scheduleTriggerDefinition, webhookTriggerDefinition, httpRequestDefinition, consoleLogDefinition, delayDefinition, conditionDefinition, forEachDefinition, groupDefinition, queryDefinition, transformDefinition, debugDefinition, errorDefinition, variablesDefinition, graphqlQueryDefinition, emailDefinition, slackMessageDefinition, whatsappSendDefinition, teamsMessageDefinition, googleChatDefinition, webhookCallDefinition, aiAgentDefinition, idpExtractDefinition, };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Condition Configuration
|
|
3
|
+
*
|
|
4
|
+
* Defines the configuration structure and default values for the Condition action.
|
|
5
|
+
* Supports two modes:
|
|
6
|
+
* - visual: a list of field/operator/value filter rows joined by AND/OR
|
|
7
|
+
* - expression: a raw JavaScript expression
|
|
8
|
+
*/
|
|
9
|
+
export type ConditionOperator = 'equals' | 'not_equals' | 'greater_than' | 'greater_than_equals' | 'less_than' | 'less_than_equals' | 'like' | 'is_null' | 'is_not_null' | 'is_empty' | 'contains' | 'starts_with' | 'ends_with';
|
|
10
|
+
export declare const CONDITION_OPERATORS: {
|
|
11
|
+
id: ConditionOperator;
|
|
12
|
+
label: string;
|
|
13
|
+
needsValue: boolean;
|
|
14
|
+
}[];
|
|
15
|
+
export interface ConditionFilter {
|
|
16
|
+
id: string;
|
|
17
|
+
field: string;
|
|
18
|
+
operator: ConditionOperator;
|
|
19
|
+
value: string;
|
|
20
|
+
logicalOperator?: 'and' | 'or';
|
|
21
|
+
}
|
|
22
|
+
export interface ConditionConfigType {
|
|
23
|
+
mode: 'visual' | 'expression';
|
|
24
|
+
filters: ConditionFilter[];
|
|
25
|
+
condition: string;
|
|
26
|
+
/** Auto-generated display name for the node */
|
|
27
|
+
name?: string;
|
|
28
|
+
}
|
|
29
|
+
export declare const ConditionConfig: {
|
|
30
|
+
defaults: ConditionConfigType;
|
|
31
|
+
schema: {
|
|
32
|
+
mode: {
|
|
33
|
+
type: string;
|
|
34
|
+
required: boolean;
|
|
35
|
+
};
|
|
36
|
+
filters: {
|
|
37
|
+
type: string;
|
|
38
|
+
required: boolean;
|
|
39
|
+
};
|
|
40
|
+
condition: {
|
|
41
|
+
type: string;
|
|
42
|
+
required: boolean;
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
validate: (config: Partial<ConditionConfigType>) => {
|
|
46
|
+
valid: boolean;
|
|
47
|
+
errors: string[];
|
|
48
|
+
};
|
|
49
|
+
merge: (userConfig: Partial<ConditionConfigType>) => ConditionConfigType;
|
|
50
|
+
/** Build a human-readable summary from visual filters */
|
|
51
|
+
generateName: (filters: ConditionFilter[]) => string;
|
|
52
|
+
getLabel: (config: ConditionConfigType) => string;
|
|
53
|
+
createFilterId: () => string;
|
|
54
|
+
};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Condition Configuration
|
|
3
|
+
*
|
|
4
|
+
* Defines the configuration structure and default values for the Condition action.
|
|
5
|
+
* Supports two modes:
|
|
6
|
+
* - visual: a list of field/operator/value filter rows joined by AND/OR
|
|
7
|
+
* - expression: a raw JavaScript expression
|
|
8
|
+
*/
|
|
9
|
+
import { randomSuffix } from '../../../ids';
|
|
10
|
+
export const CONDITION_OPERATORS = [
|
|
11
|
+
{ id: 'equals', label: 'Equals', needsValue: true },
|
|
12
|
+
{ id: 'not_equals', label: 'Not Equals', needsValue: true },
|
|
13
|
+
{ id: 'greater_than', label: 'Greater Than', needsValue: true },
|
|
14
|
+
{ id: 'greater_than_equals', label: 'Greater Than or Equals', needsValue: true },
|
|
15
|
+
{ id: 'less_than', label: 'Less Than', needsValue: true },
|
|
16
|
+
{ id: 'less_than_equals', label: 'Less Than or Equals', needsValue: true },
|
|
17
|
+
{ id: 'like', label: 'Like', needsValue: true },
|
|
18
|
+
{ id: 'contains', label: 'Contains', needsValue: true },
|
|
19
|
+
{ id: 'starts_with', label: 'Starts With', needsValue: true },
|
|
20
|
+
{ id: 'ends_with', label: 'Ends With', needsValue: true },
|
|
21
|
+
{ id: 'is_null', label: 'Is Null', needsValue: false },
|
|
22
|
+
{ id: 'is_not_null', label: 'Is Not Null', needsValue: false },
|
|
23
|
+
{ id: 'is_empty', label: 'Is Empty', needsValue: false },
|
|
24
|
+
];
|
|
25
|
+
export const ConditionConfig = {
|
|
26
|
+
defaults: {
|
|
27
|
+
mode: 'visual',
|
|
28
|
+
filters: [],
|
|
29
|
+
condition: '',
|
|
30
|
+
},
|
|
31
|
+
schema: {
|
|
32
|
+
mode: { type: 'select', required: true },
|
|
33
|
+
filters: { type: 'array', required: false },
|
|
34
|
+
condition: { type: 'expression', required: false },
|
|
35
|
+
},
|
|
36
|
+
validate: (config) => {
|
|
37
|
+
const errors = [];
|
|
38
|
+
if (config.mode === 'expression') {
|
|
39
|
+
if (!config.condition) {
|
|
40
|
+
errors.push('Condition expression is required');
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
try {
|
|
44
|
+
new Function(`return ${config.condition}`);
|
|
45
|
+
}
|
|
46
|
+
catch (e) {
|
|
47
|
+
errors.push(`Invalid expression: ${e instanceof Error ? e.message : 'Unknown error'}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
// Visual mode
|
|
53
|
+
if (!config.filters || config.filters.length === 0) {
|
|
54
|
+
errors.push('At least one condition filter is required');
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
config.filters.forEach((f, i) => {
|
|
58
|
+
if (!f.field)
|
|
59
|
+
errors.push(`Filter ${i + 1}: Field is required`);
|
|
60
|
+
if (!f.operator)
|
|
61
|
+
errors.push(`Filter ${i + 1}: Operator is required`);
|
|
62
|
+
const opDef = CONDITION_OPERATORS.find(o => o.id === f.operator);
|
|
63
|
+
if (opDef?.needsValue && !f.value) {
|
|
64
|
+
errors.push(`Filter ${i + 1}: Value is required`);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return { valid: errors.length === 0, errors };
|
|
70
|
+
},
|
|
71
|
+
merge: (userConfig) => {
|
|
72
|
+
return { ...ConditionConfig.defaults, ...userConfig };
|
|
73
|
+
},
|
|
74
|
+
/** Build a human-readable summary from visual filters */
|
|
75
|
+
generateName: (filters) => {
|
|
76
|
+
if (filters.length === 0)
|
|
77
|
+
return 'If …';
|
|
78
|
+
const parts = filters.map((f, i) => {
|
|
79
|
+
const opLabel = CONDITION_OPERATORS.find(o => o.id === f.operator)?.label || f.operator;
|
|
80
|
+
const base = `${f.field || '?'} ${opLabel}${f.value ? ` ${f.value}` : ''}`;
|
|
81
|
+
if (i === 0)
|
|
82
|
+
return base;
|
|
83
|
+
return `${(f.logicalOperator || 'and').toUpperCase()} ${base}`;
|
|
84
|
+
});
|
|
85
|
+
return `If ${parts.join(' ')}`;
|
|
86
|
+
},
|
|
87
|
+
getLabel: (config) => {
|
|
88
|
+
if (config.mode === 'expression')
|
|
89
|
+
return `If ${config.condition || '…'}`;
|
|
90
|
+
return ConditionConfig.generateName(config.filters);
|
|
91
|
+
},
|
|
92
|
+
createFilterId: () => `cond_${Date.now()}_${randomSuffix(5)}`,
|
|
93
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Condition Action
|
|
3
|
+
*
|
|
4
|
+
* Branch workflow execution based on conditions
|
|
5
|
+
*/
|
|
6
|
+
import { ActionCategory, ActionType, ActionStatus, FieldType } from '../../types';
|
|
7
|
+
export const conditionDefinition = {
|
|
8
|
+
id: 'condition',
|
|
9
|
+
name: 'Condition',
|
|
10
|
+
description: 'Branch workflow execution based on conditions',
|
|
11
|
+
category: ActionCategory.Logic,
|
|
12
|
+
type: ActionType.Condition,
|
|
13
|
+
tags: ['logic', 'condition', 'branching', 'built-in'],
|
|
14
|
+
status: ActionStatus.Stable,
|
|
15
|
+
icon: 'DecisionTree',
|
|
16
|
+
color: '#f1c21b',
|
|
17
|
+
// NOTE: the Condition node renders via its custom ConditionConfigPanel
|
|
18
|
+
// (visual builder only), so these fallback fields aren't shown in the
|
|
19
|
+
// editor. Kept minimal + consistent with the visual-only authoring model.
|
|
20
|
+
inputSchema: {
|
|
21
|
+
fields: [
|
|
22
|
+
{
|
|
23
|
+
key: 'mode',
|
|
24
|
+
label: 'Mode',
|
|
25
|
+
type: FieldType.String,
|
|
26
|
+
description: 'Authoring mode (visual builder).',
|
|
27
|
+
defaultValue: 'visual',
|
|
28
|
+
validation: { required: true },
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
key: 'filters',
|
|
32
|
+
label: 'Condition Filters',
|
|
33
|
+
type: FieldType.Array,
|
|
34
|
+
description: 'Visual condition filters (field / operator / value rows)',
|
|
35
|
+
validation: { required: false },
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
},
|
|
39
|
+
outputSchema: {
|
|
40
|
+
type: 'object',
|
|
41
|
+
properties: [
|
|
42
|
+
{
|
|
43
|
+
key: 'result',
|
|
44
|
+
type: FieldType.Boolean,
|
|
45
|
+
description: 'Result of the condition evaluation',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
key: 'branch',
|
|
49
|
+
type: FieldType.String,
|
|
50
|
+
description: 'Which branch was taken (true or false)',
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
sampleOutput: {
|
|
54
|
+
result: true,
|
|
55
|
+
branch: 'true',
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
version: '1.0.0',
|
|
59
|
+
createdAt: '2025-01-01T00:00:00Z',
|
|
60
|
+
updatedAt: '2025-12-15T00:00:00Z',
|
|
61
|
+
createdBy: 'system',
|
|
62
|
+
isOfficial: true,
|
|
63
|
+
testable: true,
|
|
64
|
+
};
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ForEach Configuration
|
|
3
|
+
*
|
|
4
|
+
* A general, mode-based iteration primitive for ETL + agentic-ETL flows.
|
|
5
|
+
* The iteration mode is the core config axis; execution, resilience and
|
|
6
|
+
* output controls layer on top of any mode.
|
|
7
|
+
*/
|
|
8
|
+
export type ForEachMode = 'records' | 'fields' | 'range' | 'nested' | 'batch' | 'cursor' | 'while' | 'array';
|
|
9
|
+
export interface ForEachConfigType {
|
|
10
|
+
/** Variable name exposed for each item (default: "item"). */
|
|
11
|
+
itemVariable: string;
|
|
12
|
+
/** Variable name exposed for the index (default: "index"). */
|
|
13
|
+
indexVariable: string;
|
|
14
|
+
/** Dot-path to the array in upstream data (e.g. "Account", "data.items"). */
|
|
15
|
+
arrayPath: string;
|
|
16
|
+
/** What to iterate over. Defaults to 'records'. */
|
|
17
|
+
iterationMode?: ForEachMode;
|
|
18
|
+
/** range mode — number of iterations (0..count-1). */
|
|
19
|
+
count?: number;
|
|
20
|
+
/** nested mode — dot-path to the sub-array inside each record. */
|
|
21
|
+
nestedPath?: string;
|
|
22
|
+
/** fields mode — allow-list of field names. Empty/absent → every field. */
|
|
23
|
+
fields?: string[];
|
|
24
|
+
/** sequential (default) or parallel. */
|
|
25
|
+
concurrency?: 'sequential' | 'parallel';
|
|
26
|
+
/** parallel cap (default 5). Never unbounded. */
|
|
27
|
+
maxConcurrency?: number;
|
|
28
|
+
/** batch mode — chunk size. */
|
|
29
|
+
batchSize: number;
|
|
30
|
+
/** throttle: max iteration launches per minute. */
|
|
31
|
+
rateLimitPerMinute?: number;
|
|
32
|
+
/** agentic throttle: max estimated tokens per minute. */
|
|
33
|
+
tokensPerMinute?: number;
|
|
34
|
+
/** continue past per-item failures (maps to onItemError: 'continue'). */
|
|
35
|
+
continueOnError: boolean;
|
|
36
|
+
/** explicit per-item failure policy (overrides continueOnError when set). */
|
|
37
|
+
onItemError?: 'fail-fast' | 'continue';
|
|
38
|
+
/** per-item retries (default 0). */
|
|
39
|
+
retryCount?: number;
|
|
40
|
+
/** base backoff between retries, doubled each attempt (default 250ms). */
|
|
41
|
+
retryBackoffMs?: number;
|
|
42
|
+
/** per-item timeout in ms (0/absent = none). */
|
|
43
|
+
itemTimeoutMs?: number;
|
|
44
|
+
/** abort once failed/processed exceeds this % (0-100). */
|
|
45
|
+
toleratedFailurePercentage?: number;
|
|
46
|
+
/** abort once this many items have failed. */
|
|
47
|
+
toleratedFailureCount?: number;
|
|
48
|
+
/** hard runaway cap for cursor/while (default 10000). */
|
|
49
|
+
maxIterations?: number;
|
|
50
|
+
/** dot-path on each item; items whose key was already seen are skipped. */
|
|
51
|
+
idempotencyKeyPath?: string;
|
|
52
|
+
/** how per-item results are collected (default 'array'). */
|
|
53
|
+
collect?: 'array' | 'none' | 'groupBy' | 'reduce';
|
|
54
|
+
/** groupBy — dot-path on each result used as the group key. */
|
|
55
|
+
groupByPath?: string;
|
|
56
|
+
/** reduce — built-in reduction over successful results. */
|
|
57
|
+
reduceOp?: 'sum' | 'count' | 'concat' | 'merge';
|
|
58
|
+
/** reduce — dot-path on each result to feed the reduction. */
|
|
59
|
+
reducePath?: string;
|
|
60
|
+
/** Per-item source schema captured for the FieldMapper (records/fields modes). */
|
|
61
|
+
_outputSchema?: unknown;
|
|
62
|
+
/** Auto-generated display name for the node. */
|
|
63
|
+
name?: string;
|
|
64
|
+
}
|
|
65
|
+
export declare const ForEachConfig: {
|
|
66
|
+
defaults: ForEachConfigType;
|
|
67
|
+
schema: {
|
|
68
|
+
arrayPath: {
|
|
69
|
+
type: string;
|
|
70
|
+
required: boolean;
|
|
71
|
+
};
|
|
72
|
+
iterationMode: {
|
|
73
|
+
type: string;
|
|
74
|
+
required: boolean;
|
|
75
|
+
};
|
|
76
|
+
itemVariable: {
|
|
77
|
+
type: string;
|
|
78
|
+
required: boolean;
|
|
79
|
+
};
|
|
80
|
+
indexVariable: {
|
|
81
|
+
type: string;
|
|
82
|
+
required: boolean;
|
|
83
|
+
};
|
|
84
|
+
batchSize: {
|
|
85
|
+
type: string;
|
|
86
|
+
required: boolean;
|
|
87
|
+
};
|
|
88
|
+
continueOnError: {
|
|
89
|
+
type: string;
|
|
90
|
+
required: boolean;
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
validate: (config: Partial<ForEachConfigType>) => {
|
|
94
|
+
valid: boolean;
|
|
95
|
+
errors: string[];
|
|
96
|
+
};
|
|
97
|
+
merge: (userConfig: Partial<ForEachConfigType>) => ForEachConfigType;
|
|
98
|
+
getLabel: (config: ForEachConfigType) => string;
|
|
99
|
+
generateName: (arrayPath: string) => string;
|
|
100
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ForEach Configuration
|
|
3
|
+
*
|
|
4
|
+
* A general, mode-based iteration primitive for ETL + agentic-ETL flows.
|
|
5
|
+
* The iteration mode is the core config axis; execution, resilience and
|
|
6
|
+
* output controls layer on top of any mode.
|
|
7
|
+
*/
|
|
8
|
+
/** Modes that don't iterate an upstream array (no arrayPath required). */
|
|
9
|
+
const SOURCELESS_MODES = new Set(['range', 'cursor', 'while']);
|
|
10
|
+
export const ForEachConfig = {
|
|
11
|
+
defaults: {
|
|
12
|
+
arrayPath: '',
|
|
13
|
+
iterationMode: 'records',
|
|
14
|
+
itemVariable: 'item',
|
|
15
|
+
indexVariable: 'index',
|
|
16
|
+
batchSize: 0,
|
|
17
|
+
continueOnError: false,
|
|
18
|
+
concurrency: 'sequential',
|
|
19
|
+
collect: 'array',
|
|
20
|
+
},
|
|
21
|
+
schema: {
|
|
22
|
+
arrayPath: { type: 'select', required: false },
|
|
23
|
+
iterationMode: { type: 'select', required: false },
|
|
24
|
+
itemVariable: { type: 'string', required: true },
|
|
25
|
+
indexVariable: { type: 'string', required: false },
|
|
26
|
+
batchSize: { type: 'number', required: false },
|
|
27
|
+
continueOnError: { type: 'boolean', required: false },
|
|
28
|
+
},
|
|
29
|
+
validate: (config) => {
|
|
30
|
+
const errors = [];
|
|
31
|
+
const mode = (config.iterationMode || 'records');
|
|
32
|
+
if (mode === 'range') {
|
|
33
|
+
if (!config.count || config.count <= 0) {
|
|
34
|
+
errors.push('Range mode needs a positive iteration count');
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
else if (mode === 'nested') {
|
|
38
|
+
if (!config.arrayPath)
|
|
39
|
+
errors.push('Select the records to drill into');
|
|
40
|
+
if (!config.nestedPath)
|
|
41
|
+
errors.push('Nested mode needs the sub-array path to iterate (e.g. "lineItems")');
|
|
42
|
+
}
|
|
43
|
+
else if (!SOURCELESS_MODES.has(mode)) {
|
|
44
|
+
if (!config.arrayPath) {
|
|
45
|
+
errors.push('Array path is required — select which records to iterate over');
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (config.concurrency === 'parallel' && config.maxConcurrency !== undefined && config.maxConcurrency < 1) {
|
|
49
|
+
errors.push('Max concurrency must be at least 1');
|
|
50
|
+
}
|
|
51
|
+
if (config.batchSize !== undefined && config.batchSize < 0) {
|
|
52
|
+
errors.push('Batch size must be 0 (all) or a positive number');
|
|
53
|
+
}
|
|
54
|
+
if (config.collect === 'groupBy' && !config.groupByPath) {
|
|
55
|
+
errors.push('Group-by collection needs a field path to group on');
|
|
56
|
+
}
|
|
57
|
+
return { valid: errors.length === 0, errors };
|
|
58
|
+
},
|
|
59
|
+
merge: (userConfig) => {
|
|
60
|
+
return { ...ForEachConfig.defaults, ...userConfig };
|
|
61
|
+
},
|
|
62
|
+
getLabel: (config) => {
|
|
63
|
+
const mode = (config.iterationMode || 'records');
|
|
64
|
+
if (mode === 'range')
|
|
65
|
+
return `ForEach ×${config.count ?? '…'}`;
|
|
66
|
+
if (mode === 'cursor')
|
|
67
|
+
return 'ForEach (paginate)';
|
|
68
|
+
if (mode === 'while')
|
|
69
|
+
return 'ForEach (while)';
|
|
70
|
+
return `ForEach in ${config.arrayPath || '…'}`;
|
|
71
|
+
},
|
|
72
|
+
generateName: (arrayPath) => {
|
|
73
|
+
return `ForEach in ${arrayPath || '…'}`;
|
|
74
|
+
},
|
|
75
|
+
};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ForEach Action
|
|
3
|
+
*
|
|
4
|
+
* Iterate over array items and execute actions for each
|
|
5
|
+
*/
|
|
6
|
+
import { ActionCategory, ActionType, ActionStatus, FieldType } from '../../types';
|
|
7
|
+
export const forEachDefinition = {
|
|
8
|
+
id: 'for_each',
|
|
9
|
+
name: 'ForEach',
|
|
10
|
+
description: 'Iterate over array items and execute actions for each',
|
|
11
|
+
category: ActionCategory.Logic,
|
|
12
|
+
type: ActionType.ForEach,
|
|
13
|
+
tags: ['logic', 'loop', 'iteration', 'array', 'built-in'],
|
|
14
|
+
status: ActionStatus.Stable,
|
|
15
|
+
icon: 'Repeat',
|
|
16
|
+
color: '#f1c21b',
|
|
17
|
+
inputSchema: {
|
|
18
|
+
fields: [
|
|
19
|
+
{
|
|
20
|
+
key: 'arrayPath',
|
|
21
|
+
label: 'Records in',
|
|
22
|
+
type: FieldType.Expression,
|
|
23
|
+
description: 'Path to the array to iterate over',
|
|
24
|
+
placeholder: 'e.g., Account, data.items',
|
|
25
|
+
// NOT required (DEV-220 rules-engine parity with config.ts): in
|
|
26
|
+
// records mode ForEach auto-iterates the upstream step's rows when
|
|
27
|
+
// no explicit path is set, and several modes (range/while/…) never
|
|
28
|
+
// use it. The per-mode validate() in config.ts enforces it for the
|
|
29
|
+
// modes that genuinely need it — an unconditional `required` here
|
|
30
|
+
// made the rules engine flag correctly-configured loops.
|
|
31
|
+
validation: { required: false },
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
key: 'itemVariable',
|
|
35
|
+
label: 'Item Variable Name',
|
|
36
|
+
type: FieldType.String,
|
|
37
|
+
description: 'Name of the variable for each item',
|
|
38
|
+
defaultValue: 'item',
|
|
39
|
+
validation: { required: true },
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
key: 'indexVariable',
|
|
43
|
+
label: 'Index Variable Name',
|
|
44
|
+
type: FieldType.String,
|
|
45
|
+
description: 'Name of the variable for the index',
|
|
46
|
+
defaultValue: 'index',
|
|
47
|
+
validation: { required: false },
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
key: 'batchSize',
|
|
51
|
+
label: 'Batch Size',
|
|
52
|
+
type: FieldType.Number,
|
|
53
|
+
description: 'Number of items to process per batch (0 = all at once)',
|
|
54
|
+
defaultValue: 0,
|
|
55
|
+
validation: { required: false },
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
key: 'continueOnError',
|
|
59
|
+
label: 'Continue on Error',
|
|
60
|
+
type: FieldType.Boolean,
|
|
61
|
+
description: 'Whether to continue processing remaining items if one fails',
|
|
62
|
+
defaultValue: false,
|
|
63
|
+
validation: { required: false },
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
outputSchema: {
|
|
68
|
+
type: 'object',
|
|
69
|
+
properties: [
|
|
70
|
+
{
|
|
71
|
+
key: 'itemsProcessed',
|
|
72
|
+
type: FieldType.Number,
|
|
73
|
+
description: 'Number of items processed',
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
key: 'results',
|
|
77
|
+
type: FieldType.Array,
|
|
78
|
+
description: 'Results from each iteration',
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
sampleOutput: {
|
|
82
|
+
itemsProcessed: 5,
|
|
83
|
+
results: [{ item: 1 }, { item: 2 }],
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
version: '1.0.0',
|
|
87
|
+
createdAt: '2025-01-01T00:00:00Z',
|
|
88
|
+
updatedAt: '2025-12-15T00:00:00Z',
|
|
89
|
+
createdBy: 'system',
|
|
90
|
+
isOfficial: true,
|
|
91
|
+
testable: true,
|
|
92
|
+
};
|