@n8n/eslint-plugin-community-nodes 0.24.0 → 0.26.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 (137) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/README.md +39 -52
  3. package/dist/plugin.d.ts +15 -93
  4. package/dist/plugin.d.ts.map +1 -1
  5. package/dist/plugin.js +0 -26
  6. package/dist/plugin.js.map +1 -1
  7. package/dist/rules/ai-node-package-json.d.ts +1 -1
  8. package/dist/rules/cred-class-field-icon-missing.d.ts +1 -1
  9. package/dist/rules/cred-class-oauth2-naming.d.ts +1 -1
  10. package/dist/rules/icon-validation.d.ts +1 -1
  11. package/dist/rules/index.d.ts +20 -33
  12. package/dist/rules/index.d.ts.map +1 -1
  13. package/dist/rules/index.js +0 -26
  14. package/dist/rules/index.js.map +1 -1
  15. package/dist/rules/no-credential-reuse.d.ts +1 -1
  16. package/dist/rules/no-dangerous-functions.d.ts +1 -1
  17. package/dist/rules/no-deprecated-workflow-functions.d.ts +1 -1
  18. package/dist/rules/no-restricted-imports.d.ts +1 -1
  19. package/dist/rules/no-restricted-imports.d.ts.map +1 -1
  20. package/dist/rules/no-restricted-imports.js +14 -5
  21. package/dist/rules/no-restricted-imports.js.map +1 -1
  22. package/dist/rules/node-class-description-icon-missing.d.ts +1 -1
  23. package/dist/rules/node-connection-type-literal.js.map +1 -1
  24. package/dist/rules/package-name-convention.d.ts +1 -1
  25. package/dist/rules/require-version.d.ts +1 -1
  26. package/dist/rules/trigger-node-conventions.d.ts +1 -1
  27. package/dist/rules/valid-author.d.ts +1 -1
  28. package/dist/rules/valid-credential-references.d.ts +1 -1
  29. package/dist/rules/valid-description.d.ts +1 -1
  30. package/dist/rules/valid-peer-dependencies.d.ts +1 -1
  31. package/dist/rules/webhook-lifecycle-complete.d.ts +1 -1
  32. package/dist/typecheck.tsbuildinfo +1 -1
  33. package/dist/utils/ast-utils.js.map +1 -1
  34. package/dist/utils/file-utils.d.ts +7 -0
  35. package/dist/utils/file-utils.d.ts.map +1 -1
  36. package/dist/utils/file-utils.js +28 -6
  37. package/dist/utils/file-utils.js.map +1 -1
  38. package/docs/rules/no-forbidden-lifecycle-scripts.md +1 -1
  39. package/docs/rules/no-restricted-imports.md +9 -0
  40. package/package.json +6 -5
  41. package/src/plugin.ts +0 -26
  42. package/src/rules/index.ts +0 -26
  43. package/src/rules/no-restricted-imports.test.ts +63 -0
  44. package/src/rules/no-restricted-imports.ts +17 -4
  45. package/src/utils/file-utils.ts +27 -6
  46. package/tsconfig.json +1 -1
  47. package/dist/rules/cred-class-name-field-conventions.d.ts +0 -2
  48. package/dist/rules/cred-class-name-field-conventions.d.ts.map +0 -1
  49. package/dist/rules/cred-class-name-field-conventions.js +0 -89
  50. package/dist/rules/cred-class-name-field-conventions.js.map +0 -1
  51. package/dist/rules/cred-class-name-suffix.d.ts +0 -2
  52. package/dist/rules/cred-class-name-suffix.d.ts.map +0 -1
  53. package/dist/rules/cred-class-name-suffix.js +0 -53
  54. package/dist/rules/cred-class-name-suffix.js.map +0 -1
  55. package/dist/rules/cred-filename-against-convention.d.ts +0 -2
  56. package/dist/rules/cred-filename-against-convention.d.ts.map +0 -1
  57. package/dist/rules/cred-filename-against-convention.js +0 -42
  58. package/dist/rules/cred-filename-against-convention.js.map +0 -1
  59. package/dist/rules/no-asterisk-in-option-names.d.ts +0 -2
  60. package/dist/rules/no-asterisk-in-option-names.d.ts.map +0 -1
  61. package/dist/rules/no-asterisk-in-option-names.js +0 -90
  62. package/dist/rules/no-asterisk-in-option-names.js.map +0 -1
  63. package/dist/rules/no-duplicate-param-options.d.ts +0 -2
  64. package/dist/rules/no-duplicate-param-options.d.ts.map +0 -1
  65. package/dist/rules/no-duplicate-param-options.js +0 -97
  66. package/dist/rules/no-duplicate-param-options.js.map +0 -1
  67. package/dist/rules/node-class-description-name-camelcase.d.ts +0 -2
  68. package/dist/rules/node-class-description-name-camelcase.d.ts.map +0 -1
  69. package/dist/rules/node-class-description-name-camelcase.js +0 -92
  70. package/dist/rules/node-class-description-name-camelcase.js.map +0 -1
  71. package/dist/rules/node-filename-against-convention.d.ts +0 -2
  72. package/dist/rules/node-filename-against-convention.d.ts.map +0 -1
  73. package/dist/rules/node-filename-against-convention.js +0 -61
  74. package/dist/rules/node-filename-against-convention.js.map +0 -1
  75. package/dist/rules/node-operation-error-itemindex.d.ts +0 -12
  76. package/dist/rules/node-operation-error-itemindex.d.ts.map +0 -1
  77. package/dist/rules/node-operation-error-itemindex.js +0 -184
  78. package/dist/rules/node-operation-error-itemindex.js.map +0 -1
  79. package/dist/rules/options-sorted-alphabetically.d.ts +0 -2
  80. package/dist/rules/options-sorted-alphabetically.d.ts.map +0 -1
  81. package/dist/rules/options-sorted-alphabetically.js +0 -95
  82. package/dist/rules/options-sorted-alphabetically.js.map +0 -1
  83. package/dist/rules/require-community-node-keyword.d.ts +0 -2
  84. package/dist/rules/require-community-node-keyword.d.ts.map +0 -1
  85. package/dist/rules/require-community-node-keyword.js +0 -65
  86. package/dist/rules/require-community-node-keyword.js.map +0 -1
  87. package/dist/rules/require-continue-on-fail.d.ts +0 -2
  88. package/dist/rules/require-continue-on-fail.d.ts.map +0 -1
  89. package/dist/rules/require-continue-on-fail.js +0 -76
  90. package/dist/rules/require-continue-on-fail.js.map +0 -1
  91. package/dist/rules/require-mit-license.d.ts +0 -2
  92. package/dist/rules/require-mit-license.d.ts.map +0 -1
  93. package/dist/rules/require-mit-license.js +0 -57
  94. package/dist/rules/require-mit-license.js.map +0 -1
  95. package/dist/rules/require-param-default.d.ts +0 -15
  96. package/dist/rules/require-param-default.d.ts.map +0 -1
  97. package/dist/rules/require-param-default.js +0 -75
  98. package/dist/rules/require-param-default.js.map +0 -1
  99. package/docs/rules/cred-class-name-field-conventions.md +0 -38
  100. package/docs/rules/cred-class-name-suffix.md +0 -46
  101. package/docs/rules/cred-filename-against-convention.md +0 -42
  102. package/docs/rules/no-asterisk-in-option-names.md +0 -61
  103. package/docs/rules/no-duplicate-param-options.md +0 -46
  104. package/docs/rules/node-class-description-name-camelcase.md +0 -41
  105. package/docs/rules/node-filename-against-convention.md +0 -50
  106. package/docs/rules/node-operation-error-itemindex.md +0 -81
  107. package/docs/rules/options-sorted-alphabetically.md +0 -63
  108. package/docs/rules/require-community-node-keyword.md +0 -45
  109. package/docs/rules/require-continue-on-fail.md +0 -56
  110. package/docs/rules/require-mit-license.md +0 -38
  111. package/docs/rules/require-param-default.md +0 -60
  112. package/src/rules/cred-class-name-field-conventions.test.ts +0 -121
  113. package/src/rules/cred-class-name-field-conventions.ts +0 -102
  114. package/src/rules/cred-class-name-suffix.test.ts +0 -74
  115. package/src/rules/cred-class-name-suffix.ts +0 -57
  116. package/src/rules/cred-filename-against-convention.test.ts +0 -72
  117. package/src/rules/cred-filename-against-convention.ts +0 -48
  118. package/src/rules/no-asterisk-in-option-names.test.ts +0 -185
  119. package/src/rules/no-asterisk-in-option-names.ts +0 -111
  120. package/src/rules/no-duplicate-param-options.test.ts +0 -125
  121. package/src/rules/no-duplicate-param-options.ts +0 -125
  122. package/src/rules/node-class-description-name-camelcase.test.ts +0 -121
  123. package/src/rules/node-class-description-name-camelcase.ts +0 -114
  124. package/src/rules/node-filename-against-convention.test.ts +0 -115
  125. package/src/rules/node-filename-against-convention.ts +0 -76
  126. package/src/rules/node-operation-error-itemindex.test.ts +0 -280
  127. package/src/rules/node-operation-error-itemindex.ts +0 -223
  128. package/src/rules/options-sorted-alphabetically.test.ts +0 -468
  129. package/src/rules/options-sorted-alphabetically.ts +0 -129
  130. package/src/rules/require-community-node-keyword.test.ts +0 -82
  131. package/src/rules/require-community-node-keyword.ts +0 -78
  132. package/src/rules/require-continue-on-fail.test.ts +0 -129
  133. package/src/rules/require-continue-on-fail.ts +0 -88
  134. package/src/rules/require-mit-license.test.ts +0 -67
  135. package/src/rules/require-mit-license.ts +0 -65
  136. package/src/rules/require-param-default.test.ts +0 -227
  137. package/src/rules/require-param-default.ts +0 -89
