@n8n/eslint-plugin-community-nodes 0.8.0 → 0.10.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/.turbo/turbo-build.log +1 -1
- package/README.md +17 -13
- package/dist/plugin.d.ts +18 -0
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +6 -0
- package/dist/plugin.js.map +1 -1
- package/dist/rules/cred-class-field-icon-missing.d.ts +2 -0
- package/dist/rules/cred-class-field-icon-missing.d.ts.map +1 -0
- package/dist/rules/cred-class-field-icon-missing.js +51 -0
- package/dist/rules/cred-class-field-icon-missing.js.map +1 -0
- package/dist/rules/icon-validation.d.ts +1 -1
- package/dist/rules/index.d.ts +4 -1
- package/dist/rules/index.d.ts.map +1 -1
- package/dist/rules/index.js +6 -0
- package/dist/rules/index.js.map +1 -1
- package/dist/rules/no-deprecated-workflow-functions.d.ts.map +1 -1
- package/dist/rules/no-deprecated-workflow-functions.js +1 -13
- package/dist/rules/no-deprecated-workflow-functions.js.map +1 -1
- package/dist/rules/no-http-request-with-manual-auth.d.ts +19 -0
- package/dist/rules/no-http-request-with-manual-auth.d.ts.map +1 -0
- package/dist/rules/no-http-request-with-manual-auth.js +65 -0
- package/dist/rules/no-http-request-with-manual-auth.js.map +1 -0
- package/dist/rules/node-class-description-icon-missing.d.ts +2 -0
- package/dist/rules/node-class-description-icon-missing.d.ts.map +1 -0
- package/dist/rules/node-class-description-icon-missing.js +57 -0
- package/dist/rules/node-class-description-icon-missing.js.map +1 -0
- package/dist/utils/ast-utils.d.ts +6 -0
- package/dist/utils/ast-utils.d.ts.map +1 -1
- package/dist/utils/ast-utils.js +21 -0
- package/dist/utils/ast-utils.js.map +1 -1
- package/docs/rules/ai-node-package-json.md +62 -0
- package/docs/rules/cred-class-field-icon-missing.md +47 -0
- package/docs/rules/credential-documentation-url.md +5 -3
- package/docs/rules/no-http-request-with-manual-auth.md +57 -0
- package/docs/rules/node-class-description-icon-missing.md +52 -0
- package/package.json +1 -1
- package/src/plugin.ts +6 -0
- package/src/rules/cred-class-field-icon-missing.test.ts +96 -0
- package/src/rules/cred-class-field-icon-missing.ts +59 -0
- package/src/rules/index.ts +6 -0
- package/src/rules/no-deprecated-workflow-functions.ts +1 -17
- package/src/rules/no-http-request-with-manual-auth.test.ts +104 -0
- package/src/rules/no-http-request-with-manual-auth.ts +78 -0
- package/src/rules/node-class-description-icon-missing.test.ts +113 -0
- package/src/rules/node-class-description-icon-missing.ts +71 -0
- package/src/utils/ast-utils.ts +30 -0
|
@@ -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":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Enforce consistency between n8n.aiNodeSdkVersion and ai-node-sdk peer dependency in community node packages (`@n8n/community-nodes/ai-node-package-json`)
|
|
2
|
+
|
|
3
|
+
💼 This rule is enabled in the following configs: ✅ `recommended`, ☑️ `recommendedWithoutN8nCloudSupport`.
|
|
4
|
+
|
|
5
|
+
<!-- end auto-generated rule header -->
|
|
6
|
+
|
|
7
|
+
## Rule Details
|
|
8
|
+
|
|
9
|
+
Enforces consistency between `n8n.aiNodeSdkVersion` in `package.json` and the `ai-node-sdk` peer dependency. When a community node uses the AI Node SDK, both fields must be present and correct.
|
|
10
|
+
|
|
11
|
+
The rule checks four conditions:
|
|
12
|
+
|
|
13
|
+
- `aiNodeSdkVersion` is declared inside the `n8n` section (not at the root level)
|
|
14
|
+
- `aiNodeSdkVersion` is a positive integer
|
|
15
|
+
- If `n8n.aiNodeSdkVersion` is set, `ai-node-sdk` must appear in `peerDependencies`
|
|
16
|
+
- If `ai-node-sdk` is in `peerDependencies`, `n8n.aiNodeSdkVersion` must be set
|
|
17
|
+
|
|
18
|
+
## Examples
|
|
19
|
+
|
|
20
|
+
### ❌ Incorrect
|
|
21
|
+
|
|
22
|
+
```json
|
|
23
|
+
{
|
|
24
|
+
"name": "n8n-nodes-my-ai-node",
|
|
25
|
+
"n8n": {
|
|
26
|
+
"aiNodeSdkVersion": "1"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
```json
|
|
32
|
+
{
|
|
33
|
+
"name": "n8n-nodes-my-ai-node",
|
|
34
|
+
"aiNodeSdkVersion": 1,
|
|
35
|
+
"peerDependencies": {
|
|
36
|
+
"ai-node-sdk": "*"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"name": "n8n-nodes-my-ai-node",
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"ai-node-sdk": "*"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### ✅ Correct
|
|
51
|
+
|
|
52
|
+
```json
|
|
53
|
+
{
|
|
54
|
+
"name": "n8n-nodes-my-ai-node",
|
|
55
|
+
"n8n": {
|
|
56
|
+
"aiNodeSdkVersion": 1
|
|
57
|
+
},
|
|
58
|
+
"peerDependencies": {
|
|
59
|
+
"ai-node-sdk": "*"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
```
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Credential class must have an `icon` property defined (`@n8n/community-nodes/cred-class-field-icon-missing`)
|
|
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 credential classes define an `icon` class field. Icons are required for credentials to display correctly in the n8n editor.
|
|
12
|
+
|
|
13
|
+
## Examples
|
|
14
|
+
|
|
15
|
+
### ❌ Incorrect
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
export class MyServiceApi implements ICredentialType {
|
|
19
|
+
name = 'myServiceApi';
|
|
20
|
+
displayName = 'My Service API';
|
|
21
|
+
// Missing icon property
|
|
22
|
+
|
|
23
|
+
properties: INodeProperties[] = [];
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### ✅ Correct
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
export class MyServiceApi implements ICredentialType {
|
|
31
|
+
name = 'myServiceApi';
|
|
32
|
+
displayName = 'My Service API';
|
|
33
|
+
icon = 'file:myService.svg' as const;
|
|
34
|
+
|
|
35
|
+
properties: INodeProperties[] = [];
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
export class MyServiceApi implements ICredentialType {
|
|
41
|
+
name = 'myServiceApi';
|
|
42
|
+
displayName = 'My Service API';
|
|
43
|
+
icon = { light: 'file:myService.svg', dark: 'file:myService.dark.svg' } as const;
|
|
44
|
+
|
|
45
|
+
properties: INodeProperties[] = [];
|
|
46
|
+
}
|
|
47
|
+
```
|
|
@@ -2,16 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
💼 This rule is enabled in the following configs: ✅ `recommended`, ☑️ `recommendedWithoutN8nCloudSupport`.
|
|
4
4
|
|
|
5
|
+
🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).
|
|
6
|
+
|
|
5
7
|
<!-- end auto-generated rule header -->
|
|
6
8
|
|
|
7
9
|
## Options
|
|
8
10
|
|
|
9
11
|
<!-- begin auto-generated rule options list -->
|
|
10
12
|
|
|
11
|
-
| Name | Description
|
|
12
|
-
| :----------- |
|
|
13
|
+
| Name | Description | Type |
|
|
14
|
+
| :----------- | :--------------------------------------------------------- | :------ |
|
|
13
15
|
| `allowSlugs` | Whether to allow lowercase alphanumeric slugs with slashes | Boolean |
|
|
14
|
-
| `allowUrls` | Whether to allow valid URLs
|
|
16
|
+
| `allowUrls` | Whether to allow valid URLs | Boolean |
|
|
15
17
|
|
|
16
18
|
<!-- end auto-generated rule options list -->
|
|
17
19
|
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Disallow this.helpers.httpRequest() in functions that call this.getCredentials(). Use this.helpers.httpRequestWithAuthentication() instead (`@n8n/community-nodes/no-http-request-with-manual-auth`)
|
|
2
|
+
|
|
3
|
+
💼 This rule is enabled in the following configs: ✅ `recommended`, ☑️ `recommendedWithoutN8nCloudSupport`.
|
|
4
|
+
|
|
5
|
+
<!-- end auto-generated rule header -->
|
|
6
|
+
|
|
7
|
+
## Rule Details
|
|
8
|
+
|
|
9
|
+
When a function calls `this.getCredentials()` to retrieve credentials, it should use `this.helpers.httpRequestWithAuthentication()` for HTTP requests instead of `this.helpers.httpRequest()`.
|
|
10
|
+
|
|
11
|
+
Manually extracting credentials and setting auth headers (e.g. `Authorization`) bypasses n8n's authentication layer, which provides:
|
|
12
|
+
|
|
13
|
+
- Consistent credential handling across all nodes
|
|
14
|
+
- Future improvements like token refresh and audit logging
|
|
15
|
+
- Better security review surface
|
|
16
|
+
|
|
17
|
+
## Examples
|
|
18
|
+
|
|
19
|
+
### ❌ Incorrect
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
async function apiRequest(this: IExecuteFunctions, endpoint: string) {
|
|
23
|
+
const credentials = await this.getCredentials('myServiceApi');
|
|
24
|
+
|
|
25
|
+
const options: IHttpRequestOptions = {
|
|
26
|
+
method: 'GET',
|
|
27
|
+
url: `https://api.example.com/${endpoint}`,
|
|
28
|
+
headers: {
|
|
29
|
+
Authorization: `Bearer ${credentials.apiKey}`,
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
return this.helpers.httpRequest(options);
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### ✅ Correct
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
async function apiRequest(this: IExecuteFunctions, endpoint: string) {
|
|
41
|
+
const options: IHttpRequestOptions = {
|
|
42
|
+
method: 'GET',
|
|
43
|
+
url: `https://api.example.com/${endpoint}`,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
return this.helpers.httpRequestWithAuthentication.call(this, 'myServiceApi', options);
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## When to Disable
|
|
51
|
+
|
|
52
|
+
If a function genuinely retrieves credentials for a non-HTTP purpose (e.g. reading a config value) *and* also makes an unauthenticated HTTP request, you can suppress this rule with an inline comment:
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
// eslint-disable-next-line @n8n/community-nodes/no-http-request-with-manual-auth
|
|
56
|
+
return this.helpers.httpRequest(options);
|
|
57
|
+
```
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Node class description must have an `icon` property defined (`@n8n/community-nodes/node-class-description-icon-missing`)
|
|
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 node classes define an `icon` property in their `description` object. Icons are required for nodes to display correctly in the n8n editor.
|
|
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
|
+
// Missing icon property
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### ✅ Correct
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
export class MyNode implements INodeType {
|
|
31
|
+
description: INodeTypeDescription = {
|
|
32
|
+
displayName: 'My Node',
|
|
33
|
+
name: 'myNode',
|
|
34
|
+
icon: 'file:myNode.svg',
|
|
35
|
+
// ...
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
export class MyNode implements INodeType {
|
|
42
|
+
description: INodeTypeDescription = {
|
|
43
|
+
displayName: 'My Node',
|
|
44
|
+
name: 'myNode',
|
|
45
|
+
icon: {
|
|
46
|
+
light: 'file:myNode.svg',
|
|
47
|
+
dark: 'file:myNode.dark.svg',
|
|
48
|
+
},
|
|
49
|
+
// ...
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
```
|
package/package.json
CHANGED
package/src/plugin.ts
CHANGED
|
@@ -29,9 +29,12 @@ const configs = {
|
|
|
29
29
|
'@n8n/community-nodes/package-name-convention': 'error',
|
|
30
30
|
'@n8n/community-nodes/credential-test-required': 'error',
|
|
31
31
|
'@n8n/community-nodes/no-credential-reuse': 'error',
|
|
32
|
+
'@n8n/community-nodes/no-http-request-with-manual-auth': 'error',
|
|
32
33
|
'@n8n/community-nodes/icon-validation': 'error',
|
|
33
34
|
'@n8n/community-nodes/resource-operation-pattern': 'warn',
|
|
34
35
|
'@n8n/community-nodes/credential-documentation-url': 'error',
|
|
36
|
+
'@n8n/community-nodes/node-class-description-icon-missing': 'error',
|
|
37
|
+
'@n8n/community-nodes/cred-class-field-icon-missing': 'error',
|
|
35
38
|
},
|
|
36
39
|
},
|
|
37
40
|
recommendedWithoutN8nCloudSupport: {
|
|
@@ -47,9 +50,12 @@ const configs = {
|
|
|
47
50
|
'@n8n/community-nodes/package-name-convention': 'error',
|
|
48
51
|
'@n8n/community-nodes/credential-test-required': 'error',
|
|
49
52
|
'@n8n/community-nodes/no-credential-reuse': 'error',
|
|
53
|
+
'@n8n/community-nodes/no-http-request-with-manual-auth': 'error',
|
|
50
54
|
'@n8n/community-nodes/icon-validation': 'error',
|
|
51
55
|
'@n8n/community-nodes/credential-documentation-url': 'error',
|
|
52
56
|
'@n8n/community-nodes/resource-operation-pattern': 'warn',
|
|
57
|
+
'@n8n/community-nodes/node-class-description-icon-missing': 'error',
|
|
58
|
+
'@n8n/community-nodes/cred-class-field-icon-missing': 'error',
|
|
53
59
|
},
|
|
54
60
|
},
|
|
55
61
|
} satisfies Record<string, Linter.Config>;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { RuleTester } from '@typescript-eslint/rule-tester';
|
|
2
|
+
|
|
3
|
+
import { CredClassFieldIconMissingRule } from './cred-class-field-icon-missing.js';
|
|
4
|
+
|
|
5
|
+
const ruleTester = new RuleTester();
|
|
6
|
+
|
|
7
|
+
const credFilePath = '/tmp/TestCredential.credentials.ts';
|
|
8
|
+
const nonCredFilePath = '/tmp/SomeHelper.ts';
|
|
9
|
+
|
|
10
|
+
function createCredentialCode(withIcon: boolean): string {
|
|
11
|
+
const iconLine = withIcon ? "\n\ticon = 'file:testCredential.svg' as const;" : '';
|
|
12
|
+
return `
|
|
13
|
+
import type { ICredentialType, INodeProperties } from 'n8n-workflow';
|
|
14
|
+
|
|
15
|
+
export class TestCredential implements ICredentialType {
|
|
16
|
+
name = 'testApi';
|
|
17
|
+
displayName = 'Test API';
|
|
18
|
+
documentationUrl = 'https://docs.example.com';${iconLine}
|
|
19
|
+
|
|
20
|
+
properties: INodeProperties[] = [];
|
|
21
|
+
}`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function createCredentialWithLightDarkIcon(): string {
|
|
25
|
+
return `
|
|
26
|
+
import type { ICredentialType, INodeProperties } from 'n8n-workflow';
|
|
27
|
+
|
|
28
|
+
export class TestCredential implements ICredentialType {
|
|
29
|
+
name = 'testApi';
|
|
30
|
+
displayName = 'Test API';
|
|
31
|
+
icon = { light: 'file:testCredential.svg', dark: 'file:testCredential.dark.svg' } as const;
|
|
32
|
+
|
|
33
|
+
properties: INodeProperties[] = [];
|
|
34
|
+
}`;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function createRegularClass(): string {
|
|
38
|
+
return `
|
|
39
|
+
export class RegularClass {
|
|
40
|
+
name = 'test';
|
|
41
|
+
}`;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
ruleTester.run('cred-class-field-icon-missing', CredClassFieldIconMissingRule, {
|
|
45
|
+
valid: [
|
|
46
|
+
{
|
|
47
|
+
name: 'credential with icon defined',
|
|
48
|
+
filename: credFilePath,
|
|
49
|
+
code: createCredentialCode(true),
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: 'credential with light/dark icon object',
|
|
53
|
+
filename: credFilePath,
|
|
54
|
+
code: createCredentialWithLightDarkIcon(),
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: 'class not implementing ICredentialType is ignored',
|
|
58
|
+
filename: credFilePath,
|
|
59
|
+
code: createRegularClass(),
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: 'non-.credentials.ts file is ignored',
|
|
63
|
+
filename: nonCredFilePath,
|
|
64
|
+
code: createCredentialCode(false),
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
invalid: [
|
|
68
|
+
{
|
|
69
|
+
name: 'credential missing icon property',
|
|
70
|
+
filename: credFilePath,
|
|
71
|
+
code: createCredentialCode(false),
|
|
72
|
+
errors: [
|
|
73
|
+
{
|
|
74
|
+
messageId: 'missingIcon',
|
|
75
|
+
suggestions: [
|
|
76
|
+
{
|
|
77
|
+
messageId: 'addPlaceholder',
|
|
78
|
+
output: `
|
|
79
|
+
import type { ICredentialType, INodeProperties } from 'n8n-workflow';
|
|
80
|
+
|
|
81
|
+
export class TestCredential implements ICredentialType {
|
|
82
|
+
name = 'testApi';
|
|
83
|
+
displayName = 'Test API';
|
|
84
|
+
documentationUrl = 'https://docs.example.com';
|
|
85
|
+
|
|
86
|
+
properties: INodeProperties[] = [];
|
|
87
|
+
|
|
88
|
+
icon = "file:./icon.svg";
|
|
89
|
+
}`,
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
},
|
|
95
|
+
],
|
|
96
|
+
});
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isCredentialTypeClass,
|
|
3
|
+
findClassProperty,
|
|
4
|
+
isFileType,
|
|
5
|
+
createRule,
|
|
6
|
+
} from '../utils/index.js';
|
|
7
|
+
|
|
8
|
+
export const CredClassFieldIconMissingRule = createRule({
|
|
9
|
+
name: 'cred-class-field-icon-missing',
|
|
10
|
+
meta: {
|
|
11
|
+
type: 'problem',
|
|
12
|
+
docs: {
|
|
13
|
+
description: 'Credential class must have an `icon` property defined',
|
|
14
|
+
},
|
|
15
|
+
messages: {
|
|
16
|
+
missingIcon: 'Credential class is missing required `icon` property',
|
|
17
|
+
addPlaceholder: 'Add icon property with placeholder',
|
|
18
|
+
},
|
|
19
|
+
schema: [],
|
|
20
|
+
hasSuggestions: true,
|
|
21
|
+
},
|
|
22
|
+
defaultOptions: [],
|
|
23
|
+
create(context) {
|
|
24
|
+
if (!isFileType(context.filename, '.credentials.ts')) {
|
|
25
|
+
return {};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
ClassDeclaration(node) {
|
|
30
|
+
if (!isCredentialTypeClass(node)) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const iconProperty = findClassProperty(node, 'icon');
|
|
35
|
+
if (iconProperty?.value) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
context.report({
|
|
40
|
+
node,
|
|
41
|
+
messageId: 'missingIcon',
|
|
42
|
+
suggest: [
|
|
43
|
+
{
|
|
44
|
+
messageId: 'addPlaceholder',
|
|
45
|
+
fix(fixer) {
|
|
46
|
+
const classBody = node.body.body;
|
|
47
|
+
const lastProperty = classBody[classBody.length - 1];
|
|
48
|
+
if (lastProperty) {
|
|
49
|
+
return fixer.insertTextAfter(lastProperty, '\n\n\ticon = "file:./icon.svg";');
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
});
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
},
|
|
59
|
+
});
|
package/src/rules/index.ts
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import type { AnyRuleModule } from '@typescript-eslint/utils/ts-eslint';
|
|
2
2
|
|
|
3
3
|
import { AiNodePackageJsonRule } from './ai-node-package-json.js';
|
|
4
|
+
import { CredClassFieldIconMissingRule } from './cred-class-field-icon-missing.js';
|
|
4
5
|
import { CredentialDocumentationUrlRule } from './credential-documentation-url.js';
|
|
5
6
|
import { CredentialPasswordFieldRule } from './credential-password-field.js';
|
|
6
7
|
import { CredentialTestRequiredRule } from './credential-test-required.js';
|
|
7
8
|
import { IconValidationRule } from './icon-validation.js';
|
|
8
9
|
import { NoCredentialReuseRule } from './no-credential-reuse.js';
|
|
9
10
|
import { NoDeprecatedWorkflowFunctionsRule } from './no-deprecated-workflow-functions.js';
|
|
11
|
+
import { NoHttpRequestWithManualAuthRule } from './no-http-request-with-manual-auth.js';
|
|
10
12
|
import { NoRestrictedGlobalsRule } from './no-restricted-globals.js';
|
|
11
13
|
import { NoRestrictedImportsRule } from './no-restricted-imports.js';
|
|
14
|
+
import { NodeClassDescriptionIconMissingRule } from './node-class-description-icon-missing.js';
|
|
12
15
|
import { NodeUsableAsToolRule } from './node-usable-as-tool.js';
|
|
13
16
|
import { PackageNameConventionRule } from './package-name-convention.js';
|
|
14
17
|
import { ResourceOperationPatternRule } from './resource-operation-pattern.js';
|
|
@@ -23,7 +26,10 @@ export const rules = {
|
|
|
23
26
|
'package-name-convention': PackageNameConventionRule,
|
|
24
27
|
'credential-test-required': CredentialTestRequiredRule,
|
|
25
28
|
'no-credential-reuse': NoCredentialReuseRule,
|
|
29
|
+
'no-http-request-with-manual-auth': NoHttpRequestWithManualAuthRule,
|
|
26
30
|
'icon-validation': IconValidationRule,
|
|
27
31
|
'resource-operation-pattern': ResourceOperationPatternRule,
|
|
28
32
|
'credential-documentation-url': CredentialDocumentationUrlRule,
|
|
33
|
+
'node-class-description-icon-missing': NodeClassDescriptionIconMissingRule,
|
|
34
|
+
'cred-class-field-icon-missing': CredClassFieldIconMissingRule,
|
|
29
35
|
} satisfies Record<string, AnyRuleModule>;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import type { TSESTree } from '@typescript-eslint/utils';
|
|
2
1
|
import { AST_NODE_TYPES } from '@typescript-eslint/utils';
|
|
3
2
|
|
|
4
|
-
import { createRule } from '../utils/index.js';
|
|
3
|
+
import { createRule, isThisHelpersAccess } from '../utils/index.js';
|
|
5
4
|
|
|
6
5
|
const DEPRECATED_FUNCTIONS = {
|
|
7
6
|
request: 'httpRequest',
|
|
@@ -167,21 +166,6 @@ export const NoDeprecatedWorkflowFunctionsRule = createRule({
|
|
|
167
166
|
},
|
|
168
167
|
});
|
|
169
168
|
|
|
170
|
-
/**
|
|
171
|
-
* Check if the MemberExpression follows the this.helpers.* pattern
|
|
172
|
-
*/
|
|
173
|
-
function isThisHelpersAccess(node: TSESTree.MemberExpression): boolean {
|
|
174
|
-
if (node.object?.type === AST_NODE_TYPES.MemberExpression) {
|
|
175
|
-
const outerObject = node.object;
|
|
176
|
-
return (
|
|
177
|
-
outerObject.object?.type === AST_NODE_TYPES.ThisExpression &&
|
|
178
|
-
outerObject.property?.type === AST_NODE_TYPES.Identifier &&
|
|
179
|
-
outerObject.property.name === 'helpers'
|
|
180
|
-
);
|
|
181
|
-
}
|
|
182
|
-
return false;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
169
|
function getDeprecationMessage(functionName: string): string {
|
|
186
170
|
switch (functionName) {
|
|
187
171
|
case 'request':
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { RuleTester } from '@typescript-eslint/rule-tester';
|
|
2
|
+
|
|
3
|
+
import { NoHttpRequestWithManualAuthRule } from './no-http-request-with-manual-auth.js';
|
|
4
|
+
|
|
5
|
+
const ruleTester = new RuleTester();
|
|
6
|
+
|
|
7
|
+
ruleTester.run('no-http-request-with-manual-auth', NoHttpRequestWithManualAuthRule, {
|
|
8
|
+
valid: [
|
|
9
|
+
{
|
|
10
|
+
name: 'httpRequest and getCredentials at module top level (no function scope)',
|
|
11
|
+
code: `
|
|
12
|
+
const credentials = await this.getCredentials('myApi');
|
|
13
|
+
const result = await this.helpers.httpRequest({ url: 'https://api.example.com' });`,
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
name: 'httpRequest without getCredentials (unauthenticated call)',
|
|
17
|
+
code: `
|
|
18
|
+
async function makeRequest() {
|
|
19
|
+
return this.helpers.httpRequest({ url: 'https://public.api.com' });
|
|
20
|
+
}`,
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
name: 'httpRequestWithAuthentication with getCredentials (correct pattern)',
|
|
24
|
+
code: `
|
|
25
|
+
async function makeRequest() {
|
|
26
|
+
const credentials = await this.getCredentials('myApi');
|
|
27
|
+
return this.helpers.httpRequestWithAuthentication.call(this, 'myApi', {
|
|
28
|
+
url: 'https://api.example.com',
|
|
29
|
+
});
|
|
30
|
+
}`,
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: 'getCredentials called but no httpRequest in same function',
|
|
34
|
+
code: `
|
|
35
|
+
async function loadConfig() {
|
|
36
|
+
const credentials = await this.getCredentials('myApi');
|
|
37
|
+
return credentials.apiKey;
|
|
38
|
+
}`,
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: 'getCredentials in outer function, httpRequest in nested function (separate scopes)',
|
|
42
|
+
code: `
|
|
43
|
+
async function execute() {
|
|
44
|
+
const credentials = await this.getCredentials('myApi');
|
|
45
|
+
const makeRequest = async () => {
|
|
46
|
+
return this.helpers.httpRequest({ url: 'https://api.example.com' });
|
|
47
|
+
};
|
|
48
|
+
return makeRequest();
|
|
49
|
+
}`,
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: 'other object with helpers.httpRequest is not flagged',
|
|
53
|
+
code: `
|
|
54
|
+
async function test() {
|
|
55
|
+
const credentials = await this.getCredentials('myApi');
|
|
56
|
+
const otherObject = { helpers: { httpRequest: async () => {} } };
|
|
57
|
+
return otherObject.helpers.httpRequest({ url: 'https://example.com' });
|
|
58
|
+
}`,
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
invalid: [
|
|
62
|
+
{
|
|
63
|
+
name: 'function calls both getCredentials and httpRequest',
|
|
64
|
+
code: `
|
|
65
|
+
async function makeRequest() {
|
|
66
|
+
const credentials = await this.getCredentials('myApi');
|
|
67
|
+
const options = {
|
|
68
|
+
headers: { Authorization: \`Bearer \${credentials.apiKey}\` },
|
|
69
|
+
url: 'https://api.example.com',
|
|
70
|
+
};
|
|
71
|
+
return this.helpers.httpRequest(options);
|
|
72
|
+
}`,
|
|
73
|
+
errors: [{ messageId: 'useHttpRequestWithAuthentication' }],
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
name: 'two httpRequest calls in a function that also calls getCredentials — both flagged',
|
|
77
|
+
code: `
|
|
78
|
+
async function makeRequests() {
|
|
79
|
+
const credentials = await this.getCredentials('myApi');
|
|
80
|
+
const r1 = await this.helpers.httpRequest({ url: 'https://api.example.com/a' });
|
|
81
|
+
const r2 = await this.helpers.httpRequest({ url: 'https://api.example.com/b' });
|
|
82
|
+
return [r1, r2];
|
|
83
|
+
}`,
|
|
84
|
+
errors: [
|
|
85
|
+
{ messageId: 'useHttpRequestWithAuthentication' },
|
|
86
|
+
{ messageId: 'useHttpRequestWithAuthentication' },
|
|
87
|
+
],
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
name: 'class method pattern',
|
|
91
|
+
code: `
|
|
92
|
+
class MyNode {
|
|
93
|
+
async execute() {
|
|
94
|
+
const credentials = await this.getCredentials('myApi');
|
|
95
|
+
return this.helpers.httpRequest({
|
|
96
|
+
headers: { Authorization: credentials.apiKey },
|
|
97
|
+
url: 'https://api.example.com',
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
}`,
|
|
101
|
+
errors: [{ messageId: 'useHttpRequestWithAuthentication' }],
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
});
|