lib/licensed/sources/yarn.rb in licensed-3.3.1 vs lib/licensed/sources/yarn.rb in licensed-3.4.0
- old
+ new
@@ -1,146 +1,31 @@
# frozen_string_literal: true
-require "json"
module Licensed
module Sources
- class Yarn < Source
- # `yarn licenses list --json` returns data in a table format with header
- # ordering specified in the output. Look for these specific headers and use
- # their indices to get data from the table body
- YARN_NAME_HEAD = "Name".freeze
- YARN_VERSION_HEAD = "Version".freeze
- YARN_URL_HEAD = "URL".freeze
-
- def enabled?
- return unless Licensed::Shell.tool_available?("yarn")
-
- config.pwd.join("package.json").exist? && config.pwd.join("yarn.lock").exist?
- end
-
- def enumerate_dependencies
- packages.map do |name, package|
- Dependency.new(
- name: name,
- version: package["version"],
- path: package["path"],
- metadata: {
- "type" => Yarn.type,
- "name" => package["name"],
- "homepage" => dependency_urls[package["id"]]
- }
- )
+ module Yarn
+ module ClassMethods
+ def type
+ "yarn"
end
end
- # Finds packages that the current project relies on
- def packages
- return [] if yarn_package_tree.nil?
- all_dependencies = {}
- recursive_dependencies(yarn_package_tree).each do |name, results|
- results.uniq! { |package| package["version"] }
- if results.size == 1
- # if there is only one package for a name, reference it by name
- all_dependencies[name] = results[0]
- else
- # if there is more than one package for a name, reference each by
- # "<name>-<version>"
- results.each do |package|
- all_dependencies["#{name}-#{package["version"]}"] = package
- end
- end
- end
-
- all_dependencies
+ def self.included(klass)
+ klass.extend ClassMethods
end
- # Recursively parse dependency JSON data. Returns a hash mapping the
- # package name to it's metadata
- def recursive_dependencies(dependencies, result = {})
- dependencies.each do |dependency|
- # "shadow" indicate a dependency requirement only, not a
- # resolved package identifier
- next if dependency["shadow"]
- name, _, version = dependency["name"].rpartition("@")
+ def enabled?
+ return unless Licensed::Shell.tool_available?("yarn")
+ return unless self.class.version_requirement.satisfied_by?(yarn_version)
- (result[name] ||= []) << {
- "id" => dependency["name"],
- "name" => name,
- "version" => version,
- "path" => dependency_paths[dependency["name"]]
- }
- recursive_dependencies(dependency["children"], result)
- end
- result
+ config.pwd.join("package.json").exist? && config.pwd.join("yarn.lock").exist?
end
- # Returns a hash that maps all dependency names to their location on disk
- # by parsing every package.json file under node_modules.
- def dependency_paths
- @dependency_paths ||= Dir.glob(config.pwd.join("node_modules/**/package.json")).each_with_object({}) do |file, hsh|
- dirname = File.dirname(file)
- json = JSON.parse(File.read(file))
- hsh["#{json["name"]}@#{json["version"]}"] = dirname
- end
+ def yarn_version
+ Gem::Version.new(Licensed::Shell.execute("yarn", "-v"))
end
-
- # Finds and returns the yarn package tree listing from `yarn list` output
- def yarn_package_tree
- return @yarn_package_tree if defined?(@yarn_package_tree)
- @yarn_package_tree = begin
- # parse all lines of output to json and find one that is "type": "tree"
- tree = yarn_list_command.lines
- .map(&:strip)
- .map(&JSON.method(:parse))
- .find { |json| json["type"] == "tree" }
- tree&.dig("data", "trees")
- end
- end
-
- # Returns a mapping of unique dependency identifiers to urls
- def dependency_urls
- @dependency_urls ||= begin
- table = yarn_licenses_command.lines
- .map(&:strip)
- .map(&JSON.method(:parse))
- .find { |json| json["type"] == "table" }
- return [] if table.nil?
-
- head = table.dig("data", "head")
- return [] if head.nil?
-
- name_index = head.index YARN_NAME_HEAD
- version_index = head.index YARN_VERSION_HEAD
- url_index = head.index YARN_URL_HEAD
- return [] if name_index.nil? || version_index.nil? || url_index.nil?
-
- body = table.dig("data", "body")
- return [] if body.nil?
-
- body.each_with_object({}) do |row, hsh|
- id = "#{row[name_index]}@#{row[version_index]}"
- hsh[id] = row[url_index]
- end
- end
- end
-
- # Returns the output from running `yarn list` to get project dependencies
- def yarn_list_command
- args = %w(--json -s --no-progress)
- args << "--production" unless include_non_production?
- Licensed::Shell.execute("yarn", "list", *args, allow_failure: true)
- end
-
- # Returns the output from running `yarn licenses list` to get project urls
- def yarn_licenses_command
- args = %w(--json -s --no-progress)
- args << "--production" unless include_non_production?
- Licensed::Shell.execute("yarn", "licenses", "list", *args, allow_failure: true)
- end
-
- # Returns whether to include non production dependencies based on the licensed configuration settings
- def include_non_production?
- config.dig("yarn", "production_only") == false
- end
end
end
end
+
+require "licensed/sources/yarn/v1"
+require "licensed/sources/yarn/berry"