Skip to content
This repository has been archived by the owner on Nov 23, 2021. It is now read-only.

Commit

Permalink
Support NPM dependencies (package-lock.json) in addition to yarn.lock (
Browse files Browse the repository at this point in the history
…#21)

* support npm
  • Loading branch information
misberner authored Apr 27, 2021
1 parent a29eaad commit a00139b
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 17 deletions.
8 changes: 6 additions & 2 deletions deplist.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ func init() {
log.Fatal("yarn is required in PATH")
}

if _, err := exec.LookPath("npm"); err != nil {
log.Fatal("npm is required in PATH")
}

if _, err := exec.LookPath("go"); err != nil {
log.Fatal("go is required")
}
Expand Down Expand Up @@ -86,8 +90,8 @@ func GetDeps(fullPath string) ([]Dependency, Bitmask, error) {
// paths. Useful if we're looking for top of repo

switch filename := info.Name(); filename {
// for now only go for yarn
case "yarn.lock":
// for now only go for yarn and npm
case "yarn.lock", "package-lock.json":
pkgs, err := scan.GetNodeJSDeps(path)
if err != nil {
return err
Expand Down
88 changes: 73 additions & 15 deletions internal/scan/nodejs.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package scan

import (
"encoding/json"
"fmt"
"os/exec"
"path/filepath"
"strings"
Expand All @@ -23,9 +24,36 @@ type yarnOutput struct {
}
}

type npmDependency struct {
Version string `json:"version"`
Dependencies map[string]npmDependency `json:"dependencies"`
}

type npmListOutput struct {
Dependencies map[string]npmDependency `json:"dependencies"`
}

var gathered map[string]string

func gatherNode(dep yarnDependency) {
func recordPackage(packageName, version string) {
// compare everything
if !strings.HasPrefix(version, "v") {
version = "v" + version
}
version = strings.Replace(version, "^", "", 1)
version = strings.Replace(version, "~", "", 1)

version = strings.Replace(version, "x", "0", 1)
version = strings.Replace(version, "*", "0.0.0", 1)

if oldVersion, ok := gathered[packageName]; ok {
gathered[packageName] = semver.Max(oldVersion, version)
} else {
gathered[packageName] = version
}
}

func gatherYarnNode(dep yarnDependency) {
// incase package starts with @
splitIdx := strings.LastIndex(dep.Name, "@")

Expand All @@ -40,28 +68,33 @@ func gatherNode(dep yarnDependency) {
version = "v0.0.0"
}

// compare everything
version = strings.Replace(version, "^", "", 1)
version = strings.Replace(version, "~", "", 1)

version = strings.Replace(version, "x", "0", 1)
version = strings.Replace(version, "*", "0.0.0", 1)

if _, ok := gathered[name]; ok {
gathered[name] = semver.Max(gathered[name], version)
} else {
gathered[name] = version
}
recordPackage(name, version)

if len(dep.Children) > 0 {
for _, child := range dep.Children {
gatherNode(child)
gatherYarnNode(child)
}
}
}

func gatherNPMNode(name string, dependency npmDependency) {
recordPackage(name, dependency.Version)
for childName, childDep := range dependency.Dependencies {
gatherNPMNode(childName, childDep)
}
}

func GetNodeJSDeps(path string) (map[string]string, error) {
switch filepath.Base(path) {
case "yarn.lock":
return getYarnDeps(path)
case "package-lock.json":
return getNPMDeps(path)
}
return nil, fmt.Errorf("unknown NodeJS dependency file %q", path)
}

func getYarnDeps(path string) (map[string]string, error) {
var yarnOutput yarnOutput
gathered = make(map[string]string)

Expand All @@ -79,7 +112,32 @@ func GetNodeJSDeps(path string) (map[string]string, error) {
}

for _, deps := range yarnOutput.Data.Deps {
gatherNode(deps)
gatherYarnNode(deps)
}

return gathered, nil
}

func getNPMDeps(path string) (map[string]string, error) {
var npmOutput npmListOutput
gathered = make(map[string]string)

cmd := exec.Command("npm", "list", "--prod", "--json", "--depth=99")
cmd.Dir = filepath.Dir(path)

data, err := cmd.Output()

if err != nil {
return nil, err
}

err = json.Unmarshal(data, &npmOutput)
if err != nil {
return nil, err
}

for depName, dep := range npmOutput.Dependencies {
gatherNPMNode(depName, dep)
}

return gathered, nil
Expand Down

0 comments on commit a00139b

Please sign in to comment.