Module: Dependabot::Bun

Defined in:
lib/dependabot/bun.rb,
lib/dependabot/bun/helpers.rb,
lib/dependabot/bun/version.rb,
lib/dependabot/bun/language.rb,
lib/dependabot/bun/file_parser.rb,
lib/dependabot/bun/requirement.rb,
lib/dependabot/bun/file_fetcher.rb,
lib/dependabot/bun/file_updater.rb,
lib/dependabot/bun/package_name.rb,
lib/dependabot/bun/native_helpers.rb,
lib/dependabot/bun/update_checker.rb,
lib/dependabot/bun/metadata_finder.rb,
lib/dependabot/bun/package_manager.rb,
lib/dependabot/bun/registry_helper.rb,
lib/dependabot/bun/registry_parser.rb,
lib/dependabot/bun/version_selector.rb,
lib/dependabot/bun/constraint_helper.rb,
lib/dependabot/bun/bun_package_manager.rb,
lib/dependabot/bun/file_parser/bun_lock.rb,
lib/dependabot/bun/pnpm_package_manager.rb,
lib/dependabot/bun/package/registry_finder.rb,
lib/dependabot/bun/dependency_files_filterer.rb,
lib/dependabot/bun/file_updater/npmrc_builder.rb,
lib/dependabot/bun/file_parser/lockfile_parser.rb,
lib/dependabot/bun/sub_dependency_files_filterer.rb,
lib/dependabot/bun/package/package_details_fetcher.rb,
lib/dependabot/bun/update_checker/library_detector.rb,
lib/dependabot/bun/update_checker/version_resolver.rb,
lib/dependabot/bun/file_updater/bun_lockfile_updater.rb,
lib/dependabot/bun/file_updater/package_json_updater.rb,
lib/dependabot/bun/file_updater/package_json_preparer.rb,
lib/dependabot/bun/update_checker/requirements_updater.rb,
lib/dependabot/bun/file_fetcher/path_dependency_builder.rb,
lib/dependabot/bun/update_checker/latest_version_finder.rb,
lib/dependabot/bun/update_checker/vulnerability_auditor.rb,
lib/dependabot/bun/update_checker/dependency_files_builder.rb,
lib/dependabot/bun/update_checker/subdependency_version_resolver.rb,
lib/dependabot/bun/update_checker/conflicting_dependency_resolver.rb

Defined Under Namespace

Modules: ConstraintHelper, Helpers, NativeHelpers, Package Classes: BunPackageManager, DependencyFilesFilterer, FileFetcher, FileParser, FileUpdater, Language, MetadataFinder, PNPMPackageManager, PackageManagerHelper, PackageName, RegistryHelper, RegistryParser, Requirement, SubDependencyFilesFilterer, UpdateChecker, Utils, Version, VersionSelector

Constant Summary collapse

NODE_VERSION_NOT_SATISFY_REGEX =

rubocop:disable Layout/LineLength

/The current Node version (?<current_version>v?\d+\.\d+\.\d+) does not satisfy the required version (?<required_version>v?\d+\.\d+\.\d+)\./
NPM_REGISTRY =

Used to check if package manager registry is public npm registry

"registry.npmjs.org"
HTTP_CHECK_REGEX =

Used to check if url is http or https

