@n8n/eslint-plugin-community-nodes 0.11.0 → 0.12.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 +3 -0
- 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/index.d.ts +3 -0
- 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/missing-paired-item.d.ts +16 -0
- package/dist/rules/missing-paired-item.d.ts.map +1 -0
- package/dist/rules/missing-paired-item.js +121 -0
- package/dist/rules/missing-paired-item.js.map +1 -0
- package/dist/rules/no-forbidden-lifecycle-scripts.d.ts +2 -0
- package/dist/rules/no-forbidden-lifecycle-scripts.d.ts.map +1 -0
- package/dist/rules/no-forbidden-lifecycle-scripts.js +59 -0
- package/dist/rules/no-forbidden-lifecycle-scripts.js.map +1 -0
- package/dist/rules/require-continue-on-fail.d.ts +2 -0
- package/dist/rules/require-continue-on-fail.d.ts.map +1 -0
- package/dist/rules/require-continue-on-fail.js +76 -0
- package/dist/rules/require-continue-on-fail.js.map +1 -0
- package/docs/rules/missing-paired-item.md +70 -0
- package/docs/rules/no-forbidden-lifecycle-scripts.md +46 -0
- package/docs/rules/require-continue-on-fail.md +56 -0
- package/package.json +2 -2
- package/src/plugin.ts +6 -0
- package/src/rules/index.ts +6 -0
- package/src/rules/missing-paired-item.test.ts +229 -0
- package/src/rules/missing-paired-item.ts +149 -0
- package/src/rules/no-forbidden-lifecycle-scripts.test.ts +103 -0
- package/src/rules/no-forbidden-lifecycle-scripts.ts +69 -0
- package/src/rules/require-continue-on-fail.test.ts +129 -0
- package/src/rules/require-continue-on-fail.ts +88 -0
- package/tsconfig.build.tsbuildinfo +1 -0
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
|
|
2
|
-
> @n8n/eslint-plugin-community-nodes@0.
|
|
2
|
+
> @n8n/eslint-plugin-community-nodes@0.12.0 build /home/runner/work/n8n/n8n/packages/@n8n/eslint-plugin-community-nodes
|
|
3
3
|
> tsc --project tsconfig.build.json
|
|
4
4
|
|
package/README.md
CHANGED
|
@@ -51,8 +51,10 @@ export default [
|
|
|
51
51
|
| [credential-password-field](docs/rules/credential-password-field.md) | Ensure credential fields with sensitive names have typeOptions.password = true | ✅ ☑️ | | 🔧 | |
|
|
52
52
|
| [credential-test-required](docs/rules/credential-test-required.md) | Ensure credentials have a credential test | ✅ ☑️ | | | 💡 |
|
|
53
53
|
| [icon-validation](docs/rules/icon-validation.md) | Validate node and credential icon files exist, are SVG format, and light/dark icons are different | ✅ ☑️ | | | 💡 |
|
|
54
|
+
| [missing-paired-item](docs/rules/missing-paired-item.md) | Require pairedItem on INodeExecutionData objects in execute() methods to preserve item linking. | ✅ ☑️ | | | |
|
|
54
55
|
| [no-credential-reuse](docs/rules/no-credential-reuse.md) | Prevent credential re-use security issues by ensuring nodes only reference credentials from the same package | ✅ ☑️ | | | 💡 |
|
|
55
56
|
| [no-deprecated-workflow-functions](docs/rules/no-deprecated-workflow-functions.md) | Disallow usage of deprecated functions and types from n8n-workflow package | ✅ ☑️ | | | 💡 |
|
|
57
|
+
| [no-forbidden-lifecycle-scripts](docs/rules/no-forbidden-lifecycle-scripts.md) | Ban lifecycle scripts (prepare, preinstall, postinstall, etc.) in community node packages | ✅ ☑️ | | | |
|
|
56
58
|
| [no-http-request-with-manual-auth](docs/rules/no-http-request-with-manual-auth.md) | Disallow this.helpers.httpRequest() in functions that call this.getCredentials(). Use this.helpers.httpRequestWithAuthentication() instead. | ✅ ☑️ | | | |
|
|
57
59
|
| [no-restricted-globals](docs/rules/no-restricted-globals.md) | Disallow usage of restricted global variables in community nodes. | ✅ | | | |
|
|
58
60
|
| [no-restricted-imports](docs/rules/no-restricted-imports.md) | Disallow usage of restricted imports in community nodes. | ✅ | | | |
|
|
@@ -61,6 +63,7 @@ export default [
|
|
|
61
63
|
| [node-usable-as-tool](docs/rules/node-usable-as-tool.md) | Ensure node classes have usableAsTool property | ✅ ☑️ | | 🔧 | |
|
|
62
64
|
| [options-sorted-alphabetically](docs/rules/options-sorted-alphabetically.md) | Enforce alphabetical ordering of options arrays in n8n node properties | | ✅ ☑️ | | |
|
|
63
65
|
| [package-name-convention](docs/rules/package-name-convention.md) | Enforce correct package naming convention for n8n community nodes | ✅ ☑️ | | | 💡 |
|
|
66
|
+
| [require-continue-on-fail](docs/rules/require-continue-on-fail.md) | Require continueOnFail() handling in execute() methods of node classes | ✅ ☑️ | | | |
|
|
64
67
|
| [resource-operation-pattern](docs/rules/resource-operation-pattern.md) | Enforce proper resource/operation pattern for better UX in n8n nodes | | ✅ ☑️ | | |
|
|
65
68
|
|
|
66
69
|
<!-- end auto-generated rules list -->
|
package/dist/plugin.d.ts
CHANGED
|
@@ -23,6 +23,7 @@ declare const configs: {
|
|
|
23
23
|
'@n8n/community-nodes/package-name-convention': "error";
|
|
24
24
|
'@n8n/community-nodes/credential-test-required': "error";
|
|
25
25
|
'@n8n/community-nodes/no-credential-reuse': "error";
|
|
26
|
+
'@n8n/community-nodes/no-forbidden-lifecycle-scripts': "error";
|
|
26
27
|
'@n8n/community-nodes/no-http-request-with-manual-auth': "error";
|
|
27
28
|
'@n8n/community-nodes/icon-validation': "error";
|
|
28
29
|
'@n8n/community-nodes/options-sorted-alphabetically': "warn";
|
|
@@ -31,6 +32,8 @@ declare const configs: {
|
|
|
31
32
|
'@n8n/community-nodes/node-class-description-icon-missing': "error";
|
|
32
33
|
'@n8n/community-nodes/cred-class-field-icon-missing': "error";
|
|
33
34
|
'@n8n/community-nodes/node-connection-type-literal': "error";
|
|
35
|
+
'@n8n/community-nodes/missing-paired-item': "error";
|
|
36
|
+
'@n8n/community-nodes/require-continue-on-fail': "error";
|
|
34
37
|
};
|
|
35
38
|
};
|
|
36
39
|
recommendedWithoutN8nCloudSupport: {
|
|
@@ -53,6 +56,7 @@ declare const configs: {
|
|
|
53
56
|
'@n8n/community-nodes/package-name-convention': "error";
|
|
54
57
|
'@n8n/community-nodes/credential-test-required': "error";
|
|
55
58
|
'@n8n/community-nodes/no-credential-reuse': "error";
|
|
59
|
+
'@n8n/community-nodes/no-forbidden-lifecycle-scripts': "error";
|
|
56
60
|
'@n8n/community-nodes/no-http-request-with-manual-auth': "error";
|
|
57
61
|
'@n8n/community-nodes/icon-validation': "error";
|
|
58
62
|
'@n8n/community-nodes/options-sorted-alphabetically': "warn";
|
|
@@ -61,6 +65,8 @@ declare const configs: {
|
|
|
61
65
|
'@n8n/community-nodes/node-class-description-icon-missing': "error";
|
|
62
66
|
'@n8n/community-nodes/cred-class-field-icon-missing': "error";
|
|
63
67
|
'@n8n/community-nodes/node-connection-type-literal': "error";
|
|
68
|
+
'@n8n/community-nodes/missing-paired-item': "error";
|
|
69
|
+
'@n8n/community-nodes/require-continue-on-fail': "error";
|
|
64
70
|
};
|
|
65
71
|
};
|
|
66
72
|
};
|
|
@@ -88,6 +94,7 @@ declare const pluginWithConfigs: {
|
|
|
88
94
|
'@n8n/community-nodes/package-name-convention': "error";
|
|
89
95
|
'@n8n/community-nodes/credential-test-required': "error";
|
|
90
96
|
'@n8n/community-nodes/no-credential-reuse': "error";
|
|
97
|
+
'@n8n/community-nodes/no-forbidden-lifecycle-scripts': "error";
|
|
91
98
|
'@n8n/community-nodes/no-http-request-with-manual-auth': "error";
|
|
92
99
|
'@n8n/community-nodes/icon-validation': "error";
|
|
93
100
|
'@n8n/community-nodes/options-sorted-alphabetically': "warn";
|
|
@@ -96,6 +103,8 @@ declare const pluginWithConfigs: {
|
|
|
96
103
|
'@n8n/community-nodes/node-class-description-icon-missing': "error";
|
|
97
104
|
'@n8n/community-nodes/cred-class-field-icon-missing': "error";
|
|
98
105
|
'@n8n/community-nodes/node-connection-type-literal': "error";
|
|
106
|
+
'@n8n/community-nodes/missing-paired-item': "error";
|
|
107
|
+
'@n8n/community-nodes/require-continue-on-fail': "error";
|
|
99
108
|
};
|
|
100
109
|
};
|
|
101
110
|
recommendedWithoutN8nCloudSupport: {
|
|
@@ -118,6 +127,7 @@ declare const pluginWithConfigs: {
|
|
|
118
127
|
'@n8n/community-nodes/package-name-convention': "error";
|
|
119
128
|
'@n8n/community-nodes/credential-test-required': "error";
|
|
120
129
|
'@n8n/community-nodes/no-credential-reuse': "error";
|
|
130
|
+
'@n8n/community-nodes/no-forbidden-lifecycle-scripts': "error";
|
|
121
131
|
'@n8n/community-nodes/no-http-request-with-manual-auth': "error";
|
|
122
132
|
'@n8n/community-nodes/icon-validation': "error";
|
|
123
133
|
'@n8n/community-nodes/options-sorted-alphabetically': "warn";
|
|
@@ -126,6 +136,8 @@ declare const pluginWithConfigs: {
|
|
|
126
136
|
'@n8n/community-nodes/node-class-description-icon-missing': "error";
|
|
127
137
|
'@n8n/community-nodes/cred-class-field-icon-missing': "error";
|
|
128
138
|
'@n8n/community-nodes/node-connection-type-literal': "error";
|
|
139
|
+
'@n8n/community-nodes/missing-paired-item': "error";
|
|
140
|
+
'@n8n/community-nodes/require-continue-on-fail': "error";
|
|
129
141
|
};
|
|
130
142
|
};
|
|
131
143
|
};
|
|
@@ -160,6 +172,7 @@ declare const n8nCommunityNodesPlugin: {
|
|
|
160
172
|
'@n8n/community-nodes/package-name-convention': "error";
|
|
161
173
|
'@n8n/community-nodes/credential-test-required': "error";
|
|
162
174
|
'@n8n/community-nodes/no-credential-reuse': "error";
|
|
175
|
+
'@n8n/community-nodes/no-forbidden-lifecycle-scripts': "error";
|
|
163
176
|
'@n8n/community-nodes/no-http-request-with-manual-auth': "error";
|
|
164
177
|
'@n8n/community-nodes/icon-validation': "error";
|
|
165
178
|
'@n8n/community-nodes/options-sorted-alphabetically': "warn";
|
|
@@ -168,6 +181,8 @@ declare const n8nCommunityNodesPlugin: {
|
|
|
168
181
|
'@n8n/community-nodes/node-class-description-icon-missing': "error";
|
|
169
182
|
'@n8n/community-nodes/cred-class-field-icon-missing': "error";
|
|
170
183
|
'@n8n/community-nodes/node-connection-type-literal': "error";
|
|
184
|
+
'@n8n/community-nodes/missing-paired-item': "error";
|
|
185
|
+
'@n8n/community-nodes/require-continue-on-fail': "error";
|
|
171
186
|
};
|
|
172
187
|
};
|
|
173
188
|
recommendedWithoutN8nCloudSupport: {
|
|
@@ -190,6 +205,7 @@ declare const n8nCommunityNodesPlugin: {
|
|
|
190
205
|
'@n8n/community-nodes/package-name-convention': "error";
|
|
191
206
|
'@n8n/community-nodes/credential-test-required': "error";
|
|
192
207
|
'@n8n/community-nodes/no-credential-reuse': "error";
|
|
208
|
+
'@n8n/community-nodes/no-forbidden-lifecycle-scripts': "error";
|
|
193
209
|
'@n8n/community-nodes/no-http-request-with-manual-auth': "error";
|
|
194
210
|
'@n8n/community-nodes/icon-validation': "error";
|
|
195
211
|
'@n8n/community-nodes/options-sorted-alphabetically': "warn";
|
|
@@ -198,6 +214,8 @@ declare const n8nCommunityNodesPlugin: {
|
|
|
198
214
|
'@n8n/community-nodes/node-class-description-icon-missing': "error";
|
|
199
215
|
'@n8n/community-nodes/cred-class-field-icon-missing': "error";
|
|
200
216
|
'@n8n/community-nodes/node-connection-type-literal': "error";
|
|
217
|
+
'@n8n/community-nodes/missing-paired-item': "error";
|
|
218
|
+
'@n8n/community-nodes/require-continue-on-fail': "error";
|
|
201
219
|
};
|
|
202
220
|
};
|
|
203
221
|
};
|
package/dist/plugin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAC;AAG7C,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAYzC,QAAA,MAAM,OAAO;;;;;;;;;;uBAHI,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAC;AAG7C,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAYzC,QAAA,MAAM,OAAO;;;;;;;;;;uBAHI,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uBAAtB,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;;;;;CA0DE,CAAC;AAE1C,QAAA,MAAM,iBAAiB;;;;;;;;;;;2BA5DN,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2BAAtB,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAAtB,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;CA4DiC,CAAC;AAEzE,QAAA,MAAM,uBAAuB;;;;;;;;;;;2BA9DZ,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2BAAtB,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAAtB,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;CA8DU,CAAC;AAClD,eAAe,iBAAiB,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,uBAAuB,EAAE,CAAC"}
|
package/dist/plugin.js
CHANGED
|
@@ -25,6 +25,7 @@ const configs = {
|
|
|
25
25
|
'@n8n/community-nodes/package-name-convention': 'error',
|
|
26
26
|
'@n8n/community-nodes/credential-test-required': 'error',
|
|
27
27
|
'@n8n/community-nodes/no-credential-reuse': 'error',
|
|
28
|
+
'@n8n/community-nodes/no-forbidden-lifecycle-scripts': 'error',
|
|
28
29
|
'@n8n/community-nodes/no-http-request-with-manual-auth': 'error',
|
|
29
30
|
'@n8n/community-nodes/icon-validation': 'error',
|
|
30
31
|
'@n8n/community-nodes/options-sorted-alphabetically': 'warn',
|
|
@@ -33,6 +34,8 @@ const configs = {
|
|
|
33
34
|
'@n8n/community-nodes/node-class-description-icon-missing': 'error',
|
|
34
35
|
'@n8n/community-nodes/cred-class-field-icon-missing': 'error',
|
|
35
36
|
'@n8n/community-nodes/node-connection-type-literal': 'error',
|
|
37
|
+
'@n8n/community-nodes/missing-paired-item': 'error',
|
|
38
|
+
'@n8n/community-nodes/require-continue-on-fail': 'error',
|
|
36
39
|
},
|
|
37
40
|
},
|
|
38
41
|
recommendedWithoutN8nCloudSupport: {
|
|
@@ -48,6 +51,7 @@ const configs = {
|
|
|
48
51
|
'@n8n/community-nodes/package-name-convention': 'error',
|
|
49
52
|
'@n8n/community-nodes/credential-test-required': 'error',
|
|
50
53
|
'@n8n/community-nodes/no-credential-reuse': 'error',
|
|
54
|
+
'@n8n/community-nodes/no-forbidden-lifecycle-scripts': 'error',
|
|
51
55
|
'@n8n/community-nodes/no-http-request-with-manual-auth': 'error',
|
|
52
56
|
'@n8n/community-nodes/icon-validation': 'error',
|
|
53
57
|
'@n8n/community-nodes/options-sorted-alphabetically': 'warn',
|
|
@@ -56,6 +60,8 @@ const configs = {
|
|
|
56
60
|
'@n8n/community-nodes/node-class-description-icon-missing': 'error',
|
|
57
61
|
'@n8n/community-nodes/cred-class-field-icon-missing': 'error',
|
|
58
62
|
'@n8n/community-nodes/node-connection-type-literal': 'error',
|
|
63
|
+
'@n8n/community-nodes/missing-paired-item': 'error',
|
|
64
|
+
'@n8n/community-nodes/require-continue-on-fail': 'error',
|
|
59
65
|
},
|
|
60
66
|
},
|
|
61
67
|
};
|
package/dist/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAEA,OAAO,GAAG,MAAM,iBAAiB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACxD,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEzC,MAAM,MAAM,GAAG;IACd,IAAI,EAAE;QACL,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,SAAS,EAAE,sBAAsB;KACjC;IACD,8EAA8E;IAC9E,KAAK,EAAE,KAA+B;CACd,CAAC;AAE1B,MAAM,OAAO,GAAG;IACf,WAAW,EAAE;QACZ,OAAO,EAAE,CAAC,+BAA+B,CAAC;QAC1C,OAAO,EAAE;YACR,sBAAsB,EAAE,MAAM;SAC9B;QACD,KAAK,EAAE;YACN,2CAA2C,EAAE,OAAO;YACpD,4CAA4C,EAAE,OAAO;YACrD,4CAA4C,EAAE,OAAO;YACrD,gDAAgD,EAAE,OAAO;YACzD,uDAAuD,EAAE,OAAO;YAChE,0CAA0C,EAAE,OAAO;YACnD,8CAA8C,EAAE,OAAO;YACvD,+CAA+C,EAAE,OAAO;YACxD,0CAA0C,EAAE,OAAO;YACnD,uDAAuD,EAAE,OAAO;YAChE,sCAAsC,EAAE,OAAO;YAC/C,oDAAoD,EAAE,MAAM;YAC5D,iDAAiD,EAAE,MAAM;YACzD,mDAAmD,EAAE,OAAO;YAC5D,0DAA0D,EAAE,OAAO;YACnE,oDAAoD,EAAE,OAAO;YAC7D,mDAAmD,EAAE,OAAO;
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAEA,OAAO,GAAG,MAAM,iBAAiB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACxD,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEzC,MAAM,MAAM,GAAG;IACd,IAAI,EAAE;QACL,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,SAAS,EAAE,sBAAsB;KACjC;IACD,8EAA8E;IAC9E,KAAK,EAAE,KAA+B;CACd,CAAC;AAE1B,MAAM,OAAO,GAAG;IACf,WAAW,EAAE;QACZ,OAAO,EAAE,CAAC,+BAA+B,CAAC;QAC1C,OAAO,EAAE;YACR,sBAAsB,EAAE,MAAM;SAC9B;QACD,KAAK,EAAE;YACN,2CAA2C,EAAE,OAAO;YACpD,4CAA4C,EAAE,OAAO;YACrD,4CAA4C,EAAE,OAAO;YACrD,gDAAgD,EAAE,OAAO;YACzD,uDAAuD,EAAE,OAAO;YAChE,0CAA0C,EAAE,OAAO;YACnD,8CAA8C,EAAE,OAAO;YACvD,+CAA+C,EAAE,OAAO;YACxD,0CAA0C,EAAE,OAAO;YACnD,qDAAqD,EAAE,OAAO;YAC9D,uDAAuD,EAAE,OAAO;YAChE,sCAAsC,EAAE,OAAO;YAC/C,oDAAoD,EAAE,MAAM;YAC5D,iDAAiD,EAAE,MAAM;YACzD,mDAAmD,EAAE,OAAO;YAC5D,0DAA0D,EAAE,OAAO;YACnE,oDAAoD,EAAE,OAAO;YAC7D,mDAAmD,EAAE,OAAO;YAC5D,0CAA0C,EAAE,OAAO;YACnD,+CAA+C,EAAE,OAAO;SACxD;KACD;IACD,iCAAiC,EAAE;QAClC,OAAO,EAAE,CAAC,+BAA+B,CAAC;QAC1C,OAAO,EAAE;YACR,sBAAsB,EAAE,MAAM;SAC9B;QACD,KAAK,EAAE;YACN,2CAA2C,EAAE,OAAO;YACpD,gDAAgD,EAAE,OAAO;YACzD,uDAAuD,EAAE,OAAO;YAChE,0CAA0C,EAAE,OAAO;YACnD,8CAA8C,EAAE,OAAO;YACvD,+CAA+C,EAAE,OAAO;YACxD,0CAA0C,EAAE,OAAO;YACnD,qDAAqD,EAAE,OAAO;YAC9D,uDAAuD,EAAE,OAAO;YAChE,sCAAsC,EAAE,OAAO;YAC/C,oDAAoD,EAAE,MAAM;YAC5D,mDAAmD,EAAE,OAAO;YAC5D,iDAAiD,EAAE,MAAM;YACzD,0DAA0D,EAAE,OAAO;YACnE,oDAAoD,EAAE,OAAO;YAC7D,mDAAmD,EAAE,OAAO;YAC5D,0CAA0C,EAAE,OAAO;YACnD,+CAA+C,EAAE,OAAO;SACxD;KACD;CACuC,CAAC;AAE1C,MAAM,iBAAiB,GAAG,EAAE,GAAG,MAAM,EAAE,OAAO,EAA0B,CAAC;AAEzE,MAAM,uBAAuB,GAAG,iBAAiB,CAAC;AAClD,eAAe,iBAAiB,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,uBAAuB,EAAE,CAAC"}
|
package/dist/rules/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export declare const rules: {
|
|
|
9
9
|
'package-name-convention': import("@typescript-eslint/utils/ts-eslint").RuleModule<"renameTo" | "invalidPackageName", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
10
10
|
'credential-test-required': import("@typescript-eslint/utils/ts-eslint").RuleModule<"addTemplate" | "missingCredentialTest", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
11
11
|
'no-credential-reuse': import("@typescript-eslint/utils/ts-eslint").RuleModule<"didYouMean" | "useAvailable" | "credentialNotInPackage", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
12
|
+
'no-forbidden-lifecycle-scripts': import("@typescript-eslint/utils/ts-eslint").RuleModule<"forbiddenScript", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
12
13
|
'no-http-request-with-manual-auth': import("@typescript-eslint/utils/ts-eslint").RuleModule<"useHttpRequestWithAuthentication", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
13
14
|
'icon-validation': import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingIcon" | "addPlaceholder" | "iconFileNotFound" | "iconNotSvg" | "lightDarkSame" | "invalidIconPath" | "addFileProtocol" | "changeExtension" | "similarIcon", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
14
15
|
'resource-operation-pattern': import("@typescript-eslint/utils/ts-eslint").RuleModule<"tooManyOperationsWithoutResources", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
@@ -19,5 +20,7 @@ export declare const rules: {
|
|
|
19
20
|
'node-class-description-icon-missing': import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingIcon" | "addPlaceholder", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
20
21
|
'cred-class-field-icon-missing': import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingIcon" | "addPlaceholder", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
21
22
|
'node-connection-type-literal': import("@typescript-eslint/utils/ts-eslint").RuleModule<"stringLiteralInInputs" | "stringLiteralInOutputs" | "unknownStringLiteralInInputs" | "unknownStringLiteralInOutputs", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
23
|
+
'missing-paired-item': import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingPairedItem", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
24
|
+
'require-continue-on-fail': import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingContinueOnFail", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
22
25
|
};
|
|
23
26
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":"AAuBA,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;;;;;;;;;CAqBuB,CAAC"}
|
package/dist/rules/index.js
CHANGED
|
@@ -4,8 +4,10 @@ import { CredentialDocumentationUrlRule } from './credential-documentation-url.j
|
|
|
4
4
|
import { CredentialPasswordFieldRule } from './credential-password-field.js';
|
|
5
5
|
import { CredentialTestRequiredRule } from './credential-test-required.js';
|
|
6
6
|
import { IconValidationRule } from './icon-validation.js';
|
|
7
|
+
import { MissingPairedItemRule } from './missing-paired-item.js';
|
|
7
8
|
import { NoCredentialReuseRule } from './no-credential-reuse.js';
|
|
8
9
|
import { NoDeprecatedWorkflowFunctionsRule } from './no-deprecated-workflow-functions.js';
|
|
10
|
+
import { NoForbiddenLifecycleScriptsRule } from './no-forbidden-lifecycle-scripts.js';
|
|
9
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,6 +16,7 @@ import { NodeConnectionTypeLiteralRule } from './node-connection-type-literal.js
|
|
|
14
16
|
import { NodeUsableAsToolRule } from './node-usable-as-tool.js';
|
|
15
17
|
import { OptionsSortedAlphabeticallyRule } from './options-sorted-alphabetically.js';
|
|
16
18
|
import { PackageNameConventionRule } from './package-name-convention.js';
|
|
19
|
+
import { RequireContinueOnFailRule } from './require-continue-on-fail.js';
|
|
17
20
|
import { ResourceOperationPatternRule } from './resource-operation-pattern.js';
|
|
18
21
|
export const rules = {
|
|
19
22
|
'ai-node-package-json': AiNodePackageJsonRule,
|
|
@@ -26,6 +29,7 @@ export const rules = {
|
|
|
26
29
|
'package-name-convention': PackageNameConventionRule,
|
|
27
30
|
'credential-test-required': CredentialTestRequiredRule,
|
|
28
31
|
'no-credential-reuse': NoCredentialReuseRule,
|
|
32
|
+
'no-forbidden-lifecycle-scripts': NoForbiddenLifecycleScriptsRule,
|
|
29
33
|
'no-http-request-with-manual-auth': NoHttpRequestWithManualAuthRule,
|
|
30
34
|
'icon-validation': IconValidationRule,
|
|
31
35
|
'resource-operation-pattern': ResourceOperationPatternRule,
|
|
@@ -33,5 +37,7 @@ export const rules = {
|
|
|
33
37
|
'node-class-description-icon-missing': NodeClassDescriptionIconMissingRule,
|
|
34
38
|
'cred-class-field-icon-missing': CredClassFieldIconMissingRule,
|
|
35
39
|
'node-connection-type-literal': NodeConnectionTypeLiteralRule,
|
|
40
|
+
'missing-paired-item': MissingPairedItemRule,
|
|
41
|
+
'require-continue-on-fail': RequireContinueOnFailRule,
|
|
36
42
|
};
|
|
37
43
|
//# sourceMappingURL=index.js.map
|
package/dist/rules/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,6BAA6B,EAAE,MAAM,oCAAoC,CAAC;AACnF,OAAO,EAAE,8BAA8B,EAAE,MAAM,mCAAmC,CAAC;AACnF,OAAO,EAAE,2BAA2B,EAAE,MAAM,gCAAgC,CAAC;AAC7E,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,iCAAiC,EAAE,MAAM,uCAAuC,CAAC;AAC1F,OAAO,EAAE,+BAA+B,EAAE,MAAM,uCAAuC,CAAC;AACxF,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,EAAE,mCAAmC,EAAE,MAAM,0CAA0C,CAAC;AAC/F,OAAO,EAAE,6BAA6B,EAAE,MAAM,mCAAmC,CAAC;AAClF,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,+BAA+B,EAAE,MAAM,oCAAoC,CAAC;AACrF,OAAO,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AACzE,OAAO,EAAE,4BAA4B,EAAE,MAAM,iCAAiC,CAAC;AAE/E,MAAM,CAAC,MAAM,KAAK,GAAG;IACpB,sBAAsB,EAAE,qBAAqB;IAC7C,uBAAuB,EAAE,uBAAuB;IAChD,uBAAuB,EAAE,uBAAuB;IAChD,2BAA2B,EAAE,2BAA2B;IACxD,kCAAkC,EAAE,iCAAiC;IACrE,qBAAqB,EAAE,oBAAoB;IAC3C,+BAA+B,EAAE,+BAA+B;IAChE,yBAAyB,EAAE,yBAAyB;IACpD,0BAA0B,EAAE,0BAA0B;IACtD,qBAAqB,EAAE,qBAAqB;IAC5C,kCAAkC,EAAE,+BAA+B;IACnE,iBAAiB,EAAE,kBAAkB;IACrC,4BAA4B,EAAE,4BAA4B;IAC1D,8BAA8B,EAAE,8BAA8B;IAC9D,qCAAqC,EAAE,mCAAmC;IAC1E,+BAA+B,EAAE,6BAA6B;IAC9D,8BAA8B,EAAE,6BAA6B;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,6BAA6B,EAAE,MAAM,oCAAoC,CAAC;AACnF,OAAO,EAAE,8BAA8B,EAAE,MAAM,mCAAmC,CAAC;AACnF,OAAO,EAAE,2BAA2B,EAAE,MAAM,gCAAgC,CAAC;AAC7E,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,iCAAiC,EAAE,MAAM,uCAAuC,CAAC;AAC1F,OAAO,EAAE,+BAA+B,EAAE,MAAM,qCAAqC,CAAC;AACtF,OAAO,EAAE,+BAA+B,EAAE,MAAM,uCAAuC,CAAC;AACxF,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,EAAE,mCAAmC,EAAE,MAAM,0CAA0C,CAAC;AAC/F,OAAO,EAAE,6BAA6B,EAAE,MAAM,mCAAmC,CAAC;AAClF,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,+BAA+B,EAAE,MAAM,oCAAoC,CAAC;AACrF,OAAO,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AACzE,OAAO,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AAC1E,OAAO,EAAE,4BAA4B,EAAE,MAAM,iCAAiC,CAAC;AAE/E,MAAM,CAAC,MAAM,KAAK,GAAG;IACpB,sBAAsB,EAAE,qBAAqB;IAC7C,uBAAuB,EAAE,uBAAuB;IAChD,uBAAuB,EAAE,uBAAuB;IAChD,2BAA2B,EAAE,2BAA2B;IACxD,kCAAkC,EAAE,iCAAiC;IACrE,qBAAqB,EAAE,oBAAoB;IAC3C,+BAA+B,EAAE,+BAA+B;IAChE,yBAAyB,EAAE,yBAAyB;IACpD,0BAA0B,EAAE,0BAA0B;IACtD,qBAAqB,EAAE,qBAAqB;IAC5C,gCAAgC,EAAE,+BAA+B;IACjE,kCAAkC,EAAE,+BAA+B;IACnE,iBAAiB,EAAE,kBAAkB;IACrC,4BAA4B,EAAE,4BAA4B;IAC1D,8BAA8B,EAAE,8BAA8B;IAC9D,qCAAqC,EAAE,mCAAmC;IAC1E,+BAA+B,EAAE,6BAA6B;IAC9D,8BAA8B,EAAE,6BAA6B;IAC7D,qBAAqB,EAAE,qBAAqB;IAC5C,0BAA0B,EAAE,yBAAyB;CACb,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Flags object literals with a `json` property but no `pairedItem` property
|
|
3
|
+
* inside `execute()` methods of `INodeType` classes.
|
|
4
|
+
*
|
|
5
|
+
* Missing `pairedItem` breaks downstream item-referencing expressions like
|
|
6
|
+
* `$('NodeName').item`. This rule catches the three most common patterns:
|
|
7
|
+
*
|
|
8
|
+
* - Object literals in `.map()` callbacks
|
|
9
|
+
* - Object literals passed to `.push()` calls
|
|
10
|
+
* - Object literals in return statements (typically `return [[{ json }]]`)
|
|
11
|
+
*
|
|
12
|
+
* Only flags object literals directly — variable references are skipped since
|
|
13
|
+
* their shape cannot be determined without type resolution.
|
|
14
|
+
*/
|
|
15
|
+
export declare const MissingPairedItemRule: import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingPairedItem", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
16
|
+
//# sourceMappingURL=missing-paired-item.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"missing-paired-item.d.ts","sourceRoot":"","sources":["../../src/rules/missing-paired-item.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAiCH,eAAO,MAAM,qBAAqB,sJAsGhC,CAAC"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Flags object literals with a `json` property but no `pairedItem` property
|
|
3
|
+
* inside `execute()` methods of `INodeType` classes.
|
|
4
|
+
*
|
|
5
|
+
* Missing `pairedItem` breaks downstream item-referencing expressions like
|
|
6
|
+
* `$('NodeName').item`. This rule catches the three most common patterns:
|
|
7
|
+
*
|
|
8
|
+
* - Object literals in `.map()` callbacks
|
|
9
|
+
* - Object literals passed to `.push()` calls
|
|
10
|
+
* - Object literals in return statements (typically `return [[{ json }]]`)
|
|
11
|
+
*
|
|
12
|
+
* Only flags object literals directly — variable references are skipped since
|
|
13
|
+
* their shape cannot be determined without type resolution.
|
|
14
|
+
*/
|
|
15
|
+
import { AST_NODE_TYPES } from '@typescript-eslint/utils';
|
|
16
|
+
import { createRule, findObjectProperty, isFileType, isNodeTypeClass, isThisHelpersMethodCall, } from '../utils/index.js';
|
|
17
|
+
/**
|
|
18
|
+
* Checks whether the object is inside an array argument to
|
|
19
|
+
* `this.helpers.constructExecutionMetaData()`, which adds pairedItem
|
|
20
|
+
* via the second argument's `itemData` property.
|
|
21
|
+
*/
|
|
22
|
+
function isInsideConstructExecutionMetaData(node) {
|
|
23
|
+
// Pattern: constructExecutionMetaData([{ json: ... }], { itemData: ... })
|
|
24
|
+
// Walk up: ObjectExpression -> ArrayExpression -> CallExpression
|
|
25
|
+
const parent = node.parent;
|
|
26
|
+
if (parent?.type !== AST_NODE_TYPES.ArrayExpression)
|
|
27
|
+
return false;
|
|
28
|
+
const grandparent = parent.parent;
|
|
29
|
+
if (grandparent?.type !== AST_NODE_TYPES.CallExpression)
|
|
30
|
+
return false;
|
|
31
|
+
// Check it's the first argument
|
|
32
|
+
if (grandparent.arguments[0] !== parent)
|
|
33
|
+
return false;
|
|
34
|
+
return isThisHelpersMethodCall(grandparent, 'constructExecutionMetaData');
|
|
35
|
+
}
|
|
36
|
+
export const MissingPairedItemRule = createRule({
|
|
37
|
+
name: 'missing-paired-item',
|
|
38
|
+
meta: {
|
|
39
|
+
type: 'problem',
|
|
40
|
+
docs: {
|
|
41
|
+
description: 'Require pairedItem on INodeExecutionData objects in execute() methods to preserve item linking.',
|
|
42
|
+
},
|
|
43
|
+
messages: {
|
|
44
|
+
missingPairedItem: 'Missing pairedItem on INodeExecutionData object. Add `pairedItem: { item: index }` to preserve item linking. See https://docs.n8n.io/integrations/creating-nodes/build/reference/paired-items/',
|
|
45
|
+
},
|
|
46
|
+
schema: [],
|
|
47
|
+
hasSuggestions: false,
|
|
48
|
+
},
|
|
49
|
+
defaultOptions: [],
|
|
50
|
+
create(context) {
|
|
51
|
+
if (!isFileType(context.filename, '.node.ts')) {
|
|
52
|
+
return {};
|
|
53
|
+
}
|
|
54
|
+
let inNodeTypeClass = false;
|
|
55
|
+
let inExecuteMethod = false;
|
|
56
|
+
return {
|
|
57
|
+
ClassDeclaration(node) {
|
|
58
|
+
if (isNodeTypeClass(node)) {
|
|
59
|
+
inNodeTypeClass = true;
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
'ClassDeclaration:exit'() {
|
|
63
|
+
inNodeTypeClass = false;
|
|
64
|
+
inExecuteMethod = false;
|
|
65
|
+
},
|
|
66
|
+
MethodDefinition(node) {
|
|
67
|
+
if (inNodeTypeClass &&
|
|
68
|
+
node.key.type === AST_NODE_TYPES.Identifier &&
|
|
69
|
+
node.key.name === 'execute') {
|
|
70
|
+
inExecuteMethod = true;
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
'MethodDefinition:exit'(node) {
|
|
74
|
+
if (inExecuteMethod &&
|
|
75
|
+
node.key.type === AST_NODE_TYPES.Identifier &&
|
|
76
|
+
node.key.name === 'execute') {
|
|
77
|
+
inExecuteMethod = false;
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
ObjectExpression(node) {
|
|
81
|
+
if (!inExecuteMethod)
|
|
82
|
+
return;
|
|
83
|
+
const hasJson = findObjectProperty(node, 'json') !== null;
|
|
84
|
+
if (!hasJson)
|
|
85
|
+
return;
|
|
86
|
+
const hasPairedItem = findObjectProperty(node, 'pairedItem') !== null;
|
|
87
|
+
if (hasPairedItem)
|
|
88
|
+
return;
|
|
89
|
+
// Skip if inside constructExecutionMetaData() — it adds pairedItem via itemData
|
|
90
|
+
if (isInsideConstructExecutionMetaData(node))
|
|
91
|
+
return;
|
|
92
|
+
// Skip if the object contains spread elements — they may already provide pairedItem
|
|
93
|
+
const hasSpread = node.properties.some((prop) => prop.type === AST_NODE_TYPES.SpreadElement);
|
|
94
|
+
if (hasSpread)
|
|
95
|
+
return;
|
|
96
|
+
// Only flag if this looks like an INodeExecutionData object literal —
|
|
97
|
+
// must have `json` and optionally `binary`/`error`, nothing unexpected.
|
|
98
|
+
// Objects with many unrelated keys are likely not INodeExecutionData.
|
|
99
|
+
const knownKeys = new Set([
|
|
100
|
+
'json',
|
|
101
|
+
'binary',
|
|
102
|
+
'error',
|
|
103
|
+
'pairedItem',
|
|
104
|
+
'executionStatus',
|
|
105
|
+
'metadata',
|
|
106
|
+
'evaluationData',
|
|
107
|
+
'redaction',
|
|
108
|
+
'sendMessage',
|
|
109
|
+
'index',
|
|
110
|
+
]);
|
|
111
|
+
const allPropertiesKnown = node.properties.every((prop) => prop.type === AST_NODE_TYPES.Property &&
|
|
112
|
+
prop.key.type === AST_NODE_TYPES.Identifier &&
|
|
113
|
+
knownKeys.has(prop.key.name));
|
|
114
|
+
if (!allPropertiesKnown)
|
|
115
|
+
return;
|
|
116
|
+
context.report({ node, messageId: 'missingPairedItem' });
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
//# sourceMappingURL=missing-paired-item.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"missing-paired-item.js","sourceRoot":"","sources":["../../src/rules/missing-paired-item.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-forbidden-lifecycle-scripts.d.ts","sourceRoot":"","sources":["../../src/rules/no-forbidden-lifecycle-scripts.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,+BAA+B,oJAqD1C,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { AST_NODE_TYPES } from '@typescript-eslint/utils';
|
|
2
|
+
import { createRule, findJsonProperty } from '../utils/index.js';
|
|
3
|
+
const FORBIDDEN_SCRIPTS = [
|
|
4
|
+
'prepare',
|
|
5
|
+
'preinstall',
|
|
6
|
+
'install',
|
|
7
|
+
'postinstall',
|
|
8
|
+
'prepublish',
|
|
9
|
+
'preprepare',
|
|
10
|
+
'postprepare',
|
|
11
|
+
];
|
|
12
|
+
export const NoForbiddenLifecycleScriptsRule = createRule({
|
|
13
|
+
name: 'no-forbidden-lifecycle-scripts',
|
|
14
|
+
meta: {
|
|
15
|
+
type: 'problem',
|
|
16
|
+
docs: {
|
|
17
|
+
description: 'Ban lifecycle scripts (prepare, preinstall, postinstall, etc.) in community node packages',
|
|
18
|
+
},
|
|
19
|
+
messages: {
|
|
20
|
+
forbiddenScript: 'Lifecycle script "{{ scriptName }}" is not allowed in community node packages. These scripts execute arbitrary code during installation.',
|
|
21
|
+
},
|
|
22
|
+
schema: [],
|
|
23
|
+
},
|
|
24
|
+
defaultOptions: [],
|
|
25
|
+
create(context) {
|
|
26
|
+
if (!context.filename.endsWith('package.json')) {
|
|
27
|
+
return {};
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
ObjectExpression(node) {
|
|
31
|
+
// Only process the root object, not nested ones
|
|
32
|
+
if (node.parent?.type === AST_NODE_TYPES.Property) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const scriptsProp = findJsonProperty(node, 'scripts');
|
|
36
|
+
if (!scriptsProp || scriptsProp.value.type !== AST_NODE_TYPES.ObjectExpression) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
for (const property of scriptsProp.value.properties) {
|
|
40
|
+
if (property.type !== AST_NODE_TYPES.Property)
|
|
41
|
+
continue;
|
|
42
|
+
const key = property.key.type === AST_NODE_TYPES.Identifier
|
|
43
|
+
? property.key.name
|
|
44
|
+
: property.key.type === AST_NODE_TYPES.Literal
|
|
45
|
+
? String(property.key.value)
|
|
46
|
+
: null;
|
|
47
|
+
if (key !== null && FORBIDDEN_SCRIPTS.includes(key)) {
|
|
48
|
+
context.report({
|
|
49
|
+
node: property,
|
|
50
|
+
messageId: 'forbiddenScript',
|
|
51
|
+
data: { scriptName: key },
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
//# sourceMappingURL=no-forbidden-lifecycle-scripts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-forbidden-lifecycle-scripts.js","sourceRoot":"","sources":["../../src/rules/no-forbidden-lifecycle-scripts.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAEjE,MAAM,iBAAiB,GAAG;IACzB,SAAS;IACT,YAAY;IACZ,SAAS;IACT,aAAa;IACb,YAAY;IACZ,YAAY;IACZ,aAAa;CACb,CAAC;AAEF,MAAM,CAAC,MAAM,+BAA+B,GAAG,UAAU,CAAC;IACzD,IAAI,EAAE,gCAAgC;IACtC,IAAI,EAAE;QACL,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACL,WAAW,EACV,2FAA2F;SAC5F;QACD,QAAQ,EAAE;YACT,eAAe,EACd,0IAA0I;SAC3I;QACD,MAAM,EAAE,EAAE;KACV;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACb,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;YAChD,OAAO,EAAE,CAAC;QACX,CAAC;QAED,OAAO;YACN,gBAAgB,CAAC,IAA+B;gBAC/C,gDAAgD;gBAChD,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,KAAK,cAAc,CAAC,QAAQ,EAAE,CAAC;oBACnD,OAAO;gBACR,CAAC;gBAED,MAAM,WAAW,GAAG,gBAAgB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;gBACtD,IAAI,CAAC,WAAW,IAAI,WAAW,CAAC,KAAK,CAAC,IAAI,KAAK,cAAc,CAAC,gBAAgB,EAAE,CAAC;oBAChF,OAAO;gBACR,CAAC;gBAED,KAAK,MAAM,QAAQ,IAAI,WAAW,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;oBACrD,IAAI,QAAQ,CAAC,IAAI,KAAK,cAAc,CAAC,QAAQ;wBAAE,SAAS;oBAExD,MAAM,GAAG,GACR,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;wBAC9C,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI;wBACnB,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,cAAc,CAAC,OAAO;4BAC7C,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC;4BAC5B,CAAC,CAAC,IAAI,CAAC;oBAEV,IAAI,GAAG,KAAK,IAAI,IAAI,iBAAiB,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;wBACrD,OAAO,CAAC,MAAM,CAAC;4BACd,IAAI,EAAE,QAAQ;4BACd,SAAS,EAAE,iBAAiB;4BAC5B,IAAI,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE;yBACzB,CAAC,CAAC;oBACJ,CAAC;gBACF,CAAC;YACF,CAAC;SACD,CAAC;IACH,CAAC;CACD,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"require-continue-on-fail.d.ts","sourceRoot":"","sources":["../../src/rules/require-continue-on-fail.ts"],"names":[],"mappings":"AA8CA,eAAO,MAAM,yBAAyB,0JAyCpC,CAAC"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { AST_NODE_TYPES } from '@typescript-eslint/utils';
|
|
2
|
+
import { isNodeTypeClass } from '../utils/index.js';
|
|
3
|
+
import { createRule } from '../utils/rule-creator.js';
|
|
4
|
+
/** Keys that are not child AST nodes (back-references, metadata). */
|
|
5
|
+
const NON_CHILD_KEYS = new Set(['parent', 'loc', 'range', 'start', 'end', 'tokens', 'comments']);
|
|
6
|
+
/**
|
|
7
|
+
* Recursively checks whether any descendant of the given AST node is a
|
|
8
|
+
* `this.continueOnFail()` call expression.
|
|
9
|
+
*/
|
|
10
|
+
function containsContinueOnFailCall(node) {
|
|
11
|
+
if (node.type === AST_NODE_TYPES.CallExpression &&
|
|
12
|
+
node.callee.type === AST_NODE_TYPES.MemberExpression &&
|
|
13
|
+
node.callee.object.type === AST_NODE_TYPES.ThisExpression &&
|
|
14
|
+
node.callee.property.type === AST_NODE_TYPES.Identifier &&
|
|
15
|
+
node.callee.property.name === 'continueOnFail') {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
for (const key of Object.keys(node)) {
|
|
19
|
+
if (NON_CHILD_KEYS.has(key))
|
|
20
|
+
continue;
|
|
21
|
+
const value = node[key];
|
|
22
|
+
if (Array.isArray(value)) {
|
|
23
|
+
for (const child of value) {
|
|
24
|
+
if (child && typeof child === 'object' && 'type' in child) {
|
|
25
|
+
if (containsContinueOnFailCall(child)) {
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
else if (value && typeof value === 'object' && 'type' in value) {
|
|
32
|
+
if (containsContinueOnFailCall(value)) {
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
export const RequireContinueOnFailRule = createRule({
|
|
40
|
+
name: 'require-continue-on-fail',
|
|
41
|
+
meta: {
|
|
42
|
+
type: 'problem',
|
|
43
|
+
docs: {
|
|
44
|
+
description: 'Require continueOnFail() handling in execute() methods of node classes',
|
|
45
|
+
},
|
|
46
|
+
messages: {
|
|
47
|
+
missingContinueOnFail: 'execute() method must handle this.continueOnFail() for proper error handling. ' +
|
|
48
|
+
'Wrap item processing in a try/catch and check this.continueOnFail() in the catch block.',
|
|
49
|
+
},
|
|
50
|
+
schema: [],
|
|
51
|
+
},
|
|
52
|
+
defaultOptions: [],
|
|
53
|
+
create(context) {
|
|
54
|
+
return {
|
|
55
|
+
ClassDeclaration(node) {
|
|
56
|
+
if (!isNodeTypeClass(node)) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
for (const member of node.body.body) {
|
|
60
|
+
if (member.type !== AST_NODE_TYPES.MethodDefinition ||
|
|
61
|
+
member.key.type !== AST_NODE_TYPES.Identifier ||
|
|
62
|
+
member.key.name !== 'execute') {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
if (member.value.body && !containsContinueOnFailCall(member.value.body)) {
|
|
66
|
+
context.report({
|
|
67
|
+
node: member.key,
|
|
68
|
+
messageId: 'missingContinueOnFail',
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
//# sourceMappingURL=require-continue-on-fail.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"require-continue-on-fail.js","sourceRoot":"","sources":["../../src/rules/require-continue-on-fail.ts"],"names":[],"mappings":"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"}
|