(
node: Node<FrontendNodeData>,
edges: Edge[],
component: ComponentMetadata,
secrets?: { id: string; name: string }[],
)
| 197 | * Get validation warnings for a node (e.g., required inputs not connected) |
| 198 | */ |
| 199 | export function getNodeValidationWarnings( |
| 200 | node: Node<FrontendNodeData>, |
| 201 | edges: Edge[], |
| 202 | component: ComponentMetadata, |
| 203 | secrets?: { id: string; name: string }[], |
| 204 | ): string[] { |
| 205 | const warnings: string[] = []; |
| 206 | |
| 207 | // Check for required inputs that are not connected |
| 208 | const manualParameters = (node.data.config?.params ?? {}) as Record<string, unknown>; |
| 209 | const inputOverrides = (node.data.config?.inputOverrides ?? {}) as Record<string, unknown>; |
| 210 | const config = node.data.config as any; |
| 211 | const isToolMode = Boolean(config?.isToolMode || config?.mode === 'tool'); |
| 212 | |
| 213 | component.inputs.forEach((input) => { |
| 214 | // In Tool Mode, skip validation for non-credential inputs |
| 215 | if (isToolMode && !isCredentialInput(input)) { |
| 216 | return; |
| 217 | } |
| 218 | |
| 219 | if (input.required) { |
| 220 | const hasConnection = edges.some( |
| 221 | (edge) => edge.target === node.id && edge.targetHandle === input.id, |
| 222 | ); |
| 223 | |
| 224 | const manualOverridesPort = input.valuePriority === 'manual-first'; |
| 225 | const allowsManualInput = inputSupportsManualValue(input) || manualOverridesPort; |
| 226 | const manualCandidate = inputOverrides[input.id]; |
| 227 | const manualValueProvided = |
| 228 | allowsManualInput && |
| 229 | (!hasConnection || manualOverridesPort) && |
| 230 | manualCandidate !== undefined && |
| 231 | manualCandidate !== null && |
| 232 | (typeof manualCandidate === 'string' ? manualCandidate.trim().length > 0 : true); |
| 233 | |
| 234 | if (!hasConnection && !manualValueProvided) { |
| 235 | warnings.push(`Required input "${input.label}" is not connected`); |
| 236 | } |
| 237 | } |
| 238 | }); |
| 239 | |
| 240 | // Check for required parameters that are not set |
| 241 | component.parameters.forEach((param) => { |
| 242 | if (param.required) { |
| 243 | const value = manualParameters[param.id]; |
| 244 | if (value === undefined || value === null || value === '') { |
| 245 | warnings.push(`Required parameter "${param.label}" is not set`); |
| 246 | } |
| 247 | } |
| 248 | }); |
| 249 | |
| 250 | // Check for missing secrets if secrets catalog is provided |
| 251 | if (secrets) { |
| 252 | const secretIds = secrets.map((s) => s.id); |
| 253 | const secretNames = secrets.map((s) => s.name); |
| 254 | |
| 255 | // 1. Check params |
| 256 | component.parameters.forEach((param) => { |
no test coverage detected