diff --git a/lib/importmap/commands.rb b/lib/importmap/commands.rb index 3760631..5d89077 100644 --- a/lib/importmap/commands.rb +++ b/lib/importmap/commands.rb @@ -13,16 +13,19 @@ def self.exit_on_failure? option :env, type: :string, aliases: :e, default: "production" option :from, type: :string, aliases: :f, default: "jspm" option :download, type: :boolean, aliases: :d, default: false + option :integrity, type: :boolean, aliases: :i, default: false def pin(*packages) if imports = packager.import(*packages, env: options[:env], from: options[:from]) imports.each do |package, url| if options[:download] puts %(Pinning "#{package}" to #{packager.vendor_path}/#{package}.js via download from #{url}) packager.download(package, url) - pin = packager.vendored_pin_for(package, url) + integrity = packager.calculate_integrity(package: package) if options[:integrity] + pin = packager.vendored_pin_for(package, url, integrity: integrity) else puts %(Pinning "#{package}" to #{url}) - pin = packager.pin_for(package, url) + integrity = packager.calculate_integrity(url: url) if options[:integrity] + pin = packager.pin_for(package, url, integrity: integrity) end if packager.packaged?(package) diff --git a/lib/importmap/packager.rb b/lib/importmap/packager.rb index 0828465..5fe650e 100644 --- a/lib/importmap/packager.rb +++ b/lib/importmap/packager.rb @@ -32,18 +32,23 @@ def import(*packages, env: "production", from: "jspm") end end - def pin_for(package, url) - %(pin "#{package}", to: "#{url}") + def pin_for(package, url, integrity: false) + if integrity + %(pin "#{package}", to: "#{url}", integrity: "#{integrity}") + else + %(pin "#{package}", to: "#{url}") + end end - def vendored_pin_for(package, url) + def vendored_pin_for(package, url, integrity: false) filename = package_filename(package) version = extract_package_version_from(url) + integrity_suffix = %(, integrity: "#{integrity}") if integrity if "#{package}.js" == filename - %(pin "#{package}" # #{version}) + %(pin "#{package}"#{integrity_suffix} # #{version}) else - %(pin "#{package}", to: "#{filename}" # #{version}) + %(pin "#{package}", to: "#{filename}"#{integrity_suffix} # #{version}) end end @@ -62,6 +67,13 @@ def remove(package) remove_package_from_importmap(package) end + def calculate_integrity(package: nil, url: nil) + contents = File.read(vendored_package_path(package)) if package + contents = Net::HTTP.get_response(URI(url)).body if url + integrity = Digest::SHA384.base64digest(contents) + "sha384-#{integrity}" + end + private def post_json(body) Net::HTTP.post(self.class.endpoint, body.to_json, "Content-Type" => "application/json")