@octaviaflow/flow-rules 0.1.0 → 0.1.1
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/dist/index.js +2894 -28
- package/package.json +14 -5
- package/dist/catalog/actions/console-log/config.js +0 -70
- package/dist/catalog/actions/console-log/index.js +0 -89
- package/dist/catalog/actions/delay/config.js +0 -79
- package/dist/catalog/actions/delay/index.js +0 -71
- package/dist/catalog/actions/delay/migrate.js +0 -38
- package/dist/catalog/actions/delay/types.js +0 -17
- package/dist/catalog/actions/http-request/config.js +0 -111
- package/dist/catalog/actions/http-request/index.js +0 -223
- package/dist/catalog/ai/ai-agent/index.js +0 -72
- package/dist/catalog/ai/idp-extract/index.js +0 -90
- package/dist/catalog/api/graphql-query/config.js +0 -31
- package/dist/catalog/api/graphql-query/index.js +0 -75
- package/dist/catalog/communication/email-send/config.js +0 -80
- package/dist/catalog/communication/email-send/index.js +0 -152
- package/dist/catalog/communication/google-chat/config.js +0 -28
- package/dist/catalog/communication/google-chat/index.js +0 -36
- package/dist/catalog/communication/slack-message/config.js +0 -36
- package/dist/catalog/communication/slack-message/index.js +0 -37
- package/dist/catalog/communication/teams-message/config.js +0 -29
- package/dist/catalog/communication/teams-message/index.js +0 -39
- package/dist/catalog/communication/webhook-call/config.js +0 -31
- package/dist/catalog/communication/webhook-call/index.js +0 -43
- package/dist/catalog/communication/whatsapp-send/config.js +0 -36
- package/dist/catalog/communication/whatsapp-send/index.js +0 -57
- package/dist/catalog/general/query/config.js +0 -257
- package/dist/catalog/general/query/index.js +0 -271
- package/dist/catalog/general/query/types.js +0 -82
- package/dist/catalog/general/transform/config.js +0 -95
- package/dist/catalog/general/transform/index.js +0 -63
- package/dist/catalog/index.js +0 -168
- package/dist/catalog/logic/condition/config.js +0 -93
- package/dist/catalog/logic/condition/index.js +0 -64
- package/dist/catalog/logic/for-each/config.js +0 -75
- package/dist/catalog/logic/for-each/index.js +0 -92
- package/dist/catalog/logic/for-each/pathOptions.js +0 -151
- package/dist/catalog/logic/group/index.js +0 -46
- package/dist/catalog/policies.js +0 -62
- package/dist/catalog/storage/csv-action/index.js +0 -38
- package/dist/catalog/storage/dropbox-action/index.js +0 -33
- package/dist/catalog/storage/excel-action/index.js +0 -32
- package/dist/catalog/storage/file-action/index.js +0 -119
- package/dist/catalog/storage/file-operation/config.js +0 -45
- package/dist/catalog/storage/file-operation/index.js +0 -111
- package/dist/catalog/storage/ftp-action/index.js +0 -33
- package/dist/catalog/storage/google-drive-action/index.js +0 -38
- package/dist/catalog/storage/json-action/index.js +0 -31
- package/dist/catalog/storage/onedrive-action/index.js +0 -33
- package/dist/catalog/storage/s3-action/index.js +0 -36
- package/dist/catalog/storage/storage-action/index.js +0 -72
- package/dist/catalog/storage/storageCapabilities.js +0 -207
- package/dist/catalog/storage/xml-action/index.js +0 -31
- package/dist/catalog/transforms/format/config.js +0 -19
- package/dist/catalog/transforms/format/index.js +0 -39
- package/dist/catalog/triggers/connector-trigger/index.js +0 -72
- package/dist/catalog/triggers/manual-trigger/config.js +0 -60
- package/dist/catalog/triggers/manual-trigger/index.js +0 -74
- package/dist/catalog/triggers/schedule-trigger/config.js +0 -42
- package/dist/catalog/triggers/schedule-trigger/index.js +0 -102
- package/dist/catalog/triggers/webhook-trigger/config.js +0 -27
- package/dist/catalog/triggers/webhook-trigger/index.js +0 -89
- package/dist/catalog/types.js +0 -135
- package/dist/catalog/utility/debug/config.js +0 -90
- package/dist/catalog/utility/debug/index.js +0 -38
- package/dist/catalog/utility/error/config.js +0 -25
- package/dist/catalog/utility/error/index.js +0 -46
- package/dist/catalog/utility/variables/config.js +0 -70
- package/dist/catalog/utility/variables/index.js +0 -40
- package/dist/catalog/workflow.js +0 -25
- package/dist/ids.js +0 -53
- package/dist/rules/nodeConfigStatus.js +0 -217
- package/dist/rules/workflowValidator.js +0 -358
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Transform Configuration
|
|
3
|
-
*
|
|
4
|
-
* Configuration for data transformation and field mapping between workflow steps.
|
|
5
|
-
* Supports visual field mapping (drag-and-drop) and expression-based transforms.
|
|
6
|
-
*/
|
|
7
|
-
import { randomSuffix } from '../../../ids';
|
|
8
|
-
export const TRANSFORM_OPERATIONS = [
|
|
9
|
-
{ id: 'upsert', label: 'Upsert' },
|
|
10
|
-
{ id: 'insert', label: 'Insert' },
|
|
11
|
-
{ id: 'update', label: 'Update' },
|
|
12
|
-
{ id: 'delete', label: 'Delete' },
|
|
13
|
-
];
|
|
14
|
-
/** Database connector IDs that support the database dropdown */
|
|
15
|
-
export const DATABASE_CONNECTOR_IDS = new Set(['mongodb', 'postgresql', 'mysql', 'sqlite', 'google_sheets']);
|
|
16
|
-
export const TransformConfig = {
|
|
17
|
-
defaults: {
|
|
18
|
-
name: 'Transform',
|
|
19
|
-
operation: 'upsert',
|
|
20
|
-
connectorId: '',
|
|
21
|
-
database: '',
|
|
22
|
-
objectName: '',
|
|
23
|
-
mode: 'visual',
|
|
24
|
-
mappings: [],
|
|
25
|
-
expression: '',
|
|
26
|
-
fieldDefaults: {},
|
|
27
|
-
upsertMatchKey: '',
|
|
28
|
-
sheetHeaders: [],
|
|
29
|
-
createTabIfMissing: true,
|
|
30
|
-
writeHeaderRow: true,
|
|
31
|
-
clearBeforeWrite: false,
|
|
32
|
-
sheetCustomLayout: false,
|
|
33
|
-
sheetHeaderRow: 1,
|
|
34
|
-
sheetColumns: '',
|
|
35
|
-
},
|
|
36
|
-
schema: {
|
|
37
|
-
operation: { type: 'select', required: true },
|
|
38
|
-
connectorId: { type: 'connection', required: true },
|
|
39
|
-
database: { type: 'text', required: false },
|
|
40
|
-
objectName: { type: 'select', required: true },
|
|
41
|
-
mode: { type: 'select', required: true },
|
|
42
|
-
mappings: { type: 'array', required: false },
|
|
43
|
-
expression: { type: 'code', required: false },
|
|
44
|
-
},
|
|
45
|
-
/** Auto-generate a descriptive name from the 3 dropdown selections */
|
|
46
|
-
generateName: (operation, connectorLabel, objectName) => {
|
|
47
|
-
const opLabel = TRANSFORM_OPERATIONS.find(o => o.id === operation)?.label || 'Transform';
|
|
48
|
-
const target = connectorLabel || 'Target';
|
|
49
|
-
const obj = objectName || 'Object';
|
|
50
|
-
return `${opLabel} → ${target} · ${obj}`;
|
|
51
|
-
},
|
|
52
|
-
validate: (config) => {
|
|
53
|
-
const errors = [];
|
|
54
|
-
if (!config.operation) {
|
|
55
|
-
errors.push('Operation is required');
|
|
56
|
-
}
|
|
57
|
-
if (!config.connectorId) {
|
|
58
|
-
errors.push('Target connector is required');
|
|
59
|
-
}
|
|
60
|
-
if (!config.objectName) {
|
|
61
|
-
errors.push('Object (table) is required');
|
|
62
|
-
}
|
|
63
|
-
// The Visual Field Mapper is the only authoring mode. Legacy steps saved
|
|
64
|
-
// in the retired JavaScript-expression mode still execute (the engine keeps
|
|
65
|
-
// that path for back-compat), so don't flag them invalid for lacking mappings.
|
|
66
|
-
const isLegacyExpression = config.mode === 'expression' && !!config.expression?.trim();
|
|
67
|
-
if (!isLegacyExpression) {
|
|
68
|
-
if (!config.mappings || config.mappings.length === 0) {
|
|
69
|
-
errors.push('At least one field mapping is required');
|
|
70
|
-
}
|
|
71
|
-
else {
|
|
72
|
-
config.mappings.forEach((mapping, index) => {
|
|
73
|
-
if (!mapping.sourceField) {
|
|
74
|
-
errors.push(`Mapping ${index + 1}: Source field is required`);
|
|
75
|
-
}
|
|
76
|
-
if (!mapping.targetField) {
|
|
77
|
-
errors.push(`Mapping ${index + 1}: Target field is required`);
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
return { valid: errors.length === 0, errors };
|
|
83
|
-
},
|
|
84
|
-
merge: (userConfig) => {
|
|
85
|
-
return { ...TransformConfig.defaults, ...userConfig };
|
|
86
|
-
},
|
|
87
|
-
getLabel: (config) => {
|
|
88
|
-
const count = config.mappings?.length ?? 0;
|
|
89
|
-
return `${config.name || 'Transform'} (${count} field${count !== 1 ? 's' : ''})`;
|
|
90
|
-
},
|
|
91
|
-
/** Generate a unique ID for a new mapping row */
|
|
92
|
-
createMappingId: () => {
|
|
93
|
-
return `map_${Date.now()}_${randomSuffix(5)}`;
|
|
94
|
-
},
|
|
95
|
-
};
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Transform Action
|
|
3
|
-
*
|
|
4
|
-
* Data transformation action that maps and reshapes data between workflow steps
|
|
5
|
-
* using the visual field mapper (drag-and-drop from the upstream schema).
|
|
6
|
-
*/
|
|
7
|
-
import { ActionCategory, ActionType, ActionStatus, FieldType } from '../../types';
|
|
8
|
-
export const transformDefinition = {
|
|
9
|
-
id: 'transform',
|
|
10
|
-
name: 'Transform',
|
|
11
|
-
description: 'Map and transform data between workflow steps using the visual field mapper',
|
|
12
|
-
category: ActionCategory.Transform,
|
|
13
|
-
type: ActionType.Transform,
|
|
14
|
-
tags: ['transform', 'mapping', 'data', 'reshape', 'convert', 'built-in'],
|
|
15
|
-
status: ActionStatus.Stable,
|
|
16
|
-
icon: 'Transform',
|
|
17
|
-
color: '#0043ce',
|
|
18
|
-
inputSchema: {
|
|
19
|
-
fields: [
|
|
20
|
-
{
|
|
21
|
-
key: 'name',
|
|
22
|
-
label: 'Transform Name',
|
|
23
|
-
type: FieldType.String,
|
|
24
|
-
description: 'A descriptive name for this transform step',
|
|
25
|
-
defaultValue: 'Transform',
|
|
26
|
-
validation: { required: false },
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
key: 'mappings',
|
|
30
|
-
label: 'Field Mappings',
|
|
31
|
-
type: FieldType.Array,
|
|
32
|
-
description: 'Map source fields from upstream nodes to target output fields',
|
|
33
|
-
validation: { required: false },
|
|
34
|
-
},
|
|
35
|
-
],
|
|
36
|
-
},
|
|
37
|
-
outputSchema: {
|
|
38
|
-
type: 'object',
|
|
39
|
-
properties: [
|
|
40
|
-
{
|
|
41
|
-
key: 'result',
|
|
42
|
-
type: FieldType.JSON,
|
|
43
|
-
description: 'Transformed data output',
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
key: 'mappedFieldCount',
|
|
47
|
-
type: FieldType.Number,
|
|
48
|
-
description: 'Number of fields that were mapped/transformed',
|
|
49
|
-
},
|
|
50
|
-
],
|
|
51
|
-
sampleOutput: {
|
|
52
|
-
result: { name: 'John Doe', email: 'john@example.com', age: 30 },
|
|
53
|
-
mappedFieldCount: 3,
|
|
54
|
-
},
|
|
55
|
-
dynamic: true,
|
|
56
|
-
},
|
|
57
|
-
version: '2.0.0',
|
|
58
|
-
createdAt: '2025-01-01T00:00:00Z',
|
|
59
|
-
updatedAt: '2026-02-13T00:00:00Z',
|
|
60
|
-
createdBy: 'system',
|
|
61
|
-
isOfficial: true,
|
|
62
|
-
testable: true,
|
|
63
|
-
};
|
package/dist/catalog/index.js
DELETED
|
@@ -1,168 +0,0 @@
|
|
|
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, };
|
|
@@ -1,93 +0,0 @@
|
|
|
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
|
-
};
|
|
@@ -1,64 +0,0 @@
|
|
|
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
|
-
};
|
|
@@ -1,75 +0,0 @@
|
|
|
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
|
-
};
|
|
@@ -1,92 +0,0 @@
|
|
|
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
|
-
};
|