112 lines
3.2 KiB
Ruby
112 lines
3.2 KiB
Ruby
|
# frozen_string_literal: true
|
||
|
|
||
|
module Packages
|
||
|
module Npm
|
||
|
class GenerateMetadataService
|
||
|
include API::Helpers::RelatedResourcesHelpers
|
||
|
|
||
|
# Allowed fields are those defined in the abbreviated form
|
||
|
# defined here: https://github.com/npm/registry/blob/master/docs/responses/package-metadata.md#abbreviated-version-object
|
||
|
# except: name, version, dist, dependencies and xDependencies. Those are generated by this service.
|
||
|
PACKAGE_JSON_ALLOWED_FIELDS = %w[deprecated bin directories dist engines _hasShrinkwrap].freeze
|
||
|
|
||
|
def initialize(name, packages)
|
||
|
@name = name
|
||
|
@packages = packages
|
||
|
end
|
||
|
|
||
|
def execute(only_dist_tags: false)
|
||
|
ServiceResponse.success(payload: metadata(only_dist_tags))
|
||
|
end
|
||
|
|
||
|
private
|
||
|
|
||
|
attr_reader :name, :packages
|
||
|
|
||
|
def metadata(only_dist_tags)
|
||
|
result = { dist_tags: dist_tags }
|
||
|
|
||
|
unless only_dist_tags
|
||
|
result[:name] = name
|
||
|
result[:versions] = versions
|
||
|
end
|
||
|
|
||
|
result
|
||
|
end
|
||
|
|
||
|
def versions
|
||
|
package_versions = {}
|
||
|
|
||
|
packages.each_batch do |relation|
|
||
|
batched_packages = relation.including_dependency_links
|
||
|
.preload_files
|
||
|
.preload_npm_metadatum
|
||
|
|
||
|
batched_packages.each do |package|
|
||
|
package_file = package.installable_package_files.last
|
||
|
|
||
|
next unless package_file
|
||
|
|
||
|
package_versions[package.version] = build_package_version(package, package_file)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
package_versions
|
||
|
end
|
||
|
|
||
|
def dist_tags
|
||
|
build_package_tags.tap { |t| t['latest'] ||= sorted_versions.last }
|
||
|
end
|
||
|
|
||
|
def build_package_tags
|
||
|
package_tags.to_h { |tag| [tag.name, tag.package.version] }
|
||
|
end
|
||
|
|
||
|
def build_package_version(package, package_file)
|
||
|
abbreviated_package_json(package).merge(
|
||
|
name: package.name,
|
||
|
version: package.version,
|
||
|
dist: {
|
||
|
shasum: package_file.file_sha1,
|
||
|
tarball: tarball_url(package, package_file)
|
||
|
}
|
||
|
).tap do |package_version|
|
||
|
package_version.merge!(build_package_dependencies(package))
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def tarball_url(package, package_file)
|
||
|
expose_url api_v4_projects_packages_npm_package_name___file_name_path(
|
||
|
{ id: package.project_id, package_name: package.name, file_name: package_file.file_name }, true
|
||
|
)
|
||
|
end
|
||
|
|
||
|
def build_package_dependencies(package)
|
||
|
dependencies = Hash.new { |h, key| h[key] = {} }
|
||
|
|
||
|
package.dependency_links.each do |dependency_link|
|
||
|
dependency = dependency_link.dependency
|
||
|
dependencies[dependency_link.dependency_type][dependency.name] = dependency.version_pattern
|
||
|
end
|
||
|
|
||
|
dependencies
|
||
|
end
|
||
|
|
||
|
def sorted_versions
|
||
|
versions = packages.pluck_versions.compact
|
||
|
VersionSorter.sort(versions)
|
||
|
end
|
||
|
|
||
|
def package_tags
|
||
|
Packages::Tag.for_package_ids(packages.last_of_each_version_ids)
|
||
|
.preload_package
|
||
|
end
|
||
|
|
||
|
def abbreviated_package_json(package)
|
||
|
json = package.npm_metadatum&.package_json || {}
|
||
|
json.slice(*PACKAGE_JSON_ALLOWED_FIELDS)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|