import { BrowserSyncInstance , create as createBrowserSyncInstance } from 'browser-sync' ; import * as child_process from 'child_process' ; import * as fs from 'fs' ; import * as gulp from 'gulp' ; import { buildConfig } from 'material2-build-tools' ; import * as path from 'path' ; const gulpClean = require ( 'gulp-clean' ) ; const resolveBin = require ( 'resolve-bin' ) ; const httpRewrite = require ( 'http-rewrite-middleware' ) ; const { projectDir } = buildConfig ; /** Currently active browsersync instance. */ let activeBrowserSyncInstance ; /** If the string passed in is a glob, returns it, otherwise append '**\/*' to it. */ function _globify ( maybeGlob , suffix = '**/*' ) { if ( maybeGlob . indexOf ( '*' ) > - 1 ) { return maybeGlob ; } try { if ( fs . statSync ( maybeGlob ) . isFile ( ) ) { return maybeGlob ; } } catch { } return path . join ( maybeGlob , suffix ) ; } /** Creates a task that runs the TypeScript compiler */ export function tsBuildTask ( tsConfigPath ) { return execNodeTask ( 'typescript' , 'tsc' , [ '-p' , tsConfigPath ] ) ; } /** Creates a task that runs the Angular Compiler CLI. */ export function ngcBuildTask ( tsConfigPath ) { return execNodeTask ( '@angular/compiler-cli' , 'ngc' , [ '-p' , tsConfigPath ] ) ; } /** Options that can be passed to execTask or execNodeTask. */ export interface ExecTaskOptions { silent ? : boolean ; silentStdout ? : boolean ; errMessage ? : string ; env ? : any ; failOnStderr ? : boolean ; } /** Create a task that executes a binary as if from the command line. */ export function execTask ( binPath , args , options = { } ) { return ( done ) => { const env = Object . assign ( { } , process . env , options . env ) ; const childProcess = child_process . spawn ( binPath , args , { env } ) ; const stderrData = [ ] ; if ( ! options . silentStdout && ! options . silent ) { childProcess . stdout . on ( 'data' , ( data ) => process . stdout . write ( data ) ) ; } if ( ! options . silent || options . failOnStderr ) { childProcess . stderr . on ( 'data' , ( data ) => { options . failOnStderr ? stderrData . push ( data ) : process . stderr . write ( data ) ; } ) ; } childProcess . on ( 'close' , ( code ) => { if ( options . failOnStderr && stderrData . length ) { done ( stderrData . join ( '\n' ) ) ; } else { code != 0 ? done ( options . errMessage || `Process failed with code ${ code }` ) : done ( ) ; } } ) ; } ; } /**
 * Create a task that executes an NPM Bin, by resolving the binary path then executing it. These are
 * binaries that are normally in the `./node_modules/.bin` directory, but their name might differ
 * from the package. Examples are typescript, ngc and gulp itself.
 */ export function execNodeTask ( packageName , executable , args ? , options = { } ) { if ( ! args ) { args = < string [ ] > executable ; executable = '' ; } return ( done ) => { resolveBin ( packageName , { executable : executable } , ( err , binPath ) => { if ( err ) { done ( err ) ; } else { execTask ( 'node' , [ binPath ] . concat ( args ! ) , options ) ( done ) ; } } ) ; } ; } /** Copy files from a glob to a destination. */ export function copyTask ( srcGlobOrDir , outRoot ) { if ( typeof srcGlobOrDir === 'string' ) { return ( ) => gulp . src ( _globify ( srcGlobOrDir ) ) . pipe ( gulp . dest ( outRoot ) ) ; } else { return ( ) => gulp . src ( srcGlobOrDir . map ( name => _globify ( name ) ) ) . pipe ( gulp . dest ( outRoot ) ) ; } } /** Delete files. */ export function cleanTask ( glob ) { return ( ) => gulp . src ( glob , { read : false } ) . pipe ( gulpClean ( null ) ) ; } /**
 * Create a task that serves a given directory in the project.
 * The server rewrites all node_module/ or dist/ requests to the correct directory.
 */ export function serverTask ( packagePath , rewrites ? ) { const relativePath = path . relative ( projectDir , packagePath ) ; const defaultHttpRewrites = [ { from : '^/node_modules/(.*)$' , to : '/node_modules/$1' } , { from : '^/dist/(.*)$' , to : '/dist/$1' } , { from : '^/[^.]+$' , to : `/${ relativePath }/index.html` } , { from : '^(.*)$' , to : `/${ relativePath }/$1` } , ] ; return ( ) => { if ( activeBrowserSyncInstance ) { throw new Error ( 'Cannot setup BrowserSync because there is already an instance running.' ) ; } activeBrowserSyncInstance = createBrowserSyncInstance ( ) ; activeBrowserSyncInstance . init ( { server : projectDir , port : 4200 , middleware : httpRewrite . getMiddleware ( rewrites || defaultHttpRewrites ) , notify : false , ghostMode : process . argv . includes ( '--ghostMode' ) , open : process . argv . includes ( '--open' ) , } ) ; } ; } /** Gets the currently active browsersync instance */ export function getActiveBrowserSyncInstance ( ) { if ( ! activeBrowserSyncInstance ) { throw new Error ( 'Cannot return Browsersync instance because there is no instance running.' ) ; } return activeBrowserSyncInstance ; }