@n8n/eslint-plugin-community-nodes 0.35.0 → 0.35.1
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"n8n-object-validation.d.ts","sourceRoot":"","sources":["../../src/rules/n8n-object-validation.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"n8n-object-validation.d.ts","sourceRoot":"","sources":["../../src/rules/n8n-object-validation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAY,MAAM,0BAA0B,CAAC;AAKnE,KAAK,UAAU,GACZ,kBAAkB,GAClB,yBAAyB,GACzB,wBAAwB,GACxB,wBAAwB,GACxB,iBAAiB,GACjB,kBAAkB,GAClB,eAAe,GACf,wBAAwB,GACxB,mBAAmB,GACnB,mBAAmB,GACnB,yBAAyB,GACzB,yBAAyB,GACzB,eAAe,CAAC;AAInB,eAAO,MAAM,uBAAuB;;CA8ElC,CAAC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { parseNodesApiLevel } from '@n8n/utils/nodes-api-level';
|
|
1
2
|
import { AST_NODE_TYPES } from '@typescript-eslint/utils';
|
|
2
3
|
import { createRule, findJsonProperty, getTopLevelObjectInJson } from '../utils/index.js';
|
|
3
4
|
export const N8nObjectValidationRule = createRule({
|
|
@@ -10,8 +11,8 @@ export const N8nObjectValidationRule = createRule({
|
|
|
10
11
|
messages: {
|
|
11
12
|
missingN8nObject: 'Community node package.json must contain an "n8n" object describing the package.',
|
|
12
13
|
wrongLocationApiVersion: '"n8nNodesApiVersion" must be inside the "n8n" section, not at the root level of package.json.',
|
|
13
|
-
missingNodesApiVersion: 'The "n8n" object must declare "n8nNodesApiVersion" (a positive integer).',
|
|
14
|
-
invalidNodesApiVersion: '"n8n.n8nNodesApiVersion" must be a positive integer, got {{ value }}.',
|
|
14
|
+
missingNodesApiVersion: 'The "n8n" object must declare "n8nNodesApiVersion" (a positive integer, or a "<major>" or "<major>.<minor>" string).',
|
|
15
|
+
invalidNodesApiVersion: '"n8n.n8nNodesApiVersion" must be a positive integer, or a "<major>" or "<major>.<minor>" string, got {{ value }}.',
|
|
15
16
|
missingN8nNodes: 'The "n8n" object must declare "nodes" as an array of "dist/" paths.',
|
|
16
17
|
n8nNodesNotArray: '"n8n.nodes" must be an array of "dist/" paths.',
|
|
17
18
|
emptyN8nNodes: '"n8n.nodes" must contain at least one path.',
|
|
@@ -73,7 +74,7 @@ function validateApiVersion(context, n8nObject) {
|
|
|
73
74
|
return;
|
|
74
75
|
}
|
|
75
76
|
const valueNode = apiVersionProp.value;
|
|
76
|
-
if (valueNode.type !== AST_NODE_TYPES.Literal ||
|
|
77
|
+
if (valueNode.type !== AST_NODE_TYPES.Literal || parseNodesApiLevel(valueNode.value) === null) {
|
|
77
78
|
context.report({
|
|
78
79
|
node: apiVersionProp,
|
|
79
80
|
messageId: 'invalidNodesApiVersion',
|
|
@@ -142,7 +143,4 @@ function validatePathArray(context, elements, notStringMessageId, notInDistMessa
|
|
|
142
143
|
}
|
|
143
144
|
}
|
|
144
145
|
}
|
|
145
|
-
function isPositiveInteger(value) {
|
|
146
|
-
return typeof value === 'number' && Number.isInteger(value) && value > 0;
|
|
147
|
-
}
|
|
148
146
|
//# sourceMappingURL=n8n-object-validation.js.map
|
|
@@ -17,8 +17,9 @@ register at install time and the failure is opaque to the user.
|
|
|
17
17
|
This rule enforces the structural contract:
|
|
18
18
|
|
|
19
19
|
- `package.json` must contain an `n8n` object.
|
|
20
|
-
- `n8n.n8nNodesApiVersion` must be present and a positive integer
|
|
21
|
-
|
|
20
|
+
- `n8n.n8nNodesApiVersion` must be present and a positive integer, or a
|
|
21
|
+
`"<major>"` or `"<major>.<minor>"` string such as `"3"` or `"3.1"`. It must
|
|
22
|
+
live inside `n8n`, not at the root.
|
|
22
23
|
- `n8n.nodes` must be a non-empty array of strings, each starting with `dist/`.
|
|
23
24
|
- `n8n.credentials`, if present, must be an array of strings, each starting
|
|
24
25
|
with `dist/`.
|
|
@@ -53,7 +54,7 @@ the templates published by `@n8n/node-cli` and `@n8n/create-node`.
|
|
|
53
54
|
{
|
|
54
55
|
"name": "n8n-nodes-example",
|
|
55
56
|
"n8n": {
|
|
56
|
-
"n8nNodesApiVersion": "
|
|
57
|
+
"n8nNodesApiVersion": "v1",
|
|
57
58
|
"nodes": ["nodes/Foo/Foo.node.js"]
|
|
58
59
|
}
|
|
59
60
|
}
|
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.35.
|
|
4
|
+
"version": "0.35.1",
|
|
5
5
|
"main": "./dist/plugin.js",
|
|
6
6
|
"types": "./dist/plugin.d.ts",
|
|
7
7
|
"exports": {
|
|
@@ -11,15 +11,16 @@
|
|
|
11
11
|
}
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
+
"@n8n/utils": "1.50.1",
|
|
14
15
|
"@typescript-eslint/typescript-estree": "8.70.0",
|
|
15
16
|
"@typescript-eslint/utils": "8.70.0",
|
|
16
17
|
"fastest-levenshtein": "1.0.16"
|
|
17
18
|
},
|
|
18
19
|
"devDependencies": {
|
|
19
20
|
"@n8n/typescript-config": "1.12.0",
|
|
20
|
-
"@n8n/vitest-config": "1.
|
|
21
|
+
"@n8n/vitest-config": "1.24.0",
|
|
21
22
|
"@types/node": "24.10.1",
|
|
22
|
-
"n8n-workflow": "2.
|
|
23
|
+
"n8n-workflow": "2.43.2",
|
|
23
24
|
"@typescript-eslint/rule-tester": "8.70.0",
|
|
24
25
|
"eslint-doc-generator": "^2.2.2",
|
|
25
26
|
"eslint-plugin-eslint-plugin": "^7.0.0",
|
|
@@ -26,6 +26,21 @@ ruleTester.run('n8n-object-validation', N8nObjectValidationRule, {
|
|
|
26
26
|
filename: 'package.json',
|
|
27
27
|
code: '{ "name": "n8n-nodes-example", "n8n": { "n8nNodesApiVersion": 2, "nodes": ["dist/x.js"] } }',
|
|
28
28
|
},
|
|
29
|
+
{
|
|
30
|
+
name: 'major-only string api version is allowed',
|
|
31
|
+
filename: 'package.json',
|
|
32
|
+
code: '{ "name": "n8n-nodes-example", "n8n": { "n8nNodesApiVersion": "3", "nodes": ["dist/x.js"] } }',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: 'major.minor string api version is allowed',
|
|
36
|
+
filename: 'package.json',
|
|
37
|
+
code: '{ "name": "n8n-nodes-example", "n8n": { "n8nNodesApiVersion": "3.1", "nodes": ["dist/x.js"] } }',
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: 'two-digit minor string api version is allowed',
|
|
41
|
+
filename: 'package.json',
|
|
42
|
+
code: '{ "name": "n8n-nodes-example", "n8n": { "n8nNodesApiVersion": "3.10", "nodes": ["dist/x.js"] } }',
|
|
43
|
+
},
|
|
29
44
|
{
|
|
30
45
|
name: 'non-package.json file is ignored',
|
|
31
46
|
filename: 'some-config.json',
|
|
@@ -77,10 +92,22 @@ ruleTester.run('n8n-object-validation', N8nObjectValidationRule, {
|
|
|
77
92
|
errors: [{ messageId: 'missingNodesApiVersion' }],
|
|
78
93
|
},
|
|
79
94
|
{
|
|
80
|
-
name: 'n8nNodesApiVersion is a string',
|
|
95
|
+
name: 'n8nNodesApiVersion is a non-numeric string',
|
|
96
|
+
filename: 'package.json',
|
|
97
|
+
code: '{ "name": "n8n-nodes-example", "n8n": { "n8nNodesApiVersion": "v3", "nodes": ["dist/x.js"] } }',
|
|
98
|
+
errors: [{ messageId: 'invalidNodesApiVersion', data: { value: 'v3' } }],
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
name: 'n8nNodesApiVersion is a string with a patch part',
|
|
102
|
+
filename: 'package.json',
|
|
103
|
+
code: '{ "name": "n8n-nodes-example", "n8n": { "n8nNodesApiVersion": "3.1.0", "nodes": ["dist/x.js"] } }',
|
|
104
|
+
errors: [{ messageId: 'invalidNodesApiVersion', data: { value: '3.1.0' } }],
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
name: 'n8nNodesApiVersion is a zero-major string',
|
|
81
108
|
filename: 'package.json',
|
|
82
|
-
code: '{ "name": "n8n-nodes-example", "n8n": { "n8nNodesApiVersion": "1", "nodes": ["dist/x.js"] } }',
|
|
83
|
-
errors: [{ messageId: 'invalidNodesApiVersion', data: { value: '1' } }],
|
|
109
|
+
code: '{ "name": "n8n-nodes-example", "n8n": { "n8nNodesApiVersion": "0.1", "nodes": ["dist/x.js"] } }',
|
|
110
|
+
errors: [{ messageId: 'invalidNodesApiVersion', data: { value: '0.1' } }],
|
|
84
111
|
},
|
|
85
112
|
{
|
|
86
113
|
name: 'n8nNodesApiVersion is zero',
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { parseNodesApiLevel } from '@n8n/utils/nodes-api-level';
|
|
1
2
|
import type { TSESLint, TSESTree } from '@typescript-eslint/utils';
|
|
2
3
|
import { AST_NODE_TYPES } from '@typescript-eslint/utils';
|
|
3
4
|
|
|
@@ -34,9 +35,9 @@ export const N8nObjectValidationRule = createRule<[], MessageIds>({
|
|
|
34
35
|
wrongLocationApiVersion:
|
|
35
36
|
'"n8nNodesApiVersion" must be inside the "n8n" section, not at the root level of package.json.',
|
|
36
37
|
missingNodesApiVersion:
|
|
37
|
-
'The "n8n" object must declare "n8nNodesApiVersion" (a positive integer).',
|
|
38
|
+
'The "n8n" object must declare "n8nNodesApiVersion" (a positive integer, or a "<major>" or "<major>.<minor>" string).',
|
|
38
39
|
invalidNodesApiVersion:
|
|
39
|
-
'"n8n.n8nNodesApiVersion" must be a positive integer, got {{ value }}.',
|
|
40
|
+
'"n8n.n8nNodesApiVersion" must be a positive integer, or a "<major>" or "<major>.<minor>" string, got {{ value }}.',
|
|
40
41
|
missingN8nNodes: 'The "n8n" object must declare "nodes" as an array of "dist/" paths.',
|
|
41
42
|
n8nNodesNotArray: '"n8n.nodes" must be an array of "dist/" paths.',
|
|
42
43
|
emptyN8nNodes: '"n8n.nodes" must contain at least one path.',
|
|
@@ -108,7 +109,7 @@ function validateApiVersion(context: Context, n8nObject: TSESTree.ObjectExpressi
|
|
|
108
109
|
}
|
|
109
110
|
|
|
110
111
|
const valueNode = apiVersionProp.value;
|
|
111
|
-
if (valueNode.type !== AST_NODE_TYPES.Literal ||
|
|
112
|
+
if (valueNode.type !== AST_NODE_TYPES.Literal || parseNodesApiLevel(valueNode.value) === null) {
|
|
112
113
|
context.report({
|
|
113
114
|
node: apiVersionProp,
|
|
114
115
|
messageId: 'invalidNodesApiVersion',
|
|
@@ -194,7 +195,3 @@ function validatePathArray(
|
|
|
194
195
|
}
|
|
195
196
|
}
|
|
196
197
|
}
|
|
197
|
-
|
|
198
|
-
function isPositiveInteger(value: unknown): boolean {
|
|
199
|
-
return typeof value === 'number' && Number.isInteger(value) && value > 0;
|
|
200
|
-
}
|