mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-24 04:04:06 -08:00
⚡ Improve telemetry (#2604)
* add node positions in node graph * add hover events * add tag count in save event * populate properties when default * fix delete and enable node events * add node and workflow exec events * lint * add node graph * add node id
This commit is contained in:
parent
df412e9523
commit
57016624b8
|
@ -128,16 +128,16 @@ export class Execute extends Command {
|
||||||
const externalHooks = ExternalHooks();
|
const externalHooks = ExternalHooks();
|
||||||
await externalHooks.init();
|
await externalHooks.init();
|
||||||
|
|
||||||
const instanceId = await UserSettings.getInstanceId();
|
|
||||||
const { cli } = await GenericHelpers.getVersions();
|
|
||||||
InternalHooksManager.init(instanceId, cli);
|
|
||||||
|
|
||||||
// Add the found types to an instance other parts of the application can use
|
// Add the found types to an instance other parts of the application can use
|
||||||
const nodeTypes = NodeTypes();
|
const nodeTypes = NodeTypes();
|
||||||
await nodeTypes.init(loadNodesAndCredentials.nodeTypes);
|
await nodeTypes.init(loadNodesAndCredentials.nodeTypes);
|
||||||
const credentialTypes = CredentialTypes();
|
const credentialTypes = CredentialTypes();
|
||||||
await credentialTypes.init(loadNodesAndCredentials.credentialTypes);
|
await credentialTypes.init(loadNodesAndCredentials.credentialTypes);
|
||||||
|
|
||||||
|
const instanceId = await UserSettings.getInstanceId();
|
||||||
|
const { cli } = await GenericHelpers.getVersions();
|
||||||
|
InternalHooksManager.init(instanceId, cli, nodeTypes);
|
||||||
|
|
||||||
if (!WorkflowHelpers.isWorkflowIdValid(workflowId)) {
|
if (!WorkflowHelpers.isWorkflowIdValid(workflowId)) {
|
||||||
workflowId = undefined;
|
workflowId = undefined;
|
||||||
}
|
}
|
||||||
|
|
|
@ -308,16 +308,16 @@ export class ExecuteBatch extends Command {
|
||||||
const externalHooks = ExternalHooks();
|
const externalHooks = ExternalHooks();
|
||||||
await externalHooks.init();
|
await externalHooks.init();
|
||||||
|
|
||||||
const instanceId = await UserSettings.getInstanceId();
|
|
||||||
const { cli } = await GenericHelpers.getVersions();
|
|
||||||
InternalHooksManager.init(instanceId, cli);
|
|
||||||
|
|
||||||
// Add the found types to an instance other parts of the application can use
|
// Add the found types to an instance other parts of the application can use
|
||||||
const nodeTypes = NodeTypes();
|
const nodeTypes = NodeTypes();
|
||||||
await nodeTypes.init(loadNodesAndCredentials.nodeTypes);
|
await nodeTypes.init(loadNodesAndCredentials.nodeTypes);
|
||||||
const credentialTypes = CredentialTypes();
|
const credentialTypes = CredentialTypes();
|
||||||
await credentialTypes.init(loadNodesAndCredentials.credentialTypes);
|
await credentialTypes.init(loadNodesAndCredentials.credentialTypes);
|
||||||
|
|
||||||
|
const instanceId = await UserSettings.getInstanceId();
|
||||||
|
const { cli } = await GenericHelpers.getVersions();
|
||||||
|
InternalHooksManager.init(instanceId, cli, nodeTypes);
|
||||||
|
|
||||||
// Send a shallow copy of allWorkflows so we still have all workflow data.
|
// Send a shallow copy of allWorkflows so we still have all workflow data.
|
||||||
const results = await this.runTests([...allWorkflows]);
|
const results = await this.runTests([...allWorkflows]);
|
||||||
|
|
||||||
|
|
|
@ -303,7 +303,7 @@ export class Start extends Command {
|
||||||
|
|
||||||
const instanceId = await UserSettings.getInstanceId();
|
const instanceId = await UserSettings.getInstanceId();
|
||||||
const { cli } = await GenericHelpers.getVersions();
|
const { cli } = await GenericHelpers.getVersions();
|
||||||
InternalHooksManager.init(instanceId, cli);
|
InternalHooksManager.init(instanceId, cli, nodeTypes);
|
||||||
|
|
||||||
const binaryDataConfig = config.get('binaryDataManager') as IBinaryDataConfig;
|
const binaryDataConfig = config.get('binaryDataManager') as IBinaryDataConfig;
|
||||||
await BinaryDataManager.init(binaryDataConfig, true);
|
await BinaryDataManager.init(binaryDataConfig, true);
|
||||||
|
|
|
@ -150,7 +150,7 @@ export class Webhook extends Command {
|
||||||
|
|
||||||
const instanceId = await UserSettings.getInstanceId();
|
const instanceId = await UserSettings.getInstanceId();
|
||||||
const { cli } = await GenericHelpers.getVersions();
|
const { cli } = await GenericHelpers.getVersions();
|
||||||
InternalHooksManager.init(instanceId, cli);
|
InternalHooksManager.init(instanceId, cli, nodeTypes);
|
||||||
|
|
||||||
const binaryDataConfig = config.get('binaryDataManager') as IBinaryDataConfig;
|
const binaryDataConfig = config.get('binaryDataManager') as IBinaryDataConfig;
|
||||||
await BinaryDataManager.init(binaryDataConfig);
|
await BinaryDataManager.init(binaryDataConfig);
|
||||||
|
|
|
@ -274,11 +274,11 @@ export class Worker extends Command {
|
||||||
const versions = await GenericHelpers.getVersions();
|
const versions = await GenericHelpers.getVersions();
|
||||||
const instanceId = await UserSettings.getInstanceId();
|
const instanceId = await UserSettings.getInstanceId();
|
||||||
|
|
||||||
|
InternalHooksManager.init(instanceId, versions.cli, nodeTypes);
|
||||||
|
|
||||||
const binaryDataConfig = config.get('binaryDataManager') as IBinaryDataConfig;
|
const binaryDataConfig = config.get('binaryDataManager') as IBinaryDataConfig;
|
||||||
await BinaryDataManager.init(binaryDataConfig);
|
await BinaryDataManager.init(binaryDataConfig);
|
||||||
|
|
||||||
InternalHooksManager.init(instanceId, versions.cli);
|
|
||||||
|
|
||||||
console.info('\nn8n worker is now ready');
|
console.info('\nn8n worker is now ready');
|
||||||
console.info(` * Version: ${versions.cli}`);
|
console.info(` * Version: ${versions.cli}`);
|
||||||
console.info(` * Concurrency: ${flags.concurrency}`);
|
console.info(` * Concurrency: ${flags.concurrency}`);
|
||||||
|
|
|
@ -1,19 +1,23 @@
|
||||||
/* eslint-disable import/no-cycle */
|
/* eslint-disable import/no-cycle */
|
||||||
import { BinaryDataManager } from 'n8n-core';
|
import { BinaryDataManager } from 'n8n-core';
|
||||||
import { IDataObject, IRun, TelemetryHelpers } from 'n8n-workflow';
|
import { IDataObject, INodeTypes, IRun, TelemetryHelpers } from 'n8n-workflow';
|
||||||
import {
|
import {
|
||||||
IDiagnosticInfo,
|
IDiagnosticInfo,
|
||||||
IInternalHooksClass,
|
IInternalHooksClass,
|
||||||
IPersonalizationSurveyAnswers,
|
IPersonalizationSurveyAnswers,
|
||||||
IWorkflowBase,
|
IWorkflowBase,
|
||||||
|
IWorkflowDb,
|
||||||
} from '.';
|
} from '.';
|
||||||
import { Telemetry } from './telemetry';
|
import { Telemetry } from './telemetry';
|
||||||
|
|
||||||
export class InternalHooksClass implements IInternalHooksClass {
|
export class InternalHooksClass implements IInternalHooksClass {
|
||||||
private versionCli: string;
|
private versionCli: string;
|
||||||
|
|
||||||
constructor(private telemetry: Telemetry, versionCli: string) {
|
private nodeTypes: INodeTypes;
|
||||||
|
|
||||||
|
constructor(private telemetry: Telemetry, versionCli: string, nodeTypes: INodeTypes) {
|
||||||
this.versionCli = versionCli;
|
this.versionCli = versionCli;
|
||||||
|
this.nodeTypes = nodeTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
async onServerStarted(
|
async onServerStarted(
|
||||||
|
@ -53,7 +57,7 @@ export class InternalHooksClass implements IInternalHooksClass {
|
||||||
}
|
}
|
||||||
|
|
||||||
async onWorkflowCreated(workflow: IWorkflowBase): Promise<void> {
|
async onWorkflowCreated(workflow: IWorkflowBase): Promise<void> {
|
||||||
const { nodeGraph } = TelemetryHelpers.generateNodesGraph(workflow);
|
const { nodeGraph } = TelemetryHelpers.generateNodesGraph(workflow, this.nodeTypes);
|
||||||
return this.telemetry.track('User created workflow', {
|
return this.telemetry.track('User created workflow', {
|
||||||
workflow_id: workflow.id,
|
workflow_id: workflow.id,
|
||||||
node_graph: nodeGraph,
|
node_graph: nodeGraph,
|
||||||
|
@ -67,14 +71,15 @@ export class InternalHooksClass implements IInternalHooksClass {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async onWorkflowSaved(workflow: IWorkflowBase): Promise<void> {
|
async onWorkflowSaved(workflow: IWorkflowDb): Promise<void> {
|
||||||
const { nodeGraph } = TelemetryHelpers.generateNodesGraph(workflow);
|
const { nodeGraph } = TelemetryHelpers.generateNodesGraph(workflow, this.nodeTypes);
|
||||||
|
|
||||||
return this.telemetry.track('User saved workflow', {
|
return this.telemetry.track('User saved workflow', {
|
||||||
workflow_id: workflow.id,
|
workflow_id: workflow.id,
|
||||||
node_graph: nodeGraph,
|
node_graph: nodeGraph,
|
||||||
node_graph_string: JSON.stringify(nodeGraph),
|
node_graph_string: JSON.stringify(nodeGraph),
|
||||||
version_cli: this.versionCli,
|
version_cli: this.versionCli,
|
||||||
|
num_tags: workflow.tags.length,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,6 +88,7 @@ export class InternalHooksClass implements IInternalHooksClass {
|
||||||
workflow: IWorkflowBase,
|
workflow: IWorkflowBase,
|
||||||
runData?: IRun,
|
runData?: IRun,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
const promises = [Promise.resolve()];
|
||||||
const properties: IDataObject = {
|
const properties: IDataObject = {
|
||||||
workflow_id: workflow.id,
|
workflow_id: workflow.id,
|
||||||
is_manual: false,
|
is_manual: false,
|
||||||
|
@ -91,11 +97,10 @@ export class InternalHooksClass implements IInternalHooksClass {
|
||||||
|
|
||||||
if (runData !== undefined) {
|
if (runData !== undefined) {
|
||||||
properties.execution_mode = runData.mode;
|
properties.execution_mode = runData.mode;
|
||||||
if (runData.mode === 'manual') {
|
|
||||||
properties.is_manual = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
properties.success = !!runData.finished;
|
properties.success = !!runData.finished;
|
||||||
|
properties.is_manual = runData.mode === 'manual';
|
||||||
|
|
||||||
|
let nodeGraphResult;
|
||||||
|
|
||||||
if (!properties.success && runData?.data.resultData.error) {
|
if (!properties.success && runData?.data.resultData.error) {
|
||||||
properties.error_message = runData?.data.resultData.error.message;
|
properties.error_message = runData?.data.resultData.error.message;
|
||||||
|
@ -115,7 +120,7 @@ export class InternalHooksClass implements IInternalHooksClass {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (properties.is_manual) {
|
if (properties.is_manual) {
|
||||||
const nodeGraphResult = TelemetryHelpers.generateNodesGraph(workflow);
|
nodeGraphResult = TelemetryHelpers.generateNodesGraph(workflow, this.nodeTypes);
|
||||||
properties.node_graph = nodeGraphResult.nodeGraph;
|
properties.node_graph = nodeGraphResult.nodeGraph;
|
||||||
properties.node_graph_string = JSON.stringify(nodeGraphResult.nodeGraph);
|
properties.node_graph_string = JSON.stringify(nodeGraphResult.nodeGraph);
|
||||||
|
|
||||||
|
@ -124,9 +129,51 @@ export class InternalHooksClass implements IInternalHooksClass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (properties.is_manual) {
|
||||||
|
if (!nodeGraphResult) {
|
||||||
|
nodeGraphResult = TelemetryHelpers.generateNodesGraph(workflow, this.nodeTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
const manualExecEventProperties = {
|
||||||
|
workflow_id: workflow.id,
|
||||||
|
status: properties.success ? 'success' : 'failed',
|
||||||
|
error_message: properties.error_message,
|
||||||
|
error_node_type: properties.error_node_type,
|
||||||
|
node_graph: properties.node_graph,
|
||||||
|
node_graph_string: properties.node_graph_string,
|
||||||
|
error_node_id: properties.error_node_id,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!manualExecEventProperties.node_graph) {
|
||||||
|
nodeGraphResult = TelemetryHelpers.generateNodesGraph(workflow, this.nodeTypes);
|
||||||
|
manualExecEventProperties.node_graph = nodeGraphResult.nodeGraph;
|
||||||
|
manualExecEventProperties.node_graph_string = JSON.stringify(
|
||||||
|
manualExecEventProperties.node_graph,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (runData.data.startData?.destinationNode) {
|
||||||
|
promises.push(
|
||||||
|
this.telemetry.track('Manual node exec finished', {
|
||||||
|
...manualExecEventProperties,
|
||||||
|
node_type: TelemetryHelpers.getNodeTypeForName(
|
||||||
|
workflow,
|
||||||
|
runData.data.startData?.destinationNode,
|
||||||
|
)?.type,
|
||||||
|
node_id: nodeGraphResult.nameIndices[runData.data.startData?.destinationNode],
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
promises.push(
|
||||||
|
this.telemetry.track('Manual workflow exec finished', manualExecEventProperties),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
|
...promises,
|
||||||
BinaryDataManager.getInstance().persistBinaryDataForExecutionId(executionId),
|
BinaryDataManager.getInstance().persistBinaryDataForExecutionId(executionId),
|
||||||
this.telemetry.trackWorkflowExecution(properties),
|
this.telemetry.trackWorkflowExecution(properties),
|
||||||
]).then(() => {});
|
]).then(() => {});
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
/* eslint-disable import/no-cycle */
|
/* eslint-disable import/no-cycle */
|
||||||
|
import { INodeTypes } from 'n8n-workflow';
|
||||||
import { InternalHooksClass } from './InternalHooks';
|
import { InternalHooksClass } from './InternalHooks';
|
||||||
import { Telemetry } from './telemetry';
|
import { Telemetry } from './telemetry';
|
||||||
|
|
||||||
|
@ -13,11 +14,12 @@ export class InternalHooksManager {
|
||||||
throw new Error('InternalHooks not initialized');
|
throw new Error('InternalHooks not initialized');
|
||||||
}
|
}
|
||||||
|
|
||||||
static init(instanceId: string, versionCli: string): InternalHooksClass {
|
static init(instanceId: string, versionCli: string, nodeTypes: INodeTypes): InternalHooksClass {
|
||||||
if (!this.internalHooksInstance) {
|
if (!this.internalHooksInstance) {
|
||||||
this.internalHooksInstance = new InternalHooksClass(
|
this.internalHooksInstance = new InternalHooksClass(
|
||||||
new Telemetry(instanceId, versionCli),
|
new Telemetry(instanceId, versionCli),
|
||||||
versionCli,
|
versionCli,
|
||||||
|
nodeTypes,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -891,7 +891,7 @@ class App {
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.externalHooks.run('workflow.afterUpdate', [workflow]);
|
await this.externalHooks.run('workflow.afterUpdate', [workflow]);
|
||||||
void InternalHooksManager.getInstance().onWorkflowSaved(workflow as IWorkflowBase);
|
void InternalHooksManager.getInstance().onWorkflowSaved(workflow);
|
||||||
|
|
||||||
if (workflow.active) {
|
if (workflow.active) {
|
||||||
// When the workflow is supposed to be active add it again
|
// When the workflow is supposed to be active add it again
|
||||||
|
|
|
@ -145,7 +145,7 @@ export class WorkflowRunnerProcess {
|
||||||
|
|
||||||
const instanceId = (await UserSettings.prepareUserSettings()).instanceId ?? '';
|
const instanceId = (await UserSettings.prepareUserSettings()).instanceId ?? '';
|
||||||
const { cli } = await GenericHelpers.getVersions();
|
const { cli } = await GenericHelpers.getVersions();
|
||||||
InternalHooksManager.init(instanceId, cli);
|
InternalHooksManager.init(instanceId, cli, nodeTypes);
|
||||||
|
|
||||||
const binaryDataConfig = config.get('binaryDataManager') as IBinaryDataConfig;
|
const binaryDataConfig = config.get('binaryDataManager') as IBinaryDataConfig;
|
||||||
await BinaryDataManager.init(binaryDataConfig);
|
await BinaryDataManager.init(binaryDataConfig);
|
||||||
|
|
|
@ -328,14 +328,14 @@ export default mixins(externalHooks, nodeBase, nodeHelpers, workflowHelpers).ext
|
||||||
},
|
},
|
||||||
disableNode () {
|
disableNode () {
|
||||||
this.disableNodes([this.data]);
|
this.disableNodes([this.data]);
|
||||||
this.$telemetry.track('User set node enabled status', { node_type: this.data.type, is_enabled: !this.data.disabled, workflow_id: this.$store.getters.workflowId });
|
this.$telemetry.track('User clicked node hover button', { node_type: this.data.type, button_name: 'disable', workflow_id: this.$store.getters.workflowId });
|
||||||
},
|
},
|
||||||
executeNode () {
|
executeNode () {
|
||||||
this.$emit('runWorkflow', this.data.name, 'Node.executeNode');
|
this.$emit('runWorkflow', this.data.name, 'Node.executeNode');
|
||||||
|
this.$telemetry.track('User clicked node hover button', { node_type: this.data.type, button_name: 'execute', workflow_id: this.$store.getters.workflowId });
|
||||||
},
|
},
|
||||||
deleteNode () {
|
deleteNode () {
|
||||||
this.$externalHooks().run('node.deleteNode', { node: this.data});
|
this.$telemetry.track('User clicked node hover button', { node_type: this.data.type, button_name: 'delete', workflow_id: this.$store.getters.workflowId });
|
||||||
this.$telemetry.track('User deleted node', { node_type: this.data.type, workflow_id: this.$store.getters.workflowId });
|
|
||||||
|
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
// Wait a tick else vue causes problems because the data is gone
|
// Wait a tick else vue causes problems because the data is gone
|
||||||
|
@ -343,6 +343,7 @@ export default mixins(externalHooks, nodeBase, nodeHelpers, workflowHelpers).ext
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
duplicateNode () {
|
duplicateNode () {
|
||||||
|
this.$telemetry.track('User clicked node hover button', { node_type: this.data.type, button_name: 'duplicate', workflow_id: this.$store.getters.workflowId });
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
// Wait a tick else vue causes problems because the data is gone
|
// Wait a tick else vue causes problems because the data is gone
|
||||||
this.$emit('duplicateNode', this.data.name);
|
this.$emit('duplicateNode', this.data.name);
|
||||||
|
|
|
@ -343,6 +343,8 @@ export const nodeHelpers = mixins(
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.$telemetry.track('User set node enabled status', { node_type: node.type, is_enabled: node.disabled, workflow_id: this.$store.getters.workflowId });
|
||||||
|
|
||||||
this.$store.commit('updateNodeProperties', updateInformation);
|
this.$store.commit('updateNodeProperties', updateInformation);
|
||||||
this.$store.commit('clearNodeExecutionData', node.name);
|
this.$store.commit('clearNodeExecutionData', node.name);
|
||||||
this.updateNodeParameterIssues(node);
|
this.updateNodeParameterIssues(node);
|
||||||
|
|
|
@ -2133,6 +2133,9 @@ export default mixins(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.$externalHooks().run('node.deleteNode', { node });
|
||||||
|
this.$telemetry.track('User deleted node', { node_type: node.type, workflow_id: this.$store.getters.workflowId });
|
||||||
|
|
||||||
let waitForNewConnection = false;
|
let waitForNewConnection = false;
|
||||||
// connect nodes before/after deleted node
|
// connect nodes before/after deleted node
|
||||||
const nodeType: INodeTypeDescription | null = this.$store.getters.nodeType(node.type, node.typeVersion);
|
const nodeType: INodeTypeDescription | null = this.$store.getters.nodeType(node.type, node.typeVersion);
|
||||||
|
|
|
@ -1097,6 +1097,8 @@ export interface INodeGraphItem {
|
||||||
resource?: string;
|
resource?: string;
|
||||||
operation?: string;
|
operation?: string;
|
||||||
domain?: string;
|
domain?: string;
|
||||||
|
position: [number, number];
|
||||||
|
mode?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface INodeNameIndex {
|
export interface INodeNameIndex {
|
||||||
|
|
|
@ -7,13 +7,18 @@ import {
|
||||||
INodeGraphItem,
|
INodeGraphItem,
|
||||||
INodesGraphResult,
|
INodesGraphResult,
|
||||||
IWorkflowBase,
|
IWorkflowBase,
|
||||||
|
INodeTypes,
|
||||||
|
INodeType,
|
||||||
} from '.';
|
} from '.';
|
||||||
|
|
||||||
export function getNodeTypeForName(workflow: IWorkflowBase, nodeName: string): INode | undefined {
|
export function getNodeTypeForName(workflow: IWorkflowBase, nodeName: string): INode | undefined {
|
||||||
return workflow.nodes.find((node) => node.name === nodeName);
|
return workflow.nodes.find((node) => node.name === nodeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function generateNodesGraph(workflow: IWorkflowBase): INodesGraphResult {
|
export function generateNodesGraph(
|
||||||
|
workflow: IWorkflowBase,
|
||||||
|
nodeTypes: INodeTypes,
|
||||||
|
): INodesGraphResult {
|
||||||
const nodesGraph: INodesGraph = {
|
const nodesGraph: INodesGraph = {
|
||||||
node_types: [],
|
node_types: [],
|
||||||
node_connections: [],
|
node_connections: [],
|
||||||
|
@ -25,6 +30,7 @@ export function generateNodesGraph(workflow: IWorkflowBase): INodesGraphResult {
|
||||||
nodesGraph.node_types.push(node.type);
|
nodesGraph.node_types.push(node.type);
|
||||||
const nodeItem: INodeGraphItem = {
|
const nodeItem: INodeGraphItem = {
|
||||||
type: node.type,
|
type: node.type,
|
||||||
|
position: node.position,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (node.type === 'n8n-nodes-base.httpRequest') {
|
if (node.type === 'n8n-nodes-base.httpRequest') {
|
||||||
|
@ -34,11 +40,20 @@ export function generateNodesGraph(workflow: IWorkflowBase): INodesGraphResult {
|
||||||
nodeItem.domain = node.parameters.url as string;
|
nodeItem.domain = node.parameters.url as string;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Object.keys(node.parameters).forEach((parameterName) => {
|
const nodeType = nodeTypes.getByName(node.type) as INodeType;
|
||||||
if (parameterName === 'operation' || parameterName === 'resource') {
|
nodeType.description.properties.forEach((property) => {
|
||||||
nodeItem[parameterName] = node.parameters[parameterName] as string;
|
if (
|
||||||
|
property.name === 'operation' ||
|
||||||
|
property.name === 'resource' ||
|
||||||
|
property.name === 'mode'
|
||||||
|
) {
|
||||||
|
nodeItem[property.name] = property.default ? property.default.toString() : undefined;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
nodeItem.operation = node.parameters.operation?.toString() ?? nodeItem.operation;
|
||||||
|
nodeItem.resource = node.parameters.resource?.toString() ?? nodeItem.resource;
|
||||||
|
nodeItem.mode = node.parameters.mode?.toString() ?? nodeItem.mode;
|
||||||
}
|
}
|
||||||
nodesGraph.nodes[`${index}`] = nodeItem;
|
nodesGraph.nodes[`${index}`] = nodeItem;
|
||||||
nodeNameAndIndex[node.name] = index.toString();
|
nodeNameAndIndex[node.name] = index.toString();
|
||||||
|
|
Loading…
Reference in a new issue