import * as path from 'path' ; import * as Collections from 'typescript-collections' ; import * as vscode from 'vscode' ; import { ComponentDetails } from 'jfrog-client-js' ; import { DependenciesTreeNode } from '../dependenciesTreeNode' ; import { TreesManager } from '../../treesManager' ; import { GeneralInfo } from '../../../types/generalInfo' ; import { ScanUtils } from '../../../utils/scanUtils' ; import { NpmGlobalScopes , ScopedNpmProject , NpmUtils } from '../../../utils/npmUtils' ; import { RootNode } from './rootTree' ; export class NpmTreeNode extends RootNode { private static readonly COMPONENT_PREFIX : string = 'npm://' ; constructor ( workspaceFolder , private _componentsToScan , private _treesManager , parent ? ) { super ( workspaceFolder , parent ) ; } public async refreshDependencies ( quickScan ) { const productionScope = new ScopedNpmProject ( NpmGlobalScopes . PRODUCTION ) ; const developmentScope = new ScopedNpmProject ( NpmGlobalScopes . DEVELOPMENT ) ; let npmLsFailed = false ; [ productionScope , developmentScope ] . forEach ( scopedProject => { try { scopedProject . loadProjectDetails ( this . runNpmLs ( scopedProject . scope ) ) ; } catch ( error ) { this . _treesManager . logManager . logError ( < any > error , ! quickScan ) ; this . _treesManager . logManager . logMessage ( 'Possible cause: The project needs to be installed by npm. Install it by running "npm install" from "' + this . workspaceFolder + '",.' , 'INFO' ) ; scopedProject . loadProjectDetails ( JSON . parse ( ( < any > error ) . stdout . toString ( ) ) ) ; npmLsFailed = true ; } this . populateDependenciesTree ( this , scopedProject . dependencies , quickScan , scopedProject . scope ) ; } ) ; this . generalInfo = new GeneralInfo ( npmLsFailed ? ( productionScope . projectName += ' [Not installed]' ) : productionScope . projectName , productionScope . projectVersion , [ ] , this . workspaceFolder , NpmUtils . PKG_TYPE ) ; this . label = productionScope . projectName ? productionScope . projectName : path . join ( this . workspaceFolder , 'package.json' ) ; } private populateDependenciesTree ( dependenciesTreeNode , dependencies , quickScan , globalScope ) { if ( ! dependencies ) { return ; } for ( let key in dependencies ) { let dependency = dependencies [ key ] ; let version = dependency . version ; if ( version ) { let childDependencies = dependency . dependencies ; const scope = NpmUtils . getDependencyScope ( key ) ; const currentDependencyScope = scope !== '' ? [ globalScope , scope ] : [ globalScope ] ; let generalInfo = new GeneralInfo ( key , version , currentDependencyScope , '' , NpmUtils . PKG_TYPE ) ; let treeCollapsibleState = childDependencies ? vscode . TreeItemCollapsibleState . Collapsed : vscode . TreeItemCollapsibleState . None ; let child = new DependenciesTreeNode ( generalInfo , treeCollapsibleState , dependenciesTreeNode ) ; let componentId = key + ':' + version ; if ( ! quickScan || ! this . _treesManager . scanCacheManager . isValid ( componentId ) ) { this . _componentsToScan . add ( new ComponentDetails ( NpmTreeNode . COMPONENT_PREFIX + componentId ) ) ; } this . populateDependenciesTree ( child , childDependencies , quickScan , globalScope ) ; } } } private runNpmLs ( scope ) { return JSON . parse ( ScanUtils . executeCmd ( 'npm ls --json --all --' + scope , this . workspaceFolder ) . toString ( ) ) ; } }