@n8n/eslint-plugin-community-nodes 0.4.0 → 0.6.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.
Files changed (116) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/README.md +60 -0
  3. package/dist/plugin.d.ts +144 -28
  4. package/dist/plugin.d.ts.map +1 -1
  5. package/dist/plugin.js +28 -25
  6. package/dist/plugin.js.map +1 -1
  7. package/dist/rules/credential-documentation-url.d.ts +7 -0
  8. package/dist/rules/credential-documentation-url.d.ts.map +1 -0
  9. package/dist/rules/credential-documentation-url.js +100 -0
  10. package/dist/rules/credential-documentation-url.js.map +1 -0
  11. package/dist/rules/credential-password-field.d.ts +1 -2
  12. package/dist/rules/credential-password-field.d.ts.map +1 -1
  13. package/dist/rules/credential-password-field.js +25 -14
  14. package/dist/rules/credential-password-field.js.map +1 -1
  15. package/dist/rules/credential-test-required.d.ts +1 -2
  16. package/dist/rules/credential-test-required.d.ts.map +1 -1
  17. package/dist/rules/credential-test-required.js +43 -5
  18. package/dist/rules/credential-test-required.js.map +1 -1
  19. package/dist/rules/icon-validation.d.ts +1 -2
  20. package/dist/rules/icon-validation.d.ts.map +1 -1
  21. package/dist/rules/icon-validation.js +81 -15
  22. package/dist/rules/icon-validation.js.map +1 -1
  23. package/dist/rules/index.d.ts +9 -5
  24. package/dist/rules/index.d.ts.map +1 -1
  25. package/dist/rules/index.js +7 -5
  26. package/dist/rules/index.js.map +1 -1
  27. package/dist/rules/no-credential-reuse.d.ts +1 -2
  28. package/dist/rules/no-credential-reuse.d.ts.map +1 -1
  29. package/dist/rules/no-credential-reuse.js +33 -4
  30. package/dist/rules/no-credential-reuse.js.map +1 -1
  31. package/dist/rules/no-deprecated-workflow-functions.d.ts +1 -2
  32. package/dist/rules/no-deprecated-workflow-functions.d.ts.map +1 -1
  33. package/dist/rules/no-deprecated-workflow-functions.js +38 -10
  34. package/dist/rules/no-deprecated-workflow-functions.js.map +1 -1
  35. package/dist/rules/no-restricted-globals.d.ts +2 -2
  36. package/dist/rules/no-restricted-globals.d.ts.map +1 -1
  37. package/dist/rules/no-restricted-globals.js +5 -3
  38. package/dist/rules/no-restricted-globals.js.map +1 -1
  39. package/dist/rules/no-restricted-imports.d.ts +1 -2
  40. package/dist/rules/no-restricted-imports.d.ts.map +1 -1
  41. package/dist/rules/no-restricted-imports.js +3 -3
  42. package/dist/rules/no-restricted-imports.js.map +1 -1
  43. package/dist/rules/node-usable-as-tool.d.ts +1 -2
  44. package/dist/rules/node-usable-as-tool.d.ts.map +1 -1
  45. package/dist/rules/node-usable-as-tool.js +6 -5
  46. package/dist/rules/node-usable-as-tool.js.map +1 -1
  47. package/dist/rules/package-name-convention.d.ts +1 -2
  48. package/dist/rules/package-name-convention.d.ts.map +1 -1
  49. package/dist/rules/package-name-convention.js +38 -2
  50. package/dist/rules/package-name-convention.js.map +1 -1
  51. package/dist/rules/resource-operation-pattern.d.ts +1 -2
  52. package/dist/rules/resource-operation-pattern.d.ts.map +1 -1
  53. package/dist/rules/resource-operation-pattern.js +9 -7
  54. package/dist/rules/resource-operation-pattern.js.map +1 -1
  55. package/dist/utils/ast-utils.d.ts +2 -1
  56. package/dist/utils/ast-utils.d.ts.map +1 -1
  57. package/dist/utils/ast-utils.js +37 -19
  58. package/dist/utils/ast-utils.js.map +1 -1
  59. package/dist/utils/file-utils.d.ts +1 -0
  60. package/dist/utils/file-utils.d.ts.map +1 -1
  61. package/dist/utils/file-utils.js +54 -14
  62. package/dist/utils/file-utils.js.map +1 -1
  63. package/dist/utils/index.d.ts +1 -0
  64. package/dist/utils/index.d.ts.map +1 -1
  65. package/dist/utils/index.js +1 -0
  66. package/dist/utils/index.js.map +1 -1
  67. package/dist/utils/rule-creator.d.ts +3 -0
  68. package/dist/utils/rule-creator.d.ts.map +1 -0
  69. package/dist/utils/rule-creator.js +5 -0
  70. package/dist/utils/rule-creator.js.map +1 -0
  71. package/docs/rules/credential-documentation-url.md +94 -0
  72. package/docs/rules/credential-password-field.md +45 -0
  73. package/docs/rules/credential-test-required.md +58 -0
  74. package/docs/rules/icon-validation.md +67 -0
  75. package/docs/rules/no-credential-reuse.md +82 -0
  76. package/docs/rules/no-deprecated-workflow-functions.md +61 -0
  77. package/docs/rules/no-restricted-globals.md +44 -0
  78. package/docs/rules/no-restricted-imports.md +47 -0
  79. package/docs/rules/node-usable-as-tool.md +43 -0
  80. package/docs/rules/package-name-convention.md +52 -0
  81. package/docs/rules/resource-operation-pattern.md +84 -0
  82. package/eslint.config.mjs +27 -0
  83. package/package.json +25 -4
  84. package/src/plugin.ts +30 -26
  85. package/src/rules/credential-documentation-url.test.ts +306 -0
  86. package/src/rules/credential-documentation-url.ts +129 -0
  87. package/src/rules/credential-password-field.test.ts +1 -0
  88. package/src/rules/credential-password-field.ts +34 -16
  89. package/src/rules/credential-test-required.test.ts +84 -57
  90. package/src/rules/credential-test-required.ts +51 -5
  91. package/src/rules/icon-validation.test.ts +97 -14
  92. package/src/rules/icon-validation.ts +95 -14
  93. package/src/rules/index.ts +8 -5
  94. package/src/rules/no-credential-reuse.test.ts +306 -58
  95. package/src/rules/no-credential-reuse.ts +43 -3
  96. package/src/rules/no-deprecated-workflow-functions.test.ts +70 -0
  97. package/src/rules/no-deprecated-workflow-functions.ts +44 -10
  98. package/src/rules/no-restricted-globals.test.ts +1 -0
  99. package/src/rules/no-restricted-globals.ts +6 -3
  100. package/src/rules/no-restricted-imports.test.ts +1 -0
  101. package/src/rules/no-restricted-imports.ts +8 -3
  102. package/src/rules/node-usable-as-tool.test.ts +1 -0
  103. package/src/rules/node-usable-as-tool.ts +8 -6
  104. package/src/rules/package-name-convention.test.ts +82 -5
  105. package/src/rules/package-name-convention.ts +46 -2
  106. package/src/rules/resource-operation-pattern.test.ts +1 -0
  107. package/src/rules/resource-operation-pattern.ts +13 -6
  108. package/src/utils/ast-utils.ts +47 -19
  109. package/src/utils/file-utils.ts +69 -14
  110. package/src/utils/index.ts +1 -0
  111. package/src/utils/rule-creator.ts +6 -0
  112. package/tsconfig.build.json +4 -0
  113. package/tsconfig.build.tsbuildinfo +1 -0
  114. package/tsconfig.eslint.json +5 -0
  115. package/tsconfig.json +1 -2
  116. package/tsconfig.tsbuildinfo +0 -1
