/**
 * Copyright (c) AcademyJS and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */ import "source-map-support/register" ; import { Command } from "commander" ; import chalk from "chalk" ; import path from "path" ; import fs from "fs" ; import Driver from "./driver/mocha" ; import { MetaConfiguration , SubmitConfiguration , ListConfiguration , ShowConfiguration , } from "./types" ; import excercises from "./excercises" ; const handleRunComplete = ( errors ) => { } ; const validateSolution = async ( handle , configuration ) : Promise < void > => { const driver = new Driver ( { reporter : "spec" , } ) ; driver . resolveFile = ( file ) => `../excercises/${ file }` ; const index = excercises . indexOf ( handle ) ; if ( index < 0 ) { console . log ( `${ chalk . redBright ( "[error]" ) } Cannot find excercise ${ chalk . bold ( handle ) }. Please update to the latest version and try again.` ) ; return ; } driver . addFile ( excercises [ index ] ) ; driver . run ( handleRunComplete ) ; } ; export const extractMeta = ( ) : Promise < any > => new Promise ( ( resolve ) => { const handleComplete = ( meta , suites , error ) => { resolve ( { meta , suites , error } ) ; } ; const driver = new Driver ( { dryRun : true , reporter : "json_all" , reporterOption : { onComplete : handleComplete , } , } ) ; driver . resolveFile = ( file ) => `../${ file }` ; driver . addFiles ( ... excercises . map ( ( excerciseFile ) => `./excercises/${ excerciseFile }` ) ) ; driver . run ( handleRunComplete ) ; } ) ; const generateMeta = async ( configuration ) : Promise < void > => { const { meta , error } = await extractMeta ( ) ; if ( error ) { return ; } const json = JSON . stringify ( meta , null , 2 ) ; if ( configuration . file ) { try { fs . mkdirSync ( path . dirname ( configuration . file ) , { recursive : true } ) ; fs . writeFileSync ( configuration . file , json ) ; } catch ( error ) { console . error ( `${ chalk . redBright ( "[error]" ) } Cannot write output to "${ configuration . file }". (${ error . message })\n` ) ; console . log ( json ) ; } } else { console . log ( json ) ; } } ; const listExercises = async ( configuration ) : Promise < void > => { const { meta , error } = await extractMeta ( ) ; if ( error ) { return ; } const { suites } = meta . suites [ 0 ] ; const filteredSuites = configuration . tags . length === 0 ? suites : suites . filter ( ( suite ) => suite . tags . some ( ( tag ) => configuration . tags . includes ( tag ) ) ) ; if ( filteredSuites . length > 0 ) { console . log ( ) ; for ( let i = 0 ; i < filteredSuites . length ; i ++ ) { const suite = filteredSuites [ i ] ; console . log ( `     ${ ( i + 1 + "." ) . padEnd ( 4 , " " ) } ${ chalk . yellowBright ( suite . handle . padEnd ( 30 , " " ) ) }\n          ${ chalk . bold ( suite . title ) }\n          ${ suite . tags . join ( ", " ) }\n` ) ; } } } ; const showExercise = async ( configuration ) : Promise < void > => { const { handle } = configuration ; const { suites , error } = await extractMeta ( ) ; if ( error ) { return ; } const suite = suites [ handle ] ; if ( ! suite ) { console . log ( `${ chalk . redBright ( "[error]" ) } Unknown excercise ${ chalk . bold ( handle ) }` ) ; return ; } console . log ( `\n${ chalk . yellowBright . bold ( suite . handle ) }\n\n${ chalk . bold ( suite . title ) }\n\n${ suite . description }\n\n` ) ; for ( const test of suite . tests ) { console . log ( `    ${ chalk . green ( "✔" ) } ${ chalk . bold ( test . title ) }\n      ${ test . description }\n` ) ; } } ; const packageData = require ( "../../package" ) ; const configureCommands = ( ) : Command => { const program = new Command ( ) ; program . version ( packageData . version ) ; const submitCommand = new Command ( ) ; submitCommand . name ( "submit" ) . argument ( "<handle>" , "the handle for the exercise" ) . option ( "--print-error" , "print the standard error generated by the solution" , true ) . option ( "--print-output" , "print the standard output generated by the solution" , true ) . alias ( "x" ) . description ( "validate your solution and submit the results" ) . action ( async ( handle ) => { const configuration = { ... program . opts ( ) , ... submitCommand . opts ( ) , } as SubmitConfiguration ; await validateSolution ( handle , configuration ) ; } ) ; program . addCommand ( submitCommand ) ; const listCommand = new Command ( ) ; listCommand . name ( "list" ) . alias ( "ls" ) . argument ( "[tags...]" , "tags to filter the result by" ) . description ( "list exercises" ) . action ( async ( tags ) => { const configuration = { tags , ... program . opts ( ) , ... listCommand . opts ( ) , } as ListConfiguration ; await listExercises ( configuration ) ; } ) ; program . addCommand ( listCommand ) ; const showCommand = new Command ( ) ; showCommand . name ( "show" ) . alias ( "s" ) . argument ( "<handle>" , "handle of the exercise to show" ) . description ( "prints the details of an exercise" ) . action ( async ( handle ) => { const configuration = { handle , ... program . opts ( ) , ... showCommand . opts ( ) , } as ShowConfiguration ; await showExercise ( configuration ) ; } ) ; program . addCommand ( showCommand ) ; const metaCommand = new Command ( ) ; metaCommand . name ( "meta" ) . argument ( "[file]" , "the resulting output file (default: standard output stream)" , null ) . alias ( "m" ) . description ( "extract excercise metadata as JSON" ) . action ( async ( file ) => { const configuration = { file , ... program . opts ( ) , ... metaCommand . opts ( ) , } as MetaConfiguration ; await generateMeta ( configuration ) ; } ) ; program . addCommand ( metaCommand ) ; return program ; } ; const main = ( ) => { console . log ( chalk . bold ( `rover ${ packageData . version } ${ chalk . greenBright ( "(https://academyjs.com/rover)" ) }` ) ) ; const program = configureCommands ( ) ; program . parse ( process . argv ) ; } ; export { main } ;