n8n/packages/workflow/src/node-validation.ts
Michael Kret 6e2d35644f
feat: Add AI Gateway support for AI nodes (#27593)
Co-authored-by: Alexander Gekov <40495748+alexander-gekov@users.noreply.github.com>
2026-04-07 09:11:24 +00:00

89 lines
2.3 KiB
TypeScript

import type { INode, INodeType, IConnections } from './interfaces';
import { displayParameter } from './node-helpers';
export interface NodeValidationIssue {
credential?: string;
parameter?: string;
}
export interface NodeCredentialIssue {
type: 'missing' | 'not-configured';
displayName: string;
credentialName: string;
}
/**
* Validates that all required credentials are set for a node.
* Respects displayOptions to only validate credentials that should be shown.
*/
export function validateNodeCredentials(node: INode, nodeType: INodeType): NodeCredentialIssue[] {
const issues: NodeCredentialIssue[] = [];
const credentialDescriptions = nodeType.description?.credentials || [];
for (const credDesc of credentialDescriptions) {
if (!credDesc.required) continue;
// Check if this credential should be displayed based on displayOptions
const shouldDisplay = displayParameter(node.parameters, credDesc, node, nodeType.description);
if (!shouldDisplay) continue;
const credentialName = credDesc.name;
const nodeCredential = node.credentials?.[credentialName];
const displayName = credDesc.displayName ?? credentialName;
if (!nodeCredential) {
issues.push({
type: 'missing',
displayName,
credentialName,
});
continue;
}
if (!nodeCredential.id && !nodeCredential.__aiGatewayManaged) {
issues.push({
type: 'not-configured',
displayName,
credentialName,
});
}
}
return issues;
}
/**
* Checks if a node has any incoming or outgoing connections.
*/
export function isNodeConnected(
nodeName: string,
connections: IConnections,
connectionsByDestination: IConnections,
): boolean {
// Check outgoing connections
if (connections[nodeName] && Object.keys(connections[nodeName]).length > 0) {
return true;
}
// Check incoming connections
if (
connectionsByDestination[nodeName] &&
Object.keys(connectionsByDestination[nodeName]).length > 0
) {
return true;
}
return false;
}
/**
* Checks if a node type is a trigger-like node (trigger, webhook, or poll).
* These nodes are workflow entry points and should always be validated.
*/
export function isTriggerLikeNode(nodeType: INodeType): boolean {
return (
nodeType.trigger !== undefined || nodeType.webhook !== undefined || nodeType.poll !== undefined
);
}