class PoiseJavascript::Resources::NodePackage::Provider

The default provider for the `node_package` resource.

@see Resource

Public Instance Methods

check_package_versions(resource) click to toggle source

Populate current and candidate versions for all needed packages.

@api private @param resource [PoiseJavascript::Resources::NodePackage::Resource]

Resource to load for.

@return [void]

# File lib/poise_javascript/resources/node_package.rb, line 116
def check_package_versions(resource)
  version_data = Hash.new {|hash, key| hash[key] = {current: nil, candidate: nil} }
  # Get the version for everything currently installed.
  list_args = npm_version?('>= 1.4.16') ? %w{--depth 0} : []
  npm_shell_out!('list', list_args).fetch('dependencies', {}).each do |pkg_name, pkg_data|
    version_data[pkg_name][:current] = pkg_data['version']
  end
  # If any requested packages are currently installed, run npm outdated
  # to look for candidate versions. Older npm doesn't support --json
  # here so you get slow behavior, sorry.
  requested_packages = Set.new(Array(resource.package_name))
  if npm_version?('>= 1.3.16') && version_data.any? {|pkg_name, _pkg_vers| requested_packages.include?(pkg_name) }
    outdated = npm_shell_out!('outdated') || {}
    version_data.each do |pkg_name, pkg_vers|
      pkg_vers[:candidate] = if outdated.include?(pkg_name)
        outdated[pkg_name]['wanted']
      else
        # If it was already installed and not listed in outdated, it
        # must have been up to date already.
        pkg_vers[:current]
      end
    end
  end
  # Check for candidates for anything else we didn't get from outdated.
  requested_packages.each do |pkg_name|
    version_data[pkg_name][:candidate] ||= npm_shell_out!('show', [pkg_name])['version']
  end
  # Populate the current resource and candidate versions. Youch this is
  # a gross mix of data flow.
  if(resource.package_name.is_a?(Array))
    @candidate_version = []
    versions = []
    [resource.package_name].flatten.each do |name|
      ver = version_data[name.downcase]
      versions << ver[:current]
      @candidate_version << ver[:candidate]
    end
    resource.version(versions)
  else
    ver = version_data[resource.package_name.downcase]
    resource.version(ver[:current])
    @candidate_version = ver[:candidate]
  end
end
install_package(name, version) click to toggle source

Install package(s) using npm.

@param name [String, Array<String>] Name(s) of package(s). @param version [String, Array<String>] Version(s) of package(s). @return [void]

# File lib/poise_javascript/resources/node_package.rb, line 166
def install_package(name, version)
  args = []
  # Set --unsafe-perm unless the property is nil.
  unless new_resource.unsafe_perm.nil?
    args << '--unsafe-perm'
    args << new_resource.unsafe_perm.to_s
  end
  # Build up the actual package install args.
  if new_resource.source
    args << new_resource.source
  else
    Array(name).zip(Array(version)) do |pkg_name, pkg_ver|
      args << "#{pkg_name}@#{pkg_ver}"
    end
  end
  npm_shell_out!('install', args, parse_json: false)
end
Also aliased as: upgrade_package
load_current_resource() click to toggle source

Load current and candidate versions for all needed packages.

@api private @return [Chef::Resource]

# File lib/poise_javascript/resources/node_package.rb, line 103
def load_current_resource
  @current_resource = new_resource.class.new(new_resource.name, run_context)
  current_resource.package_name(new_resource.package_name)
  check_package_versions(current_resource)
  current_resource
end
remove_package(name, version) click to toggle source

Uninstall package(s) using npm.

@param name [String, Array<String>] Name(s) of package(s). @param version [String, Array<String>] Version(s) of package(s). @return [void]

# File lib/poise_javascript/resources/node_package.rb, line 192
def remove_package(name, version)
  npm_shell_out!('uninstall', [name].flatten, parse_json: false)
end
upgrade_package(name, version)

Upgrade and install are the same for NPM.

Alias for: install_package

Private Instance Methods

npm_shell_out!(subcmd, args=[], parse_json: true) click to toggle source

Run an npm command.

@param subcmd [String] Subcommand to run. @param args [Array<String>] Command arguments. @param parse_json [Boolean] Parse the JSON on stdout. @return [Hash]

# File lib/poise_javascript/resources/node_package.rb, line 204
def npm_shell_out!(subcmd, args=[], parse_json: true)
  cmd = [new_resource.npm_binary, subcmd, '--json']
  # If path is nil, we are in global mode.
  cmd << '--global' unless new_resource.path
  # Add the rest.
  cmd.concat(args)
  # If we are in global mode, cwd will be nil so probably just fine. Add
  # the directory for the node binary to $PATH for post-install stuffs.
  new_path = [::File.dirname(new_resource.javascript), ENV['PATH'].to_s].join(::File::PATH_SEPARATOR)
  out = javascript_shell_out!(cmd, cwd: new_resource.path, group: new_resource.group, user: new_resource.user, environment: {'PATH' => new_path})
  if parse_json
    # Parse the JSON.
    if out.stdout.strip.empty?
      {}
    else
      Chef::JSONCompat.parse(out.stdout)
    end
  else
    out
  end
end
npm_version() click to toggle source

Find the version of the current npm binary.

@return [Gem::Version]

# File lib/poise_javascript/resources/node_package.rb, line 229
def npm_version
  @npm_version ||= begin
    out = javascript_shell_out!([new_resource.npm_binary, 'version'])
    # Older NPM doesn't support --json here we get to regex!
    # The line we want looks like:
    # npm: '2.12.1'
    if out.stdout =~ /npm: '([^']+)'/
      Gem::Version.new($1)
    else
      raise PoiseJavascript::Error.new("Unable to parse NPM version from #{out.stdout.inspect}")
    end
  end
end
npm_version?(req) click to toggle source

Check the NPM version against a requirement.

@param req [String] Requirement string in Gem::Requirement format. @return [Boolean]

# File lib/poise_javascript/resources/node_package.rb, line 247
def npm_version?(req)
  Gem::Requirement.new(req).satisfied_by?(npm_version)
end