@n8n/eslint-plugin-community-nodes 0.3.0 → 0.5.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 (114) 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 +14 -0
  60. package/dist/utils/file-utils.d.ts.map +1 -1
  61. package/dist/utils/file-utils.js +85 -18
  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 +108 -18
  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.eslint.json +5 -0
  114. package/tsconfig.json +1 -2
@@ -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
+ ```
@@ -0,0 +1,47 @@
1
+ # Disallow usage of restricted imports in community nodes (`@n8n/community-nodes/no-restricted-imports`)
2
+
3
+ 💼 This rule is enabled in the ✅ `recommended` config.
4
+
5
+ <!-- end auto-generated rule header -->
6
+
7
+ ## Rule Details
8
+
9
+ Prevents importing external dependencies that are not allowed on n8n Cloud. Community nodes running on n8n Cloud are restricted to a specific set of allowed modules for security and performance reasons.
10
+
11
+ **Allowed modules:** `n8n-workflow`, `lodash`, `moment`, `p-limit`, `luxon`, `zod`, `crypto`, `node:crypto`
12
+
13
+ Relative imports (starting with `./` or `../`) are always allowed.
14
+
15
+ ## Examples
16
+
17
+ ### ❌ Incorrect
18
+
19
+ ```typescript
20
+ import axios from 'axios'; // External dependency not allowed
21
+ import { readFile } from 'fs'; // Node.js modules not in allowlist
22
+ const request = require('request'); // Same applies to require()
23
+
24
+ // Dynamic imports are also restricted
25
+ const module = await import('some-package');
26
+ ```
27
+
28
+ ### ✅ Correct
29
+
30
+ ```typescript
31
+ import { IExecuteFunctions, INodeType } from 'n8n-workflow'; // Allowed
32
+ import { get } from 'lodash'; // Allowed
33
+ import moment from 'moment'; // Allowed
34
+ import { DateTime } from 'luxon'; // Allowed
35
+ import { createHash } from 'crypto'; // Allowed
36
+
37
+ import { MyHelper } from './helpers/MyHelper'; // Relative imports allowed
38
+ import config from '../config'; // Relative imports allowed
39
+
40
+ export class MyNode implements INodeType {
41
+ // ... implementation
42
+ }
43
+ ```
44
+
45
+ ## When This Rule Doesn't Apply
46
+
47
+ This rule only applies to community nodes intended for n8n Cloud. If you're building nodes exclusively for self-hosted environments, you may disable this rule, but be aware that your package will not be compatible with n8n Cloud.
@@ -0,0 +1,43 @@
1
+ # Ensure node classes have usableAsTool property (`@n8n/community-nodes/node-usable-as-tool`)
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 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
+
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
+ group: ['input'],
23
+ version: 1,
24
+ // Missing usableAsTool property
25
+ properties: [],
26
+ };
27
+ }
28
+ ```
29
+
30
+ ### ✅ Correct
31
+
32
+ ```typescript
33
+ export class MyNode implements INodeType {
34
+ description: INodeTypeDescription = {
35
+ displayName: 'My Node',
36
+ name: 'myNode',
37
+ group: ['input'],
38
+ version: 1,
39
+ usableAsTool: true,
40
+ properties: [],
41
+ };
42
+ }
43
+ ```
@@ -0,0 +1,52 @@
1
+ # Enforce correct package naming convention for n8n community nodes (`@n8n/community-nodes/package-name-convention`)
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 package name follows the correct n8n community node naming convention. Package names must start with `n8n-nodes-` and can optionally be scoped.
12
+
13
+ ## Examples
14
+
15
+ ### ❌ Incorrect
16
+
17
+ ```json
18
+ {
19
+ "name": "my-service-integration"
20
+ }
21
+ ```
22
+
23
+ ```json
24
+ {
25
+ "name": "nodes-my-service"
26
+ }
27
+ ```
28
+
29
+ ```json
30
+ {
31
+ "name": "@company/my-service"
32
+ }
33
+ ```
34
+
35
+ ### ✅ Correct
36
+
37
+ ```json
38
+ {
39
+ "name": "n8n-nodes-my-service"
40
+ }
41
+ ```
42
+
43
+ ```json
44
+ {
45
+ "name": "@company/n8n-nodes-my-service"
46
+ }
47
+ ```
48
+
49
+ ## Best Practices
50
+
51
+ - Use descriptive service names: `n8n-nodes-github` rather than `n8n-nodes-api`
52
+ - For company packages, use your organization scope: `@mycompany/n8n-nodes-internal-tool`
@@ -0,0 +1,84 @@
1
+ # Enforce proper resource/operation pattern for better UX in n8n nodes (`@n8n/community-nodes/resource-operation-pattern`)
2
+
3
+ ⚠️ This rule _warns_ in the following configs: ✅ `recommended`, ☑️ `recommendedWithoutN8nCloudSupport`.
4
+
5
+ <!-- end auto-generated rule header -->
6
+
7
+ ## Rule Details
8
+
9
+ Warns when a node has more than 5 operations without organizing them into resources. The resource/operation pattern improves user experience by grouping related operations together, making complex nodes easier to navigate.
10
+
11
+ When you have many operations, users benefit from having them organized into logical resource groups (e.g., "User", "Project", "File") rather than seeing a long flat list of operations.
12
+
13
+ ## Examples
14
+
15
+ ### ❌ Incorrect
16
+
17
+ ```typescript
18
+ export class MyNode implements INodeType {
19
+ description: INodeTypeDescription = {
20
+ displayName: 'My Service',
21
+ name: 'myService',
22
+ properties: [
23
+ {
24
+ displayName: 'Operation',
25
+ name: 'operation',
26
+ type: 'options',
27
+ options: [
28
+ { name: 'Get User', value: 'getUser' },
29
+ { name: 'Create User', value: 'createUser' },
30
+ { name: 'Update User', value: 'updateUser' },
31
+ { name: 'Delete User', value: 'deleteUser' },
32
+ { name: 'Get Project', value: 'getProject' },
33
+ { name: 'Create Project', value: 'createProject' },
34
+ { name: 'List Files', value: 'listFiles' },
35
+ // 7+ operations without resources - hard to navigate!
36
+ ],
37
+ },
38
+ // ... other properties
39
+ ],
40
+ };
41
+ }
42
+ ```
43
+
44
+ ### ✅ Correct
45
+
46
+ ```typescript
47
+ export class MyNode implements INodeType {
48
+ description: INodeTypeDescription = {
49
+ displayName: 'My Service',
50
+ name: 'myService',
51
+ properties: [
52
+ {
53
+ displayName: 'Resource',
54
+ name: 'resource',
55
+ type: 'options',
56
+ options: [
57
+ { name: 'User', value: 'user' },
58
+ { name: 'Project', value: 'project' },
59
+ { name: 'File', value: 'file' },
60
+ ],
61
+ default: 'user',
62
+ },
63
+ {
64
+ displayName: 'Operation',
65
+ name: 'operation',
66
+ type: 'options',
67
+ displayOptions: {
68
+ show: {
69
+ resource: ['user'],
70
+ },
71
+ },
72
+ options: [
73
+ { name: 'Get', value: 'get' },
74
+ { name: 'Create', value: 'create' },
75
+ { name: 'Update', value: 'update' },
76
+ { name: 'Delete', value: 'delete' },
77
+ ],
78
+ default: 'get',
79
+ },
80
+ // ... similar operation blocks for 'project' and 'file' resources
81
+ ],
82
+ };
83
+ }
84
+ ```
@@ -0,0 +1,27 @@
1
+ import { defineConfig } from 'eslint/config';
2
+ import { nodeConfig } from '@n8n/eslint-config/node';
3
+ import eslintPlugin from 'eslint-plugin-eslint-plugin';
4
+
5
+ export default defineConfig([
6
+ nodeConfig,
7
+ eslintPlugin.configs.recommended,
8
+ {
9
+ files: ['src/**/*.ts'],
10
+ languageOptions: {
11
+ parserOptions: {
12
+ project: './tsconfig.json',
13
+ allowDefaultProject: true,
14
+ },
15
+ },
16
+ rules: {
17
+ // We use RuleCreator which adds this automatically
18
+ 'eslint-plugin/require-meta-docs-url': 'off',
19
+ // typescript-eslint uses different pattern
20
+ 'eslint-plugin/require-meta-default-options': 'off',
21
+ // Disable naming convention for plugin configs (ESLint rule names use kebab-case)
22
+ '@typescript-eslint/naming-convention': 'off',
23
+ // Allow default exports for ESLint plugin
24
+ 'import-x/no-default-export': 'off',
25
+ },
26
+ },
27
+ ]);
package/package.json CHANGED
@@ -1,7 +1,9 @@
1
1
  {
2
2
  "name": "@n8n/eslint-plugin-community-nodes",
3
3
  "type": "module",
4
- "version": "0.3.0",
4
+ "version": "0.5.0",
5
+ "main": "./dist/plugin.js",
6
+ "types": "./dist/plugin.d.ts",
5
7
  "exports": {
6
8
  ".": {
7
9
  "types": "./dist/plugin.d.ts",
@@ -9,10 +11,13 @@
9
11
  }
10
12
  },
11
13
  "dependencies": {
12
- "@typescript-eslint/utils": "^8.35.0"
14
+ "@typescript-eslint/utils": "^8.35.0",
15
+ "fastest-levenshtein": "1.0.16"
13
16
  },
14
17
  "devDependencies": {
15
18
  "@typescript-eslint/rule-tester": "^8.35.0",
19
+ "eslint-doc-generator": "^2.2.2",
20
+ "eslint-plugin-eslint-plugin": "^7.0.0",
16
21
  "rimraf": "6.0.1",
17
22
  "typescript": "5.9.2",
18
23
  "vitest": "^3.1.3",
@@ -22,6 +27,18 @@
22
27
  "peerDependencies": {
23
28
  "eslint": ">= 9"
24
29
  },
30
+ "eslint-doc-generator": {
31
+ "configEmoji": [
32
+ [
33
+ "recommended",
34
+ "✅"
35
+ ],
36
+ [
37
+ "recommendedWithoutN8nCloudSupport",
38
+ "☑️"
39
+ ]
40
+ ]
41
+ },
25
42
  "license": "SEE LICENSE IN LICENSE.md",
26
43
  "homepage": "https://n8n.io",
27
44
  "author": {
@@ -33,14 +50,18 @@
33
50
  "url": "git+https://github.com/n8n-io/n8n.git"
34
51
  },
35
52
  "scripts": {
36
- "build": "tsc",
53
+ "build": "tsc --project tsconfig.build.json",
54
+ "build:docs": "eslint-doc-generator",
37
55
  "clean": "rimraf dist .turbo",
38
56
  "dev": "pnpm watch",
39
57
  "format": "biome format --write .",
40
58
  "format:check": "biome ci .",
59
+ "lint": "eslint src",
60
+ "lint:fix": "eslint src --fix",
61
+ "lint:docs": "eslint-doc-generator --check",
41
62
  "test": "vitest run",
42
63
  "test:dev": "vitest",
43
64
  "typecheck": "tsc --noEmit",
44
- "watch": "tsc --watch"
65
+ "watch": "tsc --watch --project tsconfig.build.json"
45
66
  }
46
67
  }
package/src/plugin.ts CHANGED
@@ -1,14 +1,13 @@
1
1
  import type { ESLint, Linter } from 'eslint';
2
- import { rules } from './rules/index.js';
3
- import fs from 'node:fs';
4
2
 
5
- const pkg = JSON.parse(fs.readFileSync(new URL('../package.json', import.meta.url), 'utf8'));
3
+ import pkg from '../package.json' with { type: 'json' };
4
+ import { rules } from './rules/index.js';
6
5
 
7
6
  const plugin = {
8
7
  meta: {
9
8
  name: pkg.name,
10
9
  version: pkg.version,
11
- namespace: 'n8n-community-nodes',
10
+ namespace: '@n8n/community-nodes',
12
11
  },
13
12
  // @ts-expect-error Rules type does not match for typescript-eslint and eslint
14
13
  rules: rules as ESLint.Plugin['rules'],
@@ -18,38 +17,43 @@ const configs = {
18
17
  recommended: {
19
18
  ignores: ['eslint.config.{js,mjs,ts,mts}'],
20
19
  plugins: {
21
- 'n8n-community-nodes': plugin,
20
+ '@n8n/community-nodes': plugin,
22
21
  },
23
22
  rules: {
24
- 'n8n-community-nodes/no-restricted-globals': 'error',
25
- 'n8n-community-nodes/no-restricted-imports': 'error',
26
- 'n8n-community-nodes/credential-password-field': 'error',
27
- 'n8n-community-nodes/no-deprecated-workflow-functions': 'error',
28
- 'n8n-community-nodes/node-usable-as-tool': 'error',
29
- 'n8n-community-nodes/package-name-convention': 'error',
30
- 'n8n-community-nodes/credential-test-required': 'error',
31
- 'n8n-community-nodes/no-credential-reuse': 'error',
32
- 'n8n-community-nodes/icon-validation': 'error',
33
- 'n8n-community-nodes/resource-operation-pattern': 'warn',
23
+ '@n8n/community-nodes/no-restricted-globals': 'error',
24
+ '@n8n/community-nodes/no-restricted-imports': 'error',
25
+ '@n8n/community-nodes/credential-password-field': 'error',
26
+ '@n8n/community-nodes/no-deprecated-workflow-functions': 'error',
27
+ '@n8n/community-nodes/node-usable-as-tool': 'error',
28
+ '@n8n/community-nodes/package-name-convention': 'error',
29
+ '@n8n/community-nodes/credential-test-required': 'error',
30
+ '@n8n/community-nodes/no-credential-reuse': 'error',
31
+ '@n8n/community-nodes/icon-validation': 'error',
32
+ '@n8n/community-nodes/resource-operation-pattern': 'warn',
33
+ '@n8n/community-nodes/credential-documentation-url': 'error',
34
34
  },
35
35
  },
36
36
  recommendedWithoutN8nCloudSupport: {
37
37
  ignores: ['eslint.config.{js,mjs,ts,mts}'],
38
38
  plugins: {
39
- 'n8n-community-nodes': plugin,
39
+ '@n8n/community-nodes': plugin,
40
40
  },
41
41
  rules: {
42
- 'n8n-community-nodes/credential-password-field': 'error',
43
- 'n8n-community-nodes/no-deprecated-workflow-functions': 'error',
44
- 'n8n-community-nodes/node-usable-as-tool': 'error',
45
- 'n8n-community-nodes/package-name-convention': 'error',
46
- 'n8n-community-nodes/credential-test-required': 'error',
47
- 'n8n-community-nodes/no-credential-reuse': 'error',
48
- 'n8n-community-nodes/icon-validation': 'error',
49
- 'n8n-community-nodes/resource-operation-pattern': 'warn',
42
+ '@n8n/community-nodes/credential-password-field': 'error',
43
+ '@n8n/community-nodes/no-deprecated-workflow-functions': 'error',
44
+ '@n8n/community-nodes/node-usable-as-tool': 'error',
45
+ '@n8n/community-nodes/package-name-convention': 'error',
46
+ '@n8n/community-nodes/credential-test-required': 'error',
47
+ '@n8n/community-nodes/no-credential-reuse': 'error',
48
+ '@n8n/community-nodes/icon-validation': 'error',
49
+ '@n8n/community-nodes/credential-documentation-url': 'error',
50
+ '@n8n/community-nodes/resource-operation-pattern': 'warn',
50
51
  },
51
52
  },
52
53
  } satisfies Record<string, Linter.Config>;
53
54
 
54
- export const n8nCommunityNodesPlugin = { ...plugin, configs } satisfies ESLint.Plugin;
55
- export default n8nCommunityNodesPlugin;
55
+ const pluginWithConfigs = { ...plugin, configs } satisfies ESLint.Plugin;
56
+
57
+ const n8nCommunityNodesPlugin = pluginWithConfigs;
58
+ export default pluginWithConfigs;
59
+ export { rules, configs, n8nCommunityNodesPlugin };