mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 18:12:04 +00:00
refactor(core): Trim down NodeHelpers (no-changelog) (#14829)
This commit is contained in:
committed by
GitHub
parent
88bce7fd8b
commit
3e5e3a585c
@@ -106,7 +106,7 @@ function getINodesFromNames(names: string[]): NodeConfig[] {
|
||||
const matchedNodeType = nodeTypesStore.getNodeType(node.type);
|
||||
if (matchedNodeType) {
|
||||
const issues = nodeHelpers.getNodeIssues(matchedNodeType, node, workflow.value);
|
||||
const stringifiedIssues = issues ? NodeHelpers.nodeIssuesToString(issues, node) : '';
|
||||
const stringifiedIssues = issues ? nodeHelpers.nodeIssuesToString(issues, node) : '';
|
||||
return { node, nodeType: matchedNodeType, issues: stringifiedIssues };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -746,7 +746,7 @@ function getNodeHints(): NodeHint[] {
|
||||
const workflowNode = props.workflow.getNode(node.value.name);
|
||||
|
||||
if (workflowNode) {
|
||||
const nodeHints = NodeHelpers.getNodeHints(props.workflow, workflowNode, nodeType.value, {
|
||||
const nodeHints = nodeHelpers.getNodeHints(props.workflow, workflowNode, nodeType.value, {
|
||||
runExecutionData: workflowExecution.value?.data ?? null,
|
||||
runIndex: props.runIndex,
|
||||
connectionInputData: parentNodeOutputData.value,
|
||||
|
||||
@@ -381,7 +381,7 @@ export function useCanvasMapping({
|
||||
}
|
||||
|
||||
if (node?.issues !== undefined) {
|
||||
issues.push(...NodeHelpers.nodeIssuesToString(node.issues, node));
|
||||
issues.push(...nodeHelpers.nodeIssuesToString(node.issues, node));
|
||||
}
|
||||
|
||||
acc[node.id] = issues;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { setActivePinia } from 'pinia';
|
||||
import type { INode, INodeTypeDescription, Workflow } from 'n8n-workflow';
|
||||
import { createTestingPinia } from '@pinia/testing';
|
||||
import { useNodeHelpers } from '@/composables/useNodeHelpers';
|
||||
import { createTestNode } from '@/__tests__/mocks';
|
||||
@@ -267,4 +268,98 @@ describe('useNodeHelpers()', () => {
|
||||
expect(isSingleExecution('n8n-nodes-base.redis', {})).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getNodeHints', () => {
|
||||
let getNodeHints: ReturnType<typeof useNodeHelpers>['getNodeHints'];
|
||||
beforeEach(() => {
|
||||
getNodeHints = useNodeHelpers().getNodeHints;
|
||||
});
|
||||
|
||||
//TODO: Add more tests here when hints are added to some node types
|
||||
test('should return node hints if present in node type', () => {
|
||||
const testType = {
|
||||
hints: [
|
||||
{
|
||||
message: 'TEST HINT',
|
||||
},
|
||||
],
|
||||
} as INodeTypeDescription;
|
||||
|
||||
const workflow = {} as unknown as Workflow;
|
||||
|
||||
const node: INode = {
|
||||
name: 'Test Node Hints',
|
||||
} as INode;
|
||||
const nodeType = testType;
|
||||
|
||||
const hints = getNodeHints(workflow, node, nodeType);
|
||||
|
||||
expect(hints).toHaveLength(1);
|
||||
expect(hints[0].message).toEqual('TEST HINT');
|
||||
});
|
||||
test('should not include hint if displayCondition is false', () => {
|
||||
const testType = {
|
||||
hints: [
|
||||
{
|
||||
message: 'TEST HINT',
|
||||
displayCondition: 'FALSE DISPLAY CONDITION EXPESSION',
|
||||
},
|
||||
],
|
||||
} as INodeTypeDescription;
|
||||
|
||||
const workflow = {
|
||||
expression: {
|
||||
getSimpleParameterValue(
|
||||
_node: string,
|
||||
_parameter: string,
|
||||
_mode: string,
|
||||
_additionalData = {},
|
||||
) {
|
||||
return false;
|
||||
},
|
||||
},
|
||||
} as unknown as Workflow;
|
||||
|
||||
const node: INode = {
|
||||
name: 'Test Node Hints',
|
||||
} as INode;
|
||||
const nodeType = testType;
|
||||
|
||||
const hints = getNodeHints(workflow, node, nodeType);
|
||||
|
||||
expect(hints).toHaveLength(0);
|
||||
});
|
||||
test('should include hint if displayCondition is true', () => {
|
||||
const testType = {
|
||||
hints: [
|
||||
{
|
||||
message: 'TEST HINT',
|
||||
displayCondition: 'TRUE DISPLAY CONDITION EXPESSION',
|
||||
},
|
||||
],
|
||||
} as INodeTypeDescription;
|
||||
|
||||
const workflow = {
|
||||
expression: {
|
||||
getSimpleParameterValue(
|
||||
_node: string,
|
||||
_parameter: string,
|
||||
_mode: string,
|
||||
_additionalData = {},
|
||||
) {
|
||||
return true;
|
||||
},
|
||||
},
|
||||
} as unknown as Workflow;
|
||||
|
||||
const node: INode = {
|
||||
name: 'Test Node Hints',
|
||||
} as INode;
|
||||
const nodeType = testType;
|
||||
|
||||
const hints = getNodeHints(workflow, node, nodeType);
|
||||
|
||||
expect(hints).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -28,6 +28,8 @@ import type {
|
||||
INodeTypeNameVersion,
|
||||
NodeParameterValue,
|
||||
NodeConnectionType,
|
||||
IRunExecutionData,
|
||||
NodeHint,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
import type {
|
||||
@@ -885,6 +887,113 @@ export function useNodeHelpers() {
|
||||
return false;
|
||||
}
|
||||
|
||||
function getNodeHints(
|
||||
workflow: Workflow,
|
||||
node: INode,
|
||||
nodeTypeData: INodeTypeDescription,
|
||||
nodeInputData?: {
|
||||
runExecutionData: IRunExecutionData | null;
|
||||
runIndex: number;
|
||||
connectionInputData: INodeExecutionData[];
|
||||
},
|
||||
): NodeHint[] {
|
||||
const hints: NodeHint[] = [];
|
||||
|
||||
if (nodeTypeData?.hints?.length) {
|
||||
for (const hint of nodeTypeData.hints) {
|
||||
if (hint.displayCondition) {
|
||||
try {
|
||||
let display;
|
||||
|
||||
if (nodeInputData === undefined) {
|
||||
display = (workflow.expression.getSimpleParameterValue(
|
||||
node,
|
||||
hint.displayCondition,
|
||||
'internal',
|
||||
{},
|
||||
) || false) as boolean;
|
||||
} else {
|
||||
const { runExecutionData, runIndex, connectionInputData } = nodeInputData;
|
||||
display = workflow.expression.getParameterValue(
|
||||
hint.displayCondition,
|
||||
runExecutionData ?? null,
|
||||
runIndex,
|
||||
0,
|
||||
node.name,
|
||||
connectionInputData,
|
||||
'manual',
|
||||
{},
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof display === 'string' && display.trim() === 'true') {
|
||||
display = true;
|
||||
}
|
||||
|
||||
if (typeof display !== 'boolean') {
|
||||
console.warn(
|
||||
`Condition was not resolved as boolean in '${node.name}' node for hint: `,
|
||||
hint.message,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (display) {
|
||||
hints.push(hint);
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn(
|
||||
`Could not calculate display condition in '${node.name}' node for hint: `,
|
||||
hint.message,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
hints.push(hint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hints;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the issues of the node as string
|
||||
*
|
||||
* @param {INodeIssues} issues The issues of the node
|
||||
* @param {INode} node The node
|
||||
*/
|
||||
function nodeIssuesToString(issues: INodeIssues, node?: INode): string[] {
|
||||
const nodeIssues = [];
|
||||
|
||||
if (issues.execution !== undefined) {
|
||||
nodeIssues.push('Execution Error.');
|
||||
}
|
||||
|
||||
const objectProperties = ['parameters', 'credentials', 'input'];
|
||||
|
||||
let issueText: string;
|
||||
let parameterName: string;
|
||||
for (const propertyName of objectProperties) {
|
||||
if (issues[propertyName] !== undefined) {
|
||||
for (parameterName of Object.keys(issues[propertyName] as object)) {
|
||||
for (issueText of (issues[propertyName] as INodeIssueObjectProperty)[parameterName]) {
|
||||
nodeIssues.push(issueText);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (issues.typeUnknown !== undefined) {
|
||||
if (node !== undefined) {
|
||||
nodeIssues.push(`Node Type "${node.type}" is not known.`);
|
||||
} else {
|
||||
nodeIssues.push('Node Type is not known.');
|
||||
}
|
||||
}
|
||||
|
||||
return nodeIssues;
|
||||
}
|
||||
|
||||
return {
|
||||
hasProxyAuth,
|
||||
isCustomApiCallSelected,
|
||||
@@ -914,5 +1023,7 @@ export function useNodeHelpers() {
|
||||
assignNodeId,
|
||||
assignWebhookId,
|
||||
isSingleExecution,
|
||||
getNodeHints,
|
||||
nodeIssuesToString,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user