]>
git.proxmox.com Git - pve-eslint.git/blob - src/bin/app.js
10e7e6a93389c089cb57714409eb92e241503107
6 const path
= require('path');
7 const color
= require('colors');
8 const program
= require('commander');
9 const worker
= require('worker_threads');
10 const eslint
= require('pve-eslint');
13 .usage('[options] [<file(s) ...>]')
14 .option('-c, --config <configfile>', 'uses <configfile> for eslint config instead.')
15 .option('-e, --extend <configfile>', 'uses <configfile> ontop of default eslint config.')
16 .option('-f, --fix', 'if set, fixes will be applied.')
17 .option('-s, --strict', 'if set, also exit uncleanly on warnings')
18 .option('-t, --threads <threads>', 'how many worker_threads should be used (default=4)')
19 .option('--output-config', 'if set, only output the config as JSON and exit.')
22 program
.on('--help', function() {
24 console
.log(' Description:');
26 console
.log(' lints javascript files');
30 program
.parse(process
.argv
);
32 if (program
.config
&& program
.extend
) {
33 console
.error('Cannot use both, --config and --extend, at the same time!');
37 if (program
.args
.length
< 1 && !program
.outputConfig
) {
41 let paths
= program
.args
;
44 paths
= [process
.cwd()];
48 if (program
.threads
) {
49 threadCount
= program
.threads
;
52 const defaultConfig
= {
62 es2020
: true, // automatically sets ecmaVersion to 2020 and allows es2020 globals
70 PVE_vnc_console_event
: "writable",
75 proxmoxOnlineHelpInfo
: "writable",
76 pveOnlineHelpInfo
: "writable",
79 // from eslint:recommend, with tweaks for our source
80 "constructor-super": "error",
81 "for-direction": "error",
82 "getter-return": "error",
83 "no-async-promise-executor": "error",
84 "no-case-declarations": "error",
85 "no-class-assign": "error",
86 "no-compare-neg-zero": "error",
87 "no-cond-assign": "error",
88 "no-const-assign": "error",
89 "no-constant-condition": "error",
90 "no-control-regex": "error",
91 "no-debugger": "error",
92 "no-delete-var": "error",
93 "no-dupe-args": "error",
94 "no-dupe-class-members": "error",
95 "no-dupe-else-if": "error",
96 "no-dupe-keys": "error",
97 "no-duplicate-case": "error",
99 "no-empty-character-class": "error",
100 "no-empty-pattern": "error",
101 "no-ex-assign": "error",
102 "no-extra-boolean-cast": "error",
103 "no-extra-semi": "error",
104 "no-fallthrough": "error",
105 "no-func-assign": "error",
106 "no-global-assign": "error",
107 "no-import-assign": "error",
108 "no-inner-declarations": "error",
109 "no-invalid-regexp": "error",
110 "no-irregular-whitespace": "error",
111 "no-misleading-character-class": "error",
112 "no-mixed-spaces-and-tabs": ["error", "smart-tabs"],
113 "no-new-symbol": "error",
114 "no-obj-calls": "error",
116 "no-prototype-builtins": "error",
117 "no-redeclare": "error",
118 "no-regex-spaces": "error",
119 "no-self-assign": "error",
120 "no-setter-return": "error",
121 "no-shadow-restricted-names": "error",
122 "no-sparse-arrays": "error",
123 "no-this-before-super": "error",
125 "no-unexpected-multiline": "error",
126 "no-unreachable": "error",
127 "no-unsafe-finally": "error",
128 "no-unsafe-negation": "error",
129 "no-unused-labels": "error",
130 "no-unused-vars": ["error", { vars
: "all", args
: "none", varsIgnorePattern
: "^(me|_.*)$" }],
131 "no-useless-catch": "error",
132 "no-useless-escape": "error",
134 "require-yield": "error",
135 "use-isnan": "error",
136 "valid-typeof": "error",
138 // selection of best practices
139 "accessor-pairs": "error",
140 "array-callback-return": "error",
141 "block-scoped-var": "error",
142 "consistent-return": "error",
143 "curly": ["error", "multi-line"],
144 "dot-location": ["error", "property"],
145 "dot-notation": "error",
147 "grouped-accessor-pairs": "error",
148 "guard-for-in": "error",
150 "no-await-in-loop": "error",
151 "no-caller": "error",
152 "no-constructor-return": "error",
153 "no-div-regex": "error",
154 //"no-else-return": "warn", // not a real style problem, both can be OK
155 "no-empty-function": "error",
156 "no-eq-null": "error",
158 "no-extend-native": "error",
159 "no-extra-bind": "error",
160 "no-extra-label": "error",
161 "no-extra-parens": ["error", "all", {
162 "conditionalAssign": false, // useful for if ((match = str.match(/.../))) lines
163 "enforceForArrowConditionals": false,
164 "nestedBinaryExpressions": false,
166 "no-floating-decimal": "error",
167 "no-implicit-coercion": ["error", { allow
: ["!!"] }],
168 "no-implicit-globals": "error",
169 "no-implied-eval": "error",
170 "no-invalid-this": "error",
171 "no-lone-blocks": "error",
172 "no-loop-func": "error",
173 "no-multi-spaces": "error",
174 "no-multi-str": "error",
176 "no-new-func": "error",
177 "no-new-wrappers": "error",
178 "no-octal-escape": "error",
180 "no-return-assign": "error",
181 "no-return-await": "error",
182 "no-script-url": "error",
183 "no-self-compare": "error",
184 "no-sequences": "error",
185 "no-template-curly-in-string": "error",
186 "no-unmodified-loop-condition": "error",
187 "no-unused-expressions": "error",
188 "no-useless-call": "error",
189 "no-useless-concat": "error",
190 "no-useless-return": "error",
192 "prefer-regex-literals": "error",
194 "require-atomic-updates": "error",
195 "wrap-iife": "error",
199 "no-label-var": "error",
200 "no-shadow": "error",
201 "no-undef-init": "error",
202 "no-use-before-define": "error",
204 // stylistic issues, only warn, most can be auto-fixed
205 // those are quite opinionated...
206 "array-bracket-spacing": ["warn", "never"],
207 "brace-style": ["warn", "1tbs", { allowSingleLine
: true }],
208 "comma-dangle": ["warn", "always-multiline"], // maybe only-multiline?
209 "comma-spacing": "warn",
210 "comma-style": "warn",
211 "computed-property-spacing": "warn",
212 "consistent-this": ["warn", "me"],
214 "func-call-spacing": "warn",
215 "func-name-matching": "warn",
216 "func-style": "warn",
217 "key-spacing": "warn",
218 "keyword-spacing": "warn",
219 "linebreak-style": "warn",
220 "max-len": ["warn", { code
: 110, tabWidth
: 8, ignoreComments
: true, ignoreStrings
: true, ignoreRegExpLiterals
: true }],
221 "no-array-constructor": "warn",
222 "no-lonely-if": "warn",
223 "no-mixed-operators": ["warn", {
225 //["+", "-", "*", "/", "%", "**"], // assume the devs can do basic math..
226 ["&", "|", "^", "~", "<<", ">>", ">>>"],
227 ["==", "!=", "===", "!==", ">", ">=", "<", "<="],
229 ["in", "instanceof"],
231 "allowSamePrecedence": true,
233 "no-multiple-empty-lines": "warn",
234 "no-trailing-spaces": "warn",
235 // "no-underscore-dangle": ["warn", { allowAfterThis: true }], // we use it for unused variables, like in rust
236 "no-unneeded-ternary": "warn",
237 "no-whitespace-before-property": "warn",
238 "object-curly-newline": ["warn", {
240 //"minProperties": 2, // FIXME: enable this??
243 "object-curly-spacing": ["warn", "always"],
244 "operator-linebreak": ["warn", "after", {
251 "padded-blocks": ["warn", "never"], // not sure ...
252 "quote-props": ["warn", "as-needed", { keywords
: true, unnecessary
: false }], // does nothing, maybe deactivate unnecessary
254 "semi-spacing": "warn",
255 // "semi-style": "warn", // could be useful, but for ?: we often want to allow the ; on the next line
256 "space-before-blocks": "warn",
257 "space-before-function-paren": ["warn", "never"],
258 "space-in-parens": "warn",
259 "space-unary-ops": "warn",
260 "switch-colon-spacing": "warn",
261 "unicode-bom": "warn",
262 "arrow-body-style": "warn",
263 "arrow-spacing": "warn",
264 // "no-confusing-arrow": "warn", // can be useful to do and isn't really confusing
265 "prefer-numeric-literals": "warn",
266 "template-curly-spacing": "warn",
270 let pathExpand
= (p
) => {
271 if (p
.match(/^[^/]/)) {
272 p
= process
.cwd() + "/" + p
;
277 let config
= defaultConfig
;
278 if (program
.config
) {
280 "extends": pathExpand(program
.config
),
282 } else if (program
.extend
) {
283 config
.extends = pathExpand(program
.extend
);
284 console
.log(`Extend with path: ${config.extends}`);
287 if (program
.outputConfig
) {
288 let cfg
= JSON
.stringify(config
, null, 2);
301 let filesPerThread
= Math
.round(paths
.length
/ threadCount
);
302 for (let i
= 0; i
< (threadCount
- 1); i
++) {
303 let files
= paths
.splice(0, filesPerThread
);
304 promises
.push(eslint
.createWorker({
310 // the remaining paths
311 promises
.push(eslint
.createWorker({
316 let results
= (await Promise
.all(promises
)).map(res
=> res
.results
).flat(1);
319 let files_err
= [], files_warn
= [], files_ok
= [];
321 console
.log('------------------------------------------------------------');
322 results
.forEach(function(result
) {
323 let filename
= path
.relative(process
.cwd(), result
.filePath
);
324 let msgs
= result
.messages
;
326 if (!!program
.fix
&& result
.output
) {
329 if (msgs
.length
<= 0) {
330 files_ok
.push(filename
);
333 console
.error(`[./${color.bold(filename)}]:`);
334 msgs
.forEach(function(e
) {
335 if (max_sev
< e
.severity
) {
336 max_sev
= e
.severity
;
338 let msg
= `: line ${color.bold(e.line)} col ${color.bold(e.column)}: ${e.ruleId}`;
339 if (e
.severity
=== 1) {
340 msg
= color
.yellow("WARN" + msg
);
341 if (exitcode
< 1 && !!program
.strict
) {
344 } else if (e
.severity
=== 2) {
345 msg
= color
.red("ERR " + msg
);
353 msg
+= ` - ${e.message}`;
355 if (!program
.fix
&& e
.fix
) {
361 console
.error(e
.suggestion
);
366 files_warn
.push(filename
);
367 } else if (max_sev
=== 2) {
368 files_err
.push(filename
);
371 console
.log('------------------------------------------------------------');
374 if (results
.length
> 1) {
375 console
.log(`${color.bold(files_ok.length + files_err.length)} files:`);
376 if (files_err
.length
> 0) {
377 console
.log(color
.red(` ${color.bold(files_err.length)} files have Errors`));
379 if (files_warn
.length
> 0) {
380 console
.log(color
.yellow(` ${color.bold(files_warn.length)} files have Warnings`));
382 if (files_ok
.length
> 0) {
383 console
.log(color
.green(` ${color.bold(files_ok.length)} files are OK`));
385 } else if (files_ok
.length
> 0) {
386 console
.log(color
.green(`${files_ok[0]} OK`));
388 console
.log('------------------------------------------------------------');
392 console
.log(`Writing ${color.bold(fixes)} fixed files...`);
393 eslint
.CLIEngine
.outputFixes({ results
});
396 console
.log("No fixable Errors/Warnings found.");
398 } else if (fixes
> 0) {
399 console
.log(`${color.bold(fixes)} issues marked with (*) could be auto-fixed using '--fix'.`);
402 process
.exit(exitcode
);