@n8n/workflow-sdk 0.26.0 → 0.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ast-interpreter/index.d.ts +1 -1
- package/dist/ast-interpreter/index.js +2 -1
- package/dist/ast-interpreter/index.js.map +1 -1
- package/dist/build.tsbuildinfo +1 -1
- package/dist/cli/index.js +19 -9
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/node-definition-dirs.d.ts +6 -0
- package/dist/cli/node-definition-dirs.js +63 -0
- package/dist/cli/node-definition-dirs.js.map +1 -0
- package/dist/cli/validate.d.ts +5 -0
- package/dist/cli/validate.js +203 -0
- package/dist/cli/validate.js.map +1 -0
- package/dist/codegen/code-generator.js +4 -1
- package/dist/codegen/code-generator.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +10 -2
- package/dist/index.js.map +1 -1
- package/dist/lint/ast-walk.d.ts +7 -0
- package/dist/lint/ast-walk.js +43 -0
- package/dist/lint/ast-walk.js.map +1 -0
- package/dist/lint/code-node/extract-snippets.d.ts +13 -0
- package/dist/lint/code-node/extract-snippets.js +110 -0
- package/dist/lint/code-node/extract-snippets.js.map +1 -0
- package/dist/lint/code-node/js.d.ts +8 -0
- package/dist/lint/code-node/js.js +219 -0
- package/dist/lint/code-node/js.js.map +1 -0
- package/dist/lint/code-node/python.d.ts +5 -0
- package/dist/lint/code-node/python.js +25 -0
- package/dist/lint/code-node/python.js.map +1 -0
- package/dist/lint/index.d.ts +8 -0
- package/dist/lint/index.js +25 -0
- package/dist/lint/index.js.map +1 -0
- package/dist/lint/lint-workflow-source.d.ts +2 -0
- package/dist/lint/lint-workflow-source.js +47 -0
- package/dist/lint/lint-workflow-source.js.map +1 -0
- package/dist/lint/sdk/workflow-sdk-lint.d.ts +12 -0
- package/dist/lint/sdk/workflow-sdk-lint.js +271 -0
- package/dist/lint/sdk/workflow-sdk-lint.js.map +1 -0
- package/dist/lint/types.d.ts +15 -0
- package/dist/lint/types.js +7 -0
- package/dist/lint/types.js.map +1 -0
- package/dist/mock-data/context.d.ts +5 -2
- package/dist/mock-data/context.js +109 -6
- package/dist/mock-data/context.js.map +1 -1
- package/dist/mock-data/index.d.ts +2 -1
- package/dist/mock-data/index.js +4 -1
- package/dist/mock-data/index.js.map +1 -1
- package/dist/mock-data/parse.js +11 -2
- package/dist/mock-data/parse.js.map +1 -1
- package/dist/mock-data/prompt.js +9 -1
- package/dist/mock-data/prompt.js.map +1 -1
- package/dist/mock-data/types.d.ts +12 -0
- package/dist/mock-data/validate.d.ts +10 -0
- package/dist/mock-data/validate.js +77 -0
- package/dist/mock-data/validate.js.map +1 -0
- package/dist/prompts/sdk-reference/sdk-language.js +10 -5
- package/dist/prompts/sdk-reference/sdk-language.js.map +1 -1
- package/dist/types/base.d.ts +9 -1
- package/dist/validation/index.d.ts +7 -34
- package/dist/validation/index.js +22 -698
- package/dist/validation/index.js.map +1 -1
- package/dist/validation/informational-validation-codes.d.ts +1 -0
- package/dist/validation/informational-validation-codes.js +7 -0
- package/dist/validation/informational-validation-codes.js.map +1 -0
- package/dist/validation/issue-severity.d.ts +6 -0
- package/dist/validation/issue-severity.js +24 -0
- package/dist/validation/issue-severity.js.map +1 -0
- package/dist/validation/{resolve-schema.d.ts → node-parameter-schema/resolve-schema.d.ts} +1 -1
- package/dist/validation/{resolve-schema.js → node-parameter-schema/resolve-schema.js} +1 -1
- package/dist/validation/node-parameter-schema/resolve-schema.js.map +1 -0
- package/dist/validation/{schema-helpers.d.ts → node-parameter-schema/schema-helpers.d.ts} +1 -1
- package/dist/validation/{schema-helpers.js → node-parameter-schema/schema-helpers.js} +1 -1
- package/dist/validation/node-parameter-schema/schema-helpers.js.map +1 -0
- package/dist/validation/{schema-validator.js → node-parameter-schema/schema-validator.js} +1 -1
- package/dist/validation/node-parameter-schema/schema-validator.js.map +1 -0
- package/dist/validation/{test-schema-setup.js → node-parameter-schema/test-schema-setup.js} +3 -3
- package/dist/validation/node-parameter-schema/test-schema-setup.js.map +1 -0
- package/dist/validation/{input-resolver.js → node-port-resolvers/resolve-main-input-count.js} +1 -1
- package/dist/validation/node-port-resolvers/resolve-main-input-count.js.map +1 -0
- package/dist/validation/{output-resolver.js → node-port-resolvers/resolve-main-output-count.js} +1 -1
- package/dist/validation/node-port-resolvers/resolve-main-output-count.js.map +1 -0
- package/dist/validation/validate-workflow-builder.d.ts +44 -0
- package/dist/validation/validate-workflow-builder.js +132 -0
- package/dist/validation/validate-workflow-builder.js.map +1 -0
- package/dist/validation/validate-workflow.d.ts +36 -0
- package/dist/validation/validate-workflow.js +723 -0
- package/dist/validation/validate-workflow.js.map +1 -0
- package/dist/validation.d.ts +2 -2
- package/dist/validation.js +6 -2
- package/dist/validation.js.map +1 -1
- package/dist/workflow-builder/plugins/serializers/json-serializer.js +11 -6
- package/dist/workflow-builder/plugins/serializers/json-serializer.js.map +1 -1
- package/dist/workflow-builder/plugins/types.d.ts +6 -7
- package/dist/workflow-builder/plugins/types.js.map +1 -1
- package/dist/workflow-builder/plugins/validators/disconnected-node-validator.js +1 -1
- package/dist/workflow-builder/plugins/validators/disconnected-node-validator.js.map +1 -1
- package/dist/workflow-builder/plugins/validators/missing-trigger-validator.js +1 -1
- package/dist/workflow-builder/plugins/validators/missing-trigger-validator.js.map +1 -1
- package/dist/workflow-builder/workflow-import.d.ts +2 -6
- package/dist/workflow-builder/workflow-import.js +5 -2
- package/dist/workflow-builder/workflow-import.js.map +1 -1
- package/dist/workflow-builder.js +7 -9
- package/dist/workflow-builder.js.map +1 -1
- package/package.json +11 -6
- package/dist/validation/input-resolver.js.map +0 -1
- package/dist/validation/output-resolver.js.map +0 -1
- package/dist/validation/resolve-schema.js.map +0 -1
- package/dist/validation/schema-helpers.js.map +0 -1
- package/dist/validation/schema-validator.js.map +0 -1
- package/dist/validation/test-schema-setup.js.map +0 -1
- /package/dist/validation/{schema-validator.d.ts → node-parameter-schema/schema-validator.d.ts} +0 -0
- /package/dist/validation/{test-schema-setup.d.ts → node-parameter-schema/test-schema-setup.d.ts} +0 -0
- /package/dist/validation/{input-resolver.d.ts → node-port-resolvers/resolve-main-input-count.d.ts} +0 -0
- /package/dist/validation/{output-resolver.d.ts → node-port-resolvers/resolve-main-output-count.d.ts} +0 -0
package/dist/validation/index.js
CHANGED
|
@@ -1,701 +1,25 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
Object.defineProperty(exports, "
|
|
20
|
-
Object.defineProperty(exports, "
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
exports.ValidationError = ValidationError;
|
|
31
|
-
class ValidationWarning {
|
|
32
|
-
constructor(code, message, nodeName, parameterPath, originalName, violationLevel) {
|
|
33
|
-
this.code = code;
|
|
34
|
-
this.message = message;
|
|
35
|
-
this.nodeName = nodeName;
|
|
36
|
-
this.parameterPath = parameterPath;
|
|
37
|
-
this.originalName = originalName;
|
|
38
|
-
this.violationLevel = violationLevel;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
exports.ValidationWarning = ValidationWarning;
|
|
42
|
-
function isTriggerNode(type) {
|
|
43
|
-
return (type.includes('Trigger') ||
|
|
44
|
-
type.includes('trigger') ||
|
|
45
|
-
type.includes('Webhook') ||
|
|
46
|
-
type.includes('webhook') ||
|
|
47
|
-
type.includes('Schedule') ||
|
|
48
|
-
type.includes('schedule') ||
|
|
49
|
-
type.includes('Poll') ||
|
|
50
|
-
type.includes('poll'));
|
|
51
|
-
}
|
|
52
|
-
const AI_CONNECTION_TYPES = [
|
|
53
|
-
'ai_languageModel',
|
|
54
|
-
'ai_memory',
|
|
55
|
-
'ai_tool',
|
|
56
|
-
'ai_outputParser',
|
|
57
|
-
'ai_embedding',
|
|
58
|
-
'ai_vectorStore',
|
|
59
|
-
'ai_retriever',
|
|
60
|
-
'ai_document',
|
|
61
|
-
'ai_textSplitter',
|
|
62
|
-
'ai_reranker',
|
|
63
|
-
];
|
|
64
|
-
const AI_CONNECTION_TO_SUBNODE_FIELD = {
|
|
65
|
-
ai_languageModel: 'model',
|
|
66
|
-
ai_memory: 'memory',
|
|
67
|
-
ai_tool: 'tools',
|
|
68
|
-
ai_outputParser: 'outputParser',
|
|
69
|
-
ai_embedding: 'embedding',
|
|
70
|
-
ai_vectorStore: 'vectorStore',
|
|
71
|
-
ai_retriever: 'retriever',
|
|
72
|
-
ai_document: 'documentLoader',
|
|
73
|
-
ai_textSplitter: 'textSplitter',
|
|
74
|
-
ai_reranker: 'reranker',
|
|
75
|
-
};
|
|
76
|
-
const AI_ARRAY_TYPES = new Set(['ai_tool']);
|
|
77
|
-
function reconstructSubnodesFromConnections(targetNodeName, json) {
|
|
78
|
-
const subnodes = {};
|
|
79
|
-
const nodesByName = new Map();
|
|
80
|
-
for (const node of json.nodes) {
|
|
81
|
-
if (node.name) {
|
|
82
|
-
nodesByName.set(node.name, node);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
for (const [sourceNodeName, nodeConnections] of Object.entries(json.connections)) {
|
|
86
|
-
for (const connType of AI_CONNECTION_TYPES) {
|
|
87
|
-
const aiConns = nodeConnections[connType];
|
|
88
|
-
if (!aiConns || !Array.isArray(aiConns))
|
|
89
|
-
continue;
|
|
90
|
-
for (const outputs of aiConns) {
|
|
91
|
-
if (!outputs)
|
|
92
|
-
continue;
|
|
93
|
-
for (const conn of outputs) {
|
|
94
|
-
if (conn.node === targetNodeName) {
|
|
95
|
-
const subnodeField = AI_CONNECTION_TO_SUBNODE_FIELD[connType];
|
|
96
|
-
if (!subnodeField)
|
|
97
|
-
continue;
|
|
98
|
-
const sourceNode = nodesByName.get(sourceNodeName);
|
|
99
|
-
if (!sourceNode)
|
|
100
|
-
continue;
|
|
101
|
-
const subnodeConfig = {
|
|
102
|
-
type: sourceNode.type,
|
|
103
|
-
version: sourceNode.typeVersion,
|
|
104
|
-
parameters: sourceNode.parameters ?? {},
|
|
105
|
-
};
|
|
106
|
-
if (AI_ARRAY_TYPES.has(connType)) {
|
|
107
|
-
const existing = subnodes[subnodeField];
|
|
108
|
-
if (Array.isArray(existing)) {
|
|
109
|
-
existing.push(subnodeConfig);
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
subnodes[subnodeField] = [subnodeConfig];
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
else {
|
|
116
|
-
subnodes[subnodeField] = subnodeConfig;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
return Object.keys(subnodes).length > 0 ? subnodes : undefined;
|
|
124
|
-
}
|
|
125
|
-
function hasAiConnectionToParent(nodeName, json) {
|
|
126
|
-
const nodeConnections = json.connections[nodeName];
|
|
127
|
-
if (!nodeConnections)
|
|
128
|
-
return false;
|
|
129
|
-
for (const connType of AI_CONNECTION_TYPES) {
|
|
130
|
-
const aiConns = nodeConnections[connType];
|
|
131
|
-
if (aiConns && Array.isArray(aiConns)) {
|
|
132
|
-
for (const outputs of aiConns) {
|
|
133
|
-
if (outputs && outputs.length > 0) {
|
|
134
|
-
return true;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
return false;
|
|
140
|
-
}
|
|
141
|
-
function isToolSubnode(nodeName, json) {
|
|
142
|
-
const nodeConnections = json.connections[nodeName];
|
|
143
|
-
if (!nodeConnections)
|
|
144
|
-
return false;
|
|
145
|
-
const toolConns = nodeConnections.ai_tool;
|
|
146
|
-
if (toolConns && Array.isArray(toolConns)) {
|
|
147
|
-
for (const outputs of toolConns) {
|
|
148
|
-
if (outputs && outputs.length > 0) {
|
|
149
|
-
return true;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
return false;
|
|
154
|
-
}
|
|
155
|
-
function findDisconnectedNodes(json) {
|
|
156
|
-
const hasIncoming = new Set();
|
|
157
|
-
for (const [_sourceName, nodeConnections] of Object.entries(json.connections)) {
|
|
158
|
-
if (nodeConnections.main) {
|
|
159
|
-
for (const outputs of nodeConnections.main) {
|
|
160
|
-
if (outputs) {
|
|
161
|
-
for (const connection of outputs) {
|
|
162
|
-
hasIncoming.add(connection.node);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
const disconnected = [];
|
|
169
|
-
for (const node of json.nodes) {
|
|
170
|
-
if (!node.name)
|
|
171
|
-
continue;
|
|
172
|
-
if (hasIncoming.has(node.name))
|
|
173
|
-
continue;
|
|
174
|
-
if (isTriggerNode(node.type))
|
|
175
|
-
continue;
|
|
176
|
-
if ((0, node_types_1.isStickyNoteType)(node.type))
|
|
177
|
-
continue;
|
|
178
|
-
if (hasAiConnectionToParent(node.name, json))
|
|
179
|
-
continue;
|
|
180
|
-
disconnected.push(node.name);
|
|
181
|
-
}
|
|
182
|
-
return disconnected;
|
|
183
|
-
}
|
|
184
|
-
function validateWorkflow(workflowOrJson, options = {}) {
|
|
185
|
-
const json = 'toJSON' in workflowOrJson ? workflowOrJson.toJSON() : workflowOrJson;
|
|
186
|
-
const errors = [];
|
|
187
|
-
const warnings = [];
|
|
188
|
-
if (!options.allowNoTrigger) {
|
|
189
|
-
const hasTrigger = json.nodes.some((node) => isTriggerNode(node.type));
|
|
190
|
-
if (!hasTrigger) {
|
|
191
|
-
warnings.push(new ValidationWarning('MISSING_TRIGGER', 'Workflow has no trigger node. It will need to be started manually.'));
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
if (!options.allowDisconnectedNodes) {
|
|
195
|
-
const disconnected = findDisconnectedNodes(json);
|
|
196
|
-
for (const nodeName of disconnected) {
|
|
197
|
-
warnings.push(new ValidationWarning('DISCONNECTED_NODE', `Node '${nodeName}' is not connected to any input. It will not receive data.`, nodeName));
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
if (options.strictMode) {
|
|
201
|
-
for (const node of json.nodes) {
|
|
202
|
-
if ((0, node_types_1.isHttpRequestType)(node.type)) {
|
|
203
|
-
if (!node.parameters?.url && !node.parameters?.requestUrl) {
|
|
204
|
-
warnings.push(new ValidationWarning('MISSING_PARAMETER', `HTTP Request node '${node.name}' may be missing URL parameter`, node.name));
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
if (options.validateSchema !== false) {
|
|
210
|
-
for (const node of json.nodes) {
|
|
211
|
-
const version = typeof node.typeVersion === 'string'
|
|
212
|
-
? parseFloat(node.typeVersion)
|
|
213
|
-
: (node.typeVersion ?? 1);
|
|
214
|
-
const config = {};
|
|
215
|
-
if (node.parameters !== undefined) {
|
|
216
|
-
config.parameters = node.parameters;
|
|
217
|
-
}
|
|
218
|
-
const nodeWithSubnodes = node;
|
|
219
|
-
if (nodeWithSubnodes.subnodes !== undefined) {
|
|
220
|
-
config.subnodes = nodeWithSubnodes.subnodes;
|
|
221
|
-
}
|
|
222
|
-
else if (node.name) {
|
|
223
|
-
const reconstructed = reconstructSubnodesFromConnections(node.name, json);
|
|
224
|
-
if (reconstructed) {
|
|
225
|
-
config.subnodes = reconstructed;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
const isToolNode = node.name ? isToolSubnode(node.name, json) : false;
|
|
229
|
-
const schemaResult = (0, schema_validator_1.validateNodeConfig)(node.type, version, config, { isToolNode });
|
|
230
|
-
if (!schemaResult.valid) {
|
|
231
|
-
for (const error of schemaResult.errors) {
|
|
232
|
-
let message = error.message;
|
|
233
|
-
if (error.path === 'subnodes' &&
|
|
234
|
-
message.includes('Unknown field') &&
|
|
235
|
-
options.nodeTypesProvider) {
|
|
236
|
-
const nodeType = options.nodeTypesProvider.getByNameAndVersion(node.type, version);
|
|
237
|
-
const validInputs = nodeType?.description?.builderHint?.inputs;
|
|
238
|
-
if (validInputs) {
|
|
239
|
-
const validSubnodes = Object.keys(validInputs)
|
|
240
|
-
.map((k) => AI_CONNECTION_TO_SUBNODE_FIELD[k])
|
|
241
|
-
.filter(Boolean);
|
|
242
|
-
if (validSubnodes.length > 0) {
|
|
243
|
-
message = message.replace(/Unknown field\(s\) at "subnodes": (.+)\./, `Invalid subnode(s) $1. This node only accepts: ${validSubnodes.join(', ')}.`);
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
warnings.push(new ValidationWarning('INVALID_PARAMETER', `Node "${node.name}": ${message}`, node.name));
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
if (options.nodeTypesProvider) {
|
|
253
|
-
checkNodeInputIndices(json, options.nodeTypesProvider, warnings);
|
|
254
|
-
checkNodeOutputIndices(json, options.nodeTypesProvider, warnings);
|
|
255
|
-
validateSubnodeParameters(json, options.nodeTypesProvider, warnings);
|
|
256
|
-
validateParentSupportsInputs(json, options.nodeTypesProvider, warnings);
|
|
257
|
-
validateRequiredInputsConnected(json, options.nodeTypesProvider, errors);
|
|
258
|
-
validateOutputUsage(json, options.nodeTypesProvider, warnings);
|
|
259
|
-
validatePlaceholderSlots(json, options.nodeTypesProvider, errors);
|
|
260
|
-
}
|
|
261
|
-
validateSwitchHasOutgoingConnections(json, warnings);
|
|
262
|
-
validateSwitchFallbackOutputConnections(json, warnings);
|
|
263
|
-
checkMergeNodeInputCount(json, warnings);
|
|
264
|
-
return {
|
|
265
|
-
valid: errors.length === 0,
|
|
266
|
-
errors,
|
|
267
|
-
warnings,
|
|
268
|
-
};
|
|
269
|
-
}
|
|
270
|
-
function checkMergeNodeInputCount(json, warnings) {
|
|
271
|
-
const connectionsByDest = (0, n8n_workflow_1.mapConnectionsByDestination)(json.connections);
|
|
272
|
-
for (const node of json.nodes) {
|
|
273
|
-
if (!node.name)
|
|
274
|
-
continue;
|
|
275
|
-
if (node.type !== 'n8n-nodes-base.merge')
|
|
276
|
-
continue;
|
|
277
|
-
const numberInputsParam = node.parameters?.numberInputs;
|
|
278
|
-
const declaredInputs = typeof numberInputsParam === 'number' ? numberInputsParam : 2;
|
|
279
|
-
const incomingMain = connectionsByDest[node.name]?.main;
|
|
280
|
-
if (!incomingMain)
|
|
281
|
-
continue;
|
|
282
|
-
let maxConnectedIndex = -1;
|
|
283
|
-
for (let i = 0; i < incomingMain.length; i++) {
|
|
284
|
-
const slot = incomingMain[i];
|
|
285
|
-
if (Array.isArray(slot) && slot.length > 0) {
|
|
286
|
-
maxConnectedIndex = i;
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
if (maxConnectedIndex >= declaredInputs) {
|
|
290
|
-
warnings.push(new ValidationWarning('INVALID_INPUT_INDEX', `Merge node '${node.name}' has a connection to input index ${maxConnectedIndex} but 'numberInputs' is ${declaredInputs}. Set 'numberInputs' to ${maxConnectedIndex + 1} so every branch is accepted.`, node.name, 'numberInputs', undefined, 'major'));
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
const AI_CONNECTION_TO_SDK_FUNCTION = {
|
|
295
|
-
ai_languageModel: 'languageModel()',
|
|
296
|
-
ai_memory: 'memory()',
|
|
297
|
-
ai_tool: 'tool()',
|
|
298
|
-
ai_outputParser: 'outputParser()',
|
|
299
|
-
ai_embedding: 'embeddings()',
|
|
300
|
-
ai_vectorStore: 'vectorStore()',
|
|
301
|
-
ai_retriever: 'retriever()',
|
|
302
|
-
ai_document: 'documentLoader()',
|
|
303
|
-
ai_textSplitter: 'textSplitter()',
|
|
304
|
-
ai_reranker: 'reranker()',
|
|
305
|
-
};
|
|
306
|
-
function checkDisplayOptionsMatch(subnodeParams, displayOptions) {
|
|
307
|
-
const mismatches = [];
|
|
308
|
-
if (!displayOptions.show)
|
|
309
|
-
return { matches: true, mismatches };
|
|
310
|
-
for (const [paramName, expectedValues] of Object.entries(displayOptions.show)) {
|
|
311
|
-
if (!expectedValues)
|
|
312
|
-
continue;
|
|
313
|
-
const actualValue = subnodeParams[paramName];
|
|
314
|
-
if (!expectedValues.includes(actualValue)) {
|
|
315
|
-
mismatches.push({
|
|
316
|
-
param: paramName,
|
|
317
|
-
expected: expectedValues,
|
|
318
|
-
actual: actualValue,
|
|
319
|
-
});
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
return { matches: mismatches.length === 0, mismatches };
|
|
323
|
-
}
|
|
324
|
-
function validateSubnodeParameters(json, nodeTypesProvider, warnings) {
|
|
325
|
-
const nodesByName = new Map();
|
|
326
|
-
for (const node of json.nodes) {
|
|
327
|
-
if (node.name) {
|
|
328
|
-
nodesByName.set(node.name, node);
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
const connectionsByDest = (0, n8n_workflow_1.mapConnectionsByDestination)(json.connections);
|
|
332
|
-
for (const parentNode of json.nodes) {
|
|
333
|
-
if (!parentNode.name)
|
|
334
|
-
continue;
|
|
335
|
-
const parentNodeType = nodeTypesProvider.getByNameAndVersion(parentNode.type, typeof parentNode.typeVersion === 'string'
|
|
336
|
-
? parseFloat(parentNode.typeVersion)
|
|
337
|
-
: (parentNode.typeVersion ?? 1));
|
|
338
|
-
const builderHintInputs = parentNodeType?.description?.builderHint?.inputs;
|
|
339
|
-
if (!builderHintInputs)
|
|
340
|
-
continue;
|
|
341
|
-
for (const [connectionType, inputConfig] of Object.entries(builderHintInputs)) {
|
|
342
|
-
if (!connectionType.startsWith('ai_'))
|
|
343
|
-
continue;
|
|
344
|
-
if (!inputConfig?.displayOptions?.show)
|
|
345
|
-
continue;
|
|
346
|
-
const incomingConnections = connectionsByDest[parentNode.name]?.[connectionType];
|
|
347
|
-
if (!incomingConnections)
|
|
348
|
-
continue;
|
|
349
|
-
for (const connList of incomingConnections) {
|
|
350
|
-
if (!connList)
|
|
351
|
-
continue;
|
|
352
|
-
for (const conn of connList) {
|
|
353
|
-
const subnodeName = conn.node;
|
|
354
|
-
const subnode = nodesByName.get(subnodeName);
|
|
355
|
-
if (!subnode?.parameters)
|
|
356
|
-
continue;
|
|
357
|
-
const { matches, mismatches } = checkDisplayOptionsMatch(subnode.parameters, inputConfig.displayOptions);
|
|
358
|
-
if (!matches) {
|
|
359
|
-
const subnodeOwnsAnyParam = mismatches.some((m) => m.actual !== undefined);
|
|
360
|
-
if (!subnodeOwnsAnyParam)
|
|
361
|
-
continue;
|
|
362
|
-
const sdkFn = AI_CONNECTION_TO_SDK_FUNCTION[connectionType] || connectionType;
|
|
363
|
-
const mismatchDetails = mismatches
|
|
364
|
-
.map((m) => `${m.param}='${String(m.actual)}' (expected: ${m.expected.map((v) => `'${String(v)}'`).join(' or ')})`)
|
|
365
|
-
.join(', ');
|
|
366
|
-
warnings.push(new ValidationWarning('SUBNODE_PARAMETER_MISMATCH', `'${subnodeName}' is connected to '${parentNode.name}' using ${sdkFn} but has ${mismatchDetails}. Update parameters to match the SDK function used.`, subnodeName, mismatches[0]?.param));
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
function buildConditionSummary(displayOptions, parentParams) {
|
|
374
|
-
if (!displayOptions.show)
|
|
375
|
-
return '';
|
|
376
|
-
const parts = [];
|
|
377
|
-
for (const [paramName, expectedValues] of Object.entries(displayOptions.show)) {
|
|
378
|
-
if (!expectedValues)
|
|
379
|
-
continue;
|
|
380
|
-
const actual = (0, get_1.default)(parentParams, paramName);
|
|
381
|
-
const expectedStr = expectedValues.map((v) => `'${String(v)}'`).join(' or ');
|
|
382
|
-
parts.push(`${paramName} should be ${expectedStr} (currently '${String(actual)}')`);
|
|
383
|
-
}
|
|
384
|
-
return parts.length > 0 ? `Required: ${parts.join(', ')}.` : '';
|
|
385
|
-
}
|
|
386
|
-
function buildTriggeringConditionSummary(displayOptions, parentParams) {
|
|
387
|
-
if (!displayOptions.show)
|
|
388
|
-
return '';
|
|
389
|
-
const parts = [];
|
|
390
|
-
for (const [paramName, _expectedValues] of Object.entries(displayOptions.show)) {
|
|
391
|
-
const actual = (0, get_1.default)(parentParams, paramName);
|
|
392
|
-
parts.push(`${paramName}='${String(actual)}'`);
|
|
393
|
-
}
|
|
394
|
-
return parts.join(', ');
|
|
395
|
-
}
|
|
396
|
-
function validateParentSupportsInputs(json, nodeTypesProvider, warnings) {
|
|
397
|
-
const nodesByName = new Map();
|
|
398
|
-
for (const node of json.nodes) {
|
|
399
|
-
if (node.name) {
|
|
400
|
-
nodesByName.set(node.name, node);
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
const connectionsByDest = (0, n8n_workflow_1.mapConnectionsByDestination)(json.connections);
|
|
404
|
-
for (const parentNode of json.nodes) {
|
|
405
|
-
if (!parentNode.name)
|
|
406
|
-
continue;
|
|
407
|
-
const version = typeof parentNode.typeVersion === 'string'
|
|
408
|
-
? parseFloat(parentNode.typeVersion)
|
|
409
|
-
: (parentNode.typeVersion ?? 1);
|
|
410
|
-
const parentNodeType = nodeTypesProvider.getByNameAndVersion(parentNode.type, version);
|
|
411
|
-
const builderHintInputs = parentNodeType?.description?.builderHint?.inputs;
|
|
412
|
-
if (!builderHintInputs)
|
|
413
|
-
continue;
|
|
414
|
-
const parentContext = {
|
|
415
|
-
parameters: (parentNode.parameters ?? {}),
|
|
416
|
-
nodeVersion: version,
|
|
417
|
-
rootParameters: (parentNode.parameters ?? {}),
|
|
418
|
-
};
|
|
419
|
-
for (const [connectionType, inputConfig] of Object.entries(builderHintInputs)) {
|
|
420
|
-
if (!connectionType.startsWith('ai_'))
|
|
421
|
-
continue;
|
|
422
|
-
if (!inputConfig?.displayOptions)
|
|
423
|
-
continue;
|
|
424
|
-
const parentSupportsInput = (0, display_options_1.matchesDisplayOptions)(parentContext, inputConfig.displayOptions);
|
|
425
|
-
if (parentSupportsInput)
|
|
426
|
-
continue;
|
|
427
|
-
const incomingConnections = connectionsByDest[parentNode.name]?.[connectionType];
|
|
428
|
-
if (!incomingConnections)
|
|
429
|
-
continue;
|
|
430
|
-
for (const connList of incomingConnections) {
|
|
431
|
-
if (!connList)
|
|
432
|
-
continue;
|
|
433
|
-
for (const conn of connList) {
|
|
434
|
-
const subnodeName = conn.node;
|
|
435
|
-
const subnodeField = AI_CONNECTION_TO_SUBNODE_FIELD[connectionType] || connectionType;
|
|
436
|
-
const conditionDetails = buildConditionSummary(inputConfig.displayOptions, (parentNode.parameters ?? {}));
|
|
437
|
-
warnings.push(new ValidationWarning('UNSUPPORTED_SUBNODE_INPUT', `'${parentNode.name}' has a ${subnodeField} subnode ('${subnodeName}') connected, but its current configuration does not accept one. ${conditionDetails} These parameters must be set on '${parentNode.name}' itself, NOT on the ${subnodeField} subnode. Alternatively, remove the ${subnodeField} connection if this capability isn't needed.`, parentNode.name, undefined, undefined, 'major'));
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
function validateRequiredInputsConnected(json, nodeTypesProvider, errors) {
|
|
444
|
-
const connectionsByDest = (0, n8n_workflow_1.mapConnectionsByDestination)(json.connections);
|
|
445
|
-
for (const parentNode of json.nodes) {
|
|
446
|
-
if (!parentNode.name)
|
|
447
|
-
continue;
|
|
448
|
-
const version = typeof parentNode.typeVersion === 'string'
|
|
449
|
-
? parseFloat(parentNode.typeVersion)
|
|
450
|
-
: (parentNode.typeVersion ?? 1);
|
|
451
|
-
const parentNodeType = nodeTypesProvider.getByNameAndVersion(parentNode.type, version);
|
|
452
|
-
const builderHintInputs = parentNodeType?.description?.builderHint?.inputs;
|
|
453
|
-
if (!builderHintInputs)
|
|
454
|
-
continue;
|
|
455
|
-
const parentContext = {
|
|
456
|
-
parameters: (parentNode.parameters ?? {}),
|
|
457
|
-
nodeVersion: version,
|
|
458
|
-
rootParameters: (parentNode.parameters ?? {}),
|
|
459
|
-
};
|
|
460
|
-
for (const [connectionType, inputConfig] of Object.entries(builderHintInputs)) {
|
|
461
|
-
if (!connectionType.startsWith('ai_'))
|
|
462
|
-
continue;
|
|
463
|
-
if (!inputConfig?.required)
|
|
464
|
-
continue;
|
|
465
|
-
if (inputConfig.displayOptions) {
|
|
466
|
-
const conditionsMet = (0, display_options_1.matchesDisplayOptions)(parentContext, inputConfig.displayOptions);
|
|
467
|
-
if (!conditionsMet)
|
|
468
|
-
continue;
|
|
469
|
-
}
|
|
470
|
-
const incoming = connectionsByDest[parentNode.name]?.[connectionType];
|
|
471
|
-
const hasConnection = Array.isArray(incoming) && incoming.some((slot) => Array.isArray(slot) && slot.length > 0);
|
|
472
|
-
if (hasConnection)
|
|
473
|
-
continue;
|
|
474
|
-
const subnodeField = AI_CONNECTION_TO_SUBNODE_FIELD[connectionType] || connectionType;
|
|
475
|
-
const triggerDetails = inputConfig.displayOptions
|
|
476
|
-
? ` (triggered by ${buildTriggeringConditionSummary(inputConfig.displayOptions, (parentNode.parameters ?? {}))})`
|
|
477
|
-
: '';
|
|
478
|
-
const alternative = inputConfig.displayOptions
|
|
479
|
-
? ` Either connect a ${subnodeField} subnode, or change those parameters to remove the requirement.`
|
|
480
|
-
: '';
|
|
481
|
-
errors.push(new ValidationError('MISSING_REQUIRED_INPUT', `'${parentNode.name}' requires a ${subnodeField} subnode connected to its ${connectionType} input${triggerDetails}, but none is connected.${alternative}`, parentNode.name, undefined, 'major'));
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
function describeOutputWiring(connectionType, target = false) {
|
|
486
|
-
if (connectionType === 'main')
|
|
487
|
-
return target ? '.to(...)' : 'wired with .to()';
|
|
488
|
-
const field = AI_CONNECTION_TO_SUBNODE_FIELD[connectionType];
|
|
489
|
-
if (field)
|
|
490
|
-
return target ? `subnodes.${field}` : `attached as subnodes.${field}`;
|
|
491
|
-
return target ? connectionType : `connected via ${connectionType}`;
|
|
492
|
-
}
|
|
493
|
-
function findEnabledAlternativeOutput(outputsHint, ctx, excludeType) {
|
|
494
|
-
for (const [type, cfg] of Object.entries(outputsHint)) {
|
|
495
|
-
if (type === excludeType)
|
|
496
|
-
continue;
|
|
497
|
-
if (!cfg)
|
|
498
|
-
continue;
|
|
499
|
-
if (cfg.displayOptions && !(0, display_options_1.matchesDisplayOptions)(ctx, cfg.displayOptions)) {
|
|
500
|
-
continue;
|
|
501
|
-
}
|
|
502
|
-
return type;
|
|
503
|
-
}
|
|
504
|
-
return undefined;
|
|
505
|
-
}
|
|
506
|
-
function validateOutputUsage(json, nodeTypesProvider, warnings) {
|
|
507
|
-
for (const sourceNode of json.nodes) {
|
|
508
|
-
if (!sourceNode.name)
|
|
509
|
-
continue;
|
|
510
|
-
const outgoing = json.connections[sourceNode.name];
|
|
511
|
-
if (!outgoing)
|
|
512
|
-
continue;
|
|
513
|
-
const version = typeof sourceNode.typeVersion === 'string'
|
|
514
|
-
? parseFloat(sourceNode.typeVersion)
|
|
515
|
-
: (sourceNode.typeVersion ?? 1);
|
|
516
|
-
const nodeType = nodeTypesProvider.getByNameAndVersion(sourceNode.type, version);
|
|
517
|
-
const outputsHint = nodeType?.description?.builderHint?.outputs;
|
|
518
|
-
if (!outputsHint)
|
|
519
|
-
continue;
|
|
520
|
-
const ctx = {
|
|
521
|
-
parameters: (sourceNode.parameters ?? {}),
|
|
522
|
-
nodeVersion: version,
|
|
523
|
-
rootParameters: (sourceNode.parameters ?? {}),
|
|
524
|
-
};
|
|
525
|
-
for (const [connectionType, cfg] of Object.entries(outputsHint)) {
|
|
526
|
-
if (!cfg?.displayOptions)
|
|
527
|
-
continue;
|
|
528
|
-
const edges = outgoing[connectionType];
|
|
529
|
-
if (!edges)
|
|
530
|
-
continue;
|
|
531
|
-
const hasEdges = edges.some((slot) => Array.isArray(slot) && slot.length > 0);
|
|
532
|
-
if (!hasEdges)
|
|
533
|
-
continue;
|
|
534
|
-
const enabled = (0, display_options_1.matchesDisplayOptions)(ctx, cfg.displayOptions);
|
|
535
|
-
if (enabled)
|
|
536
|
-
continue;
|
|
537
|
-
const conditionDetails = buildConditionSummary(cfg.displayOptions, (sourceNode.parameters ?? {}));
|
|
538
|
-
const usedWiring = describeOutputWiring(connectionType);
|
|
539
|
-
const enabledAlt = findEnabledAlternativeOutput(outputsHint, ctx, connectionType);
|
|
540
|
-
const altSuggestion = enabledAlt
|
|
541
|
-
? ` To use this node as-is, attach it as ${describeOutputWiring(enabledAlt, true)} of a parent (it exposes ${enabledAlt} in this configuration).`
|
|
542
|
-
: '';
|
|
543
|
-
warnings.push(new ValidationWarning('INVALID_OUTPUT_FOR_MODE', `'${sourceNode.name}' is ${usedWiring} but its current parameters disable that output. ${conditionDetails}${altSuggestion}`, sourceNode.name, undefined, undefined, 'major'));
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
function getSwitchRulesCount(parameters) {
|
|
548
|
-
const rules = parameters?.rules;
|
|
549
|
-
if (!(0, is_record_1.isRecord)(rules))
|
|
550
|
-
return 0;
|
|
551
|
-
const values = rules.values;
|
|
552
|
-
if (Array.isArray(values))
|
|
553
|
-
return values.length;
|
|
554
|
-
const legacyRules = rules.rules;
|
|
555
|
-
if (Array.isArray(legacyRules))
|
|
556
|
-
return legacyRules.length;
|
|
557
|
-
return 0;
|
|
558
|
-
}
|
|
559
|
-
function getSwitchFallbackOutput(parameters) {
|
|
560
|
-
const options = parameters?.options;
|
|
561
|
-
if (!(0, is_record_1.isRecord)(options))
|
|
562
|
-
return undefined;
|
|
563
|
-
return options.fallbackOutput;
|
|
564
|
-
}
|
|
565
|
-
function hasOutputConnections(outputs, outputIndex) {
|
|
566
|
-
const output = outputs[outputIndex];
|
|
567
|
-
return Array.isArray(output) && output.length > 0;
|
|
568
|
-
}
|
|
569
|
-
function hasAnyMainOutputConnection(nodeConnections) {
|
|
570
|
-
if (!(0, is_record_1.isRecord)(nodeConnections))
|
|
571
|
-
return false;
|
|
572
|
-
const main = nodeConnections.main;
|
|
573
|
-
if (!Array.isArray(main))
|
|
574
|
-
return false;
|
|
575
|
-
return main.some((slot) => Array.isArray(slot) && slot.length > 0);
|
|
576
|
-
}
|
|
577
|
-
function validateSwitchHasOutgoingConnections(json, warnings) {
|
|
578
|
-
for (const sourceNode of json.nodes) {
|
|
579
|
-
if (!sourceNode.name || sourceNode.type !== 'n8n-nodes-base.switch')
|
|
580
|
-
continue;
|
|
581
|
-
if (hasAnyMainOutputConnection(json.connections[sourceNode.name]))
|
|
582
|
-
continue;
|
|
583
|
-
warnings.push(new ValidationWarning('SWITCH_NO_OUTPUT_CONNECTIONS', `Switch node '${sourceNode.name}' has no outgoing connections. Connect at least one output branch to downstream action nodes, or remove the Switch node.`, sourceNode.name, 'connections', undefined, 'major'));
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
function validateSwitchFallbackOutputConnections(json, warnings) {
|
|
587
|
-
for (const sourceNode of json.nodes) {
|
|
588
|
-
if (!sourceNode.name || sourceNode.type !== 'n8n-nodes-base.switch')
|
|
589
|
-
continue;
|
|
590
|
-
const mode = sourceNode.parameters?.mode;
|
|
591
|
-
if (mode !== undefined && mode !== 'rules')
|
|
592
|
-
continue;
|
|
593
|
-
const outgoing = json.connections[sourceNode.name];
|
|
594
|
-
const mainOutputs = outgoing?.main;
|
|
595
|
-
if (!Array.isArray(mainOutputs))
|
|
596
|
-
continue;
|
|
597
|
-
const rulesCount = getSwitchRulesCount(sourceNode.parameters);
|
|
598
|
-
const fallbackOutput = getSwitchFallbackOutput(sourceNode.parameters);
|
|
599
|
-
if (fallbackOutput === 'extra')
|
|
600
|
-
continue;
|
|
601
|
-
for (let outputIndex = rulesCount; outputIndex < mainOutputs.length; outputIndex++) {
|
|
602
|
-
if (!hasOutputConnections(mainOutputs, outputIndex))
|
|
603
|
-
continue;
|
|
604
|
-
const isErrorOutput = sourceNode.onError === 'continueErrorOutput' && outputIndex === rulesCount;
|
|
605
|
-
if (isErrorOutput)
|
|
606
|
-
continue;
|
|
607
|
-
warnings.push(new ValidationWarning('SWITCH_FALLBACK_OUTPUT_DISABLED', `Switch node '${sourceNode.name}' has a connection from output ${outputIndex}, but rules mode only creates fallback output ${rulesCount} when options.fallbackOutput is set to 'extra'. Set options.fallbackOutput to 'extra' before wiring a catch-all branch, or route unmatched items to an existing rule output with a numeric fallbackOutput value.`, sourceNode.name, 'options.fallbackOutput', undefined, 'major'));
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
function validatePlaceholderSlots(json, nodeTypesProvider, errors) {
|
|
612
|
-
for (const node of json.nodes) {
|
|
613
|
-
if (!node.name || !node.parameters)
|
|
614
|
-
continue;
|
|
615
|
-
const version = typeof node.typeVersion === 'string' ? parseFloat(node.typeVersion) : (node.typeVersion ?? 1);
|
|
616
|
-
const nodeType = nodeTypesProvider.getByNameAndVersion(node.type, version);
|
|
617
|
-
const properties = nodeType?.description?.properties;
|
|
618
|
-
if (!properties)
|
|
619
|
-
continue;
|
|
620
|
-
const params = node.parameters;
|
|
621
|
-
for (const prop of properties) {
|
|
622
|
-
if (prop.builderHint?.placeholderSupported !== false)
|
|
623
|
-
continue;
|
|
624
|
-
const value = params[prop.name];
|
|
625
|
-
if (!(0, string_utils_1.containsPlaceholderMarker)(value))
|
|
626
|
-
continue;
|
|
627
|
-
errors.push(new ValidationError('INVALID_PARAMETER', `Node "${node.name}": placeholder() is not supported for parameter '${prop.name}'. Use a literal value or expr() instead.`, node.name, prop.name));
|
|
628
|
-
}
|
|
629
|
-
}
|
|
630
|
-
}
|
|
631
|
-
function checkNodeOutputIndices(json, nodeTypesProvider, warnings) {
|
|
632
|
-
const nodesByName = new Map();
|
|
633
|
-
for (const node of json.nodes) {
|
|
634
|
-
if (node.name) {
|
|
635
|
-
nodesByName.set(node.name, node);
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
|
-
for (const [sourceName, nodeConnections] of Object.entries(json.connections)) {
|
|
639
|
-
const mainConnections = nodeConnections.main;
|
|
640
|
-
if (!mainConnections || !Array.isArray(mainConnections))
|
|
641
|
-
continue;
|
|
642
|
-
const sourceNode = nodesByName.get(sourceName);
|
|
643
|
-
if (!sourceNode)
|
|
644
|
-
continue;
|
|
645
|
-
const version = typeof sourceNode.typeVersion === 'string'
|
|
646
|
-
? parseFloat(sourceNode.typeVersion)
|
|
647
|
-
: (sourceNode.typeVersion ?? 1);
|
|
648
|
-
const mainOutputCount = (0, output_resolver_1.resolveMainOutputCount)(nodeTypesProvider, sourceNode.type, version);
|
|
649
|
-
if (mainOutputCount === undefined)
|
|
650
|
-
continue;
|
|
651
|
-
const errorPinCount = sourceNode.onError === 'continueErrorOutput' ? 1 : 0;
|
|
652
|
-
const allowedOutputCount = mainOutputCount + errorPinCount;
|
|
653
|
-
for (let outputIndex = 0; outputIndex < mainConnections.length; outputIndex++) {
|
|
654
|
-
const outputs = mainConnections[outputIndex];
|
|
655
|
-
if (!outputs || outputs.length === 0)
|
|
656
|
-
continue;
|
|
657
|
-
if (outputIndex >= allowedOutputCount) {
|
|
658
|
-
warnings.push(new ValidationWarning('INVALID_OUTPUT_INDEX', `Connection from '${sourceName}' uses output index ${outputIndex}, but node only has ${allowedOutputCount} output(s) (indices 0-${allowedOutputCount - 1}). To route the error output, set onError: 'continueErrorOutput' on the node and use .onError(target).`, sourceName));
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
}
|
|
663
|
-
function checkNodeInputIndices(json, nodeTypesProvider, warnings) {
|
|
664
|
-
const nodesByName = new Map();
|
|
665
|
-
for (const node of json.nodes) {
|
|
666
|
-
if (node.name) {
|
|
667
|
-
nodesByName.set(node.name, node);
|
|
668
|
-
}
|
|
669
|
-
}
|
|
670
|
-
const warnedInputs = new Set();
|
|
671
|
-
for (const [_sourceName, nodeConnections] of Object.entries(json.connections)) {
|
|
672
|
-
const mainConnections = nodeConnections.main;
|
|
673
|
-
if (!mainConnections || !Array.isArray(mainConnections))
|
|
674
|
-
continue;
|
|
675
|
-
for (const outputs of mainConnections) {
|
|
676
|
-
if (!outputs)
|
|
677
|
-
continue;
|
|
678
|
-
for (const conn of outputs) {
|
|
679
|
-
const targetNodeName = conn.node;
|
|
680
|
-
const targetInputIndex = conn.index;
|
|
681
|
-
const targetNode = nodesByName.get(targetNodeName);
|
|
682
|
-
if (!targetNode)
|
|
683
|
-
continue;
|
|
684
|
-
const version = typeof targetNode.typeVersion === 'string'
|
|
685
|
-
? parseFloat(targetNode.typeVersion)
|
|
686
|
-
: (targetNode.typeVersion ?? 1);
|
|
687
|
-
const mainInputCount = (0, input_resolver_1.resolveMainInputCount)(nodeTypesProvider, targetNode.type, version);
|
|
688
|
-
if (mainInputCount === undefined)
|
|
689
|
-
continue;
|
|
690
|
-
if (targetInputIndex >= mainInputCount) {
|
|
691
|
-
const warnKey = `${targetNodeName}:${targetInputIndex}`;
|
|
692
|
-
if (!warnedInputs.has(warnKey)) {
|
|
693
|
-
warnedInputs.add(warnKey);
|
|
694
|
-
warnings.push(new ValidationWarning('INVALID_INPUT_INDEX', `Connection to '${targetNodeName}' uses input index ${targetInputIndex}, but node only has ${mainInputCount} input(s) (indices 0-${mainInputCount - 1})`, targetNodeName));
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
}
|
|
700
|
-
}
|
|
3
|
+
exports.resolveMainOutputCount = exports.resolveMainInputCount = exports.checkConditions = exports.matchesDisplayOptions = exports.buildUncheckedNotes = exports.validateWorkflowBuilder = exports.partitionValidationIssues = exports.isInformationalIssue = exports.validateNodeConfig = exports.setSchemaBaseDirs = exports.getSchemaBaseDirs = exports.ValidationWarning = exports.ValidationError = exports.validateWorkflow = void 0;
|
|
4
|
+
var validate_workflow_1 = require("./validate-workflow");
|
|
5
|
+
Object.defineProperty(exports, "validateWorkflow", { enumerable: true, get: function () { return validate_workflow_1.validateWorkflow; } });
|
|
6
|
+
Object.defineProperty(exports, "ValidationError", { enumerable: true, get: function () { return validate_workflow_1.ValidationError; } });
|
|
7
|
+
Object.defineProperty(exports, "ValidationWarning", { enumerable: true, get: function () { return validate_workflow_1.ValidationWarning; } });
|
|
8
|
+
var schema_validator_1 = require("./node-parameter-schema/schema-validator");
|
|
9
|
+
Object.defineProperty(exports, "getSchemaBaseDirs", { enumerable: true, get: function () { return schema_validator_1.getSchemaBaseDirs; } });
|
|
10
|
+
Object.defineProperty(exports, "setSchemaBaseDirs", { enumerable: true, get: function () { return schema_validator_1.setSchemaBaseDirs; } });
|
|
11
|
+
Object.defineProperty(exports, "validateNodeConfig", { enumerable: true, get: function () { return schema_validator_1.validateNodeConfig; } });
|
|
12
|
+
var issue_severity_1 = require("./issue-severity");
|
|
13
|
+
Object.defineProperty(exports, "isInformationalIssue", { enumerable: true, get: function () { return issue_severity_1.isInformationalIssue; } });
|
|
14
|
+
Object.defineProperty(exports, "partitionValidationIssues", { enumerable: true, get: function () { return issue_severity_1.partitionValidationIssues; } });
|
|
15
|
+
var validate_workflow_builder_1 = require("./validate-workflow-builder");
|
|
16
|
+
Object.defineProperty(exports, "validateWorkflowBuilder", { enumerable: true, get: function () { return validate_workflow_builder_1.validateWorkflowBuilder; } });
|
|
17
|
+
Object.defineProperty(exports, "buildUncheckedNotes", { enumerable: true, get: function () { return validate_workflow_builder_1.buildUncheckedNotes; } });
|
|
18
|
+
var display_options_1 = require("./display-options");
|
|
19
|
+
Object.defineProperty(exports, "matchesDisplayOptions", { enumerable: true, get: function () { return display_options_1.matchesDisplayOptions; } });
|
|
20
|
+
Object.defineProperty(exports, "checkConditions", { enumerable: true, get: function () { return display_options_1.checkConditions; } });
|
|
21
|
+
var resolve_main_input_count_1 = require("./node-port-resolvers/resolve-main-input-count");
|
|
22
|
+
Object.defineProperty(exports, "resolveMainInputCount", { enumerable: true, get: function () { return resolve_main_input_count_1.resolveMainInputCount; } });
|
|
23
|
+
var resolve_main_output_count_1 = require("./node-port-resolvers/resolve-main-output-count");
|
|
24
|
+
Object.defineProperty(exports, "resolveMainOutputCount", { enumerable: true, get: function () { return resolve_main_output_count_1.resolveMainOutputCount; } });
|
|
701
25
|
//# sourceMappingURL=index.js.map
|