import * as fs from 'fs' ; import * as cp from 'child_process' ; import execa , { ExecaReturnValue } from 'execa' ; export interface IDependency { name : string ; type : DependencyType ; } type DependencyType = keyof DependencyTypes ; interface DependencyTypes { dependency : InstallationInstruction ; devDependency : InstallationInstruction ; } type Installer = keyof InstallationInstruction ; type InstallationInstruction = { yarn : string ; npm : string ; } ; export const dependencyTypes = [ 'dependency' , 'devDependency' ] ; export const instructions = { dependency : { yarn : 'yarn add' , npm : 'npm install --save' } , devDependency : { yarn : 'yarn add -D' , npm : 'npm install --save-dev' } , } ; param dependency export function getNextDependencyType ( type ) { return dependencyTypes [ dependencyTypes . indexOf ( type ) + 1 ] ; } param deps param type export async function install ( deps , type ) { const installer = getInstaller ( ) ; const dependencies = deps . filter ( dep => dep . type === type ) ; const [ , , ... argvs ] = process . argv ; if ( dependencies . length === 0 ) { return Promise . resolve ( null ) ; } const command = instructions [ type ] [ installer ] ; const pkgs = dependencies . map ( ( { name } ) => name ) . join ( ' ' ) ; const args = argvs . join ( ' ' ) ; return execa ( `${ command } ${ pkgs } ${ args }` , { stdio : `ignore` , shell : true } ) ; } /**
 * Finds installer for the current system.
 */ function getInstaller ( ) { if ( ! fs . existsSync ( 'package-lock.json' ) && isYarnInstalled ( ) ) { return 'yarn' ; } else { return 'npm' ; } } /**
 * Checks whether Yarn is installed on the computer.
 */ function isYarnInstalled ( ) { try { cp . execSync ( `yarnpkg --version` , { stdio : `ignore` } ) ; return true ; } catch ( err ) { return false ; } }