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 }