@@ -1,121 +0,0 @@
1
- import { RuleTester } from '@typescript-eslint/rule-tester';
2
-
3
- import { CredClassNameFieldConventionsRule } from './cred-class-name-field-conventions.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(name: string): string {
11
- return `
12
- import type { ICredentialType, INodeProperties } from 'n8n-workflow';
13
-
14
- export class TestApi implements ICredentialType {
15
- name = '${name}';
16
- displayName = 'Test API';
17
- properties: INodeProperties[] = [];
18
- }`;
19
- }
20
-
21
- function createRegularClass(name: string): string {
22
- return `
23
- export class SomeHelper {
24
- name = '${name}';
25
- }`;
26
- }
27
-
28
- // Embeds the raw literal text (including its quotes) verbatim, so tests can
29
- // exercise names containing quote characters that need escaping.
30
- function createCredentialCodeWithLiteral(literal: string): string {
31
- return `
32
- import type { ICredentialType, INodeProperties } from 'n8n-workflow';
33
-
34
- export class TestApi implements ICredentialType {
35
- name = ${literal};
36
- displayName = 'Test API';
37
- properties: INodeProperties[] = [];
38
- }`;
39
- }
40
-
41
- ruleTester.run('cred-class-name-field-conventions', CredClassNameFieldConventionsRule, {
42
- valid: [
43
- {
44
- name: 'name field with Api suffix and lowercase first char',
45
- filename: credFilePath,
46
- code: createCredentialCode('githubApi'),
47
- },
48
- {
49
- name: 'OAuth2 name field is also valid',
50
- filename: credFilePath,
51
- code: createCredentialCode('githubOAuth2Api'),
52
- },
53
- {
54
- name: 'class not implementing ICredentialType is ignored',
55
- filename: credFilePath,
56
- code: createRegularClass('Github'),
57
- },
58
- {
59
- name: 'non-.credentials.ts file is ignored',
60
- filename: nonCredFilePath,
61
- code: createCredentialCode('Github'),
62
- },
63
- ],
64
- invalid: [
65
- {
66
- name: 'name field missing Api suffix',
67
- filename: credFilePath,
68
- code: createCredentialCode('github'),
69
- errors: [{ messageId: 'missingSuffix', data: { value: 'github' } }],
70
- output: createCredentialCode('githubApi'),
71
- },
72
- {
73
- name: 'name field with uppercase first char',
74
- filename: credFilePath,
75
- code: createCredentialCode('GithubApi'),
76
- errors: [{ messageId: 'uppercaseFirstChar', data: { value: 'GithubApi' } }],
77
- output: createCredentialCode('githubApi'),
78
- },
79
- {
80
- name: 'name field with both uppercase first char and missing suffix',
81
- filename: credFilePath,
82
- code: createCredentialCode('Github'),
83
- errors: [
84
- { messageId: 'uppercaseFirstChar', data: { value: 'Github' } },
85
- { messageId: 'missingSuffix', data: { value: 'Github' } },
86
- ],
87
- output: createCredentialCode('githubApi'),
88
- },
89
- {
90
- name: 'name field ending in Ap',
91
- filename: credFilePath,
92
- code: createCredentialCode('githubAp'),
93
- errors: [{ messageId: 'missingSuffix', data: { value: 'githubAp' } }],
94
- output: createCredentialCode('githubApi'),
95
- },
96
- {
97
- name: 'name field ending in A',
98
- filename: credFilePath,
99
- code: createCredentialCode('githubA'),
100
- errors: [{ messageId: 'missingSuffix', data: { value: 'githubA' } }],
101
- output: createCredentialCode('githubApi'),
102
- },
103
- {
104
- name: 'autofix escapes single quotes in the name value',
105
- filename: credFilePath,
106
- code: createCredentialCodeWithLiteral("'git\\'hub'"),
107
- errors: [{ messageId: 'missingSuffix', data: { value: "git'hub" } }],
108
- output: createCredentialCodeWithLiteral("'git\\'hubApi'"),
109
- },
110
- {
111
- name: 'autofix preserves double quotes and escapes them in the name value',
112
- filename: credFilePath,
113
- code: createCredentialCodeWithLiteral('"Git\\"hub"'),
114
- errors: [
115
- { messageId: 'uppercaseFirstChar', data: { value: 'Git"hub' } },
116
- { messageId: 'missingSuffix', data: { value: 'Git"hub' } },
117
- ],
118
- output: createCredentialCodeWithLiteral('"git\\"hubApi"'),
119
- },
120
- ],
121
- });
@@ -1,102 +0,0 @@
1
- import {
2
- createRule,
3
- findClassProperty,
4
- getStringLiteralValue,
5
- isCredentialTypeClass,
6
- isFileType,
7
- } from '../utils/index.js';
8
-
9
- function lowercaseFirstChar(name: string): string {
10
- return name.charAt(0).toLowerCase() + name.slice(1);
11
- }
12
-
13
- function addApiSuffix(name: string): string {
14
- if (name.endsWith('Api')) return name;
15
- if (name.endsWith('Ap')) return `${name}i`;
16
- if (name.endsWith('A')) return `${name}pi`;
17
- return `${name}Api`;
18
- }
19
-
20
- // Serialize a value as a string literal using the original quote character,
21
- // escaping any characters that would otherwise break the literal so the
22
- // autofix never emits invalid code (e.g. names containing quotes).
23
- function toStringLiteral(value: string, quote: string): string {
24
- const escaped = value
25
- .replace(/\\/g, '\\\\')
26
- .replace(/\n/g, '\\n')
27
- .replace(/\r/g, '\\r')
28
- .split(quote)
29
- .join(`\\${quote}`);
30
- return `${quote}${escaped}${quote}`;
31
- }
32
-
33
- export const CredClassNameFieldConventionsRule = createRule({
34
- name: 'cred-class-name-field-conventions',
35
- meta: {
36
- type: 'problem',
37
- docs: {
38
- description: 'Credential `name` field must end with `Api` and start with a lowercase letter',
39
- },
40
- messages: {
41
- missingSuffix: "Credential `name` field '{{value}}' must end with 'Api'",
42
- uppercaseFirstChar: "Credential `name` field '{{value}}' must start with a lowercase letter",
43
- },
44
- fixable: 'code',
45
- schema: [],
46
- },
47
- defaultOptions: [],
48
- create(context) {
49
- if (!isFileType(context.filename, '.credentials.ts')) {
50
- return {};
51
- }
52
-
53
- return {
54
- ClassDeclaration(node) {
55
- if (!isCredentialTypeClass(node)) {
56
- return;
57
- }
58
-
59
- const nameProperty = findClassProperty(node, 'name');
60
- if (!nameProperty?.value) {
61
- return;
62
- }
63
-
64
- const nameValue = getStringLiteralValue(nameProperty.value);
65
- if (nameValue === null) {
66
- return;
67
- }
68
-
69
- const startsLowercase = !/^[A-Z]/.test(nameValue);
70
- const endsWithApi = nameValue.endsWith('Api');
71
- if (startsLowercase && endsWithApi) {
72
- return;
73
- }
74
-
75
- // Compute the fully-corrected value once so each fix yields the
76
- // same result in a single pass, regardless of which one applies.
77
- const fixedValue = addApiSuffix(lowercaseFirstChar(nameValue));
78
- const valueNode = nameProperty.value;
79
- const quote = context.sourceCode.getText(valueNode).charAt(0);
80
- const replacement = toStringLiteral(fixedValue, quote);
81
-
82
- if (!startsLowercase) {
83
- context.report({
84
- node: valueNode,
85
- messageId: 'uppercaseFirstChar',
86
- data: { value: nameValue },
87
- fix: (fixer) => fixer.replaceText(valueNode, replacement),
88
- });
89
- }
90
-
91
- if (!endsWithApi) {
92
- context.report({
93
- node: valueNode,
94
- messageId: 'missingSuffix',
95
- data: { value: nameValue },
96
- fix: (fixer) => fixer.replaceText(valueNode, replacement),
97
- });
98
- }
99
- },
100
- };
101
- },
102
- });
@@ -1,74 +0,0 @@
1
- import { RuleTester } from '@typescript-eslint/rule-tester';
2
-
3
- import { CredClassNameSuffixRule } from './cred-class-name-suffix.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(className: string): string {
11
- return `
12
- import type { ICredentialType, INodeProperties } from 'n8n-workflow';
13
-
14
- export class ${className} implements ICredentialType {
15
- name = 'testApi';
16
- displayName = 'Test API';
17
- properties: INodeProperties[] = [];
18
- }`;
19
- }
20
-
21
- function createRegularClass(className: string): string {
22
- return `
23
- export class ${className} {
24
- name = 'test';
25
- }`;
26
- }
27
-
28
- ruleTester.run('cred-class-name-suffix', CredClassNameSuffixRule, {
29
- valid: [
30
- {
31
- name: 'credential class with Api suffix',
32
- filename: credFilePath,
33
- code: createCredentialCode('TestApi'),
34
- },
35
- {
36
- name: 'credential class with OAuth2Api suffix',
37
- filename: credFilePath,
38
- code: createCredentialCode('TestOAuth2Api'),
39
- },
40
- {
41
- name: 'class not implementing ICredentialType is ignored',
42
- filename: credFilePath,
43
- code: createRegularClass('SomeHelper'),
44
- },
45
- {
46
- name: 'non-.credentials.ts file is ignored',
47
- filename: nonCredFilePath,
48
- code: createCredentialCode('TestCredential'),
49
- },
50
- ],
51
- invalid: [
52
- {
53
- name: 'credential class missing Api suffix',
54
- filename: credFilePath,
55
- code: createCredentialCode('TestCredential'),
56
- errors: [{ messageId: 'missingSuffix', data: { name: 'TestCredential' } }],
57
- output: createCredentialCode('TestCredentialApi'),
58
- },
59
- {
60
- name: 'credential class name ending in Ap',
61
- filename: credFilePath,
62
- code: createCredentialCode('TestAp'),
63
- errors: [{ messageId: 'missingSuffix', data: { name: 'TestAp' } }],
64
- output: createCredentialCode('TestApi'),
65
- },
66
- {
67
- name: 'credential class name ending in A',
68
- filename: credFilePath,
69
- code: createCredentialCode('TestA'),
70
- errors: [{ messageId: 'missingSuffix', data: { name: 'TestA' } }],
71
- output: createCredentialCode('TestApi'),
72
- },
73
- ],
74
- });
@@ -1,57 +0,0 @@
1
- import { isCredentialTypeClass, isFileType, createRule } from '../utils/index.js';
2
-
3
- function addApiSuffix(name: string): string {
4
- if (name.endsWith('Ap')) return `${name}i`;
5
- if (name.endsWith('A')) return `${name}pi`;
6
- return `${name}Api`;
7
- }
8
-
9
- export const CredClassNameSuffixRule = createRule({
10
- name: 'cred-class-name-suffix',
11
- meta: {
12
- type: 'problem',
13
- docs: {
14
- description: 'Credential class names must be suffixed with `Api`',
15
- },
16
- messages: {
17
- missingSuffix: "Credential class name '{{name}}' must end with 'Api'",
18
- },
19
- fixable: 'code',
20
- schema: [],
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 classNameNode = node.id;
35
- if (!classNameNode) {
36
- return;
37
- }
38
-
39
- const className = classNameNode.name;
40
- if (className.endsWith('Api')) {
41
- return;
42
- }
43
-
44
- const fixedName = addApiSuffix(className);
45
-
46
- context.report({
47
- node: classNameNode,
48
- messageId: 'missingSuffix',
49
- data: { name: className },
50
- fix(fixer) {
51
- return fixer.replaceText(classNameNode, fixedName);
52
- },
53
- });
54
- },
55
- };
56
- },
57
- });
@@ -1,72 +0,0 @@
1
- import { RuleTester } from '@typescript-eslint/rule-tester';
2
-
3
- import { CredFilenameAgainstConventionRule } from './cred-filename-against-convention.js';
4
-
5
- const ruleTester = new RuleTester();
6
-
7
- function createCredentialCode(className: string): string {
8
- return `
9
- import type { ICredentialType, INodeProperties } from 'n8n-workflow';
10
-
11
- export class ${className} implements ICredentialType {
12
- name = '${className.charAt(0).toLowerCase() + className.slice(1)}';
13
- displayName = '${className}';
14
- properties: INodeProperties[] = [];
15
- }`;
16
- }
17
-
18
- function createRegularClass(): string {
19
- return `
20
- export class SomeHelper {
21
- name = 'githubApi';
22
- }`;
23
- }
24
-
25
- ruleTester.run('cred-filename-against-convention', CredFilenameAgainstConventionRule, {
26
- valid: [
27
- {
28
- name: 'filename matches credential class name',
29
- filename: '/tmp/GithubApi.credentials.ts',
30
- code: createCredentialCode('GithubApi'),
31
- },
32
- {
33
- name: 'multi-word class name matches filename',
34
- filename: '/tmp/GoogleSheetsOAuth2Api.credentials.ts',
35
- code: createCredentialCode('GoogleSheetsOAuth2Api'),
36
- },
37
- {
38
- name: 'class not implementing ICredentialType is ignored',
39
- filename: '/tmp/Github.credentials.ts',
40
- code: createRegularClass(),
41
- },
42
- {
43
- name: 'non-.credentials.ts file is ignored',
44
- filename: '/tmp/GithubApi.ts',
45
- code: createCredentialCode('Mismatch'),
46
- },
47
- ],
48
- invalid: [
49
- {
50
- name: 'filename does not match class name',
51
- filename: '/tmp/GithubApi.credentials.ts',
52
- code: createCredentialCode('GitlabApi'),
53
- errors: [
54
- {
55
- messageId: 'renameFile',
56
- data: { className: 'GitlabApi', expected: 'GitlabApi.credentials.ts' },
57
- },
58
- ],
59
- },
60
- {
61
- name: 'filename has wrong casing',
62
- filename: '/tmp/githubApi.credentials.ts',
63
- code: createCredentialCode('GithubApi'),
64
- errors: [
65
- {
66
- messageId: 'renameFile',
67
- data: { className: 'GithubApi', expected: 'GithubApi.credentials.ts' },
68
- },
69
- ],
70
- },
71
- ],
72
- });
@@ -1,48 +0,0 @@
1
- import * as path from 'node:path';
2
-
3
- import { isCredentialTypeClass, isFileType, createRule } from '../utils/index.js';
4
-
5
- export const CredFilenameAgainstConventionRule = createRule({
6
- name: 'cred-filename-against-convention',
7
- meta: {
8
- type: 'problem',
9
- docs: {
10
- description: 'Credential filename must match the credential class name',
11
- },
12
- messages: {
13
- renameFile:
14
- 'Credential filename must match the class name "{{className}}". Rename file to "{{expected}}".',
15
- },
16
- schema: [],
17
- },
18
- defaultOptions: [],
19
- create(context) {
20
- if (!isFileType(context.filename, '.credentials.ts')) {
21
- return {};
22
- }
23
-
24
- return {
25
- ClassDeclaration(node) {
26
- if (!isCredentialTypeClass(node)) {
27
- return;
28
- }
29
-
30
- const classNameNode = node.id;
31
- if (!classNameNode) {
32
- return;
33
- }
34
-
35
- const className = classNameNode.name;
36
- const actualBaseName = path.basename(context.filename, '.credentials.ts');
37
-
38
- if (actualBaseName !== className) {
39
- context.report({
40
- node: classNameNode,
41
- messageId: 'renameFile',
42
- data: { className, expected: `${className}.credentials.ts` },
43
- });
44
- }
45
- },
46
- };
47
- },
48
- });
@@ -1,185 +0,0 @@
1
- import { RuleTester } from '@typescript-eslint/rule-tester';
2
-
3
- import { NoAsteriskInOptionNamesRule } from './no-asterisk-in-option-names.js';
4
-
5
- const ruleTester = new RuleTester();
6
-
7
- function createNodeCode(body: string): string {
8
- return `
9
- import type { INodeType, INodeTypeDescription } from 'n8n-workflow';
10
-
11
- export class TestNode implements INodeType {
12
- description: INodeTypeDescription = {
13
- ${body}
14
- };
15
- }
16
- `;
17
- }
18
-
19
- ruleTester.run('no-asterisk-in-option-names', NoAsteriskInOptionNamesRule, {
20
- valid: [
21
- {
22
- name: 'class that does not implement INodeType',
23
- filename: '/tmp/TestNode.node.ts',
24
- code: `
25
- export class NotANode {
26
- description = {
27
- properties: [
28
- { options: [{ name: '* All', value: 'all' }] },
29
- ],
30
- };
31
- }
32
- `,
33
- },
34
- {
35
- name: 'non .node.ts file is ignored',
36
- filename: '/tmp/helper.ts',
37
- code: `
38
- export class TestNode {
39
- description = {
40
- properties: [
41
- { options: [{ name: '* All', value: 'all' }] },
42
- ],
43
- };
44
- }
45
- `,
46
- },
47
- {
48
- name: 'option names without asterisk',
49
- filename: '/tmp/TestNode.node.ts',
50
- code: createNodeCode(`
51
- displayName: 'Test Node',
52
- name: 'testNode',
53
- properties: [
54
- {
55
- displayName: 'Operation',
56
- name: 'operation',
57
- type: 'options',
58
- options: [
59
- { name: 'Create', value: 'create' },
60
- { name: '[All]', value: 'all' },
61
- ],
62
- default: 'create',
63
- },
64
- ],
65
- `),
66
- },
67
- {
68
- name: 'asterisk in displayName outside options is ignored',
69
- filename: '/tmp/TestNode.node.ts',
70
- code: createNodeCode(`
71
- displayName: 'Test * Node',
72
- name: 'testNode',
73
- properties: [
74
- { displayName: 'Field *', name: 'field', type: 'string', default: '' },
75
- ],
76
- `),
77
- },
78
- ],
79
- invalid: [
80
- {
81
- name: 'asterisk in option name within options array',
82
- filename: '/tmp/TestNode.node.ts',
83
- code: createNodeCode(`
84
- displayName: 'Test Node',
85
- name: 'testNode',
86
- properties: [
87
- {
88
- displayName: 'Resource',
89
- name: 'resource',
90
- type: 'options',
91
- options: [
92
- { name: '* All', value: 'all' },
93
- { name: 'User', value: 'user' },
94
- ],
95
- default: 'all',
96
- },
97
- ],
98
- `),
99
- errors: [
100
- {
101
- messageId: 'asteriskInOptionName',
102
- data: { name: '* All' },
103
- suggestions: [
104
- {
105
- messageId: 'replaceAsterisk',
106
- output: createNodeCode(`
107
- displayName: 'Test Node',
108
- name: 'testNode',
109
- properties: [
110
- {
111
- displayName: 'Resource',
112
- name: 'resource',
113
- type: 'options',
114
- options: [
115
- { name: '[All] All', value: 'all' },
116
- { name: 'User', value: 'user' },
117
- ],
118
- default: 'all',
119
- },
120
- ],
121
- `),
122
- },
123
- ],
124
- },
125
- ],
126
- },
127
- {
128
- name: 'asterisk in nested collection options',
129
- filename: '/tmp/TestNode.node.ts',
130
- code: createNodeCode(`
131
- displayName: 'Test Node',
132
- name: 'testNode',
133
- properties: [
134
- {
135
- displayName: 'Filters',
136
- name: 'filters',
137
- type: 'collection',
138
- default: {},
139
- options: [
140
- {
141
- displayName: 'Status',
142
- name: 'status',
143
- type: 'options',
144
- options: [{ name: '*', value: 'any' }],
145
- default: 'any',
146
- },
147
- ],
148
- },
149
- ],
150
- `),
151
- errors: [
152
- {
153
- messageId: 'asteriskInOptionName',
154
- data: { name: '*' },
155
- suggestions: [
156
- {
157
- messageId: 'replaceAsterisk',
158
- output: createNodeCode(`
159
- displayName: 'Test Node',
160
- name: 'testNode',
161
- properties: [
162
- {
163
- displayName: 'Filters',
164
- name: 'filters',
165
- type: 'collection',
166
- default: {},
167
- options: [
168
- {
169
- displayName: 'Status',
170
- name: 'status',
171
- type: 'options',
172
- options: [{ name: '[All]', value: 'any' }],
173
- default: 'any',
174
- },
175
- ],
176
- },
177
- ],
178
- `),
179
- },
180
- ],
181
- },
182
- ],
183
- },
184
- ],
185
- });