Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
if (!node.hasOwnProperty('color')) {
// If no color is defined set the default color of the node type
if (nodeType && nodeType.defaults.color) {
node.color = nodeType.defaults.color as string;
}
}
if (!node.hasOwnProperty('parameters')) {
node.parameters = {};
}
// Load the defaul parameter values because only values which differ
// from the defaults get saved
if (nodeType !== null) {
let nodeParameters = null;
try {
nodeParameters = NodeHelpers.getNodeParameters(nodeType.properties, node.parameters, true, false);
} catch (e) {
console.error(`There was a problem loading the node-parameters of node: "${node.name}"`); // eslint-disable-line no-console
console.error(e); // eslint-disable-line no-console
}
node.parameters = nodeParameters !== null ? nodeParameters : {};
}
foundNodeIssues = this.getNodeIssues(nodeType, node);
if (foundNodeIssues !== null) {
node.issues = foundNodeIssues;
}
this.$store.commit('addNode', node);
});
try {
tempNode = new tempModule[className]() as INodeType;
} catch (error) {
throw new Error(`Error loading node "${nodeTypeName}" from: "${filePath}"`);
}
nodeTypesData[nodeTypeName] = {
type: tempNode,
sourcePath: filePath,
};
}
const nodeTypes = NodeTypes();
await nodeTypes.init(nodeTypesData);
this.workflow = new Workflow(this.data.workflowData.id as string | undefined, this.data.workflowData!.nodes, this.data.workflowData!.connections, this.data.workflowData!.active, nodeTypes, this.data.workflowData!.staticData);
const additionalData = await WorkflowExecuteAdditionalData.getBase(this.data.credentials);
additionalData.hooks = this.getProcessForwardHooks();
if (this.data.executionData !== undefined) {
this.workflowExecute = new WorkflowExecute(additionalData, this.data.executionMode, this.data.executionData);
return this.workflowExecute.processRunExecutionData(this.workflow);
} else if (this.data.runData === undefined || this.data.startNodes === undefined || this.data.startNodes.length === 0 || this.data.destinationNode === undefined) {
// Execute all nodes
// Can execute without webhook so go on
this.workflowExecute = new WorkflowExecute(additionalData, this.data.executionMode);
return this.workflowExecute.run(this.workflow, undefined, this.data.destinationNode);
} else {
// Execute only the nodes between start and destination nodes
this.workflowExecute = new WorkflowExecute(additionalData, this.data.executionMode);
return this.workflowExecute.runPartialWorkflow(this.workflow, this.data.runData, this.data.startNodes, this.data.destinationNode);
const mode = 'integrated';
if (Db.collections!.Workflow === null) {
// The first time executeWorkflow gets called the Database has
// to get initialized first
await Db.init();
}
const workflowData = await Db.collections!.Workflow!.findOne(workflowId);
if (workflowData === undefined) {
throw new Error(`The workflow with the id "${workflowId}" does not exist.`);
}
const nodeTypes = NodeTypes();
const workflow = new Workflow(workflowId as string | undefined, workflowData!.nodes, workflowData!.connections, workflowData!.active, nodeTypes, workflowData!.staticData);
// Does not get used so set it simply to empty string
const executionId = '';
// Create new additionalData to have different workflow loaded and to call
// different webooks
const additionalDataIntegrated = await getBase(additionalData.credentials);
additionalDataIntegrated.hooks = getWorkflowHooksIntegrated(mode, executionId, workflowData, { parentProcessMode: additionalData.hooks!.mode });
// Find Start-Node
const requiredNodeTypes = ['n8n-nodes-base.start'];
let startNode: INode | undefined;
for (const node of workflowData!.nodes) {
if (requiredNodeTypes.includes(node.type)) {
startNode = node;
break;
export async function executeErrorWorkflow(workflowId: string, workflowErrorData: IWorkflowErrorData): Promise {
// Wrap everything in try/catch to make sure that no errors bubble up and all get caught here
try {
const workflowData = await Db.collections.Workflow!.findOne({ id: workflowId });
if (workflowData === undefined) {
// The error workflow could not be found
console.error(`ERROR: Calling Error Workflow for "${workflowErrorData.workflow.id}". Could not find error workflow "${workflowId}"`);
return;
}
const executionMode = 'error';
const nodeTypes = NodeTypes();
const workflowInstance = new Workflow(workflowId, workflowData.nodes, workflowData.connections, workflowData.active, nodeTypes, workflowData.staticData, workflowData.settings);
let node: INode;
let workflowStartNode: INode | undefined;
for (const nodeName of Object.keys(workflowInstance.nodes)) {
node = workflowInstance.nodes[nodeName];
if (node.type === ERROR_TRIGGER_TYPE) {
workflowStartNode = node;
}
}
if (workflowStartNode === undefined) {
console.error(`ERROR: Calling Error Workflow for "${workflowErrorData.workflow.id}". Could not find "${ERROR_TRIGGER_TYPE}" in workflow "${workflowId}"`);
return;
}
// Update happens in NodeView so emit event
const sendData = {
value: newValue,
oldValue: nodeNameBefore,
name: parameterData.name,
};
this.$emit('valueChanged', sendData);
this.$store.commit('setActiveNode', newValue);
} else if (parameterData.name.startsWith('parameters.')) {
// A node parameter changed
const nodeType = this.$store.getters.nodeType(node.type);
// Get only the parameters which are different to the defaults
let nodeParameters = NodeHelpers.getNodeParameters(nodeType.properties, node.parameters, false, false);
// Copy the data because it is the data of vuex so make sure that
// we do not edit it directly
nodeParameters = JSON.parse(JSON.stringify(nodeParameters));
// Remove the 'parameters.' from the beginning to just have the
// actual parameter name
const parameterPath = parameterData.name.split('.').slice(1).join('.');
// Check if the path is supposed to change an array and if so get
// the needed data like path and index
const parameterPathArray = parameterPath.match(/(.*)\[(\d+)\]$/);
// Apply the new value
if (parameterData.value === undefined && parameterPathArray !== null) {
// Delete array item
const path = parameterPathArray[1];
const index = parameterPathArray[2];
const data = get(nodeParameters, path);
if (Array.isArray(data)) {
data.splice(parseInt(index, 10), 1);
Vue.set(nodeParameters as object, path, data);
}
} else {
// For everything else
set(nodeParameters as object, parameterPath, newValue);
}
// Get the parameters with the now new defaults according to the
// from the user actually defined parameters
nodeParameters = NodeHelpers.getNodeParameters(nodeType.properties, nodeParameters as INodeParameters, true, false);
for (const key of Object.keys(nodeParameters as object)) {
if (nodeParameters && nodeParameters[key] !== null && nodeParameters[key] !== undefined) {
this.setValue(`parameters.${key}`, nodeParameters[key] as string);
}
}
// Update the data in vuex
const updateInformation = {
name: node.name,
value: nodeParameters,
};
this.$store.commit('setNodeParameters', updateInformation);
// All data got updated everywhere so update now the issues
const fullNodeIssues: INodeIssues | null = NodeHelpers.getNodeParametersIssues(nodeType.properties, node);
for (const key of Object.keys(nodeParameters as object)) {
if (nodeParameters && nodeParameters[key] !== null && nodeParameters[key] !== undefined) {
this.setValue(`parameters.${key}`, nodeParameters[key] as string);
}
}
// Update the data in vuex
const updateInformation = {
name: node.name,
value: nodeParameters,
};
this.$store.commit('setNodeParameters', updateInformation);
// All data got updated everywhere so update now the issues
const fullNodeIssues: INodeIssues | null = NodeHelpers.getNodeParametersIssues(nodeType.properties, node);
let newIssues: INodeIssueObjectProperty | null = null;
if (fullNodeIssues !== null) {
newIssues = fullNodeIssues.parameters!;
}
this.$store.commit('setNodeIssue', {
node: node.name,
type: 'parameters',
value: newIssues,
} as INodeIssueData);
this.updateNodeCredentialIssues(node);
} else {
// A property on the node itself changed
getIssues (): string[] {
if (this.isCredential === true || this.node === null) {
return [];
}
const newPath = this.shortPath.split('.');
newPath.pop();
const issues = NodeHelpers.getParameterIssues(this.parameter, this.node.parameters, newPath.join('.'));
if (['options', 'multiOptions'].includes(this.parameter.type) && this.remoteParameterOptionsLoading === false && this.remoteParameterOptionsLoadingIssues === null) {
// Check if the value resolves to a valid option
// Currently it only displays an error in the node itself in
// case the value is not valid. The workflow can still be executed
// and the error is not displayed on the node in the workflow
const validOptions = this.parameterOptions!.map((options: INodePropertyOptions) => options.value);
const checkValues: string[] = [];
if (Array.isArray(this.displayValue)) {
checkValues.push.apply(checkValues, this.displayValue);
} else {
checkValues.push(this.displayValue as string);
}
for (const checkValue of checkValues) {
const runData: IRunData | undefined = req.body.runData;
const startNodes: string[] | undefined = req.body.startNodes;
const destinationNode: string | undefined = req.body.destinationNode;
const executionMode = 'manual';
const sessionId = GenericHelpers.getSessionId(req);
// Check if workflow is saved as webhooks can only be tested with saved workflows.
// If that is the case check if any webhooks calls are present we have to wait for and
// if that is the case wait till we receive it.
if (WorkflowHelpers.isWorkflowIdValid(workflowData.id) === true && (runData === undefined || startNodes === undefined || startNodes.length === 0 || destinationNode === undefined)) {
// Webhooks can only be tested with saved workflows
const credentials = await WorkflowCredentials(workflowData.nodes);
const additionalData = await WorkflowExecuteAdditionalData.getBase(credentials);
const nodeTypes = NodeTypes();
const workflowInstance = new Workflow(workflowData.id, workflowData.nodes, workflowData.connections, false, nodeTypes, undefined, workflowData.settings);
const needsWebhook = await this.testWebhooks.needsWebhookData(workflowData, workflowInstance, additionalData, executionMode, sessionId, destinationNode);
if (needsWebhook === true) {
return {
waitingForWebhook: true,
};
}
}
// For manual testing always set to not active
workflowData.active = false;
const credentials = await WorkflowCredentials(workflowData.nodes);
// Start the workflow
const data: IWorkflowExecutionDataProcess = {
credentials,
async add(workflowId: string, workflowData?: IWorkflowDb): Promise {
if (this.activeWorkflows === null) {
throw new Error(`The "activeWorkflows" instance did not get initialized yet.`);
}
let workflowInstance: Workflow;
try {
if (workflowData === undefined) {
workflowData = await Db.collections.Workflow!.findOne(workflowId) as IWorkflowDb;
}
if (!workflowData) {
throw new Error(`Could not find workflow with id "${workflowId}".`);
}
const nodeTypes = NodeTypes();
workflowInstance = new Workflow(workflowId, workflowData.nodes, workflowData.connections, workflowData.active, nodeTypes, workflowData.staticData, workflowData.settings);
const canBeActivated = workflowInstance.checkIfWorkflowCanBeActivated(['n8n-nodes-base.start']);
if (canBeActivated === false) {
throw new Error(`The workflow can not be activated because it does not contain any nodes which could start the workflow. Only workflows which have trigger or webhook nodes can be activated.`);
}
const mode = 'trigger';
const credentials = await WorkflowCredentials(workflowData.nodes);
const additionalData = await WorkflowExecuteAdditionalData.getBase(credentials);
const getTriggerFunctions = this.getExecuteTriggerFunctions(workflowData, additionalData, mode);
// Add the workflows which have webhooks defined
await this.addWorkflowWebhooks(workflowInstance, additionalData, mode);
await this.activeWorkflows.add(workflowId, workflowInstance, additionalData, getTriggerFunctions);
if (this.activationErrors[workflowId] !== undefined) {