@n8n/eslint-plugin-community-nodes 0.28.0 → 0.30.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/rules/index.d.ts +1 -1
- package/dist/rules/node-registration-complete.d.ts.map +1 -1
- package/dist/rules/node-registration-complete.js +26 -3
- package/dist/rules/node-registration-complete.js.map +1 -1
- package/dist/rules/node-usable-as-tool.d.ts +1 -1
- package/dist/rules/node-usable-as-tool.d.ts.map +1 -1
- package/dist/rules/node-usable-as-tool.js +23 -1
- package/dist/rules/node-usable-as-tool.js.map +1 -1
- package/dist/rules/trigger-node-conventions.d.ts.map +1 -1
- package/dist/rules/trigger-node-conventions.js +2 -2
- package/dist/rules/trigger-node-conventions.js.map +1 -1
- package/dist/utils/ast-utils.d.ts +8 -0
- package/dist/utils/ast-utils.d.ts.map +1 -1
- package/dist/utils/ast-utils.js +16 -0
- package/dist/utils/ast-utils.js.map +1 -1
- package/docs/rules/node-registration-complete.md +26 -0
- package/docs/rules/node-usable-as-tool.md +59 -0
- package/package.json +4 -4
- package/src/rules/node-registration-complete.test.ts +35 -0
- package/src/rules/node-registration-complete.ts +31 -3
- package/src/rules/node-usable-as-tool.test.ts +62 -3
- package/src/rules/node-usable-as-tool.ts +28 -0
- package/src/rules/trigger-node-conventions.ts +2 -1
- package/src/utils/ast-utils.ts +26 -0
- package/.turbo/turbo-build.log +0 -4
- package/dist/typecheck.tsbuildinfo +0 -1
- package/tsconfig.json +0 -9
package/dist/rules/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export declare const rules: {
|
|
|
5
5
|
'credential-password-field': import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingPasswordOption", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
6
6
|
'no-deprecated-workflow-functions': import("@typescript-eslint/utils/ts-eslint").RuleModule<"deprecatedFunction" | "deprecatedRequestFunction" | "deprecatedType" | "deprecatedWithoutReplacement" | "suggestReplaceFunction" | "suggestReplaceType", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
7
7
|
'no-emoji-in-options': import("@typescript-eslint/utils/ts-eslint").RuleModule<"emojiInOption", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
8
|
-
'node-usable-as-tool': import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingUsableAsTool", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
8
|
+
'node-usable-as-tool': import("@typescript-eslint/utils/ts-eslint").RuleModule<"aiOnlyUsableAsTool" | "missingUsableAsTool" | "triggerUsableAsTool", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
9
9
|
'package-name-convention': import("@typescript-eslint/utils/ts-eslint").RuleModule<"defaultPlaceholderName" | "invalidPackageName" | "missingName" | "renameTo", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
10
10
|
'credential-test-required': import("@typescript-eslint/utils/ts-eslint").RuleModule<"addTemplate" | "missingCredentialTest", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
11
11
|
'credential-unnecessary-password': import("@typescript-eslint/utils/ts-eslint").RuleModule<"unnecessaryPasswordOption", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-registration-complete.d.ts","sourceRoot":"","sources":["../../src/rules/node-registration-complete.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"node-registration-complete.d.ts","sourceRoot":"","sources":["../../src/rules/node-registration-complete.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,4BAA4B,sJAkEvC,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AST_NODE_TYPES } from '@typescript-eslint/utils';
|
|
2
2
|
import * as path from 'node:path';
|
|
3
|
-
import { createRule, findJsonProperty, findNodeSourceFilesOnDisk, readPackageJsonNodes, } from '../utils/index.js';
|
|
3
|
+
import { createRule, findJsonProperty, findNodeSourceFilesOnDisk, isContainedWithin, readPackageJsonNodes, } from '../utils/index.js';
|
|
4
4
|
export const NodeRegistrationCompleteRule = createRule({
|
|
5
5
|
name: 'node-registration-complete',
|
|
6
6
|
meta: {
|
|
@@ -28,11 +28,23 @@ export const NodeRegistrationCompleteRule = createRule({
|
|
|
28
28
|
if (nodeFilesOnDisk.length === 0) {
|
|
29
29
|
return;
|
|
30
30
|
}
|
|
31
|
-
const
|
|
31
|
+
const registeredFiles = readPackageJsonNodes(context.filename).map((filePath) => path.resolve(filePath));
|
|
32
|
+
const registered = new Set(registeredFiles);
|
|
33
|
+
// Directories of registered entry files, used to recognise versioned
|
|
34
|
+
// nodes: a `VersionedNodeType` entry file (e.g. `SoterGuard.node.ts`) is
|
|
35
|
+
// registered, and its per-version implementations live in subdirectories
|
|
36
|
+
// (e.g. `v1/SoterGuardV1.node.ts`) pulled in by that entry file.
|
|
37
|
+
const registeredDirs = registeredFiles.map((filePath) => path.dirname(filePath));
|
|
32
38
|
const packageDir = path.dirname(context.filename);
|
|
33
39
|
const reportTarget = resolveReportTarget(node);
|
|
34
40
|
for (const nodeFile of nodeFilesOnDisk) {
|
|
35
|
-
|
|
41
|
+
const resolvedNodeFile = path.resolve(nodeFile);
|
|
42
|
+
if (registered.has(resolvedNodeFile)) {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
// Skip per-version implementation files nested under a registered
|
|
46
|
+
// versioned node's entry directory.
|
|
47
|
+
if (isRegisteredThroughVersionedEntry(resolvedNodeFile, registeredDirs)) {
|
|
36
48
|
continue;
|
|
37
49
|
}
|
|
38
50
|
context.report({
|
|
@@ -45,6 +57,17 @@ export const NodeRegistrationCompleteRule = createRule({
|
|
|
45
57
|
};
|
|
46
58
|
},
|
|
47
59
|
});
|
|
60
|
+
/**
|
|
61
|
+
* Determines whether a node file is a per-version implementation of a registered
|
|
62
|
+
* versioned node. Such files sit in a subdirectory of the registered
|
|
63
|
+
* `VersionedNodeType` entry file (e.g. `SoterGuard/v1/SoterGuardV1.node.ts` under
|
|
64
|
+
* the entry `SoterGuard/SoterGuard.node.ts`), so they are discovered through the
|
|
65
|
+
* entry file rather than being listed individually in `n8n.nodes`.
|
|
66
|
+
*/
|
|
67
|
+
function isRegisteredThroughVersionedEntry(nodeFile, registeredDirs) {
|
|
68
|
+
const nodeDir = path.dirname(nodeFile);
|
|
69
|
+
return registeredDirs.some((registeredDir) => registeredDir !== nodeDir && isContainedWithin(registeredDir, nodeDir));
|
|
70
|
+
}
|
|
48
71
|
/**
|
|
49
72
|
* Reports against the most specific available node: the `n8n.nodes` array, the
|
|
50
73
|
* `n8n` object, or the package.json root object as a fallback.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-registration-complete.js","sourceRoot":"","sources":["../../src/rules/node-registration-complete.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EACN,UAAU,EACV,gBAAgB,EAChB,yBAAyB,EACzB,oBAAoB,GACpB,MAAM,mBAAmB,CAAC;AAE3B,MAAM,CAAC,MAAM,4BAA4B,GAAG,UAAU,CAAC;IACtD,IAAI,EAAE,4BAA4B;IAClC,IAAI,EAAE;QACL,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACL,WAAW,EACV,+GAA+G;SAChH;QACD,QAAQ,EAAE;YACT,iBAAiB,EAChB,iIAAiI;SAClI;QACD,MAAM,EAAE,EAAE;KACV;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACb,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;YAChD,OAAO,EAAE,CAAC;QACX,CAAC;QAED,OAAO;YACN,gBAAgB,CAAC,IAA+B;gBAC/C,yDAAyD;gBACzD,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,KAAK,cAAc,CAAC,mBAAmB,EAAE,CAAC;oBAC9D,OAAO;gBACR,CAAC;gBAED,MAAM,eAAe,GAAG,yBAAyB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;gBACpE,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAClC,OAAO;gBACR,CAAC;gBAED,MAAM,
|
|
1
|
+
{"version":3,"file":"node-registration-complete.js","sourceRoot":"","sources":["../../src/rules/node-registration-complete.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const NodeUsableAsToolRule: import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingUsableAsTool", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
1
|
+
export declare const NodeUsableAsToolRule: import("@typescript-eslint/utils/ts-eslint").RuleModule<"aiOnlyUsableAsTool" | "missingUsableAsTool" | "triggerUsableAsTool", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
2
2
|
//# sourceMappingURL=node-usable-as-tool.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-usable-as-tool.d.ts","sourceRoot":"","sources":["../../src/rules/node-usable-as-tool.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"node-usable-as-tool.d.ts","sourceRoot":"","sources":["../../src/rules/node-usable-as-tool.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,oBAAoB,uMA2G/B,CAAC"}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { TSESTree } from '@typescript-eslint/utils';
|
|
2
|
-
import { isNodeTypeClass, findClassProperty, findObjectProperty, createRule, } from '../utils/index.js';
|
|
2
|
+
import { isNodeTypeClass, isTriggerNode, findClassProperty, findObjectProperty, createRule, } from '../utils/index.js';
|
|
3
|
+
function isSetToTrue(property) {
|
|
4
|
+
return property?.value.type === TSESTree.AST_NODE_TYPES.Literal && property.value.value === true;
|
|
5
|
+
}
|
|
3
6
|
export const NodeUsableAsToolRule = createRule({
|
|
4
7
|
name: 'node-usable-as-tool',
|
|
5
8
|
meta: {
|
|
@@ -9,6 +12,8 @@ export const NodeUsableAsToolRule = createRule({
|
|
|
9
12
|
},
|
|
10
13
|
messages: {
|
|
11
14
|
missingUsableAsTool: 'Node class should have usableAsTool property. When in doubt, set it to true.',
|
|
15
|
+
triggerUsableAsTool: 'Trigger nodes must not set usableAsTool: true. Trigger nodes cannot be invoked as AI tools and doing so pollutes the tool picker. Remove this property.',
|
|
16
|
+
aiOnlyUsableAsTool: 'AI-only nodes (non-main output, no inputs) must not set usableAsTool: true. These nodes are only usable through their AI connection type, not as a generic tool, and doing so pollutes the tool picker. Remove this property.',
|
|
12
17
|
},
|
|
13
18
|
fixable: 'code',
|
|
14
19
|
schema: [],
|
|
@@ -29,6 +34,15 @@ export const NodeUsableAsToolRule = createRule({
|
|
|
29
34
|
return;
|
|
30
35
|
}
|
|
31
36
|
const usableAsToolProperty = findObjectProperty(descriptionValue, 'usableAsTool');
|
|
37
|
+
if (isTriggerNode(node, descriptionValue)) {
|
|
38
|
+
if (isSetToTrue(usableAsToolProperty)) {
|
|
39
|
+
context.report({
|
|
40
|
+
node: usableAsToolProperty,
|
|
41
|
+
messageId: 'triggerUsableAsTool',
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
32
46
|
const outputsProperty = findObjectProperty(descriptionValue, 'outputs');
|
|
33
47
|
const inputsProperty = findObjectProperty(descriptionValue, 'inputs');
|
|
34
48
|
if (outputsProperty?.value?.type === TSESTree.AST_NODE_TYPES.ArrayExpression &&
|
|
@@ -44,6 +58,14 @@ export const NodeUsableAsToolRule = createRule({
|
|
|
44
58
|
});
|
|
45
59
|
const isEmptyInputs = inputsProperty?.value?.elements?.length === 0;
|
|
46
60
|
if (isAiOutput && isEmptyInputs) {
|
|
61
|
+
// These nodes are only ever consumed via their AI connection type (e.g. as an
|
|
62
|
+
// Agent's memory/language model), never invoked directly like a regular tool.
|
|
63
|
+
if (isSetToTrue(usableAsToolProperty)) {
|
|
64
|
+
context.report({
|
|
65
|
+
node: usableAsToolProperty,
|
|
66
|
+
messageId: 'aiOnlyUsableAsTool',
|
|
67
|
+
});
|
|
68
|
+
}
|
|
47
69
|
return;
|
|
48
70
|
}
|
|
49
71
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-usable-as-tool.js","sourceRoot":"","sources":["../../src/rules/node-usable-as-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEpD,OAAO,EACN,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,UAAU,GACV,MAAM,mBAAmB,CAAC;AAE3B,MAAM,CAAC,MAAM,oBAAoB,GAAG,UAAU,CAAC;IAC9C,IAAI,EAAE,qBAAqB;IAC3B,IAAI,EAAE;QACL,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACL,WAAW,EAAE,gDAAgD;SAC7D;QACD,QAAQ,EAAE;YACT,mBAAmB,EAClB,8EAA8E;
|
|
1
|
+
{"version":3,"file":"node-usable-as-tool.js","sourceRoot":"","sources":["../../src/rules/node-usable-as-tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trigger-node-conventions.d.ts","sourceRoot":"","sources":["../../src/rules/trigger-node-conventions.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"trigger-node-conventions.d.ts","sourceRoot":"","sources":["../../src/rules/trigger-node-conventions.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,0BAA0B,uMAgFrC,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TSESTree } from '@typescript-eslint/utils';
|
|
2
|
-
import { isNodeTypeClass, findClassProperty, findObjectProperty, getStringLiteralValue, isFileType, createRule, } from '../utils/index.js';
|
|
2
|
+
import { isNodeTypeClass, isTriggerNodeClass, findClassProperty, findObjectProperty, getStringLiteralValue, isFileType, createRule, } from '../utils/index.js';
|
|
3
3
|
export const TriggerNodeConventionsRule = createRule({
|
|
4
4
|
name: 'trigger-node-conventions',
|
|
5
5
|
meta: {
|
|
@@ -24,7 +24,7 @@ export const TriggerNodeConventionsRule = createRule({
|
|
|
24
24
|
if (!isNodeTypeClass(node)) {
|
|
25
25
|
return;
|
|
26
26
|
}
|
|
27
|
-
if (!node
|
|
27
|
+
if (!isTriggerNodeClass(node)) {
|
|
28
28
|
return;
|
|
29
29
|
}
|
|
30
30
|
const descriptionProperty = findClassProperty(node, 'description');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trigger-node-conventions.js","sourceRoot":"","sources":["../../src/rules/trigger-node-conventions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEpD,OAAO,EACN,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,EACrB,UAAU,EACV,UAAU,GACV,MAAM,mBAAmB,CAAC;AAE3B,MAAM,CAAC,MAAM,0BAA0B,GAAG,UAAU,CAAC;IACpD,IAAI,EAAE,0BAA0B;IAChC,IAAI,EAAE;QACL,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACL,WAAW,EACV,+FAA+F;SAChG;QACD,QAAQ,EAAE;YACT,iBAAiB,EAAE,qEAAqE;YACxF,yBAAyB,EACxB,2EAA2E;YAC5E,cAAc,EAAE,+DAA+D;SAC/E;QACD,MAAM,EAAE,EAAE;KACV;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACb,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,QAAQ,EAAE,UAAU,CAAC,EAAE,CAAC;YAC/C,OAAO,EAAE,CAAC;QACX,CAAC;QAED,OAAO;YACN,gBAAgB,CAAC,IAAI;gBACpB,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC5B,OAAO;gBACR,CAAC;gBAED,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"trigger-node-conventions.js","sourceRoot":"","sources":["../../src/rules/trigger-node-conventions.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import type { TSESTree } from '@typescript-eslint/utils';
|
|
2
2
|
export declare function isNodeTypeClass(node: TSESTree.ClassDeclaration): boolean;
|
|
3
3
|
export declare function isCredentialTypeClass(node: TSESTree.ClassDeclaration): boolean;
|
|
4
|
+
/** Matches this plugin's convention for identifying trigger nodes: class name ends with `Trigger`. */
|
|
5
|
+
export declare function isTriggerNodeClass(node: TSESTree.ClassDeclaration): boolean;
|
|
6
|
+
/**
|
|
7
|
+
* `group` is the authoritative signal for "is this a trigger node" (also catches e.g. Cron,
|
|
8
|
+
* Webhook, versioned `*TriggerV1` classes); the name suffix is kept as a fallback for dynamic
|
|
9
|
+
* `group` values.
|
|
10
|
+
*/
|
|
11
|
+
export declare function isTriggerNode(node: TSESTree.ClassDeclaration, descriptionValue: TSESTree.ObjectExpression): boolean;
|
|
4
12
|
export declare function findClassProperty(node: TSESTree.ClassDeclaration, propertyName: string): TSESTree.PropertyDefinition | null;
|
|
5
13
|
export declare function findObjectProperty(obj: TSESTree.ObjectExpression, propertyName: string): TSESTree.Property | null;
|
|
6
14
|
export declare function getLiteralValue(node: TSESTree.Node | null): string | boolean | number | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ast-utils.d.ts","sourceRoot":"","sources":["../../src/utils/ast-utils.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ast-utils.d.ts","sourceRoot":"","sources":["../../src/utils/ast-utils.ts"],"names":[],"mappings":"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"}
|
package/dist/utils/ast-utils.js
CHANGED
|
@@ -17,6 +17,22 @@ export function isNodeTypeClass(node) {
|
|
|
17
17
|
export function isCredentialTypeClass(node) {
|
|
18
18
|
return implementsInterface(node, 'ICredentialType');
|
|
19
19
|
}
|
|
20
|
+
/** Matches this plugin's convention for identifying trigger nodes: class name ends with `Trigger`. */
|
|
21
|
+
export function isTriggerNodeClass(node) {
|
|
22
|
+
return node.id?.name.endsWith('Trigger') ?? false;
|
|
23
|
+
}
|
|
24
|
+
function hasTriggerGroup(descriptionValue) {
|
|
25
|
+
const groupArray = findArrayLiteralProperty(descriptionValue, 'group');
|
|
26
|
+
return (groupArray?.elements.some((element) => element?.type === AST_NODE_TYPES.Literal && element.value === 'trigger') ?? false);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* `group` is the authoritative signal for "is this a trigger node" (also catches e.g. Cron,
|
|
30
|
+
* Webhook, versioned `*TriggerV1` classes); the name suffix is kept as a fallback for dynamic
|
|
31
|
+
* `group` values.
|
|
32
|
+
*/
|
|
33
|
+
export function isTriggerNode(node, descriptionValue) {
|
|
34
|
+
return hasTriggerGroup(descriptionValue) || isTriggerNodeClass(node);
|
|
35
|
+
}
|
|
20
36
|
export function findClassProperty(node, propertyName) {
|
|
21
37
|
const property = node.body.body.find((member) => member.type === AST_NODE_TYPES.PropertyDefinition &&
|
|
22
38
|
member.key?.type === AST_NODE_TYPES.Identifier &&
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ast-utils.js","sourceRoot":"","sources":["../../src/utils/ast-utils.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ast-utils.js","sourceRoot":"","sources":["../../src/utils/ast-utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAE/C,SAAS,mBAAmB,CAAC,IAA+B,EAAE,aAAqB;IAClF,OAAO,CACN,IAAI,CAAC,UAAU,EAAE,IAAI,CACpB,CAAC,IAAI,EAAE,EAAE,CACR,IAAI,CAAC,IAAI,KAAK,cAAc,CAAC,iBAAiB;QAC9C,IAAI,CAAC,UAAU,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;QAClD,IAAI,CAAC,UAAU,CAAC,IAAI,KAAK,aAAa,CACvC,IAAI,KAAK,CACV,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAA+B;IAC9D,IAAI,mBAAmB,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE,CAAC;QAC5C,OAAO,IAAI,CAAC;IACb,CAAC;IAED,IAAI,IAAI,CAAC,UAAU,EAAE,IAAI,KAAK,cAAc,CAAC,UAAU,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC5F,OAAO,IAAI,CAAC;IACb,CAAC;IAED,OAAO,KAAK,CAAC;AACd,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,IAA+B;IACpE,OAAO,mBAAmB,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;AACrD,CAAC;AAED,sGAAsG;AACtG,MAAM,UAAU,kBAAkB,CAAC,IAA+B;IACjE,OAAO,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC;AACnD,CAAC;AAED,SAAS,eAAe,CAAC,gBAA2C;IACnE,MAAM,UAAU,GAAG,wBAAwB,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;IACvE,OAAO,CACN,UAAU,EAAE,QAAQ,CAAC,IAAI,CACxB,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,EAAE,IAAI,KAAK,cAAc,CAAC,OAAO,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,CACpF,IAAI,KAAK,CACV,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAC5B,IAA+B,EAC/B,gBAA2C;IAE3C,OAAO,eAAe,CAAC,gBAAgB,CAAC,IAAI,kBAAkB,CAAC,IAAI,CAAC,CAAC;AACtE,CAAC;AAED,MAAM,UAAU,iBAAiB,CAChC,IAA+B,EAC/B,YAAoB;IAEpB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CACnC,CAAC,MAAM,EAAE,EAAE,CACV,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,kBAAkB;QACjD,MAAM,CAAC,GAAG,EAAE,IAAI,KAAK,cAAc,CAAC,UAAU;QAC9C,MAAM,CAAC,GAAG,CAAC,IAAI,KAAK,YAAY,CACjC,CAAC;IACF,OAAO,QAAQ,EAAE,IAAI,KAAK,cAAc,CAAC,kBAAkB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;AAC/E,CAAC;AAED,MAAM,UAAU,kBAAkB,CACjC,GAA8B,EAC9B,YAAoB;IAEpB,MAAM,QAAQ,GAAG,GAAG,CAAC,UAAU,CAAC,IAAI,CACnC,CAAC,IAAI,EAAE,EAAE,CACR,IAAI,CAAC,IAAI,KAAK,cAAc,CAAC,QAAQ;QACrC,IAAI,CAAC,GAAG,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;QAC3C,IAAI,CAAC,GAAG,CAAC,IAAI,KAAK,YAAY,CAC/B,CAAC;IACF,OAAO,QAAQ,EAAE,IAAI,KAAK,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAA0B;IACzD,IAAI,IAAI,EAAE,IAAI,KAAK,cAAc,CAAC,OAAO,EAAE,CAAC;QAC3C,OAAO,IAAI,CAAC,KAAyC,CAAC;IACvD,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,IAA0B;IAC/D,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IACpC,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAA0B;IACvD,MAAM,WAAW,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;IAChD,IAAI,WAAW,EAAE,CAAC;QACjB,OAAO,WAAW,CAAC;IACpB,CAAC;IAED,IACC,IAAI,EAAE,IAAI,KAAK,cAAc,CAAC,eAAe;QAC7C,IAAI,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC;QAC7B,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EACvB,CAAC;QACF,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,IAAI,IAAI,CAAC;IAC7C,CAAC;IAED,OAAO,IAAI,CAAC;AACb,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,IAA0B;IAChE,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IACpC,OAAO,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC/B,GAA8B,EAC9B,YAAoB;IAEpB,MAAM,QAAQ,GAAG,GAAG,CAAC,UAAU,CAAC,IAAI,CACnC,CAAC,IAAI,EAAE,EAAE,CACR,IAAI,CAAC,IAAI,KAAK,cAAc,CAAC,QAAQ;QACrC,IAAI,CAAC,GAAG,CAAC,IAAI,KAAK,cAAc,CAAC,OAAO;QACxC,IAAI,CAAC,GAAG,CAAC,KAAK,KAAK,YAAY,CAChC,CAAC;IACF,OAAO,QAAQ,EAAE,IAAI,KAAK,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,wBAAwB,CACvC,GAA8B,EAC9B,YAAoB;IAEpB,MAAM,QAAQ,GAAG,kBAAkB,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IACvD,IAAI,QAAQ,EAAE,KAAK,CAAC,IAAI,KAAK,cAAc,CAAC,eAAe,EAAE,CAAC;QAC7D,OAAO,QAAQ,CAAC,KAAK,CAAC;IACvB,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAED,MAAM,UAAU,oBAAoB,CACnC,IAAiC,EACjC,WAAmB;IAEnB,IAAI,IAAI,CAAC,KAAK,EAAE,IAAI,KAAK,cAAc,CAAC,eAAe;QAAE,OAAO,KAAK,CAAC;IAEtE,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAC9B,CAAC,OAAO,EAAE,EAAE,CACX,OAAO,EAAE,IAAI,KAAK,cAAc,CAAC,OAAO;QACxC,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ;QACjC,OAAO,CAAC,KAAK,KAAK,WAAW,CAC9B,CAAC;AACH,CAAC;AAED,MAAM,UAAU,uBAAuB,CACtC,IAA+B;IAE/B,yEAAyE;IACzE,sEAAsE;IACtE,yEAAyE;IACzE,oBAAoB;IACpB,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,KAAK,cAAc,CAAC,mBAAmB,EAAE,CAAC;QAC9D,OAAO,IAAI,CAAC;IACb,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,QAAgB,EAAE,SAAiB;IAC7D,OAAO,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,IAA6B;IAChE,OAAO,CACN,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;QAC9C,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS;QAC9B,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CACzB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,IAA6B;IAChE,OAAO,CACN,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,gBAAgB;QACpD,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;QACrD,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS;QACrC,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CACzB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,8BAA8B,CAC7C,OAAqD;IAErD,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAE1B,MAAM,WAAW,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;IACnD,IAAI,WAAW,EAAE,CAAC;QACjB,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IAC7C,CAAC;IAED,IAAI,OAAO,CAAC,IAAI,KAAK,cAAc,CAAC,gBAAgB,EAAE,CAAC;QACtD,MAAM,YAAY,GAAG,kBAAkB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACzD,MAAM,gBAAgB,GAAG,kBAAkB,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAEjE,IAAI,YAAY,EAAE,CAAC;YAClB,MAAM,SAAS,GAAG,qBAAqB,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;YAC5D,MAAM,aAAa,GAAG,gBAAgB;gBACrC,CAAC,CAAC,qBAAqB,CAAC,gBAAgB,CAAC,KAAK,CAAC;gBAC/C,CAAC,CAAC,SAAS,CAAC;YAEb,IAAI,SAAS,EAAE,CAAC;gBACf,OAAO;oBACN,IAAI,EAAE,SAAS;oBACf,QAAQ,EAAE,aAAa,IAAI,SAAS;oBACpC,IAAI,EAAE,YAAY,CAAC,KAAK;iBACxB,CAAC;YACH,CAAC;QACF,CAAC;IACF,CAAC;IAED,OAAO,IAAI,CAAC;AACb,CAAC;AAED,MAAM,UAAU,8BAA8B,CAC7C,OAAqD;IAErD,MAAM,IAAI,GAAG,8BAA8B,CAAC,OAAO,CAAC,CAAC;IACrD,OAAO,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC3D,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,mBAAmB,CAAC,IAA+B;IAClE,OAAO,CACN,IAAI,CAAC,MAAM,EAAE,IAAI,KAAK,cAAc,CAAC,gBAAgB;QACrD,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,KAAK,cAAc,CAAC,cAAc;QAC1D,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,KAAK,cAAc,CAAC,UAAU;QACxD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,SAAS,CACvC,CAAC;AACH,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,gBAAgB,CAAC,IAA6B,EAAE,MAAc;IAC7E,OAAO,CACN,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,gBAAgB;QACpD,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,cAAc;QACzD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;QACvD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,MAAM,CACpC,CAAC;AACH,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,uBAAuB,CAAC,IAA6B,EAAE,MAAc;IACpF,OAAO,CACN,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,gBAAgB;QACpD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;QACvD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,MAAM;QACpC,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,CAChC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CACjC,MAAc,EACd,UAAuB,EACvB,WAAW,GAAW,CAAC,EACvB,UAAU,GAAW,CAAC;IAEtB,MAAM,OAAO,GAA8C,EAAE,CAAC;IAE9D,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACpC,MAAM,mBAAmB,GAAG,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,SAAS,CAAC,WAAW,EAAE,CAAC,CAAC;QAEpF,IAAI,mBAAmB,IAAI,WAAW,EAAE,CAAC;YACxC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,mBAAmB,EAAE,CAAC,CAAC;QAClE,CAAC;IACF,CAAC;IAED,OAAO,OAAO;SACZ,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC;SACvC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC;SACpB,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AAC9B,CAAC"}
|
|
@@ -44,3 +44,29 @@ Every node file is registered:
|
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
```
|
|
47
|
+
|
|
48
|
+
### Versioned nodes
|
|
49
|
+
|
|
50
|
+
A versioned node registers only its `VersionedNodeType` entry file. Its per-version
|
|
51
|
+
implementations live in subdirectories of that entry file and are pulled in by it, so
|
|
52
|
+
they must **not** be listed individually in `n8n.nodes`. The rule recognises this and
|
|
53
|
+
does not flag the version files.
|
|
54
|
+
|
|
55
|
+
Given:
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
nodes/SoterGuard/SoterGuard.node.ts
|
|
59
|
+
nodes/SoterGuard/v1/SoterGuardV1.node.ts
|
|
60
|
+
nodes/SoterGuard/v2/SoterGuardV2.node.ts
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
registering just the entry file is correct:
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"name": "n8n-nodes-my-service",
|
|
68
|
+
"n8n": {
|
|
69
|
+
"nodes": ["dist/nodes/SoterGuard/SoterGuard.node.js"]
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
@@ -10,6 +10,11 @@
|
|
|
10
10
|
|
|
11
11
|
Ensures your nodes declare whether they can be used as tools in AI workflows. This property helps n8n determine if your node is suitable for AI-assisted automation.
|
|
12
12
|
|
|
13
|
+
Two categories of node are exempt from the "must declare `usableAsTool`" requirement, and are additionally forbidden from setting `usableAsTool: true`, since doing so gets them converted into a synthetic tool variant that pollutes the AI Agent's tool picker even though they can't be meaningfully invoked as one:
|
|
14
|
+
|
|
15
|
+
- **Trigger nodes** — cannot be invoked as AI tools. A node is treated as a trigger if `description.group` includes `'trigger'`, or (as a fallback) its class name ends with `Trigger`.
|
|
16
|
+
- **AI-only nodes** — nodes with a non-`main` output (e.g. `NodeConnectionTypes.AiLanguageModel`, `AiMemory`, `AiEmbedding`) and no inputs. These are only usable through their AI connection type (e.g. plugged into an Agent as its memory or language model), not as a generic callable tool.
|
|
17
|
+
|
|
13
18
|
## Examples
|
|
14
19
|
|
|
15
20
|
### ❌ Incorrect
|
|
@@ -27,6 +32,35 @@ export class MyNode implements INodeType {
|
|
|
27
32
|
}
|
|
28
33
|
```
|
|
29
34
|
|
|
35
|
+
```typescript
|
|
36
|
+
export class MyTrigger implements INodeType {
|
|
37
|
+
description: INodeTypeDescription = {
|
|
38
|
+
displayName: 'My Trigger',
|
|
39
|
+
name: 'myTrigger',
|
|
40
|
+
group: ['trigger'],
|
|
41
|
+
version: 1,
|
|
42
|
+
// Trigger nodes must not opt into the AI tool picker
|
|
43
|
+
usableAsTool: true,
|
|
44
|
+
properties: [],
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
export class MyMemory implements INodeType {
|
|
51
|
+
description: INodeTypeDescription = {
|
|
52
|
+
displayName: 'My Memory',
|
|
53
|
+
name: 'myMemory',
|
|
54
|
+
version: 1,
|
|
55
|
+
inputs: [],
|
|
56
|
+
outputs: [NodeConnectionTypes.AiMemory],
|
|
57
|
+
// AI-only nodes must not opt into the AI tool picker
|
|
58
|
+
usableAsTool: true,
|
|
59
|
+
properties: [],
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
30
64
|
### ✅ Correct
|
|
31
65
|
|
|
32
66
|
```typescript
|
|
@@ -41,3 +75,28 @@ export class MyNode implements INodeType {
|
|
|
41
75
|
};
|
|
42
76
|
}
|
|
43
77
|
```
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
export class MyTrigger implements INodeType {
|
|
81
|
+
description: INodeTypeDescription = {
|
|
82
|
+
displayName: 'My Trigger',
|
|
83
|
+
name: 'myTrigger',
|
|
84
|
+
group: ['trigger'],
|
|
85
|
+
version: 1,
|
|
86
|
+
properties: [],
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
export class MyMemory implements INodeType {
|
|
93
|
+
description: INodeTypeDescription = {
|
|
94
|
+
displayName: 'My Memory',
|
|
95
|
+
name: 'myMemory',
|
|
96
|
+
version: 1,
|
|
97
|
+
inputs: [],
|
|
98
|
+
outputs: [NodeConnectionTypes.AiMemory],
|
|
99
|
+
properties: [],
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
```
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@n8n/eslint-plugin-community-nodes",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.30.0",
|
|
5
5
|
"main": "./dist/plugin.js",
|
|
6
6
|
"types": "./dist/plugin.d.ts",
|
|
7
7
|
"exports": {
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
"typescript": "npm:@typescript/typescript6@6.0.2",
|
|
26
26
|
"vite": "^8.0.2",
|
|
27
27
|
"vitest": "^4.1.9",
|
|
28
|
-
"@n8n/typescript-config": "1.
|
|
29
|
-
"@n8n/vitest-config": "1.
|
|
30
|
-
"n8n-workflow": "2.
|
|
28
|
+
"@n8n/typescript-config": "1.10.0",
|
|
29
|
+
"@n8n/vitest-config": "1.21.0",
|
|
30
|
+
"n8n-workflow": "2.37.0"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"eslint": "9.29.0",
|
|
@@ -20,6 +20,16 @@ const packageJsonPath = '/tmp/package.json';
|
|
|
20
20
|
const fooNode = '/tmp/nodes/Foo/Foo.node.ts';
|
|
21
21
|
const barNode = '/tmp/nodes/Bar/Bar.node.ts';
|
|
22
22
|
|
|
23
|
+
// Versioned node: the v1/v2 implementations sit behind a `VersionedNodeType`
|
|
24
|
+
// entry file, and only that entry file is listed in `n8n.nodes`.
|
|
25
|
+
const versionedEntryNode = '/tmp/nodes/SoterGuard/SoterGuard.node.ts';
|
|
26
|
+
const versionedV1Node = '/tmp/nodes/SoterGuard/v1/SoterGuardV1.node.ts';
|
|
27
|
+
const versionedV2Node = '/tmp/nodes/SoterGuard/v2/SoterGuardV2.node.ts';
|
|
28
|
+
|
|
29
|
+
// A sibling node file in the same directory as a registered node (not nested in a
|
|
30
|
+
// version subdirectory) is not a versioned implementation and must still be flagged.
|
|
31
|
+
const fooSiblingNode = '/tmp/nodes/Foo/FooExtra.node.ts';
|
|
32
|
+
|
|
23
33
|
const ruleTester = new RuleTester();
|
|
24
34
|
|
|
25
35
|
function setup(onDisk: string[], registered: string[]): void {
|
|
@@ -46,6 +56,17 @@ ruleTester.run('node-registration-complete', NodeRegistrationCompleteRule, {
|
|
|
46
56
|
filename: 'some-config.json',
|
|
47
57
|
code: '{ "name": "n8n-nodes-example" }',
|
|
48
58
|
},
|
|
59
|
+
{
|
|
60
|
+
// A versioned node registers only its `VersionedNodeType` entry file in
|
|
61
|
+
// `n8n.nodes`; the per-version implementation files (v1/v2) are pulled in
|
|
62
|
+
// by that entry file and must not be flagged as unregistered.
|
|
63
|
+
name: 'versioned node registered via its entry file does not flag its version implementations',
|
|
64
|
+
filename: packageJsonPath,
|
|
65
|
+
code: '{ "name": "n8n-nodes-example", "n8n": { "nodes": ["dist/nodes/SoterGuard/SoterGuard.node.js"] } }',
|
|
66
|
+
before() {
|
|
67
|
+
setup([versionedEntryNode, versionedV1Node, versionedV2Node], [versionedEntryNode]);
|
|
68
|
+
},
|
|
69
|
+
},
|
|
49
70
|
],
|
|
50
71
|
invalid: [
|
|
51
72
|
{
|
|
@@ -74,6 +95,20 @@ ruleTester.run('node-registration-complete', NodeRegistrationCompleteRule, {
|
|
|
74
95
|
{ messageId: 'nodeNotRegistered', data: { nodeFile: 'nodes/Bar/Bar.node.ts' } },
|
|
75
96
|
],
|
|
76
97
|
},
|
|
98
|
+
{
|
|
99
|
+
// The unregistered file sits directly beside a registered node, not in a
|
|
100
|
+
// version subdirectory, so it is not covered by the versioned-node entry
|
|
101
|
+
// and must still be reported.
|
|
102
|
+
name: 'unregistered sibling in a registered node directory is still flagged',
|
|
103
|
+
filename: packageJsonPath,
|
|
104
|
+
code: '{ "name": "n8n-nodes-example", "n8n": { "nodes": ["dist/nodes/Foo/Foo.node.js"] } }',
|
|
105
|
+
before() {
|
|
106
|
+
setup([fooNode, fooSiblingNode], [fooNode]);
|
|
107
|
+
},
|
|
108
|
+
errors: [
|
|
109
|
+
{ messageId: 'nodeNotRegistered', data: { nodeFile: 'nodes/Foo/FooExtra.node.ts' } },
|
|
110
|
+
],
|
|
111
|
+
},
|
|
77
112
|
{
|
|
78
113
|
name: 'node files exist on disk but there is no n8n object',
|
|
79
114
|
filename: packageJsonPath,
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
createRule,
|
|
7
7
|
findJsonProperty,
|
|
8
8
|
findNodeSourceFilesOnDisk,
|
|
9
|
+
isContainedWithin,
|
|
9
10
|
readPackageJsonNodes,
|
|
10
11
|
} from '../utils/index.js';
|
|
11
12
|
|
|
@@ -41,15 +42,28 @@ export const NodeRegistrationCompleteRule = createRule({
|
|
|
41
42
|
return;
|
|
42
43
|
}
|
|
43
44
|
|
|
44
|
-
const
|
|
45
|
-
|
|
45
|
+
const registeredFiles = readPackageJsonNodes(context.filename).map((filePath) =>
|
|
46
|
+
path.resolve(filePath),
|
|
46
47
|
);
|
|
48
|
+
const registered = new Set(registeredFiles);
|
|
49
|
+
// Directories of registered entry files, used to recognise versioned
|
|
50
|
+
// nodes: a `VersionedNodeType` entry file (e.g. `SoterGuard.node.ts`) is
|
|
51
|
+
// registered, and its per-version implementations live in subdirectories
|
|
52
|
+
// (e.g. `v1/SoterGuardV1.node.ts`) pulled in by that entry file.
|
|
53
|
+
const registeredDirs = registeredFiles.map((filePath) => path.dirname(filePath));
|
|
47
54
|
|
|
48
55
|
const packageDir = path.dirname(context.filename);
|
|
49
56
|
const reportTarget = resolveReportTarget(node);
|
|
50
57
|
|
|
51
58
|
for (const nodeFile of nodeFilesOnDisk) {
|
|
52
|
-
|
|
59
|
+
const resolvedNodeFile = path.resolve(nodeFile);
|
|
60
|
+
if (registered.has(resolvedNodeFile)) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Skip per-version implementation files nested under a registered
|
|
65
|
+
// versioned node's entry directory.
|
|
66
|
+
if (isRegisteredThroughVersionedEntry(resolvedNodeFile, registeredDirs)) {
|
|
53
67
|
continue;
|
|
54
68
|
}
|
|
55
69
|
|
|
@@ -64,6 +78,20 @@ export const NodeRegistrationCompleteRule = createRule({
|
|
|
64
78
|
},
|
|
65
79
|
});
|
|
66
80
|
|
|
81
|
+
/**
|
|
82
|
+
* Determines whether a node file is a per-version implementation of a registered
|
|
83
|
+
* versioned node. Such files sit in a subdirectory of the registered
|
|
84
|
+
* `VersionedNodeType` entry file (e.g. `SoterGuard/v1/SoterGuardV1.node.ts` under
|
|
85
|
+
* the entry `SoterGuard/SoterGuard.node.ts`), so they are discovered through the
|
|
86
|
+
* entry file rather than being listed individually in `n8n.nodes`.
|
|
87
|
+
*/
|
|
88
|
+
function isRegisteredThroughVersionedEntry(nodeFile: string, registeredDirs: string[]): boolean {
|
|
89
|
+
const nodeDir = path.dirname(nodeFile);
|
|
90
|
+
return registeredDirs.some(
|
|
91
|
+
(registeredDir) => registeredDir !== nodeDir && isContainedWithin(registeredDir, nodeDir),
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
67
95
|
/**
|
|
68
96
|
* Reports against the most specific available node: the `n8n.nodes` array, the
|
|
69
97
|
* `n8n` object, or the package.json root object as a fallback.
|
|
@@ -51,6 +51,37 @@ export class RegularClass {
|
|
|
51
51
|
}`;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
function createTriggerNodeCode(
|
|
55
|
+
options: { className?: string; usableAsTool?: boolean } = {},
|
|
56
|
+
): string {
|
|
57
|
+
const { className = 'TestTrigger', usableAsTool } = options;
|
|
58
|
+
const group = className.endsWith('Trigger') ? "['trigger']" : "['trigger', 'schedule']";
|
|
59
|
+
|
|
60
|
+
const properties = [
|
|
61
|
+
`displayName: '${className}'`,
|
|
62
|
+
`name: '${className.charAt(0).toLowerCase()}${className.slice(1)}'`,
|
|
63
|
+
`group: ${group}`,
|
|
64
|
+
'version: 1',
|
|
65
|
+
"description: 'A test trigger node'",
|
|
66
|
+
`defaults: { name: '${className}' }`,
|
|
67
|
+
'inputs: []',
|
|
68
|
+
"outputs: ['main']",
|
|
69
|
+
'properties: []',
|
|
70
|
+
];
|
|
71
|
+
if (usableAsTool) {
|
|
72
|
+
properties.push('usableAsTool: true');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return `
|
|
76
|
+
import type { INodeType, INodeTypeDescription } from 'n8n-workflow';
|
|
77
|
+
|
|
78
|
+
export class ${className} implements INodeType {
|
|
79
|
+
description: INodeTypeDescription = {
|
|
80
|
+
${properties.join(',\n\t\t')},
|
|
81
|
+
};
|
|
82
|
+
}`;
|
|
83
|
+
}
|
|
84
|
+
|
|
54
85
|
function createNodeCodeWithOutputsInputs(
|
|
55
86
|
outputs: string,
|
|
56
87
|
inputs: string,
|
|
@@ -97,22 +128,50 @@ ruleTester.run('node-usable-as-tool', NodeUsableAsToolRule, {
|
|
|
97
128
|
code: createNodeCode(undefined, false),
|
|
98
129
|
},
|
|
99
130
|
{
|
|
100
|
-
name: 'AI-only node: NodeConnectionTypes non-Main output and empty inputs
|
|
131
|
+
name: 'AI-only node: NodeConnectionTypes non-Main output and empty inputs does not require usableAsTool',
|
|
101
132
|
code: createNodeCodeWithOutputsInputs('[NodeConnectionTypes.AiAgent]', '[]'),
|
|
102
133
|
},
|
|
103
134
|
{
|
|
104
|
-
name: 'AI-only node: multiple non-Main NodeConnectionTypes outputs and empty inputs
|
|
135
|
+
name: 'AI-only node: multiple non-Main NodeConnectionTypes outputs and empty inputs does not require usableAsTool',
|
|
105
136
|
code: createNodeCodeWithOutputsInputs(
|
|
106
137
|
'[NodeConnectionTypes.AiAgent, NodeConnectionTypes.AiTool]',
|
|
107
138
|
'[]',
|
|
108
139
|
),
|
|
109
140
|
},
|
|
110
141
|
{
|
|
111
|
-
name: 'AI-only node: non-main string literal output and empty inputs
|
|
142
|
+
name: 'AI-only node: non-main string literal output and empty inputs does not require usableAsTool',
|
|
112
143
|
code: createNodeCodeWithOutputsInputs("['ai_agent']", '[]'),
|
|
113
144
|
},
|
|
145
|
+
{
|
|
146
|
+
name: 'trigger node (class name ends with Trigger) without usableAsTool skips check',
|
|
147
|
+
code: createTriggerNodeCode(),
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
name: "trigger node identified by group: ['trigger'] (class name does not end with Trigger) skips check",
|
|
151
|
+
code: createTriggerNodeCode({ className: 'TestCron' }),
|
|
152
|
+
},
|
|
114
153
|
],
|
|
115
154
|
invalid: [
|
|
155
|
+
{
|
|
156
|
+
name: 'trigger node (class name ends with Trigger) with usableAsTool set to true is forbidden',
|
|
157
|
+
code: createTriggerNodeCode({ usableAsTool: true }),
|
|
158
|
+
errors: [{ messageId: 'triggerUsableAsTool' }],
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
name: "trigger node identified by group: ['trigger'] with usableAsTool set to true is forbidden",
|
|
162
|
+
code: createTriggerNodeCode({ className: 'TestCron', usableAsTool: true }),
|
|
163
|
+
errors: [{ messageId: 'triggerUsableAsTool' }],
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
name: 'AI-only node: non-Main output and empty inputs with usableAsTool set to true is forbidden',
|
|
167
|
+
code: createNodeCodeWithOutputsInputs('[NodeConnectionTypes.AiAgent]', '[]', true),
|
|
168
|
+
errors: [{ messageId: 'aiOnlyUsableAsTool' }],
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
name: 'AI-only node: non-main string literal output and empty inputs with usableAsTool set to true is forbidden',
|
|
172
|
+
code: createNodeCodeWithOutputsInputs("['ai_agent']", '[]', true),
|
|
173
|
+
errors: [{ messageId: 'aiOnlyUsableAsTool' }],
|
|
174
|
+
},
|
|
116
175
|
{
|
|
117
176
|
name: 'node missing usableAsTool property',
|
|
118
177
|
code: createNodeCode('missing'),
|