Class: Licensed::Sources::NPM

Inherits:
Source
  • Object
show all
Defined in:
lib/licensed/sources/npm.rb

Defined Under Namespace

Classes: Dependency

Instance Attribute Summary

Attributes inherited from Source

#config

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Source

#dependencies, #ignored?, inherited, #initialize

Constructor Details

This class inherits a constructor from Licensed::Sources::Source

Class Method Details

.typeObject



26
27
28
# File 'lib/licensed/sources/npm.rb', line 26

def self.type
  "npm"
end

Instance Method Details

#enabled?Boolean

Returns:

  • (Boolean)


30
31
32
# File 'lib/licensed/sources/npm.rb', line 30

def enabled?
  Licensed::Shell.tool_available?("npm") && File.exist?(config.pwd.join("package.json"))
end

#enumerate_dependenciesObject



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/licensed/sources/npm.rb', line 34

def enumerate_dependencies
  packages.map do |name, package|
    errors = package["problems"] unless package["path"]
    Dependency.new(
      name: name,
      version: package["version"] || package["required"],
      path: package["path"],
      errors: Array(errors),
      metadata: {
        "type"     => NPM.type,
        "name"     => package["name"],
        "summary"  => package["description"],
        "homepage" => package["homepage"]
      }
    )
  end
end

#include_non_production?Boolean

Returns whether to include non production dependencies based on the licensed configuration settings

Returns:

  • (Boolean)


135
136
137
# File 'lib/licensed/sources/npm.rb', line 135

def include_non_production?
  config.dig("npm", "production_only") == false
end

#npm_versionObject

Returns the currently installed version of npm as a Gem::Version object



123
124
125
126
127
# File 'lib/licensed/sources/npm.rb', line 123

def npm_version
  @npm_version ||= begin
    Gem::Version.new(Licensed::Shell.execute("npm", "-v").strip)
  end
end

#package_metadataObject

Returns parsed package metadata returned from ‘npm list`



83
84
85
86
87
88
89
90
91
# File 'lib/licensed/sources/npm.rb', line 83

def 
  return @package_metadata if defined?(@package_metadata)
  @package_metadata = JSON.parse()
rescue JSON::ParserError => e
  message = "Licensed was unable to parse the output from 'npm list'. JSON Error: #{e.message}"
  npm_error = 
  message = "#{message}. npm Error: #{npm_error}" if npm_error
  raise Licensed::Sources::Source::Error, message
end

#package_metadata_argsObject

Returns an array of arguments that should be used for all ‘npm list` calls, regardless of how the output is formatted



111
112
113
114
115
116
117
118
119
120
# File 'lib/licensed/sources/npm.rb', line 111

def 
  args = []
  args << "--production" unless include_non_production?

  # on npm 7+, the --all argument is necessary to evaluate the project's
  # full dependency tree
  args << "--all" if npm_version >= Gem::Version.new("7.0.0")

  return args
end

#package_metadata_commandObject

Returns the output from running ‘npm list` to get package metadata



102
103
104
105
106
107
# File 'lib/licensed/sources/npm.rb', line 102

def 
  args = %w(--json --long)
  args.concat()

  Licensed::Shell.execute("npm", "list", *args, allow_failure: true)
end

#package_metadata_errorObject

Returns an error, if one exists, from running ‘npm list` to get package metadata



94
95
96
97
98
99
# File 'lib/licensed/sources/npm.rb', line 94

def 
  Licensed::Shell.execute("npm", "list", *)
  return ""
rescue Licensed::Shell::Error => e
  return e.message
end

#packagesObject



52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/licensed/sources/npm.rb', line 52

def packages
  root_dependencies = ["dependencies"]
  recursive_dependencies(root_dependencies).each_with_object({}) do |(name, results), hsh|
    results.uniq! { |package| package["version"] }
    if results.size == 1
      hsh[name] = results[0]
    else
      results.each do |package|
        name_with_version = "#{name}-#{package["version"]}"
        hsh[name_with_version] = package
      end
    end
  end
end

#recursive_dependencies(dependencies, result = {}) ⇒ Object

Recursively parse dependency JSON data. Returns a hash mapping the package name to it’s metadata



69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/licensed/sources/npm.rb', line 69

def recursive_dependencies(dependencies, result = {})
  dependencies.each do |name, dependency|
    next if dependency["peerMissing"]
    next if yarn_lock_present && dependency["missing"]
    next if dependency["extraneous"] && dependency["missing"]

    dependency["name"] = name
    (result[name] ||= []) << dependency
    recursive_dependencies(dependency["dependencies"] || {}, result)
  end
  result
end

#yarn_lock_presentObject

Returns true if a yarn.lock file exists in the current directory



130
131
132
# File 'lib/licensed/sources/npm.rb', line 130

def yarn_lock_present
  @yarn_lock_present ||= File.exist?(config.pwd.join("yarn.lock"))
end