export = pluck ; import * as semver from 'semver' ; import { parsePackageString as moduleToObject } from 'snyk-module' ; import * as debugModule from 'debug' ; import { PackageExpanded } from './types' ; const debug = debugModule ( 'snyk:resolve:pluck' ) ; const parseOptions = { loose : true } ; function pluck ( root , path , name , range ) { if ( range === 'latest' ) { range = '*' ; } let from = path . slice ( 0 ) ; let rootPath = moduleToObject ( from . shift ( ) ! , parseOptions ) . name ; if ( rootPath !== root . name ) { return false ; } if ( from . length !== 0 && moduleToObject ( from . slice ( - 1 ) . pop ( ) ! , parseOptions ) . name === name ) { from . pop ( ) ; } from . push ( name + '@' + range ) ; debug ( 'using forward search %s@%s in %s' , from . join ( ' > ' ) ) ; let match = false ; let leaf = root ; let realPath = [ ] ; while ( from . length ) { let pkg = moduleToObject ( from [ 0 ] , parseOptions ) ; let test = getMatch ( leaf , pkg . name , pkg . version ) ; if ( test ) { from . shift ( ) ; realPath . push ( leaf ) ; leaf = test ; } else { let maybeLeaf = realPath . pop ( ) ; if ( ! maybeLeaf ) { return false ; } leaf = maybeLeaf ; } } return leaf . name === name ? leaf : false ; } function getMatch ( root , name , range ) { let dep = root . dependencies && root . dependencies [ name ] ; if ( ! dep ) { return false ; } let version = dep . version ; debug ( 'pluck match on name...checking version: %s ~= %s' , version , range ) ; let semverMatch = semver . validRange ( range ) && semver . valid ( version ) && semver . satisfies ( version , range ) ; let externalPackage = ! semver . validRange ( range ) && range . indexOf ( ':/' ) !== - 1 ; if ( semverMatch || externalPackage ) { debug ( 'pluck match' ) ; if ( ! dep . dep ) { dep . dep = range ; } return dep ; } return false ; }