import { mkdirp , remove } from "fs-extra" ; import * as yargs from "yargs" ; import { FS , getDefinitelyTyped } from "./get-definitely-typed" ; import { Options } from "./lib/common" ; import { AllPackages , getFullNpmName } from "./lib/packages" ; import { validateOutputPath } from "./lib/settings" ; import { readChangedPackages } from "./lib/versions" ; import { writeFile , writeJson } from "./util/io" ; import { LoggerWithErrors , loggerWithErrors , moveLogsWithErrors , quietLoggerWithErrors , writeLog } from "./util/logging" ; import { exec , joinPaths , logUncaughtErrors , nAtATime } from "./util/util" ; if ( ! module . parent ) { const all = ! ! yargs . argv . all ; const packageNames = yargs . argv . _ ; if ( all && packageNames . length ) { throw new Error ( "Can't combine --all with listed package names." ) ; } if ( all ) { console . log ( "Validating all packages" ) ; logUncaughtErrors ( doAll ( ) ) ; } else if ( packageNames . length ) { console . log ( `Validating: ${ JSON . stringify ( packageNames ) }` ) ; logUncaughtErrors ( doValidate ( packageNames ) ) ; } else { const log = loggerWithErrors ( ) [ 0 ] ; logUncaughtErrors ( getDefinitelyTyped ( Options . defaults , log ) . then ( validate ) ) ; } } export default async function validate ( dt ) { await doValidate ( ( await readChangedPackages ( await AllPackages . read ( dt ) ) ) . changedTypings . map ( c => c . pkg . name ) ) ; } async function doAll ( ) { const packageNames = ( await AllPackages . readTypings ( ) ) . map ( t => t . name ) . sort ( ) ; await doValidate ( packageNames ) ; } async function doValidate ( packageNames ) { const [ log , logResult ] = loggerWithErrors ( ) ; await validatePackages ( packageNames , validateOutputPath , log ) ; const { infos , errors } = logResult ( ) ; await Promise . all ( [ writeLog ( "validate.md" , infos ) , writeLog ( "validate-errors.md" , errors ) , ] ) ; } async function validatePackages ( packageNames , outPath , log ) { log . info ( "" ) ; log . info ( `Using output path: ${ outPath }` ) ; log . info ( "Running tests...." ) ; log . info ( "" ) ; const failed = [ ] ; const passed = [ ] ; try { await remove ( outPath ) ; await mkdirp ( outPath ) ; } catch ( e ) { log . error ( `Could not recreate output directory. ${ e }` ) ; return ; } await nAtATime ( 25 , packageNames , async ( packageName ) => { if ( await validatePackage ( packageName , outPath , log ) ) { passed . push ( packageName ) ; } else { failed . push ( packageName ) ; } } ) ; log . info ( "" ) ; log . info ( "" ) ; log . info ( `Total  ${ packageNames . length }` ) ; log . info ( `Passed ${ passed . length }` ) ; log . info ( `Failed ${ failed . length }` ) ; log . info ( "" ) ; if ( failed . length ) { log . info ( `These packages failed: ${ failed . toString ( ) }` ) ; } } async function validatePackage ( packageName , outputDirecory , mainLog ) { const [ log , logResult ] = quietLoggerWithErrors ( ) ; let passed = false ; try { const packageDirectory = joinPaths ( outputDirecory , packageName ) ; log . info ( "" ) ; log . info ( `Processing \`${ packageName }\`...` ) ; await mkdirp ( packageDirectory ) ; await writePackage ( packageDirectory , packageName ) ; if ( await runCommand ( "npm" , log , packageDirectory , "../../node_modules/npm/bin/npm-cli.js" , "install" ) && await runCommand ( "tsc" , log , packageDirectory , "../../node_modules/typescript/lib/tsc.js" ) ) { await remove ( packageDirectory ) ; log . info ( "Passed." ) ; passed = true ; } } catch ( e ) { log . info ( `Error: ${ e }` ) ; log . info ( "Failed!" ) ; } moveLogsWithErrors ( mainLog , logResult ( ) ) ; console . info ( `${ packageName } -- ${ passed ? "Passed" : "Failed" }.` ) ; return passed ; } async function writePackage ( packageDirectory , packageName ) { await writeJson ( joinPaths ( packageDirectory , "package.json" ) , { name : `${ packageName }_test` , version : "1.0.0" , description : "test" , author : "" , license : "ISC" , repository : "https://github.com/Microsoft/types-publisher" , dependencies : { [ getFullNpmName ( packageName ) ] : "latest" } , } ) ; await writeJson ( joinPaths ( packageDirectory , "tsconfig.json" ) , { compilerOptions : { module : "commonjs" , target : "es5" , noImplicitAny : false , strictNullChecks : false , noEmit : true , lib : [ "es5" , "es2015.promise" , "dom" ] , } , } ) ; await writeFile ( joinPaths ( packageDirectory , "index.ts" ) , `/// <reference types="${ packageName }" />\r\n` ) ; } async function runCommand ( commandDescription , log , directory , cmd , ... args ) { const nodeCmd = `node ${ cmd } ${ args . join ( " " ) }` ; log . info ( `Run ${ nodeCmd }` ) ; const { error , stdout , stderr } = await exec ( nodeCmd , directory ) ; if ( error ) { log . error ( stderr ) ; log . info ( stdout ) ; log . error ( `${ commandDescription } failed: ${ JSON . stringify ( error ) }` ) ; log . info ( `${ commandDescription } failed, refer to error log` ) ; return false ; } log . info ( stdout ) ; return true ; }