%r{https?://}
URL_CAPTURE =

Used to check capture url match in regex capture group

"url"
INVALID_NAME_IN_PACKAGE_JSON =

When package name contains package.json name cannot contain characters like empty string or @.

"Name contains illegal characters"
PACKAGE_MISSING_REGEX =

Used to identify error messages indicating a package is missing, unreachable, or there are network issues (e.g., ENOBUFS, ETIMEDOUT, registry down).

/(ENOBUFS|ETIMEDOUT|The registry may be down)/
TIMEOUT_FETCHING_PACKAGE_REGEX =

Used to check if error message contains timeout fetching package

%r{(?<url>.+)/(?<package>[^/]+): ETIMEDOUT}
ESOCKETTIMEDOUT =
/(?<package>.*?): ESOCKETTIMEDOUT/
SOCKET_HANG_UP =
/(?<url>.*?): socket hang up/
EEXIST =

Misc errors

/EEXIST: file already exists, mkdir '(?<regis>.*)'/
REQUEST_ERROR_E403 =

registry access errors

/Request "(?<url>.*)" returned a 403/
AUTH_REQUIRED_ERROR =

Authentication is required for the URL.

/(?<url>.*): authentication required/
PERMISSION_DENIED =

Lack of permission to access the URL.

/(?<url>.*): Permission denied/
BAD_REQUEST =

Inconsistent request while accessing resource.

/(?<url>.*): bad_request/
INTERNAL_SERVER_ERROR =

Server error response by remote registry.

/Request failed "500 Internal Server Error"/
UNREACHABLE_GIT_CHECK_REGEX =

Used to identify git unreachable error

/ls-remote --tags --heads (?<url>.*)/
ONLY_PRIVATE_WORKSPACE_TEXT =

Used to check if yarn workspace is enabled in non-private workspace

"Workspaces can only be enabled in priva"
SUB_DEP_LOCAL_PATH_TEXT =

Used to identify local path error in yarn when installing sub-dependency

"refers to a non-existing file"
INVALID_PACKAGE_REGEX =

Used to identify invalid package error when package is not found in registry

/Can't add "[\w\-.]+": invalid/
PACKAGE_NOT_FOUND =

Used to identify error if package not found in registry

"Couldn't find package"
PACKAGE_NOT_FOUND_PACKAGE_NAME_REGEX =
/package "(?<package_req>.*?)"/
PACKAGE_NOT_FOUND_PACKAGE_NAME_CAPTURE =
"package_req"
PACKAGE_NOT_FOUND_PACKAGE_NAME_CAPTURE_SPLIT_REGEX =
/(?<=\w)\@/
YARN_PACKAGE_NOT_FOUND_CODE =
/npm package "(?<dep>.*)" does not exist under owner "(?<regis>.*)"/
YARN_PACKAGE_NOT_FOUND_CODE_1 =
/Couldn't find package "[^@].*(?<dep>.*)" on the "(?<regis>.*)" registry./
YARN_PACKAGE_NOT_FOUND_CODE_2 =

rubocop:disable Layout/LineLength

/Couldn't find package "[^@].*(?<dep>.*)" required by "(?<pkg>.*)" on the "(?<regis>.*)" registry./
PACKAGE_NOT_FOUND2 =
%r{/[^/]+: Not found}
PACKAGE_NOT_FOUND2_PACKAGE_NAME_REGEX =
%r{/(?<package_name>[^/]+): Not found}
PACKAGE_NOT_FOUND2_PACKAGE_NAME_CAPTURE =
"package_name"
DEPENDENCY_VERSION_NOT_FOUND =

Used to identify error if package not found in registry

"Couldn't find any versions"
DEPENDENCY_NOT_FOUND =
": Not found"
DEPENDENCY_MATCH_NOT_FOUND =
"Couldn't find match for"
DEPENDENCY_NO_VERSION_FOUND =
"Couldn't find any versions"
MANIFEST_NOT_FOUND =

Manifest not found

/Cannot read properties of undefined \(reading '(?<file>.*)'\)/
NODE_MODULES_STATE_FILE_NOT_FOUND =

Used to identify error if node_modules state file not resolved

"Couldn't find the node_modules state file"
YARN_USAGE_ERROR_TEXT =

Used to find error message in yarn error output

"Usage Error:"
TARBALL_IS_NOT_IN_NETWORK =

Used to identify error if tarball is not in network

"Tarball is not in network and can not be located in cache"
AUTHENTICATION_TOKEN_NOT_PROVIDED =

Used to identify if authentication failure error

"authentication token not provided"
AUTHENTICATION_IS_NOT_CONFIGURED =
"No authentication configured for request"
AUTHENTICATION_HEADER_NOT_PROVIDED =
"Unauthenticated: request did not include an Authorization header."
DEPENDENCY_FILE_NOT_RESOLVABLE =

Used to identify if error message is related to yarn workspaces

"conflicts with direct dependency"
ENV_VAR_NOT_RESOLVABLE =
/Failed to replace env in config: \$\{(?<var>.*)\}/
OUT_OF_DISKSPACE =
/ Out of diskspace/
REGISTRY_NOT_REACHABLE =

registry returns malformed response

/Received malformed response from registry for "(?<ver>.*)". The registry may be down./
ErrorHandler =

A type used for defining a proc that creates a new error object

T.type_alias do
  T.proc
   .params(message: String, error: Dependabot::DependabotError, params: T::Hash[Symbol, T.untyped])
   .returns(Dependabot::DependabotError)
end
VALIDATION_GROUP_PATTERNS =

Group of patterns to validate error message and raise specific error

T.let(
  [
    {
      patterns: [INVALID_NAME_IN_PACKAGE_JSON],
      handler: lambda { |message, _error, _params|
        Dependabot::DependencyFileNotResolvable.new(message)
      },
      in_usage: false,
      matchfn: nil
    },
    {
      # Check if sub dependency is using local path and raise a resolvability error
      patterns: [INVALID_PACKAGE_REGEX, SUB_DEP_LOCAL_PATH_TEXT],
      handler: lambda { |message, _error, params|
        Dependabot::DependencyFileNotResolvable.new(
          Utils.sanitize_resolvability_message(
            message,
            params[:dependencies],
            params[:yarn_lock]
          )
        )
      },
      in_usage: false,
      matchfn: nil
    },
    {
      patterns: [NODE_MODULES_STATE_FILE_NOT_FOUND],
      handler: lambda { |message, _error, _params|
        Dependabot::MisconfiguredTooling.new("Yarn", message)
      },
      in_usage: true,
      matchfn: nil
    },
    {
      patterns: [TARBALL_IS_NOT_IN_NETWORK],
      handler: lambda { |message, _error, _params|
        Dependabot::DependencyFileNotResolvable.new(message)
      },
      in_usage: false,
      matchfn: nil
    },
    {
      patterns: [NODE_VERSION_NOT_SATISFY_REGEX],
      handler: lambda { |message, _error, _params|
        versions = Utils.extract_node_versions(message)
        current_version = versions[:current_version]
        required_version = versions[:required_version]

        return Dependabot::DependabotError.new(message) unless current_version && required_version

        Dependabot::ToolVersionNotSupported.new("Yarn", current_version, required_version)
      },
      in_usage: false,
      matchfn: nil
    },
    {
      patterns: [AUTHENTICATION_TOKEN_NOT_PROVIDED, AUTHENTICATION_IS_NOT_CONFIGURED,
                 AUTHENTICATION_HEADER_NOT_PROVIDED],
      handler: lambda { |message, _error, _params|
        Dependabot::PrivateSourceAuthenticationFailure.new(message)
      },
      in_usage: false,
      matchfn: nil
    },
    {
      patterns: [DEPENDENCY_FILE_NOT_RESOLVABLE],
      handler: lambda { |message, _error, _params|
        DependencyFileNotResolvable.new(message)
      },
      in_usage: false,
      matchfn: nil
    },
    {
      patterns: [ENV_VAR_NOT_RESOLVABLE],
      handler: lambda { |message, _error, _params|
        var = Utils.extract_var(message)

        Dependabot::MissingEnvironmentVariable.new(var, message)
      },
      in_usage: false,
      matchfn: nil
    },
    {
      patterns: [ONLY_PRIVATE_WORKSPACE_TEXT],
      handler: lambda { |message, _error, _params|
        Dependabot::DependencyFileNotEvaluatable.new(message)
      },
      in_usage: false,
      matchfn: nil
    },
    {
      patterns: [UNREACHABLE_GIT_CHECK_REGEX],
      handler: lambda { |message, _error, _params|
        dependency_url = message.match(UNREACHABLE_GIT_CHECK_REGEX).named_captures.fetch(URL_CAPTURE)

        Dependabot::GitDependenciesNotReachable.new(dependency_url)
      },
      in_usage: false,
      matchfn: nil
    },
    {
      patterns: [SOCKET_HANG_UP],
      handler: lambda { |message, _error, _params|
        url = message.match(SOCKET_HANG_UP).named_captures.fetch(URL_CAPTURE)

        Dependabot::PrivateSourceTimedOut.new(url.gsub(HTTP_CHECK_REGEX, ""))
      },
      in_usage: false,
      matchfn: nil
    },
    {
      patterns: [ESOCKETTIMEDOUT],
      handler: lambda { |message, _error, _params|
        package_req = message.match(ESOCKETTIMEDOUT).named_captures.fetch("package")

        Dependabot::PrivateSourceTimedOut.new(package_req.gsub(HTTP_CHECK_REGEX, ""))
      },
      in_usage: false,
      matchfn: nil
    },
    {
      patterns: [OUT_OF_DISKSPACE],
      handler: lambda { |message, _error, _params|
        Dependabot::OutOfDisk.new(message)
      },
      in_usage: false,
      matchfn: nil
    },
    {
      patterns: [YARN_PACKAGE_NOT_FOUND_CODE, YARN_PACKAGE_NOT_FOUND_CODE_1, YARN_PACKAGE_NOT_FOUND_CODE_2],
      handler: lambda { |message, _error, _params|
        msg = message.match(YARN_PACKAGE_NOT_FOUND_CODE) || message.match(YARN_PACKAGE_NOT_FOUND_CODE_1) ||
        message.match(YARN_PACKAGE_NOT_FOUND_CODE_2)

        Dependabot::DependencyFileNotResolvable.new(msg)
      },
      in_usage: false,
      matchfn: nil
    },
    {
      patterns: [REQUEST_ERROR_E403, AUTH_REQUIRED_ERROR, PERMISSION_DENIED, BAD_REQUEST],
      handler: lambda { |message, _error, _params|
        dependency_url = T.must(URI.decode_www_form_component(message).split("https://").last).split("/").first

        Dependabot::PrivateSourceAuthenticationFailure.new(dependency_url)
      },
      in_usage: false,
      matchfn: nil
    },
    {
      patterns: [MANIFEST_NOT_FOUND],
      handler: lambda { |message, _error, _params|
        msg = message.match(MANIFEST_NOT_FOUND)
        Dependabot::DependencyFileNotResolvable.new(msg)
      },
      in_usage: false,
      matchfn: nil
    },
    {
      patterns: [INTERNAL_SERVER_ERROR],
      handler: lambda { |message, _error, _params|
        msg = message.match(INTERNAL_SERVER_ERROR)
        Dependabot::DependencyFileNotResolvable.new(msg)
      },
      in_usage: false,
      matchfn: nil
    },
    {
      patterns: [REGISTRY_NOT_REACHABLE],
      handler: lambda { |message, _error, _params|
        msg = message.match(REGISTRY_NOT_REACHABLE)
        Dependabot::DependencyFileNotResolvable.new(msg)
      },
      in_usage: false,
      matchfn: nil
    }
  ].freeze,
  T::Array[{
    patterns: T::Array[T.any(String, Regexp)],
    handler: ErrorHandler,
    in_usage: T.nilable(T::Boolean),
    matchfn: T.nilable(T.proc.params(usage: String, message: String).returns(T::Boolean))
  }]
)
ECOSYSTEM =
"bun"
MANIFEST_FILENAME =
"package.json"
LERNA_JSON_FILENAME =
"lerna.json"
PACKAGE_MANAGER_VERSION_REGEX =
/
  ^                        # Start of string
  (?<major>\d+)            # Major version (required, numeric)
  \.                       # Separator between major and minor versions
  (?<minor>\d+)            # Minor version (required, numeric)
  \.                       # Separator between minor and patch versions
  (?<patch>\d+)            # Patch version (required, numeric)
  (                        # Start pre-release section
    -(?<pre_release>[a-zA-Z0-9.]+) # Pre-release label (optional, alphanumeric or dot-separated)
  )?
  (                        # Start build metadata section
    \+(?<build>[a-zA-Z0-9.]+) # Build metadata (optional, alphanumeric or dot-separated)
  )?
  $                        # End of string
/x
VALID_REQUIREMENT_CONSTRAINT =

Extended mode for readability

/
  ^                        # Start of string
  (?<operator>=|>|>=|<|<=|~>|\\^) # Allowed operators
  \s*                      # Optional whitespace
  (?<major>\d+)            # Major version (required)
  (\.(?<minor>\d+))?       # Minor version (optional)
  (\.(?<patch>\d+))?       # Patch version (optional)
  (                        # Start pre-release section
    -(?<pre_release>[a-zA-Z0-9.]+) # Pre-release label (optional)
  )?
  (                        # Start build metadata section
    \+(?<build>[a-zA-Z0-9.]+) # Build metadata (optional)
  )?
  $                        # End of string
/x
MANIFEST_PACKAGE_MANAGER_KEY =

Extended mode for readability

"packageManager"
MANIFEST_ENGINES_KEY =
"engines"
ERROR_MALFORMED_VERSION_NUMBER =

Error malformed version number string

"Malformed version number"