github.com/noqcks/syft@v0.0.0-20230920222752-a9e2c4e288e5/syft/pkg/cataloger/javascript/parse_javascript.go (about)

     1  package javascript
     2  
     3  import (
     4  	"path"
     5  	"strings"
     6  
     7  	"github.com/anchore/syft/syft/artifact"
     8  	"github.com/anchore/syft/syft/file"
     9  	"github.com/anchore/syft/syft/pkg"
    10  	"github.com/anchore/syft/syft/pkg/cataloger/generic"
    11  	"github.com/anchore/syft/syft/pkg/cataloger/javascript/filter"
    12  )
    13  
    14  var _ generic.GroupedParser = parseJavaScript
    15  
    16  var path2dir = func(relpath string) string { return path.Dir(strings.ReplaceAll(relpath, `\`, `/`)) }
    17  
    18  func parseJavaScript(resolver file.Resolver, e *generic.Environment, readers []file.LocationReadCloser) (pkgs []pkg.Package, relationships []artifact.Relationship, err error) {
    19  	jsonMap := map[string]*packageJSON{}
    20  	lockMap := map[string]*packageLock{}
    21  	yarnMap := map[string]map[string]*yarnLockPackage{}
    22  	pnpmMap := map[string]map[string]*pnpmLockPackage{}
    23  	pnpmLock := map[string]pnpmLockYaml{}
    24  	pnpmLocation := file.Location{}
    25  	yarnLocation := file.Location{}
    26  	lockLocation := file.Location{}
    27  
    28  	for _, reader := range readers {
    29  		// in the case we find matching files in the node_modules directories, skip those
    30  		// as the whole purpose of the lock file is for the specific dependencies of the root project
    31  		if pathContainsNodeModulesDirectory(reader.AccessPath()) {
    32  			return nil, nil, nil
    33  		}
    34  
    35  		path := reader.Location.RealPath
    36  		if filter.JavaScriptYarnLock(path) {
    37  			yarnMap[path2dir(path)] = parseYarnLockFile(resolver, reader)
    38  			yarnLocation = reader.Location
    39  		}
    40  		if filter.JavaScriptPackageJSON(path) {
    41  			js, err := parsePackageJSONFile(resolver, e, reader)
    42  			if err != nil {
    43  				return nil, nil, err
    44  			}
    45  			js.File = path
    46  			jsonMap[js.Name] = js
    47  		}
    48  		if filter.JavaScriptPackageLock(path) {
    49  			lock, err := parsePackageLockFile(reader)
    50  			if err != nil {
    51  				return nil, nil, err
    52  			}
    53  			lockMap[lock.Name] = &lock
    54  			lockLocation = reader.Location
    55  		}
    56  		if filter.JavaScriptPmpmLock(path) {
    57  			pMap, pLock := parsePnpmLockFile(reader)
    58  			pnpmMap[path2dir(path)] = pMap
    59  			pnpmLock[path2dir(path)] = pLock
    60  			pnpmLocation = reader.Location
    61  		}
    62  	}
    63  
    64  	for name, js := range jsonMap {
    65  		if lock, ok := lockMap[name]; ok {
    66  			p, rels := finalizePackageLockWithPackageJSON(resolver, js, lock, lockLocation)
    67  			pkgs = append(pkgs, p...)
    68  			relationships = append(relationships, rels...)
    69  		}
    70  
    71  		if js.File != "" {
    72  			if yarn, ok := yarnMap[path2dir(js.File)]; ok {
    73  				p, rels := finalizeYarnLockWithPackageJSON(resolver, js, yarn, yarnLocation)
    74  				pkgs = append(pkgs, p...)
    75  				relationships = append(relationships, rels...)
    76  			}
    77  			if pnpm, ok := pnpmMap[path2dir(js.File)]; ok {
    78  				pLock := pnpmLock[path2dir(js.File)]
    79  				p, rels := finalizePnpmLockWithPackageJSON(resolver, js, &pLock, pnpm, pnpmLocation)
    80  				pkgs = append(pkgs, p...)
    81  				relationships = append(relationships, rels...)
    82  			}
    83  		}
    84  	}
    85  
    86  	pkg.Sort(pkgs)
    87  	pkg.SortRelationships(relationships)
    88  	return pkgs, relationships, nil
    89  }