@@ -1,8 +1,8 @@
1
- import { readFileSync, existsSync } from 'node:fs';
1
+ import { parse, simpleTraverse, AST_NODE_TYPES } from '@typescript-eslint/typescript-estree';
2
+ import { readFileSync, existsSync, readdirSync } from 'node:fs';
2
3
  import * as path from 'node:path';
3
4
  import { dirname, parse as parsePath } from 'node:path';
4
- import { parse, simpleTraverse, TSESTree } from '@typescript-eslint/typescript-estree';
5
- import { isCredentialTypeClass, isNodeTypeClass, findClassProperty, getStringLiteralValue, findArrayLiteralProperty, extractCredentialInfoFromArray, } from './ast-utils.js';
5
+ import { isCredentialTypeClass, isNodeTypeClass, findClassProperty, getStringLiteralValue, findArrayLiteralProperty, extractCredentialInfoFromArray, findSimilarStrings, } from './ast-utils.js';
6
6
  /**
7
7
  * Checks if the given childPath is contained within the parentPath. Resolves
8
8
  * the paths before comparing them, so that relative paths are also supported.
@@ -30,20 +30,27 @@ export function safeJoinPath(parentPath, ...paths) {
30
30
  return candidate;
31
31
  }
32
32
  export function findPackageJson(startPath) {
33
- let currentDir = startPath;
33
+ let currentDir = path.dirname(startPath);
34
34
  while (parsePath(currentDir).dir !== parsePath(currentDir).root) {
35
35
  const testPath = safeJoinPath(currentDir, 'package.json');
36
- if (existsSync(testPath)) {
36
+ if (fileExistsWithCaseSync(testPath)) {
37
37
  return testPath;
38
38
  }
39
39
  currentDir = dirname(currentDir);
40
40
  }
41
41
  return null;
42
42
  }
43
+ function isValidPackageJson(obj) {
44
+ return typeof obj === 'object' && obj !== null;
45
+ }
43
46
  function readPackageJsonN8n(packageJsonPath) {
44
47
  try {
45
- const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
46
- return packageJson.n8n || {};
48
+ const content = readFileSync(packageJsonPath, 'utf8');
49
+ const parsed = JSON.parse(content);
50
+ if (isValidPackageJson(parsed)) {
51
+ return parsed.n8n ?? {};
52
+ }
53
+ return {};
47
54
  }
48
55
  catch {
49
56
  return {};
@@ -63,7 +70,7 @@ function resolveN8nFilePaths(packageJsonPath, filePaths) {
63
70
  }
64
71
  export function readPackageJsonCredentials(packageJsonPath) {
65
72
  const n8nConfig = readPackageJsonN8n(packageJsonPath);
66
- const credentialPaths = n8nConfig.credentials || [];
73
+ const credentialPaths = n8nConfig.credentials ?? [];
67
74
  const credentialFiles = resolveN8nFilePaths(packageJsonPath, credentialPaths);
68
75
  const credentialNames = [];
69
76
  for (const credentialFile of credentialFiles) {
@@ -89,7 +96,7 @@ export function extractCredentialNameFromFile(credentialFilePath) {
89
96
  let credentialName = null;
90
97
  simpleTraverse(ast, {
91
98
  enter(node) {
92
- if (node.type === 'ClassDeclaration' && isCredentialTypeClass(node)) {
99
+ if (node.type === AST_NODE_TYPES.ClassDeclaration && isCredentialTypeClass(node)) {
93
100
  const nameProperty = findClassProperty(node, 'name');
94
101
  if (nameProperty) {
95
102
  const nameValue = getStringLiteralValue(nameProperty.value);
@@ -110,8 +117,9 @@ export function validateIconPath(iconPath, baseDir) {
110
117
  const isFile = iconPath.startsWith('file:');
111
118
  const relativePath = iconPath.replace(/^file:/, '');
112
119
  const isSvg = relativePath.endsWith('.svg');
113
- const fullPath = safeJoinPath(baseDir, relativePath);
114
- const exists = existsSync(fullPath);
120
+ // Should not use safeJoinPath here because iconPath can be outside of the node class folder
121
+ const fullPath = path.join(baseDir, relativePath);
122
+ const exists = fileExistsWithCaseSync(fullPath);
115
123
  return {
116
124
  isValid: isFile && isSvg && exists,
117
125
  isFile,
@@ -121,7 +129,7 @@ export function validateIconPath(iconPath, baseDir) {
121
129
  }
122
130
  export function readPackageJsonNodes(packageJsonPath) {
123
131
  const n8nConfig = readPackageJsonN8n(packageJsonPath);
124
- const nodePaths = n8nConfig.nodes || [];
132
+ const nodePaths = n8nConfig.nodes ?? [];
125
133
  return resolveN8nFilePaths(packageJsonPath, nodePaths);
126
134
  }
127
135
  export function areAllCredentialUsagesTestedByNodes(credentialName, packageDir) {
@@ -150,10 +158,10 @@ function checkCredentialUsageInFile(nodeFile, credentialName) {
150
158
  let allTestedBy = true;
151
159
  simpleTraverse(ast, {
152
160
  enter(node) {
153
- if (node.type === 'ClassDeclaration' && isNodeTypeClass(node)) {
161
+ if (node.type === AST_NODE_TYPES.ClassDeclaration && isNodeTypeClass(node)) {
154
162
  const descriptionProperty = findClassProperty(node, 'description');
155
163
  if (!descriptionProperty?.value ||
156
- descriptionProperty.value.type !== 'ObjectExpression') {
164
+ descriptionProperty.value.type !== AST_NODE_TYPES.ObjectExpression) {
157
165
  return;
158
166
  }
159
167
  const credentialsArray = findArrayLiteralProperty(descriptionProperty.value, 'credentials');
@@ -178,4 +186,36 @@ function checkCredentialUsageInFile(nodeFile, credentialName) {
178
186
  return { hasUsage: false, allTestedBy: true };
179
187
  }
180
188
  }
189
+ function fileExistsWithCaseSync(filePath) {
190
+ try {
191
+ const dir = path.dirname(filePath);
192
+ const file = path.basename(filePath);
193
+ const files = new Set(readdirSync(dir));
194
+ return files.has(file);
195
+ }
196
+ catch {
197
+ return false;
198
+ }
199
+ }
200
+ export function findSimilarSvgFiles(targetPath, baseDir) {
201
+ try {
202
+ const targetFileName = path.basename(targetPath, path.extname(targetPath));
203
+ const targetDir = path.dirname(targetPath);
204
+ // Should not use safeJoinPath here because iconPath can be outside of the node class folder
205
+ const searchDir = path.join(baseDir, targetDir);
206
+ if (!existsSync(searchDir)) {
207
+ return [];
208
+ }
209
+ const files = readdirSync(searchDir);
210
+ const svgFileNames = files
211
+ .filter((file) => file.endsWith('.svg'))
212
+ .map((file) => path.basename(file, '.svg'));
213
+ const candidateNames = new Set(svgFileNames);
214
+ const similarNames = findSimilarStrings(targetFileName, candidateNames);
215
+ return similarNames.map((name) => path.join(targetDir, `${name}.svg`));
216
+ }
217
+ catch {
218
+ return [];
219
+ }
220
+ }
181
221
  //# sourceMappingURL=file-utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"file-utils.js","sourceRoot":"","sources":["../../src/utils/file-utils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"file-utils.js","sourceRoot":"","sources":["../../src/utils/file-utils.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
1
  export * from './ast-utils.js';
2
2
  export * from './file-utils.js';
3
+ export * from './rule-creator.js';
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC"}
@@ -1,3 +1,4 @@
1
1
  export * from './ast-utils.js';
2
2
  export * from './file-utils.js';
3
+ export * from './rule-creator.js';
3
4
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { ESLintUtils } from '@typescript-eslint/utils';
2
+ export declare const createRule: <Options extends readonly unknown[], MessageIds extends string>({ meta, name, ...rule }: Readonly<ESLintUtils.RuleWithMetaAndName<Options, MessageIds, unknown>>) => ESLintUtils.RuleModule<MessageIds, Options, unknown, ESLintUtils.RuleListener>;
3
+ //# sourceMappingURL=rule-creator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-creator.d.ts","sourceRoot":"","sources":["../../src/utils/rule-creator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAKvD,eAAO,MAAM,UAAU,qPAA2E,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { ESLintUtils } from '@typescript-eslint/utils';
2
+ const REPO_URL = 'https://github.com/n8n-io/n8n';
3
+ const DOCS_PATH = 'blob/master/packages/@n8n/eslint-plugin-community-nodes/docs/rules';
4
+ export const createRule = ESLintUtils.RuleCreator((name) => `${REPO_URL}/${DOCS_PATH}/${name}.md`);
5
+ //# sourceMappingURL=rule-creator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-creator.js","sourceRoot":"","sources":["../../src/utils/rule-creator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvD,MAAM,QAAQ,GAAG,+BAA+B,CAAC;AACjD,MAAM,SAAS,GAAG,oEAAoE,CAAC;AAEvF,MAAM,CAAC,MAAM,UAAU,GAAG,WAAW,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,QAAQ,IAAI,SAAS,IAAI,IAAI,KAAK,CAAC,CAAC"}
@@ -0,0 +1,94 @@
1
+ # Enforce valid credential documentationUrl format (URL or lowercase alphanumeric slug) (`@n8n/community-nodes/credential-documentation-url`)
2
+
3
+ 💼 This rule is enabled in the following configs: ✅ `recommended`, ☑️ `recommendedWithoutN8nCloudSupport`.
4
+
5
+ <!-- end auto-generated rule header -->
6
+
7
+ ## Options
8
+
9
+ <!-- begin auto-generated rule options list -->
10
+
11
+ | Name | Description | Type |
12
+ | :----------- | :----------------------------------------------------- | :------ |
13
+ | `allowSlugs` | Whether to allow lowercase alphanumeric slugs with slashes | Boolean |
14
+ | `allowUrls` | Whether to allow valid URLs | Boolean |
15
+
16
+ <!-- end auto-generated rule options list -->
17
+
18
+ ## Rule Details
19
+
20
+ Ensures that credential `documentationUrl` values are in a valid format. For community packages, this should always be a complete URL to your documentation.
21
+
22
+ The lowercase alphanumeric slug option (`allowSlugs`) is only intended for internal n8n use when referring to slugs on docs.n8n.io, and should not be used in community packages. When enabled, uppercase letters in slugs will be automatically converted to lowercase.
23
+
24
+ ## Examples
25
+
26
+ ### ❌ Incorrect
27
+
28
+ ```typescript
29
+ export class MyApiCredential implements ICredentialType {
30
+ name = 'myApi';
31
+ displayName = 'My API';
32
+ documentationUrl = 'invalid-url-format'; // Not a valid URL
33
+ // ...
34
+ }
35
+ ```
36
+
37
+ ```typescript
38
+ export class MyApiCredential implements ICredentialType {
39
+ name = 'myApi';
40
+ displayName = 'My API';
41
+ documentationUrl = 'MyApi'; // Invalid: uppercase letters (will be autofixed to 'myapi')
42
+ // ...
43
+ }
44
+ ```
45
+
46
+ ```typescript
47
+ export class MyApiCredential implements ICredentialType {
48
+ name = 'myApi';
49
+ displayName = 'My API';
50
+ documentationUrl = 'my-api'; // Invalid: special characters not allowed
51
+ // ...
52
+ }
53
+ ```
54
+
55
+ ### ✅ Correct
56
+
57
+ ```typescript
58
+ export class MyApiCredential implements ICredentialType {
59
+ name = 'myApi';
60
+ displayName = 'My API';
61
+ documentationUrl = 'https://docs.myservice.com/api-setup'; // Complete URL to documentation
62
+ // ...
63
+ }
64
+ ```
65
+
66
+ ```typescript
67
+ export class MyApiCredential implements ICredentialType {
68
+ name = 'myApi';
69
+ displayName = 'My API';
70
+ documentationUrl = 'https://github.com/myuser/n8n-nodes-myapi#credentials'; // GitHub README section
71
+ // ...
72
+ }
73
+ ```
74
+
75
+ ## Configuration
76
+
77
+ By default, only URLs are allowed, which is the recommended setting for community packages.
78
+
79
+ The `allowSlugs` option is available for internal n8n development:
80
+
81
+ ```json
82
+ {
83
+ "rules": {
84
+ "@n8n/community-nodes/credential-documentation-url": [
85
+ "error",
86
+ {
87
+ "allowSlugs": true
88
+ }
89
+ ]
90
+ }
91
+ }
92
+ ```
93
+
94
+ **Note:** Community package developers should keep the default settings and always use complete URLs for their documentation.
@@ -0,0 +1,45 @@
1
+ # Ensure credential fields with sensitive names have typeOptions.password = true (`@n8n/community-nodes/credential-password-field`)
2
+
3
+ 💼 This rule is enabled in the following configs: ✅ `recommended`, ☑️ `recommendedWithoutN8nCloudSupport`.
4
+
5
+ 🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).
6
+
7
+ <!-- end auto-generated rule header -->
8
+
9
+ ## Rule Details
10
+
11
+ Ensures that credential fields with names like "password", "secret", "token", or "key" are properly masked in the UI by having `typeOptions.password = true`.
12
+
13
+ ## Examples
14
+
15
+ ### ❌ Incorrect
16
+
17
+ ```typescript
18
+ export class MyApiCredential implements ICredentialType {
19
+ properties: INodeProperties[] = [
20
+ {
21
+ displayName: 'API Key',
22
+ name: 'apiKey',
23
+ type: 'string',
24
+ default: '',
25
+ // Missing typeOptions.password
26
+ },
27
+ ];
28
+ }
29
+ ```
30
+
31
+ ### ✅ Correct
32
+
33
+ ```typescript
34
+ export class MyApiCredential implements ICredentialType {
35
+ properties: INodeProperties[] = [
36
+ {
37
+ displayName: 'API Key',
38
+ name: 'apiKey',
39
+ type: 'string',
40
+ typeOptions: { password: true },
41
+ default: '',
42
+ },
43
+ ];
44
+ }
45
+ ```
@@ -0,0 +1,58 @@
1
+ # Ensure credentials have a credential test (`@n8n/community-nodes/credential-test-required`)
2
+
3
+ 💼 This rule is enabled in the following configs: ✅ `recommended`, ☑️ `recommendedWithoutN8nCloudSupport`.
4
+
5
+ 💡 This rule is manually fixable by [editor suggestions](https://eslint.org/docs/latest/use/core-concepts#rule-suggestions).
6
+
7
+ <!-- end auto-generated rule header -->
8
+
9
+ ## Rule Details
10
+
11
+ Ensures that your credentials include a `test` method to validate user credentials. This helps users verify their credentials are working correctly.
12
+
13
+ ## Examples
14
+
15
+ ### ❌ Incorrect
16
+
17
+ ```typescript
18
+ export class MyApiCredential implements ICredentialType {
19
+ name = 'myApi';
20
+ displayName = 'My API';
21
+ properties: INodeProperties[] = [
22
+ {
23
+ displayName: 'API Key',
24
+ name: 'apiKey',
25
+ type: 'string',
26
+ typeOptions: { password: true },
27
+ default: '',
28
+ },
29
+ ];
30
+ // Missing test method
31
+ }
32
+ ```
33
+
34
+ ### ✅ Correct
35
+
36
+ ```typescript
37
+ export class MyApiCredential implements ICredentialType {
38
+ name = 'myApi';
39
+ displayName = 'My API';
40
+ properties: INodeProperties[] = [
41
+ {
42
+ displayName: 'API Key',
43
+ name: 'apiKey',
44
+ type: 'string',
45
+ typeOptions: { password: true },
46
+ default: '',
47
+ },
48
+ ];
49
+
50
+ test: ICredentialTestRequest = {
51
+ request: {
52
+ baseURL: 'https://api.myservice.com',
53
+ url: '/user',
54
+ method: 'GET',
55
+ },
56
+ };
57
+ }
58
+ ```
@@ -0,0 +1,67 @@
1
+ # Validate node and credential icon files exist, are SVG format, and light/dark icons are different (`@n8n/community-nodes/icon-validation`)
2
+
3
+ 💼 This rule is enabled in the following configs: ✅ `recommended`, ☑️ `recommendedWithoutN8nCloudSupport`.
4
+
5
+ 💡 This rule is manually fixable by [editor suggestions](https://eslint.org/docs/latest/use/core-concepts#rule-suggestions).
6
+
7
+ <!-- end auto-generated rule header -->
8
+
9
+ ## Rule Details
10
+
11
+ Validates that your node and credential icon files exist, are in SVG format, and use the correct `file:` protocol. Icons must be different files when providing light/dark theme variants.
12
+
13
+ ## Examples
14
+
15
+ ### ❌ Incorrect
16
+
17
+ ```typescript
18
+ export class MyNode implements INodeType {
19
+ description: INodeTypeDescription = {
20
+ displayName: 'My Node',
21
+ name: 'myNode',
22
+ icon: 'icons/my-icon.png', // Missing 'file:' prefix, wrong format
23
+ // ...
24
+ };
25
+ }
26
+ ```
27
+
28
+ ```typescript
29
+ export class MyNode implements INodeType {
30
+ description: INodeTypeDescription = {
31
+ displayName: 'My Node',
32
+ name: 'myNode',
33
+ icon: {
34
+ light: 'file:icons/my-icon.svg',
35
+ dark: 'file:icons/my-icon.svg', // Same file for both themes
36
+ },
37
+ // ...
38
+ };
39
+ }
40
+ ```
41
+
42
+ ### ✅ Correct
43
+
44
+ ```typescript
45
+ export class MyNode implements INodeType {
46
+ description: INodeTypeDescription = {
47
+ displayName: 'My Node',
48
+ name: 'myNode',
49
+ icon: 'file:icons/my-service.svg', // Correct format
50
+ // ...
51
+ };
52
+ }
53
+ ```
54
+
55
+ ```typescript
56
+ export class MyNode implements INodeType {
57
+ description: INodeTypeDescription = {
58
+ displayName: 'My Node',
59
+ name: 'myNode',
60
+ icon: {
61
+ light: 'file:icons/my-service-light.svg',
62
+ dark: 'file:icons/my-service-dark.svg', // Different files
63
+ },
64
+ // ...
65
+ };
66
+ }
67
+ ```
@@ -0,0 +1,82 @@
1
+ # Prevent credential re-use security issues by ensuring nodes only reference credentials from the same package (`@n8n/community-nodes/no-credential-reuse`)
2
+
3
+ 💼 This rule is enabled in the following configs: ✅ `recommended`, ☑️ `recommendedWithoutN8nCloudSupport`.
4
+
5
+ 💡 This rule is manually fixable by [editor suggestions](https://eslint.org/docs/latest/use/core-concepts#rule-suggestions).
6
+
7
+ <!-- end auto-generated rule header -->
8
+
9
+ ## Rule Details
10
+
11
+ Ensures your nodes only reference credentials by their `name` property that match credential classes declared in your package's `package.json` file. This prevents security issues where nodes could access credentials from other packages.
12
+
13
+ ## Examples
14
+
15
+ ### ❌ Incorrect
16
+
17
+ ```typescript
18
+ // MyApiCredential.credentials.ts
19
+ export class MyApiCredential implements ICredentialType {
20
+ name = 'myApiCredential';
21
+ displayName = 'My API';
22
+ // ...
23
+ }
24
+
25
+ // package.json: "n8n": { "credentials": ["dist/credentials/MyApiCredential.credentials.js"] }
26
+
27
+ export class MyNode implements INodeType {
28
+ description: INodeTypeDescription = {
29
+ displayName: 'My Node',
30
+ name: 'myNode',
31
+ credentials: [
32
+ {
33
+ name: 'someOtherCredential', // No credential class with this name in package
34
+ required: true,
35
+ },
36
+ ],
37
+ // ...
38
+ };
39
+ }
40
+ ```
41
+
42
+ ### ✅ Correct
43
+
44
+ ```typescript
45
+ // MyApiCredential.credentials.ts
46
+ export class MyApiCredential implements ICredentialType {
47
+ name = 'myApiCredential'; // This name must match what's used in nodes
48
+ displayName = 'My API';
49
+ // ...
50
+ }
51
+
52
+ // package.json: "n8n": { "credentials": ["dist/credentials/MyApiCredential.credentials.js"] }
53
+
54
+ export class MyNode implements INodeType {
55
+ description: INodeTypeDescription = {
56
+ displayName: 'My Node',
57
+ name: 'myNode',
58
+ credentials: [
59
+ {
60
+ name: 'myApiCredential', // Matches credential class name property
61
+ required: true,
62
+ },
63
+ ],
64
+ // ...
65
+ };
66
+ }
67
+ ```
68
+
69
+ ## Setup
70
+
71
+ Declare your credential files in `package.json` and ensure the credential name in nodes matches the `name` property in your credential classes:
72
+
73
+ ```json
74
+ {
75
+ "name": "n8n-nodes-my-service",
76
+ "n8n": {
77
+ "credentials": [
78
+ "dist/credentials/MyApiCredential.credentials.js"
79
+ ]
80
+ }
81
+ }
82
+ ```
@@ -0,0 +1,61 @@
1
+ # Disallow usage of deprecated functions and types from n8n-workflow package (`@n8n/community-nodes/no-deprecated-workflow-functions`)
2
+
3
+ 💼 This rule is enabled in the following configs: ✅ `recommended`, ☑️ `recommendedWithoutN8nCloudSupport`.
4
+
5
+ 💡 This rule is manually fixable by [editor suggestions](https://eslint.org/docs/latest/use/core-concepts#rule-suggestions).
6
+
7
+ <!-- end auto-generated rule header -->
8
+
9
+ ## Rule Details
10
+
11
+ Prevents usage of deprecated functions from n8n-workflow package and suggests modern alternatives.
12
+
13
+ ## Examples
14
+
15
+ ### ❌ Incorrect
16
+
17
+ ```typescript
18
+ import { IRequestOptions } from 'n8n-workflow';
19
+
20
+ export class MyNode implements INodeType {
21
+ async execute(this: IExecuteFunctions) {
22
+ // Using deprecated request helper function
23
+ const response = await this.helpers.request({
24
+ method: 'GET',
25
+ url: 'https://api.example.com/data',
26
+ });
27
+
28
+ // Using deprecated type
29
+ const options: IRequestOptions = {
30
+ method: 'POST',
31
+ url: 'https://api.example.com/data',
32
+ };
33
+
34
+ return [this.helpers.returnJsonArray([response])];
35
+ }
36
+ }
37
+ ```
38
+
39
+ ### ✅ Correct
40
+
41
+ ```typescript
42
+ import { IHttpRequestOptions } from 'n8n-workflow';
43
+
44
+ export class MyNode implements INodeType {
45
+ async execute(this: IExecuteFunctions) {
46
+ // Using modern httpRequest helper function
47
+ const response = await this.helpers.httpRequest({
48
+ method: 'GET',
49
+ url: 'https://api.example.com/data',
50
+ });
51
+
52
+ // Using modern type
53
+ const options: IHttpRequestOptions = {
54
+ method: 'POST',
55
+ url: 'https://api.example.com/data',
56
+ };
57
+
58
+ return [this.helpers.returnJsonArray([response])];
59
+ }
60
+ }
61
+ ```
@@ -0,0 +1,44 @@
1
+ # Disallow usage of restricted global variables in community nodes (`@n8n/community-nodes/no-restricted-globals`)
2
+
3
+ 💼 This rule is enabled in the ✅ `recommended` config.
4
+
5
+ <!-- end auto-generated rule header -->
6
+
7
+ ## Rule Details
8
+
9
+ Prevents the use of Node.js global variables that are not allowed in n8n Cloud. While these globals may be available in self-hosted environments, they are restricted on n8n Cloud for security and stability reasons.
10
+
11
+ Restricted globals include: `clearInterval`, `clearTimeout`, `global`, `globalThis`, `process`, `setInterval`, `setTimeout`, `setImmediate`, `clearImmediate`, `__dirname`, `__filename`.
12
+
13
+ ## Examples
14
+
15
+ ### ❌ Incorrect
16
+
17
+ ```typescript
18
+ export class MyNode implements INodeType {
19
+ async execute(this: IExecuteFunctions) {
20
+ // These globals are not allowed on n8n Cloud
21
+ const pid = process.pid;
22
+ const dir = __dirname;
23
+
24
+ setTimeout(() => {
25
+ console.log('This will not work on n8n Cloud');
26
+ }, 1000);
27
+
28
+ return this.prepareOutputData([]);
29
+ }
30
+ }
31
+ ```
32
+
33
+ ### ✅ Correct
34
+
35
+ ```typescript
36
+ export class MyNode implements INodeType {
37
+ async execute(this: IExecuteFunctions) {
38
+ // Use n8n context methods instead
39
+ const timezone = this.getTimezone();
40
+
41
+ return this.prepareOutputData([]);
42
+ }
43
+ }
44
+ ```