import * as url from 'url' ; import * as path from 'path' ; import * as fs from 'fs' ; import { spawnSync , fork , ChildProcess , SpawnSyncOptionsWithStringEncoding } from 'child_process' ; deprecated export function uriToFilePath ( uri ) { let parsed = url . parse ( uri ) ; if ( parsed . protocol !== 'file:' || ! parsed . path ) { return undefined ; } let segments = parsed . path . split ( '/' ) ; for ( var i = 0 , len = segments . length ; i < len ; i ++ ) { segments [ i ] = decodeURIComponent ( segments [ i ] ) ; } if ( process . platform === 'win32' && segments . length > 1 ) { let first = segments [ 0 ] ; let second = segments [ 1 ] ; if ( first . length === 0 && second . length > 1 && second [ 1 ] === ':' ) { segments . shift ( ) ; } } return path . normalize ( segments . join ( '/' ) ) ; } function isWindows ( ) { return process . platform === 'win32' ; } export function resolve ( moduleName , nodePath , cwd , tracer ) { interface Message { c : string ; s ? : boolean ; a ? : any ; r ? : any ; } const nodePathKey = 'NODE_PATH' ; const app = [ 'var p = process;' , 'p.on(\'message\',function(m){' , 'if(m.c===\'e\'){' , 'p.exit(0);' , '}' , 'else if(m.c===\'rs\'){' , 'try{' , 'var r=require.resolve(m.a);' , 'p.send({c:\'r\',s:true,r:r});' , '}' , 'catch(err){' , 'p.send({c:\'r\',s:false});' , '}' , '}' , '});' ] . join ( '' ) ; return new Promise < any > ( ( resolve , reject ) => { let env = process . env ; let newEnv = Object . create ( null ) ; Object . keys ( env ) . forEach ( key => newEnv [ key ] = env [ key ] ) ; if ( nodePath && fs . existsSync ( nodePath ) ) { if ( newEnv [ nodePathKey ] ) { newEnv [ nodePathKey ] = nodePath + path . delimiter + newEnv [ nodePathKey ] ; } else { newEnv [ nodePathKey ] = nodePath ; } if ( tracer ) { tracer ( `NODE_PATH value is: ${ newEnv [ nodePathKey ] }` ) ; } } newEnv [ 'ELECTRON_RUN_AS_NODE' ] = '1' ; try { let cp = fork ( '' , [ ] , < any > { cwd : cwd , env : newEnv , execArgv : [ '-e' , app ] } ) ; if ( cp . pid === void 0 ) { reject ( new Error ( `Starting process to resolve node module  ${ moduleName } failed` ) ) ; return ; } cp . on ( 'error' , ( error ) => { reject ( error ) ; } ) ; cp . on ( 'message' , ( message ) => { if ( message . c === 'r' ) { cp . send ( { c : 'e' } ) ; if ( message . s ) { resolve ( message . r ) ; } else { reject ( new Error ( `Failed to resolve module: ${ moduleName }` ) ) ; } } } ) ; let message = { c : 'rs' , a : moduleName } ; cp . send ( message ) ; } catch ( error ) { reject ( error ) ; } } ) ; } deprecated param tracer export function resolveGlobalNodePath ( tracer ? ) { let npmCommand = 'npm' ; const env = Object . create ( null ) ; Object . keys ( process . env ) . forEach ( key => env [ key ] = process . env [ key ] ) ; env [ 'NO_UPDATE_NOTIFIER' ] = 'true' ; const options = { encoding : 'utf8' , env } ; if ( isWindows ( ) ) { npmCommand = 'npm.cmd' ; options . shell = true ; } let handler = ( ) => { } ; try { process . on ( 'SIGPIPE' , handler ) ; let stdout = spawnSync ( npmCommand , [ 'config' , 'get' , 'prefix' ] , options ) . stdout ; if ( ! stdout ) { if ( tracer ) { tracer ( `'npm config get prefix' didn't return a value.` ) ; } return undefined ; } let prefix = stdout . trim ( ) ; if ( tracer ) { tracer ( `'npm config get prefix' value is: ${ prefix }` ) ; } if ( prefix . length > 0 ) { if ( isWindows ( ) ) { return path . join ( prefix , 'node_modules' ) ; } else { return path . join ( prefix , 'lib' , 'node_modules' ) ; } } return undefined ; } catch ( err ) { return undefined ; } finally { process . removeListener ( 'SIGPIPE' , handler ) ; } } interface YarnJsonFormat { type : string ; data : string ; } export function resolveGlobalYarnPath ( tracer ? ) { let yarnCommand = 'yarn' ; let options = { encoding : 'utf8' } ; if ( isWindows ( ) ) { yarnCommand = 'yarn.cmd' ; options . shell = true ; } let handler = ( ) => { } ; try { process . on ( 'SIGPIPE' , handler ) ; let results = spawnSync ( yarnCommand , [ 'global' , 'dir' , '--json' ] , options ) ; let stdout = results . stdout ; if ( ! stdout ) { if ( tracer ) { tracer ( `'yarn global dir' didn't return a value.` ) ; if ( results . stderr ) { tracer ( results . stderr ) ; } } return undefined ; } let lines = stdout . trim ( ) . split ( /\r?\n/ ) ; for ( let line of lines ) { try { let yarn = JSON . parse ( line ) ; if ( yarn . type === 'log' ) { return path . join ( yarn . data , 'node_modules' ) ; } } catch ( e ) { } } return undefined ; } catch ( err ) { return undefined ; } finally { process . removeListener ( 'SIGPIPE' , handler ) ; } } export namespace FileSystem { let _isCaseSensitive = undefined ; export function isCaseSensitive ( ) { if ( _isCaseSensitive !== void 0 ) { return _isCaseSensitive ; } if ( process . platform === 'win32' ) { _isCaseSensitive = false ; } else { _isCaseSensitive = ! fs . existsSync ( __filename . toUpperCase ( ) ) || ! fs . existsSync ( __filename . toLowerCase ( ) ) ; } return _isCaseSensitive ; } export function isParent ( parent , child ) { if ( isCaseSensitive ( ) ) { return path . normalize ( child ) . indexOf ( path . normalize ( parent ) ) === 0 ; } else { return path . normalize ( child ) . toLowerCase ( ) . indexOf ( path . normalize ( parent ) . toLowerCase ( ) ) === 0 ; } } } export function resolveModulePath ( workspaceRoot , moduleName , nodePath , tracer ) { if ( nodePath ) { if ( ! path . isAbsolute ( nodePath ) ) { nodePath = path . join ( workspaceRoot , nodePath ) ; } return resolve ( moduleName , nodePath , nodePath , tracer ) . then ( ( value ) => { if ( FileSystem . isParent ( nodePath , value ) ) { return value ; } else { return Promise . reject < string > ( new Error ( `Failed to load ${ moduleName } from node path location.` ) ) ; } } ) . then < string , string > ( undefined , ( _error ) => { return resolve ( moduleName , resolveGlobalNodePath ( tracer ) , workspaceRoot , tracer ) ; } ) ; } else { return resolve ( moduleName , resolveGlobalNodePath ( tracer ) , workspaceRoot , tracer ) ; } }