11import pathlib from 'path' ;
2- import { Command } from '@commander-js/extra-typings' ;
2+ import { Command , InvalidArgumentError , Option } from '@commander-js/extra-typings' ;
33import { outDir } from '@sourceacademy/modules-repotools/getGitRoot' ;
44import { resolveEitherBundleOrTab } from '@sourceacademy/modules-repotools/manifest' ;
55import { divideAndRound } from '@sourceacademy/modules-repotools/utils' ;
66import chalk from 'chalk' ;
7+ import type { ESLint } from 'eslint' ;
78import { runPrebuild } from '../prebuild/index.js' ;
89import { formatLintResult , lintGlobal , runEslint } from '../prebuild/lint.js' ;
910import { formatTscResult , runTsc } from '../prebuild/tsc.js' ;
1011import { logCommandErrorAndExit } from './commandUtils.js' ;
1112
13+ export const concurrencyOption = new Option ( '--concurrency <value>' )
14+ . argParser ( ( value ) : Exclude < ESLint . Options [ 'concurrency' ] , undefined > => {
15+ switch ( value ) {
16+ case 'auto' :
17+ case 'off' :
18+ return value ;
19+ default : {
20+ const count = parseInt ( value ) ;
21+
22+ if ( Number . isNaN ( count ) ) {
23+ throw new InvalidArgumentError ( `Expected auto, off or a number, got ${ value } ` ) ;
24+ }
25+
26+ return count ;
27+ }
28+ }
29+ } )
30+ . default ( 'auto' ) ;
31+
1232/*
1333 * The lint command is provided as part of buildtools so that each bundle and tab doesn't
1434 * have to install its own copy of ESLint
@@ -20,7 +40,8 @@ export const getLintCommand = () => new Command('lint')
2040 . option ( '--fix' , 'Output linting fixes' , false )
2141 . option ( '--stats' , 'Output linting stats' , false )
2242 . option ( '--ci' , process . env . CI )
23- . action ( async ( directory , { fix, ci, stats } ) => {
43+ . addOption ( concurrencyOption )
44+ . action ( async ( directory , { ci, ...opts } ) => {
2445 const fullyResolved = pathlib . resolve ( directory ) ;
2546 const resolveResult = await resolveEitherBundleOrTab ( fullyResolved ) ;
2647
@@ -32,7 +53,7 @@ export const getLintCommand = () => new Command('lint')
3253 logCommandErrorAndExit ( resolveResult ) ;
3354 }
3455
35- const result = await runEslint ( resolveResult . asset , fix , stats ) ;
56+ const result = await runEslint ( resolveResult . asset , opts ) ;
3657 console . log ( formatLintResult ( result ) ) ;
3758
3859 switch ( result . severity ) {
@@ -50,10 +71,16 @@ export const getLintGlobalCommand = () => new Command('lintglobal')
5071 . option ( '--fix' , 'Output linting fixes' , false )
5172 . option ( '--stats' , 'Output linting stats' , false )
5273 . option ( '--ci' , process . env . CI )
53- . action ( async ( { fix, stats, ci } ) => {
54- console . log ( chalk . cyanBright ( 'Beginning lint global' ) ) ;
55- const result = await lintGlobal ( fix , stats ) ;
74+ . addOption ( concurrencyOption )
75+ . action ( async ( { ci, ...opts } ) => {
5676 const prefix = chalk . blueBright ( '[lintglobal]' ) ;
77+
78+ console . log ( `${ prefix } ${ chalk . cyanBright ( 'Beginning linting with the following options:' ) } ` ) ;
79+ Object . entries ( opts ) . forEach ( ( [ key , value ] , i ) => {
80+ console . log ( ` ${ i + 1 } . ${ chalk . greenBright ( key ) } : ${ chalk . cyanBright ( value ) } ` ) ;
81+ } ) ;
82+
83+ const result = await lintGlobal ( opts ) ;
5784 const logs = [
5885 `${ prefix } Took ${ divideAndRound ( result . filesElapsed , 1000 ) } s to find files` ,
5986 `${ prefix } Took ${ divideAndRound ( result . lintElapsed , 1000 ) } s to lint files` ,
@@ -65,7 +92,7 @@ export const getLintGlobalCommand = () => new Command('lintglobal')
6592
6693 console . log ( logs . join ( '\n' ) ) ;
6794
68- if ( stats ) {
95+ if ( opts . stats ) {
6996 const statPath = pathlib . join ( outDir , 'lintstats.csv' ) ;
7097 console . log ( chalk . greenBright ( `Stats written to ${ statPath } ` ) ) ;
7198 }
0 commit comments